[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: mswjs\nopen_collective: mswjs\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/01-issue-browser.yml",
    "content": "name: 'Bug report (Browser)'\ndescription: I experience unexpected behavior using the library in a browser.\nlabels: ['bug', 'scope:browser', 'needs:triage']\nbody:\n  - type: markdown\n    attributes:\n      value: Thank you for reporting an issue to Mock Service Worker! Please fill in the template below to help our team tackle it in the most efficient way.\n\n  - type: checkboxes\n    attributes:\n      label: Prerequisites\n      description: Before we begin, let's make sure your issue hasn't been solved already.\n      options:\n        - label: I confirm my issue is not in the [opened issues](https://github.com/mswjs/msw/issues)\n          required: true\n        - label: I confirm the [Frequently Asked Questions](https://mswjs.io/docs/faq) didn't contain the answer to my issue\n          required: true\n\n  - type: checkboxes\n    attributes:\n      label: Environment check\n      options:\n        - label: I'm using the [latest](https://github.com/mswjs/msw/releases/latest) `msw` version\n          required: true\n        - label: I'm using Node.js version 20 or higher\n          required: true\n\n  - type: dropdown\n    attributes:\n      label: Browsers\n      description: Select in which browser(s) you're experiencing the issue.\n      multiple: true\n      options:\n        - 'Chromium (Chrome, Brave, etc.)'\n        - 'Firefox'\n        - 'Safari'\n\n  - type: input\n    attributes:\n      label: Reproduction repository\n      description: A link to the repository where your issue can be reproduced. You can clone one of [our examples](https://github.com/mswjs/examples) to create a reproduction repository much faster. **Issues without a reproduction repository will be closed**.\n      placeholder: i.e. https://github.com/you/msw-issue\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Reproduction steps\n      description: Include any steps necessary to reproduce the issue in the repository above.\n      placeholder: i.e. \"npm test\"\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Current behavior\n      description: Share any details on what behavior you're experiencing (error messages, logs, context).\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Expected behavior\n      description: What do you expect to happen instead?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02-issue-nodejs.yml",
    "content": "name: 'Bug report (Node.js)'\ndescription: I experience unexpected behavior using the library in Node.js (Vitest/React Native/Express/etc.).\nlabels: ['bug', 'scope:node', 'needs:triage']\nbody:\n  - type: markdown\n    attributes:\n      value: Thank you for reporting an issue to Mock Service Worker! Please fill in the template below to help our team tackle it in the most efficient way.\n\n  - type: checkboxes\n    attributes:\n      label: Prerequisites\n      description: Before we begin, let's make sure your issue hasn't been solved already.\n      options:\n        - label: I confirm my issue is not in the [opened issues](https://github.com/mswjs/msw/issues)\n          required: true\n        - label: I confirm the [Frequently Asked Questions](https://mswjs.io/docs/faq) didn't contain the answer to my issue\n          required: true\n\n  - type: checkboxes\n    attributes:\n      label: Environment check\n      description: Next, let's make sure you're using the library in the officially supported environments.\n      options:\n        - label: I'm using the [latest](https://github.com/mswjs/msw/releases/latest) `msw` version\n          required: true\n        - label: I'm using Node.js version 20 or higher\n          required: true\n\n  - type: input\n    attributes:\n      label: Node.js version\n      description: Specify which Node.js version you're using (`node -v`).\n      placeholder: i.e. v20.18.0\n    validations:\n      required: true\n\n  - type: input\n    attributes:\n      label: Reproduction repository\n      description: A link to the repository where your issue can be reproduced. You can clone one of [our examples](https://github.com/mswjs/examples) to create a reproduction repository much faster. **Issues without a reproduction repository will be closed**.\n      placeholder: i.e. https://github.com/you/msw-issue\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Reproduction steps\n      description: Include any steps necessary to reproduce the issue in the repository above.\n      placeholder: i.e. \"npm test\"\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Current behavior\n      description: Share any details on what behavior you're experiencing (error messages, logs, context).\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Expected behavior\n      description: What do you expect to happen instead?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/03-feature.yml",
    "content": "name: 'Feature request'\ndescription: Propose a feature or improvement.\nlabels: [feature]\nbody:\n  - type: markdown\n    attributes:\n      value: Thank you for deciding to make Mock Service Worker better! Please fill in the form below so our team could understand your feature better.\n\n  - type: dropdown\n    attributes:\n      label: Scope\n      multiple: false\n      options:\n        - 'Adds a new behavior'\n        - 'Improves an existing behavior'\n    validations:\n      required: true\n\n  - type: checkboxes\n    attributes:\n      label: Compatibility\n      description: Check if your proposal is a breaking change. Leave this field unchecked if not sure.\n      options:\n        - label: This is a breaking change\n          required: false\n\n  - type: textarea\n    attributes:\n      label: Feature description\n      description: \"Describe the feature you're suggesting. Be as detailed as possible: include behavior description, pseudo-code snippets, comparison to similar features.\"\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/workflows/auto.yml",
    "content": "name: auto\n\non: [push]\n\njobs:\n  cancel-previous-workflows:\n    runs-on: macos-latest\n    timeout-minutes: 3\n    steps:\n      - uses: styfle/cancel-workflow-action@0.9.1\n        with:\n          workflow_id: ci.yml\n          access_token: ${{ github.token }}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: ci\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  workflow_dispatch:\n\njobs:\n  build-20:\n    name: build (20)\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Lint\n        run: pnpm lint\n\n      - name: Build\n        run: pnpm build\n\n      - name: Cache build output\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-20-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-build-20\n\n  build-22:\n    name: build (22)\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Lint\n        run: pnpm lint\n\n      - name: Build\n        run: pnpm build\n\n      - name: Cache build output\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-22-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-build-22\n\n  test-unit:\n    name: test (unit)\n    needs: build-20\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Restore build cache\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-20-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-node-20-build-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Install Playwright browsers\n        run: pnpm exec playwright install chromium --with-deps --only-shell\n\n      - name: Unit tests\n        run: pnpm test:unit\n\n  test-node-20:\n    name: test (node.js) (20)\n    needs: build-20\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Restore build cache\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-20-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-node-20-build-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Node.js tests\n        run: pnpm test:node\n\n  test-node-22:\n    name: test (node.js) (22)\n    needs: build-22\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n\n      - name: Restore build cache\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-22-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-node-22-build-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Node.js tests\n        run: pnpm test:node\n\n  test-e2e:\n    name: test (e2e) (20)\n    needs: build-20\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: E2E tests\n        run: pnpm test:e2e\n\n  test-browser:\n    name: test (browser)\n    needs: build-20\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Restore build cache\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-20-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-node-20-build-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Playwright install\n        run: pnpm exec playwright install chromium --with-deps --only-shell\n\n      - name: Browser tests\n        run: pnpm test:browser\n\n      - name: Upload test artifacts\n        if: always()\n        uses: actions/upload-artifact@v4\n        with:\n          name: playwright-report\n          path: test/browser/test-results\n\n  test-native:\n    name: test (react-native)\n    needs: build-20\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Restore build cache\n        uses: actions/cache@v4\n        with:\n          path: ./lib\n          key: ${{ runner.os }}-node-20-build-${{ github.sha }}\n          restore-keys: |\n            ${{ runner.os }}-node-20-build-\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: React Native tests\n        run: pnpm test:native\n"
  },
  {
    "path": ".github/workflows/compat.yml",
    "content": "name: compat\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  workflow_dispatch:\n\njobs:\n  # Validate the package.json exports and emitted CJS/ESM bundles.\n  exports:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Install Playwright browsers\n        run: pnpm exec playwright install chromium --with-deps --only-shell\n\n      - name: Build\n        run: pnpm build\n\n      - name: Lint package\n        run: pnpm publint\n\n      - name: Test modules (Node.js)\n        run: pnpm test:modules:node\n\n      - name: Test modules (browser)\n        run: pnpm test:modules:browser\n\n  # Checks the library's compatibility with different\n  # TypeScript versions to discover type regressions.\n  typescript:\n    runs-on: macos-latest\n    # Skip TypeScript compatibility check on \"main\".\n    # A merged pull request implies passing \"typescript\" job.\n    if: github.ref != 'refs/heads/main'\n    strategy:\n      fail-fast: false\n      matrix:\n        # As a general rule, when adding a new version, remove the oldest version\n        # Check if the oldest version is EOL or not first.\n        ts: ['5.0', '5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8']\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build\n\n      - name: Install TypeScript ${{ matrix.ts }}\n        run: pnpm add typescript@${{ matrix.ts }}\n\n      - name: Typings tests\n        run: |\n          pnpm tsc --version\n          pnpm test:ts\n"
  },
  {
    "path": ".github/workflows/lock-closed-issues.yml",
    "content": "name: locked-closed-issues\n\non:\n  schedule:\n    - cron: '0 0 * * *'\n\npermissions:\n  issues: write\n\njobs:\n  action:\n    runs-on: macos-latest\n    steps:\n      - uses: dessant/lock-threads@v5\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          issue-inactive-days: '14'\n          issue-lock-reason: ''\n          process-only: 'issues'\n"
  },
  {
    "path": ".github/workflows/release-preview.yml",
    "content": "name: release-preview\n\non:\n  push:\n    branches-ignore:\n      - 'main'\n    tags:\n      - '!**'\n  workflow_dispatch:\n\njobs:\n  publish:\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Install Playwright browsers\n        run: pnpm exec playwright install chromium --with-deps --only-shell\n\n      - name: Lint\n        run: pnpm lint\n\n      - name: Build\n        run: pnpm build\n\n      - name: Tests\n        run: pnpm test\n\n      - name: Publish preview\n        run: pnpm dlx pkg-pr-new@0.0 publish --compact --pnpm --comment=update\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\n\non:\n  schedule:\n    - cron: '0 1 * * *'\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          token: ${{ secrets.GH_ADMIN_TOKEN }}\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Install Playwright browsers\n        run: pnpm exec playwright install chromium --with-deps --only-shell\n\n      - name: Lint\n        run: pnpm lint\n\n      - name: Build\n        run: pnpm build\n\n      - name: Tests\n        run: pnpm test\n\n      - name: Upload build artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: build-artifacts\n          path: ./lib\n\n  release:\n    needs: [build]\n    runs-on: macos-latest\n    permissions:\n      contents: read\n      id-token: write\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n          token: ${{ secrets.GH_ADMIN_TOKEN }}\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          # Trusted Publishing only works on Node.js v24.\n          node-version: 24\n          cache: 'pnpm'\n\n      - name: Setup Git\n        run: |\n          git config --local user.name \"Artem Zakharchenko\"\n          git config --local user.email \"kettanaito@gmail.com\"\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Download build artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: build-artifacts\n          path: ./lib\n\n      - name: Release\n        run: pnpm release\n        env:\n          GITHUB_TOKEN: ${{ secrets.GH_ADMIN_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/smoke-test.yml",
    "content": "name: smoke-test\n\non:\n  # Always run smoke tests upon a successful\n  # \"ci\" job completion on \"main\".\n  workflow_run:\n    workflows: ['ci']\n    branches: [main]\n    types: [completed]\n  workflow_dispatch:\n\njobs:\n  examples:\n    if: ${{ (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') || github.event_name == 'workflow_dispatch' }}\n    runs-on: macos-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Test examples\n        run: ./config/scripts/smoke-test.sh\n"
  },
  {
    "path": ".github/workflows/typescript-nightly.yml",
    "content": "name: typescript-nightly\n\non:\n  schedule:\n    # Schedule to run nightly at midnight\n    - cron: '0 0 * * *'\n  workflow_dispatch:\n\njobs:\n  compare:\n    runs-on: macos-latest\n    steps:\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Get latest TypeScript version\n        id: get-versions\n        run: |\n          # Fetch the latest published version of TypeScript on npm\n          latest_version=$(npm show typescript dist-tags.latest)\n\n          # Get the currently installed version\n          rc_version=$(npm show typescript dist-tags.rc)\n\n          latest_major_minor=$(echo \"$latest_version\" | cut -d '.' -f 1,2)\n          rc_major_minor=$(echo \"$rc_version\" | cut -d '.' -f 1,2)\n\n          echo \"latest_version=$latest_major_minor\" >> $GITHUB_OUTPUT\n          echo \"rc_version=$rc_major_minor\" >> $GITHUB_OUTPUT\n\n  test:\n    runs-on: macos-latest\n    # Skip TypeScript compatibility check on \"main\".\n    # A merged pull request implies passing \"typescript\" job.\n    if: ${{ needs.compare.outputs.latest_version != needs.compare.outputs.rc_version }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Set up pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9.15.0\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build\n        run: pnpm build\n\n      - name: Install TypeScript RC\n        run: pnpm add typescript@rc\n\n      - name: Write tsconfig\n        run: |\n          cp test/typings/tsconfig.5.2.json test/typings/tsconfig.${needs.compare.outputs.rc_version}.json\n\n      - name: Typings tests\n        run: |\n          pnpm tsc --version\n          pnpm test:ts\n"
  },
  {
    "path": ".gitignore",
    "content": "__*\n.DS_*\nnode_modules\n/lib\ntmp\n*-error.log\n/package-lock.json\n/yarn.lock\nstats.html\n.vscode\n.idea\nmsw-*.tgz\n.husky/_\n.env\n**/test-results\n/test/modules/node/node-esm-tests\n\n# Smoke test temporary files.\n/package.json.copy\n/examples\n/test/modules/node/node-esm-tests\n*.vitest-temp.json\n"
  },
  {
    "path": ".nvmrc",
    "content": "v20\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"arrowParens\": \"always\",\n  \"bracketSpacing\": true,\n  \"semi\": false,\n  \"useTabs\": false,\n  \"trailingComma\": \"all\",\n  \"singleQuote\": true\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\nThis project adheres to [Semantic Versioning](https://semver.org/).\nEvery release, along with the migration instructions, is documented on the Github [Releases](https://github.com/mswjs/msw/releases) page.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nHey! Thank you for deciding to contribute to Mock Service Worker! This page will help you land your first contribution by giving you a better understanding about the project's structure, dependencies, and development workflow.\n\n## Tools\n\nGetting yourself familiar with the tools below will substantially ease your contribution experience.\n\n- [TypeScript](https://www.typescriptlang.org/)\n- [Vitest](https://vitest.dev/)\n- [Playwright](https://playwright.dev/)\n\n## Dependencies\n\nMock Service Worker depends on multiple other libraries.\n\n| Library name                                            | Purpose                                                                  |\n| ------------------------------------------------------- | ------------------------------------------------------------------------ |\n| [cookies](https://github.com/mswjs/cookies)             | Enables cookies persistence and inference between environments.          |\n| [headers-utils](https://github.com/mswjs/headers-utils) | `Headers` polyfill to manage request/response headers.                   |\n| [interceptors](https://github.com/mswjs/interceptors)   | Provisions request interception in Node.js (internals of `setupServer`). |\n\nThere are cases when an issue originates from one of the said dependencies. Don't hesitate to address it in the respective repository, as they all are governed by the same team.\n\n## Getting started\n\n### Fork the repository\n\nPlease use the GitHub UI to [fork this repository](https://github.com/mswjs/msw) (_read more about [Forking a repository](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo)_). Mock Service Worker has forked builds enabled in the CI, so you will see the build status of your fork's branch.\n\n### Install\n\n```bash\n$ cd msw\n$ pnpm install\n$ pnpm start\n```\n\n> Please use [PNPM][pnpm-url] version 8.15 while working on this project.\n> Guide on how to install a specific PNPM version can be [found here][pnpm-install-guide-url].\n\n## Git workflow\n\n```bash\n# Checkout the default branch and ensure it's up-to-date\n$ git checkout main\n$ git pull --rebase\n\n# Create a feature branch\n$ git checkout -b feature/graphql-subscriptions\n\n# Commit the changes\n$ git add .\n$ git commit\n# Follow the interactive prompt to compose a commit message\n\n# Push\n$ git push -u origin feature/graphql-subscriptions\n```\n\nWe are using [Conventional Commits](https://conventionalcommits.org/) naming convention. It helps us automate library releases and ensure clean and standardized commit tree. Please take a moment to read about the said convention before you name your commits.\n\n> **Tip:** running `git commit` will open an interactive prompt in your terminal. Follow the prompt to compose a valid commit message.\n\nOnce you have pushed the changes to your remote feature branch, [create a pull request](https://github.com/open-draft/msw/compare) on GitHub. Undergo the process of code review, where the maintainers of the library will help you get the changes from good to great, and enjoy your implementation merged to the default branch.\n\n> Please be respectful when requesting and going through the code review. Everyone on the team is interested in merging quality and well tested code, and we're hopeful that you have the same goal. It may take some time and iterations to get it right, and we will assist you throughout the process.\n\n## Build\n\nBuild the library with the following command:\n\n```bash\n$ pnpm build\n```\n\n## Tests\n\n### Testing levels\n\nThere are two levels of tests on the project:\n\n- [Unit tests](#unit-tests), cover small independent functions.\n- [Integration tests](#integration-tests), test in-browser usage scenarios.\n\n**Always begin your implementation from tests**. When tackling an issue, a test for it must be missing, or is incomplete. When working on a feature, starting with a test allows you to model the feature's usage before diving into implementation.\n\n### Unit tests\n\n#### Writing a unit test\n\nUnit tests are placed next to the tested code. For example, if you're testing a newly added `multiply` function, create a `multiply.test.ts` file next to where the function is located:\n\n```bash\n$ touch src/utils/multiply.test.ts\n```\n\nProceed by writing a unit test that resembles the usage of the function. Make sure to cover all the scenarios\n\n```ts\n// src/utils/multiply.test.ts\nimport { multiply } from './multiply'\n\ntest('multiplies two given numbers', () => {\n  expect(multiply(2, 3)).toEqual(6)\n})\n```\n\n> Please [avoid nesting](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing/) while you're testing.\n\n#### Running a single unit test\n\nOnce your test is written, run it in isolation.\n\n```bash\n$ pnpm test:unit src/utils/multiply.test.ts\n```\n\nAt this point, the actual implementation is not ready yet, so you can expect your test to fail. **That's perfect**. Add the necessary modules and logic, and gradually see your test cases pass.\n\n#### Running all unit tests\n\n```bash\n$ pnpm test:unit\n```\n\n### Integration tests\n\nWe follow an example-driven testing paradigm, meaning that each integration test represents a _usage example_. Mock Service Worker can be used in different environments (browser, Node.js), making such usage examples different.\n\n> **Make sure that you [build the library](#build) before running the integration tests**. It's a good idea to keep the build running (`pnpm start`) while working on the tests. Keeping both compiler and test runner in watch mode boosts your productivity.\n\n#### Browser integration tests\n\nYou can find all the browser integration tests under `./test/browser`. Those tests are run with Playwright and usually consist of two parts:\n\n- `[test-name].mocks.ts`, the usage example of MSW;\n- `[test-name].test.ts`, the test suite that loads the usage example, does actions and performs assertions.\n\nIt's also a great idea to get familiar with our Playwright configuration and extensions:\n\n- [**Playwright configuration file**](./test/browser/playwright.config.ts)\n- [Playwright extensions](./test/browser/playwright.extend.ts)\n\nLet's write an example integration test that asserts the interception of a GET request. First, start with the `*.mocks.ts` file:\n\n```js\n// test/browser/example.mocks.ts\nimport { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/books', () => {\n    return HttpResponse.json([\n      {\n        id: 'ea42ffcb-e729-4dd5-bfac-7a5b645cb1da',\n        title: 'The Lord of the Rings',\n        publishedAt: -486867600,\n      },\n    ])\n  }),\n)\n\nworker.start()\n```\n\n> Notice how there's nothing test-specific in the example? The `example.mocks.ts` file is a copy-paste example of intercepting the `GET /books` request. This allows to share these mocks with the users as a legitimate example, because it is!\n\nOnce the `*.mocks.ts` file is written, proceed by creating a test file:\n\n```ts\n// test/browser/example.test.ts\nimport * as path from 'path'\nimport { test, expect } from './playwright.extend'\n\ntest('returns a mocked response', async ({ loadExample, fetch }) => {\n  // Compile the given usage example on runtime.\n  await loadExample(new URL('./example.mocks.ts', import.meta.url))\n\n  // Perform the \"GET /books\" request in the browser.\n  const res = await fetch('/books')\n\n  // Assert the returned response body.\n  expect(await res.json()).toEqual([\n    {\n      id: 'ea42ffcb-e729-4dd5-bfac-7a5b645cb1da',\n      title: 'The Lord of the Rings',\n      publishedAt: -486867600,\n    },\n  ])\n})\n```\n\n##### Running all browser tests\n\nMake sure Playwright chromium has been installed before running browser tests.\n\n```sh\npnpm test:browser\n```\n\n#### Running a single browser test\n\n```sh\npnpm test:browser ./test/browser/example.test.ts\n```\n\n#### Node.js integration test\n\nIntegration tests showcase a usage example in Node.js and are often placed next to the in-browser tests. Node.js integration tests reside in the `./test/node` directory.\n\nSimilar to the browser tests, these are going to contain a usage example and the assertions over it. However, for Node.js tests there is no need to create a separate `*.mocks.ts` file. Instead, keep the usage example in the test file directly.\n\nLet's replicate the same `GET /books` integration test in Node.js.\n\n```ts\n// test/node/example.test.ts\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('/books', () => {\n    return HttpResponse.json([\n      {\n        id: 'ea42ffcb-e729-4dd5-bfac-7a5b645cb1da',\n        title: 'The Lord of the Rings',\n        publishedAt: -486867600,\n      },\n    ])\n  }),\n)\n\nbeforeAll(() => server.listen())\n\nafterAll(() => server.close())\n\ntest('returns a mocked response', async () => {\n  const res = await fetch('/books')\n\n  expect(await res.json()).toEqual([\n    {\n      id: 'ea42ffcb-e729-4dd5-bfac-7a5b645cb1da',\n      title: 'The Lord of the Rings',\n      publishedAt: -486867600,\n    },\n  ])\n})\n```\n\n##### Running all Node.js tests\n\n```sh\npnpm test:node\n```\n\n##### Running a single Node.js test\n\n```sh\npnpm test:node ./test/node/example.test.ts\n```\n\n## Build\n\nBuild the library with the following command:\n\n```bash\n$ pnpm build\n```\n\n[pnpm-url]: https://pnpm.io/\n[page-with-url]: https://github.com/kettanaito/page-with\n[pnpm-install-guide-url]: https://pnpm.io/8.x/installation#installing-a-specific-version\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2018–present Artem Zakharchenko\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": "<br />\n\n<p align=\"center\">\n  <img src=\"media/msw-logo.svg\" width=\"100\" alt=\"The Mock Service Worker logo\" />\n</p>\n\n<h1 align=\"center\">Mock Service Worker</h1>\n<p align=\"center\">Industry standard API mocking for JavaScript.</p>\n\n<p align=\"center\">\n   <a href=\"https://kettanaito.com/discord\" target=\"_blank\">Join our Discord server</a>\n</p>\n\n<br />\n<br />\n\n## Features\n\n- **Seamless**. A dedicated layer of requests interception at your disposal. Keep your application's code and tests unaware of whether something is mocked or not.\n- **Deviation-free**. Request the same production resources and test the actual behavior of your app. Augment an existing API, or design it as you go when there is none.\n- **Familiar & Powerful**. Use [Express](https://github.com/expressjs/express)-like routing syntax to intercept requests. Use parameters, wildcards, and regular expressions to match requests, and respond with necessary status codes, headers, cookies, delays, or completely custom resolvers.\n\n---\n\n> \"_I found MSW and was thrilled that not only could I still see the mocked responses in my DevTools, but that the mocks didn't have to be written in a Service Worker and could instead live alongside the rest of my app. This made it silly easy to adopt. The fact that I can use it for testing as well makes MSW a huge productivity booster._\"\n>\n> — [Kent C. Dodds](https://twitter.com/kentcdodds)\n\n## Documentation\n\nThis README will give you a brief overview of the library, but there's no better place to start with Mock Service Worker than its official documentation.\n\n- [Documentation](https://mswjs.io/docs)\n- [**Quick start**](https://mswjs.io/docs/quick-start)\n- [FAQ](https://mswjs.io/docs/faq)\n\n## Examples\n\n- See the list of [**Usage examples**](https://github.com/mswjs/examples)\n\n## Courses\n\nWe've partnered with Egghead to bring you quality paid materials to learn the best practices of API mocking on the web. Please give them a shot! The royalties earned from them help sustain the project's development. Thank you.\n\n- 🚀 [**Mocking REST and GraphQL APIs with Mock Service Worker**](https://egghead.io/courses/mock-rest-and-graphql-apis-with-mock-service-worker-8d471ece?af=8mci9b)\n- 🔌 [Mocking (and testing) WebSocket APIs with Mock Service Worker](https://egghead.io/courses/mocking-websocket-apis-with-mock-service-worker-9933b7f5)\n\n## Browser\n\n- [Learn more about using MSW in a browser](https://mswjs.io/docs/integrations/browser)\n- [`setupWorker` API](https://mswjs.io/docs/api/setup-worker)\n\n### How does it work?\n\nIn-browser usage is what sets Mock Service Worker apart from other tools. Utilizing the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API), which can intercept requests for the purpose of caching, Mock Service Worker responds to intercepted requests with your mock definition on the network level. This way your application knows nothing about the mocking.\n\n**Take a look at this quick presentation on how Mock Service Worker functions in a browser:**\n\n[![What is Mock Service Worker?](https://raw.githubusercontent.com/mswjs/msw/main/media/msw-video-thumbnail.jpg)](https://youtu.be/HcQCqboatZk)\n\n### How is it different?\n\n- This library intercepts requests on the network level, which means _after_ they have been performed and \"left\" your application. As a result, the entirety of your code runs, giving you more confidence when mocking;\n- Imagine your application as a box. Every API mocking library out there opens your box and removes the part that does the request, placing a blackbox in its stead. Mock Service Worker leaves your box intact, 1-1 as it is in production. Instead, MSW lives in a separate box next to yours;\n- No more stubbing of `fetch`, `axios`, `react-query`, you-name-it;\n- You can reuse the same mock definition for the unit, integration, and E2E testing. Did we mention local development and debugging? Yep. All running against the same network description without the need for adapters or bloated configurations.\n\n### Usage example\n\n```js\n// 1. Import the library.\nimport { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\n// 2. Describe network behavior with request handlers.\nconst worker = setupWorker(\n  http.get('https://github.com/octocat', ({ request, params, cookies }) => {\n    return HttpResponse.json(\n      {\n        message: 'Mocked response',\n      },\n      {\n        status: 202,\n        statusText: 'Mocked status',\n      },\n    )\n  }),\n)\n\n// 3. Start mocking by starting the Service Worker.\nawait worker.start()\n```\n\nPerforming a `GET https://github.com/octocat` request in your application will result into a mocked response that you can inspect in your browser's \"Network\" tab:\n\n![Chrome DevTools Network screenshot with the request mocked](https://github.com/mswjs/msw/blob/main/media/msw-quick-look-network.png?raw=true)\n\n> **Tip:** Did you know that although Service Worker runs in a separate thread, your request handlers execute entirely on the client? This way you can use the same languages, like TypeScript, third-party libraries, and internal logic to create the mocks you need.\n\n## Node.js\n\n- [Learn more about using MSW in Node.js](https://mswjs.io/docs/integrations/node)\n- [`setupServer` API](https://mswjs.io/docs/api/setup-server)\n\n### How does it work?\n\nThere's no such thing as Service Workers in Node.js. Instead, MSW implements a [low-level interception algorithm](https://github.com/mswjs/interceptors) that can utilize the very same request handlers you have for the browser. This blends the boundary between environments, allowing you to focus on your network behaviors.\n\n### How is it different?\n\n- Does not stub `fetch`, `axios`, etc. As a result, your tests know _nothing_ about mocking;\n- You can reuse the same request handlers for local development and debugging, as well as for testing. Truly a single source of truth for your network behavior across all environments and all tools.\n\n### Usage example\n\nHere's an example of using Mock Service Worker while developing your Express server:\n\n```js\nimport express from 'express'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst app = express()\nconst server = setupServer()\n\napp.get(\n  '/checkout/session',\n  server.boundary((req, res) => {\n    // Describe the network for this Express route.\n    server.use(\n      http.get(\n        'https://api.stripe.com/v1/checkout/sessions/:id',\n        ({ params }) => {\n          return HttpResponse.json({\n            id: params.id,\n            mode: 'payment',\n            status: 'open',\n          })\n        },\n      ),\n    )\n\n    // Continue with processing the checkout session.\n    handleSession(req, res)\n  }),\n)\n```\n\n> This example showcases [`server.boundary()`](https://mswjs.io/docs/api/setup-server/boundary) to scope request interception to a particular closure, which is extremely handy!\n\n## Sponsors\n\nMock Service Worker is trusted by hundreds of thousands of engineers around the globe. It's used by companies like Google, Microsoft, Spotify, Amazon, Netflix, and countless others. Despite that, it remains a hobby project maintained in a spare time and has no opportunity to financially support even a single full-time contributor.\n\n**You can change that!** Consider [sponsoring the effort](https://github.com/sponsors/mswjs) behind one of the most innovative approaches around API mocking. Raise a topic of open source sponsorships with your boss and colleagues. Let's build sustainable open source together!\n\n### Golden sponsors\n\n> Become our _golden sponsor_ and get featured right here, enjoying other perks like issue prioritization and a personal consulting session with us.\n>\n> **Learn more on our [GitHub Sponsors profile](https://github.com/sponsors/mswjs)**.\n\n<br />\n\n<table>\n  <tr>\n    <td>\n      <a href=\"https://www.github.com/\" target=\"_blank\">\n        <picture>\n          <source media=\"(prefers-color-scheme: dark)\" srcset=\"media/sponsors/github-light.svg\" />\n          <img src=\"media/sponsors/github.svg\" alt=\"GitHub\" height=\"64\" />\n        </picture>\n      </a>\n    </td>\n    <td>\n      <a href=\"https://www.codacy.com/\" target=\"_blank\">\n        <img src=\"media/sponsors/codacy.svg\" alt=\"Codacy\" height=\"64\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://workleap.com/\" target=\"_blank\">\n        <img src=\"media/sponsors/workleap.svg\" alt=\"Workleap\" height=\"64\" width=\"174\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://www.chromatic.com/?ref=mswjs\" target=\"_blank\">\n        <img src=\"media/sponsors/chromatic.svg\" alt=\"Chromatic\" height=\"64\" />\n      </a>\n    </td>\n  </tr>\n  <tr>\n    <td align=\"center\">\n      <a href=\"https://stackblitz.com/\" target=\"_blank\">\n        <img src=\"media/sponsors/stackblitz.svg\" alt=\"StackBlitz\" height=\"64\" />\n      </a>\n    </td>\n  </tr>\n</table>\n\n### Silver sponsors\n\n> Become our _silver sponsor_ and get your profile image and link featured right here.\n>\n> **Learn more on our [GitHub Sponsors profile](https://github.com/sponsors/mswjs)**.\n\n<br />\n\n<table>\n  <tr>\n    <td>\n      <a href=\"https://www.replay.io/\" target=\"_blank\">\n        <img src=\"media/sponsors/replay.svg\" alt=\"Replay\" height=\"64\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://codemod.com/\" target=\"_blank\">\n        <img src=\"media/sponsors/codemod.svg\" alt=\"Codemod\" height=\"64\" width=\"128\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://github.com/ryanmagoon\" target=\"_blank\">\n        <img src=\"https://github.com/ryanmagoon.png\" alt=\"Ryan Magoon\" height=\"64\" />\n      </a>\n    </td>\n  </tr>\n</table>\n\n### Bronze sponsors\n\n> Become our _bronze sponsor_ and get your profile image and link featured in this section.\n>\n> **Learn more on our [GitHub Sponsors profile](https://github.com/sponsors/mswjs)**.\n\n<br />\n\n<table>\n  <tr>\n    <td>\n      <a href=\"https://materialize.com/\" target=\"_blank\">\n        <img src=\"media/sponsors/materialize.svg\" alt=\"Materialize\" height=\"64\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://trigger.dev/\" target=\"_blank\">\n        <img src=\"media/sponsors/trigger-dev.png\" alt=\"Trigger.dev\" height=\"64\" />\n      </a>\n    </td>\n    <td>\n      <a href=\"https://vital.io/\" target=\"_blank\">\n        <img src=\"media/sponsors/vital.svg\" alt=\"Vital\" width=\"64\" />\n      </a>\n    </td>\n  </tr>\n</table>\n\n## Awards & mentions\n\nWe've been extremely humbled to receive awards and mentions from the community for all the innovation and reach Mock Service Worker brings to the JavaScript ecosystem.\n\n<table>\n  <tr valign=\"middle\">\n    <td width=\"124\">\n      <img src=\"https://raw.githubusercontent.com/mswjs/msw/main/media/tech-radar.png\" width=\"124\" alt=\"Technology Radar\">\n    </td>\n    <td>\n      <h4>Solution Worth Pursuing</h4>\n      <p><em><a href=\"https://www.thoughtworks.com/radar/languages-and-frameworks/mock-service-worker\">Technology Radar</a> (2020–2021)</em></p>\n    </td>\n  </tr>\n  <tr>\n    <td width=\"124\">\n      <img src=\"https://raw.githubusercontent.com/mswjs/msw/main/media/os-awards.png\" width=\"124\" alt=\"Open Source Awards 2020\">\n    </td>\n    <td>\n      <h4>The Most Exciting Use of Technology</h4>\n      <p><em><a href=\"https://osawards.com/javascript/2020\">Open Source Awards</a> (2020)</em></p>\n    </td>\n  </tr>\n</table>\n"
  },
  {
    "path": "browser/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"main\": \"../lib/browser/index.js\",\n  \"module\": \"../lib/browser/index.mjs\",\n  \"types\": \"../lib/browser/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"module-sync\": {\n        \"types\": \"./../lib/browser/index.d.mts\",\n        \"default\": \"./../lib/browser/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./../lib/browser/index.d.mts\",\n        \"default\": \"./../lib/browser/index.mjs\"\n      },\n      \"browser\": {\n        \"types\": \"./../lib/browser/index.d.mts\",\n        \"default\": \"./../lib/browser/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./../lib/browser/index.d.mts\",\n        \"default\": \"./../lib/browser/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./../lib/browser/index.d.ts\",\n        \"default\": \"./../lib/browser/index.js\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  }\n}\n"
  },
  {
    "path": "cli/index.js",
    "content": "#!/usr/bin/env node\nimport yargs from 'yargs'\nimport { init } from './init.js'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-expressions\nyargs(process.argv.slice(2))\n  .usage('$0 <cmd> [args]')\n  .command(\n    'init',\n    'Initializes Mock Service Worker at the specified directory',\n    (yargs) => {\n      yargs\n        .positional('publicDir', {\n          type: 'string',\n          description: 'Relative path to the public directory',\n          demandOption: false,\n          normalize: true,\n        })\n        .option('save', {\n          type: 'boolean',\n          description: 'Save the worker directory in your package.json',\n        })\n        .option('cwd', {\n          type: 'string',\n          description: 'Custom current worker directory',\n          normalize: true,\n        })\n        .example('msw init')\n        .example('msw init ./public')\n        .example('msw init ./static --save')\n    },\n    init,\n  )\n  .demandCommand()\n  .help().argv\n"
  },
  {
    "path": "cli/init.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport colors from 'picocolors'\nimport confirm from '@inquirer/confirm'\nimport { invariant } from './invariant.js'\nimport { SERVICE_WORKER_BUILD_PATH } from '../config/constants.js'\n\nexport async function init(args) {\n  const CWD = args.cwd || process.cwd()\n  const publicDir = args._[1] ? normalizePath(args._[1]) : undefined\n\n  const packageJsonPath = path.resolve(CWD, 'package.json')\n  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))\n  const savedWorkerDirectories = Array.prototype\n    .concat((packageJson.msw && packageJson.msw.workerDirectory) || [])\n    .map(normalizePath)\n\n  if (publicDir) {\n    // If the public directory was provided, copy the worker script\n    // to that directory only. Even if there are paths stored in \"msw.workerDirectory\",\n    // those will not be touched.\n    await copyWorkerScript(publicDir, CWD)\n    const relativePublicDir = path.relative(CWD, publicDir)\n    printSuccessMessage([publicDir])\n\n    if (args.save) {\n      // Only save the public path if it's not already saved in \"package.json\".\n      if (!savedWorkerDirectories.includes(relativePublicDir)) {\n        saveWorkerDirectory(packageJsonPath, relativePublicDir)\n      }\n    }\n    // Explicitly check if \"save\" was not provided (was null).\n    // You can also provide the \"--no-save\" option, and then \"args.save\"\n    // will equal to false.\n    else if (args.save == null) {\n      // eslint-disable-next-line no-console\n      console.log(`\\\n      ${colors.cyan(\n        'INFO',\n      )} In order to ease the future updates to the worker script,\n      we recommend saving the path to the worker directory in your package.json.`)\n\n      // If the \"--save\" flag was not provided, prompt to save\n      // the public path.\n      promptWorkerDirectoryUpdate(\n        `Do you wish to save \"${relativePublicDir}\" as the worker directory?`,\n        packageJsonPath,\n        relativePublicDir,\n      )\n    }\n\n    return\n  }\n\n  // Calling \"init\" without a public directory but with the \"--save\" flag is a no-op.\n  invariant(\n    args.save == null,\n    'Failed to copy the worker script: cannot call the \"init\" command without a public directory but with the \"--save\" flag. Either drop the \"--save\" flag to copy the worker script to all paths listed in \"msw.workerDirectory\", or add an explicit public directory to the command, like \"npx msw init ./public\".',\n  )\n\n  // If the public directory was not provided, check any existing\n  // paths in \"msw.workerDirectory\". When called without the public\n  // directory, the \"init\" command must copy the worker script\n  // to all the paths stored in \"msw.workerDirectory\".\n  if (savedWorkerDirectories.length > 0) {\n    const copyResults = await Promise.allSettled(\n      savedWorkerDirectories.map((destination) => {\n        return copyWorkerScript(destination, CWD).catch((error) => {\n          // Inject the absolute destination path onto the copy function rejections\n          // so it's available in the failed paths array below.\n          throw [toAbsolutePath(destination, CWD), error]\n        })\n      }),\n    )\n    const successfulPaths = copyResults\n      .filter((result) => result.status === 'fulfilled')\n      .map((result) => result.value)\n    const failedPathsWithErrors = copyResults\n      .filter((result) => result.status === 'rejected')\n      .map((result) => result.reason)\n\n    // Notify about failed copies, if any.\n    if (failedPathsWithErrors.length > 0) {\n      printFailureMessage(failedPathsWithErrors)\n    }\n\n    // Notify about successful copies, if any.\n    if (successfulPaths.length > 0) {\n      printSuccessMessage(successfulPaths)\n    }\n  }\n}\n\n/**\n * @param {string} maybeAbsolutePath\n * @param {string} cwd\n * @returns {string}\n */\nfunction toAbsolutePath(maybeAbsolutePath, cwd) {\n  return path.isAbsolute(maybeAbsolutePath)\n    ? maybeAbsolutePath\n    : path.resolve(cwd, maybeAbsolutePath)\n}\n\n/**\n * @param {string} destination\n * @param {string} cwd\n * @returns {Promise<string>}\n */\nasync function copyWorkerScript(destination, cwd) {\n  // When running as a part of \"postinstall\" script, \"cwd\" equals the library's directory.\n  // The \"postinstall\" script resolves the right absolute public directory path.\n  const absolutePublicDir = toAbsolutePath(destination, cwd)\n\n  if (!fs.existsSync(absolutePublicDir)) {\n    await fs.promises\n      .mkdir(absolutePublicDir, { recursive: true })\n      .catch((error) => {\n        throw new Error(\n          invariant(\n            false,\n            'Failed to copy the worker script at \"%s\": directory does not exist and could not be created.\\nMake sure to include a relative path to the public directory of your application.\\n\\nSee the original error below:\\n\\n%s',\n            absolutePublicDir,\n            error,\n          ),\n        )\n      })\n  }\n\n  // eslint-disable-next-line no-console\n  console.log('Copying the worker script at \"%s\"...', absolutePublicDir)\n\n  const workerFilename = path.basename(SERVICE_WORKER_BUILD_PATH)\n  const workerDestinationPath = path.resolve(absolutePublicDir, workerFilename)\n\n  fs.copyFileSync(SERVICE_WORKER_BUILD_PATH, workerDestinationPath)\n\n  return workerDestinationPath\n}\n\n/**\n * @param {Array<string>} paths\n */\nfunction printSuccessMessage(paths) {\n  // eslint-disable-next-line no-console\n  console.log(`\n${colors.green('Worker script successfully copied!')}\n${paths.map((path) => colors.gray(`  - ${path}\\n`))}\nContinue by describing the network in your application:\n\n\n${colors.red(colors.bold('https://mswjs.io/docs/quick-start'))}\n`)\n}\n\nfunction printFailureMessage(pathsWithErrors) {\n  // eslint-disable-next-line no-console\n  console.error(`\\\n${colors.red('Copying the worker script failed at following paths:')}\n${pathsWithErrors\n  .map(([path, error]) => colors.gray(`  - ${path}`) + '\\n' + `  ${error}`)\n  .join('\\n\\n')}\n  `)\n}\n\n/**\n * @param {string} packageJsonPath\n * @param {string} publicDir\n */\nfunction saveWorkerDirectory(packageJsonPath, publicDir) {\n  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))\n\n  // eslint-disable-next-line no-console\n  console.log(\n    colors.gray('Updating \"msw.workerDirectory\" at \"%s\"...'),\n    packageJsonPath,\n  )\n\n  const prevWorkerDirectory = Array.prototype.concat(\n    (packageJson.msw && packageJson.msw.workerDirectory) || [],\n  )\n  const nextWorkerDirectory = Array.from(\n    new Set(prevWorkerDirectory).add(publicDir),\n  )\n\n  const nextPackageJson = Object.assign({}, packageJson, {\n    msw: {\n      workerDirectory: nextWorkerDirectory,\n    },\n  })\n\n  fs.writeFileSync(\n    packageJsonPath,\n    JSON.stringify(nextPackageJson, null, 2),\n    'utf8',\n  )\n}\n\n/**\n * @param {string} message\n * @param {string} packageJsonPath\n * @param {string} publicDir\n * @returns {void}\n */\nfunction promptWorkerDirectoryUpdate(message, packageJsonPath, publicDir) {\n  return confirm({\n    theme: {\n      prefix: colors.yellowBright('?'),\n    },\n    message,\n  }).then((answer) => {\n    if (answer) {\n      saveWorkerDirectory(packageJsonPath, publicDir)\n    }\n  })\n}\n\n/**\n * Normalizes the given path, replacing ambiguous path separators\n * with the platform-specific path separator.\n * @param {string} input Path to normalize.\n * @returns {string}\n */\nfunction normalizePath(input) {\n  return input.replace(/[\\\\|\\/]+/g, path.sep)\n}\n"
  },
  {
    "path": "cli/invariant.js",
    "content": "import colors from 'picocolors'\n\nexport function invariant(predicate, message, ...args) {\n  if (!predicate) {\n    // eslint-disable-next-line no-console\n    console.error(colors.red(message), ...args)\n    process.exit(1)\n  }\n}\n"
  },
  {
    "path": "cli/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "commitlint.config.js",
    "content": "module.exports = {\n  extends: ['@commitlint/config-conventional'],\n  rules: {\n    'body-max-line-length': [0, 'always', Infinity],\n    'footer-max-line-length': [1, 'always'],\n  },\n}\n"
  },
  {
    "path": "config/constants.js",
    "content": "import url from 'node:url'\nimport path from 'node:path'\n\nexport const SERVICE_WORKER_SOURCE_PATH = url.fileURLToPath(\n  new URL('../src/mockServiceWorker.js', import.meta.url),\n)\n\nexport const SERVICE_WORKER_BUILD_PATH = url.fileURLToPath(\n  new URL(\n    path.join('../lib', path.basename(SERVICE_WORKER_SOURCE_PATH)),\n    import.meta.url,\n  ),\n)\n"
  },
  {
    "path": "config/copyServiceWorker.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { until } from 'until-async'\n\n/**\n * Copies the given Service Worker source file into the destination.\n * Injects the integrity checksum into the destination file.\n */\nexport default async function copyServiceWorker(\n  sourceFilePath: string,\n  destFilePath: string,\n  checksum: string,\n): Promise<void> {\n  // eslint-disable-next-line no-console\n  console.log('Compiling Service Worker...')\n\n  const [readFileError, readFileResult] = await until(() =>\n    fs.promises.readFile(sourceFilePath, 'utf8'),\n  )\n\n  if (readFileError) {\n    throw new Error('Failed to read file.\\n${readError.message}')\n  }\n\n  const destFileDirectory = path.dirname(destFilePath)\n  // eslint-disable-next-line no-console\n  console.log('Checking if \"%s\" path exists...', destFileDirectory)\n\n  if (!fs.existsSync(destFileDirectory)) {\n    // eslint-disable-next-line no-console\n    console.log('Destination directory does not exist, creating...')\n    await fs.promises.mkdir(destFileDirectory, { recursive: true })\n  }\n\n  const packageJson = JSON.parse(\n    fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'),\n  )\n\n  const nextFileContent = readFileResult\n    .replace('<INTEGRITY_CHECKSUM>', checksum)\n    .replace('<PACKAGE_VERSION>', packageJson.version)\n\n  const [writeFileError] = await until(() =>\n    fs.promises.writeFile(destFilePath, nextFileContent),\n  )\n\n  if (writeFileError) {\n    throw new Error(`Failed to write file.\\n${writeFileError.message}`)\n  }\n\n  // eslint-disable-next-line no-console\n  console.log('Service Worker copied to: %s', destFilePath)\n}\n"
  },
  {
    "path": "config/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "config/plugins/esbuild/copyWorkerPlugin.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'crypto'\nimport minify from 'babel-minify'\nimport { invariant } from 'outvariant'\nimport type { Plugin } from 'esbuild'\nimport copyServiceWorker from '../../copyServiceWorker.js'\n\nconst SERVICE_WORKER_ENTRY_PATH = path.resolve(\n  process.cwd(),\n  './src/mockServiceWorker.js',\n)\n\nconst SERVICE_WORKER_OUTPUT_PATH = path.resolve(\n  process.cwd(),\n  './lib/mockServiceWorker.js',\n)\n\nfunction getChecksum(contents: string): string {\n  const { code } = minify(contents, {}, { comments: false })\n\n  return crypto.createHash('md5').update(code, 'utf8').digest('hex')\n}\n\nexport function getWorkerChecksum(): string {\n  const workerContents = fs.readFileSync(SERVICE_WORKER_ENTRY_PATH, 'utf8')\n  return getChecksum(workerContents)\n}\n\nexport function copyWorkerPlugin(checksum: string): Plugin {\n  return {\n    name: 'copyWorkerPlugin',\n    async setup(build) {\n      invariant(\n        SERVICE_WORKER_ENTRY_PATH,\n        'Failed to locate the worker script source file',\n      )\n\n      if (fs.existsSync(SERVICE_WORKER_OUTPUT_PATH)) {\n        console.warn(\n          'Skipped copying the worker script to \"%s\": already exists',\n          SERVICE_WORKER_OUTPUT_PATH,\n        )\n        return\n      }\n\n      // Generate the checksum from the worker script's contents.\n      // const workerContents = await fs.readFile(workerSourcePath, 'utf8')\n      // const checksum = getChecksum(workerContents)\n\n      build.onLoad({ filter: /mockServiceWorker\\.js$/ }, async () => {\n        return {\n          // Prevent the worker script from being transpiled.\n          // But, generally, the worker script is not in the entrypoints.\n          contents: '',\n        }\n      })\n\n      build.onEnd(() => {\n        // eslint-disable-next-line no-console\n        console.log('worker script checksum:', checksum)\n\n        // Copy the worker script on the next tick.\n        process.nextTick(async () => {\n          await copyServiceWorker(\n            SERVICE_WORKER_ENTRY_PATH,\n            SERVICE_WORKER_OUTPUT_PATH,\n            checksum,\n          )\n        })\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "config/plugins/esbuild/forceEsmExtensionsPlugin.ts",
    "content": "import { type Plugin } from 'esbuild'\n\nexport const ESM_EXTENSION = '.mjs'\nexport const CJS_EXTENSION = '.js'\n\nexport function forceEsmExtensionsPlugin(): Plugin {\n  return {\n    name: 'forceEsmExtensionsPlugin',\n    setup(build) {\n      const isEsm = build.initialOptions.format === 'esm'\n\n      build.onEnd(async (result) => {\n        if (result.errors.length > 0) {\n          return\n        }\n\n        for (const outputFile of result.outputFiles || []) {\n          // Only target CJS/ESM files.\n          // This ignores additional files emitted, like sourcemaps (\"*.js.map\").\n          if (\n            !(\n              outputFile.path.endsWith(ESM_EXTENSION) ||\n              outputFile.path.endsWith('.mjs')\n            )\n          ) {\n            continue\n          }\n\n          const fileContents = outputFile.text\n          const nextFileContents = modifyRelativeImports(fileContents, isEsm)\n\n          outputFile.contents = Buffer.from(nextFileContents)\n        }\n      })\n    },\n  }\n}\n\nconst CJS_RELATIVE_IMPORT_EXP = /require\\([\"'](\\..+)[\"']\\)(;)?/gm\nconst ESM_RELATIVE_IMPORT_EXP = /from [\"'](\\..+)[\"'](;)?/gm\n\nfunction modifyRelativeImports(contents: string, isEsm: boolean): string {\n  const extension = isEsm ? ESM_EXTENSION : CJS_EXTENSION\n  const importExpression = isEsm\n    ? ESM_RELATIVE_IMPORT_EXP\n    : CJS_RELATIVE_IMPORT_EXP\n\n  return contents.replace(\n    importExpression,\n    (_, importPath, maybeSemicolon = '') => {\n      if (importPath.endsWith('.') || importPath.endsWith('/')) {\n        return isEsm\n          ? `from '${importPath}/index${extension}'${maybeSemicolon}`\n          : `require(\"${importPath}/index${extension}\")${maybeSemicolon}`\n      }\n\n      if (importPath.endsWith(extension)) {\n        return isEsm\n          ? `from '${importPath}'${maybeSemicolon}`\n          : `require(\"${importPath}\")${maybeSemicolon}`\n      }\n\n      return isEsm\n        ? `from '${importPath}${extension}'${maybeSemicolon}`\n        : `require(\"${importPath}${extension}\")${maybeSemicolon}`\n    },\n  )\n}\n"
  },
  {
    "path": "config/plugins/esbuild/graphQLImportPlugin.ts",
    "content": "import fs from 'node:fs'\nimport type { Plugin } from 'esbuild'\n\n/**\n * A plugin to replace `require('graphql')` statements with `await import('graphql')`\n * only for ESM bundles. This makes the GraphQL module to be imported lazily\n * while maintaining the CommonJS compatibility.\n * @see https://github.com/mswjs/msw/issues/2254\n */\nexport function graphqlImportPlugin(): Plugin {\n  return {\n    name: 'graphql-import-plugin',\n    setup(build) {\n      if (build.initialOptions.format !== 'esm') {\n        return\n      }\n\n      build.onLoad({ filter: /\\.ts$/ }, async (args) => {\n        const contents = await fs.promises.readFile(args.path, 'utf-8')\n        const match = /require\\(['\"]graphql['\"]\\)/g.exec(contents)\n\n        if (match) {\n          return {\n            loader: 'ts',\n            contents:\n              contents.slice(0, match.index - 1) +\n              `await import('graphql').catch((error) => {console.error('[MSW] Failed to parse a GraphQL query: cannot import the \"graphql\" module. Please make sure you install it if you wish to intercept GraphQL requests. See the original import error below.'); throw error})` +\n              contents.slice(match.index + match[0].length),\n          }\n        }\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "config/plugins/esbuild/resolveCoreImportsPlugin.ts",
    "content": "import { Plugin } from 'esbuild'\nimport { replaceCoreImports } from '../../replaceCoreImports.js'\nimport { ESM_EXTENSION } from './forceEsmExtensionsPlugin.js'\n\nexport function resolveCoreImportsPlugin(): Plugin {\n  return {\n    name: 'resolveCoreImportsPlugin',\n    setup(build) {\n      build.onEnd(async (result) => {\n        if (result.errors.length > 0) {\n          return\n        }\n\n        for (const outputFile of result.outputFiles || []) {\n          const isEsm = outputFile.path.endsWith(ESM_EXTENSION)\n          const fileContents = outputFile.text\n          const nextFileContents = replaceCoreImports(\n            outputFile.path,\n            fileContents,\n            isEsm,\n          )\n\n          outputFile.contents = Buffer.from(nextFileContents)\n        }\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "config/polyfills-node.ts",
    "content": "import { setTimeout as nodeSetTimeout } from 'timers'\n\n// Polyfill the global \"setTimeout\" so MSW could be used\n// with \"jest.useFakeTimers()\". MSW response handling\n// is wrapped in \"setTimeout\", and without this polyfill\n// you'd have to manually advance the timers for the response\n// to finally resolve.\nexport const setTimeout = nodeSetTimeout\n"
  },
  {
    "path": "config/replaceCoreImports.js",
    "content": "const CORE_ESM_IMPORT_PATTERN = /from [\"'](~\\/core(.*))[\"'](;)?/gm\nconst CORE_CJS_IMPORT_PATTERN = /require\\([\"'](~\\/core(.*))[\"']\\)(;)?/gm\n\nfunction getCoreImportPattern(isEsm) {\n  return isEsm ? CORE_ESM_IMPORT_PATTERN : CORE_CJS_IMPORT_PATTERN\n}\n\nexport function hasCoreImports(fileContents, isEsm) {\n  return getCoreImportPattern(isEsm).test(fileContents)\n}\n\nexport function replaceCoreImports(moduleFilePath, fileContents, isEsm) {\n  return fileContents.replace(\n    getCoreImportPattern(isEsm),\n    (_, __, maybeSubmodulePath, maybeSemicolon) => {\n      const submodulePath = maybeSubmodulePath || '/index'\n      /**\n       * @note Although all .d.ts are considered ESM, append different\n       * file extension for d.mts files.\n       */\n      const extension = moduleFilePath.endsWith('.d.mts') ? '.mjs' : ''\n      const semicolon = maybeSemicolon || ''\n\n      return isEsm\n        ? `from \"../core${submodulePath}${extension}\"${semicolon}`\n        : `require(\"../core${submodulePath}\")${semicolon}`\n    },\n  )\n}\n"
  },
  {
    "path": "config/scripts/patch-ts.js",
    "content": "import fs from 'node:fs'\nimport { exec } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { invariant } from 'outvariant'\nimport * as glob from 'glob'\nimport { hasCoreImports, replaceCoreImports } from '../replaceCoreImports.js'\n\nconst execAsync = promisify(exec)\n\nconst BUILD_DIR = new URL('../../lib/', import.meta.url)\n\nasync function patchTypeDefs() {\n  const typeDefsPaths = glob.sync('**/*.d.{ts,mts}', {\n    cwd: BUILD_DIR,\n    absolute: true,\n  })\n  const typeDefsWithCoreImports = typeDefsPaths\n    .map((modulePath) => {\n      const fileContents = fs.readFileSync(modulePath, 'utf8')\n      /**\n       * @note Treat all type definition files as ESM because even\n       * CJS .d.ts use `import` statements.\n       */\n      if (hasCoreImports(fileContents, true)) {\n        return [modulePath, fileContents]\n      }\n    })\n    .filter(Boolean)\n\n  if (typeDefsWithCoreImports.length === 0) {\n    console.log(\n      'Found no .d.ts modules containing the \"~/core\" import, skipping...',\n    )\n    return process.exit(0)\n  }\n\n  console.log(\n    'Found %d module(s) with the \"~/core\" import, resolving...',\n    typeDefsWithCoreImports.length,\n  )\n\n  for (const [typeDefsPath, fileContents] of typeDefsWithCoreImports) {\n    // Treat \".d.ts\" files as ESM to replace \"import\" statements.\n    // Force no extension on the \".d.ts\" imports.\n    const nextFileContents = replaceCoreImports(\n      typeDefsPath,\n      fileContents,\n      true,\n    )\n    fs.writeFileSync(typeDefsPath, nextFileContents, 'utf8')\n    console.log('Successfully patched \"%s\"!', typeDefsPath)\n  }\n\n  console.log(\n    'Imports resolved in %d file(s), verifying...',\n    typeDefsWithCoreImports.length,\n  )\n\n  // Next, validate that we left no \"~/core\" imports unresolved.\n  const result = await execAsync(\n    `grep \"~/core\" ./**/*.d.{ts,mts} -R -l || exit 0`,\n    {\n      cwd: BUILD_DIR,\n      shell: '/bin/bash',\n    },\n  )\n\n  invariant(\n    result.stderr === '',\n    'Failed to validate the .d.ts modules for the presence of the \"~/core\" import. See the original error below.',\n    result.stderr,\n  )\n\n  if (result.stdout !== '') {\n    const modulesWithUnresolvedImports = result.stdout\n      .split('\\n')\n      .filter(Boolean)\n\n    console.error(\n      `Found .d.ts modules containing unresolved \"~/core\" import after the patching:\n\n${modulesWithUnresolvedImports.map((path) => `  - ${new URL(path, BUILD_DIR).pathname}`).join('\\n')}\n        `,\n    )\n\n    return process.exit(1)\n  }\n\n  // Ensure that the .d.ts files compile without errors after resolving the \"~/core\" imports.\n  console.log('Compiling the .d.ts modules with tsc...')\n  const tscCompilation = await execAsync(\n    `tsc --noEmit --skipLibCheck ${typeDefsPaths.join(' ')}`,\n    {\n      cwd: BUILD_DIR,\n    },\n  )\n\n  if (tscCompilation.stderr !== '') {\n    console.error(\n      'Failed to compile the .d.ts modules with tsc. See the original error below.',\n      tscCompilation.stderr,\n    )\n\n    return process.exit(1)\n  }\n\n  // Ensure that CJS .d.ts file never reference .mjs files.\n  const mjsInCjsResult = await execAsync(\n    `grep \".mjs\" ./**/*.d.ts -R -l || exit 0`,\n    {\n      cwd: BUILD_DIR,\n      shell: '/bin/bash',\n    },\n  )\n\n  invariant(\n    mjsInCjsResult.stderr === '',\n    'Failed to validate the .d.ts modules not referencing \".mjs\" files. See the original error below.',\n    mjsInCjsResult.stderr,\n  )\n\n  if (mjsInCjsResult.stdout !== '') {\n    const modulesWithUnresolvedImports = mjsInCjsResult.stdout\n      .split('\\n')\n      .filter(Boolean)\n\n    console.error(\n      `Found .d.ts modules referencing \".mjs\" files after patching:\n\n${modulesWithUnresolvedImports.map((path) => `  - ${new URL(path, BUILD_DIR).pathname}`).join('\\n')}\n        `,\n    )\n\n    return process.exit(1)\n  }\n\n  console.log(\n    'The \"~/core\" imports resolved successfully in %d .d.ts modules! 🎉',\n    typeDefsWithCoreImports.length,\n  )\n}\n\npatchTypeDefs()\n"
  },
  {
    "path": "config/scripts/postinstall.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFileSync } from 'node:child_process'\n\n// When executing the \"postinstall\" script, the \"process.cwd\" equals\n// the package directory, not the parent project where the package is installed.\n// NPM stores the parent project directory in the \"INIT_CWD\" env variable.\nconst parentPackageCwd = process.env.INIT_CWD\n\nfunction postInstall() {\n  const packageJson = JSON.parse(\n    fs.readFileSync(path.resolve(parentPackageCwd, 'package.json'), 'utf8'),\n  )\n\n  if (!packageJson.msw || !packageJson.msw.workerDirectory) {\n    return\n  }\n\n  const cliExecutable = path.resolve(process.cwd(), 'cli/index.js')\n\n  try {\n    /**\n     * @note Call the \"init\" command directly. It will now copy the worker script\n     * to all saved paths in \"msw.workerDirectory\"\n     */\n    execFileSync(process.execPath, [cliExecutable, 'init'], {\n      cwd: parentPackageCwd,\n    })\n  } catch (error) {\n    console.error(\n      `[MSW] Failed to automatically update the worker script.\\n\\n${error}`,\n    )\n  }\n}\n\npostInstall()\n"
  },
  {
    "path": "config/scripts/smoke-test.sh",
    "content": "#!/bin/bash\nset -e\n\nCOMMIT_HASH=$(git rev-parse HEAD)\nMSW_VERSION=\"0.0.0-$COMMIT_HASH\"\necho \"Latest commit: $COMMIT_HASH\"\necho \"In-progress MSW version: $MSW_VERSION\"\n\nPKG_JSON_COPY=\"package.json.copy\"\ncp package.json $PKG_JSON_COPY\n\npnpm version $MSW_VERSION --no-git-tag-version --allow-same-version\n\necho \"\"\necho \"Packing MSW...\"\npnpm pack\n\nEXAMPLES_REPO=https://github.com/mswjs/examples.git\nEXAMPLES_DIR=./examples\necho \"\"\necho \"Cloning the examples from \"$EXAMPLES_REPO\"...\"\n\nif [[ -d \"$EXAMPLES_DIR\" ]]; then\n  echo \"Examples already cloned, skipping...\"\nelse\n  git clone $EXAMPLES_REPO $EXAMPLES_DIR\nfi\n\necho \"\"\necho \"Installing dependencies...\"\ncd $EXAMPLES_DIR\npnpm install \n\necho \"\"\necho \"Linking MSW...\"\npnpm add msw --filter=\"with-*\" file:../../../msw-$MSW_VERSION.tgz\npnpm ls msw\n\necho \"\"\necho \"Running tests...\"\nCI=1 pnpm test ; (cd ../ && mv $PKG_JSON_COPY ./package.json)\n"
  },
  {
    "path": "decisions/jest-support.md",
    "content": "# Jest support\n\nWith the introduction of [Mock Service Worker 2.0](https://mswjs.io/blog/introducing-msw-2.0), the library has made a significant step forward in the effort of embracing and promoting web standards. Since that release, its contributors have reported multiple issues with Node.js simply because MSW exposed developers to using standard Node.js APIs.\n\nBetting on the web standards is one of the goals behind this project. One of such standards is ESM. It's the present and the future of JavaScript, and we are planning on switching to ESM-only in the years to come. For that transition to happen, we need to prioritize and, at times, make hard decisions.\n\n**MSW offers no official support for Jest.** It doesn't mean MSW cannot be used in Jest. We maintain usage examples of both [Jest](https://github.com/mswjs/examples/tree/main/examples/with-jest) and [Jest+JSDOM](https://github.com/mswjs/examples/tree/main/examples/with-jest-jsdom) to attest to that. Although it's necessary to mention that those examples require additional setup to tackle underlying Jest or JSDOM issues.\n\nWhat this means is that **we are not going to address any issues specific to Jest or JSDOM**. Those pose a significant time investment just to uncover another inconsistency between the browser and JSDOM, or the lacking features in Jest, like proper ESM support. That is not a reasonable use of the limited contributors' time. You will have a far better chance of getting your issue solved by reporting it to the Jest or JSDOM repo for the respective teams to address it.\n\n## What's next?\n\n> [!IMPORTANT]\n> If you are experiencing issues with using MSW in Jest, **please verify them outside of Jest before reporting them**.\n\nYou can verify the issue in a plain Node.js script, or by copying your problematic test to [Vitest](https://vitest.dev/). Please note that we do not support issue reports from non-standard environments, like Deno or Bun either.\n\nYou can use one of our existing [Usage examples](https://github.com/mswjs/examples) as a template project to reproduce your issue.\n"
  },
  {
    "path": "decisions/linting-worker-script.md",
    "content": "# Linting the worker script\n\nWhen linting your application, you may encounter warnings or errors originating from the `mockServiceWorker.js` script. Please refrain from opening pull requests to add the `ignore` pragma comments to the script itself.\n\n## Solution\n\n**Make sure that the worker script is ignored by your linting tools**. The worker script isn't a part of your application's code but a static asset. It must be ignored during linting and prettifying in the same way all your static assets in `/public` are ignored. Please configure your tools respectively.\n\nIf there are warnings/errors originating from the worker script, it's likely your public directory is not ignored by your linting tools. You may consider ignoring the entire public directory if that suits your project's conventions.\n"
  },
  {
    "path": "decisions/releases.md",
    "content": "# Releases\n\nMSW uses the [Release](https://github.com/ossjs/release) library to automate its releases to NPM.\n\n## Release schedule\n\nThe next version of **the library releases automatically every day**.\n\nWe do our best to choose the optimal release window to accumulate multiple changes under a single release. We do deviate from the release schedule in emergency cases, like when a critical issue has been fixed and needs an immediate release.\n\n> [!IMPORTANT]\n> Please do not ping the library maintainers to release a new version of MSW. Be patient and wait for the automated release to happen. Subscribe to any issue or pull request you are interested in, and you will be notified whenever it gets released.\n\n## Preview releases\n\nThis repository is configured to **release work-in-progress pull requests** using [okg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new). Once the pull request in question is approved, it will automatically be published to a temporary registry. Follow the instructions in the automated comment to install the work-in-progress version of the package.\n"
  },
  {
    "path": "decisions/typescript-versioning.md",
    "content": "# TypeScript versioning\n\n## Strict TypeScript peer dependency version\n\nIn the past, MSW set the explicit upper version range for the `typescript` peer dependency (`>= 4.4.x <= 5.1.x`). While that provides better stability and predictability, we acknowledge that it negatively impacts our users, forcing them to wait for MSW to update the TypeScript version range in order to migrate to newest versions of TypeScript in their projects.\n\n> Context: TypeScript is [not distributed according to semver](https://github.com/microsoft/TypeScript/issues/14116). Instead, it's `{marketing}.{major}.{minor}` versioning pattern. This means that it may and does contain breaking changes across what consumers perceive as _minor_ versions. I've had numerous fights with this as it's not uncommon for TypeScript to exhibit different behavior across minor versions (the same types compile on 4.6, break on 4.7, then compile without issue on 4.8).\n\nWith this in mind, _we are removing the upper range_ of the `typescript` peer dependency. We have an [automated job](../.github/workflows/typescript-nightly.yml) in place that validates the latest build of MSW against the nightly releases of TypeScript, which should ensure early issue detection and help us resolve those issues before they happen.\n\n## TypeScript version compliance\n\nEvery version within the `typescript` peer dependency version range must have a corresponding TypeScript compliance test to guarantee the library's operatbility on that version.\n\nA compliance test is represented as a regular _typings test_ compiled using a specific version of TypeScript. You can learn more in the [typings tests](/test/typings).\n\nThe typings test will automatically attempt to look up `tsconfig.{major}.{minor}.json` file corresponding to the currently installed version of TypeScript. The compliance is then achieved by installing different TypeScript versions from the supported range and running the existing typings tests on that version.\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "// @ts-check\n\nimport eslint from '@eslint/js'\nimport tseslint from 'typescript-eslint'\nimport eslintConfigPrettier from 'eslint-config-prettier'\nimport eslintPluginPrettier from 'eslint-plugin-prettier/recommended'\n\nexport default tseslint.config(\n  eslint.configs.recommended,\n  eslintConfigPrettier,\n  ...tseslint.configs.recommended,\n  {\n    languageOptions: {\n      parserOptions: {\n        ecmaVersion: 2020,\n        sourceType: 'module',\n      },\n    },\n    ignores: ['/lib', '/node', '/native', '/config', '/test'],\n    rules: {\n      'no-console': [\n        'error',\n        {\n          allow: ['warn', 'error', 'group', 'groupCollapsed', 'groupEnd'],\n        },\n      ],\n      'no-async-promise-executor': 'off',\n      'require-yield': 'off',\n      'no-empty-pattern': 'off',\n      'no-control-regex': 'off',\n      '@typescript-eslint/no-empty-object-type': 'off',\n      '@typescript-eslint/prefer-ts-expect-error': 'error',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\n      '@typescript-eslint/ban-ts-comment': 'off',\n      '@typescript-eslint/no-namespace': [\n        'error',\n        {\n          allowDeclarations: true,\n        },\n      ],\n      '@typescript-eslint/no-var-requires': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          varsIgnorePattern: '^_',\n          argsIgnorePattern: '^_',\n        },\n      ],\n    },\n  },\n  // Unused variables are useful in test files, and type test files\n  {\n    files: [\n      '**/*.test.ts',\n      '**/*.test-d.ts',\n      '**/*.mocks.ts',\n      '**/*.setup.ts',\n      '**/*.config.ts',\n    ],\n    rules: {\n      'no-console': 'off',\n      '@typescript-eslint/prefer-ts-expect-error': 'off',\n      '@typescript-eslint/no-unused-vars': 'off',\n    },\n  },\n  {\n    files: ['**/*.test-d.ts'],\n    rules: {\n      '@typescript-eslint/no-unused-expressions': 'off',\n    },\n  },\n  eslintPluginPrettier,\n)\n"
  },
  {
    "path": "global.d.ts",
    "content": "declare module 'babel-minify' {\n  export default function babelMinify(\n    code: string,\n    opts: Record<string, any>,\n    babelOpts: Record<string, any>,\n  ): { code: string }\n}\n"
  },
  {
    "path": "knip.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/knip@5/schema.json\",\n  \"entry\": [\n    \"src/{core,browser,node,native}/index.ts!\",\n    \"src/mockServiceWorker.js!\",\n    \"cli/index.js!\",\n    \"config/**/*.{js,ts}!\",\n    \"test/**/*ts\"\n  ],\n  \"project\": [\"src/**/*.ts!\", \"cli/**/*.js!\", \"config/**/*.{js,ts}!\"]\n}\n"
  },
  {
    "path": "native/package.json",
    "content": "{\n  \"type\": \"commonjs\",\n  \"browser\": null,\n  \"main\": \"../lib/native/index.js\",\n  \"module\": \"../lib/native/index.mjs\",\n  \"types\": \"../lib/native/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"react-native\": {\n        \"import\": {\n          \"types\": \"./../lib/native/index.d.mts\",\n          \"default\": \"./../lib/native/index.mjs\"\n        },\n        \"default\": {\n          \"types\": \"./../lib/native/index.d.ts\",\n          \"default\": \"./../lib/native/index.js\"\n        }\n      },\n      \"browser\": null,\n      \"import\": {\n        \"types\": \"./../lib/native/index.d.mts\",\n        \"default\": \"./../lib/native/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./../lib/native/index.d.ts\",\n        \"default\": \"./../lib/native/index.js\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "node/package.json",
    "content": "{\n  \"type\": \"commonjs\",\n  \"browser\": null,\n  \"main\": \"../lib/node/index.js\",\n  \"module\": \"../lib/node/index.mjs\",\n  \"types\": \"../lib/node/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"module-sync\": {\n        \"types\": \"./../lib/node/index.d.mts\",\n        \"default\": \"./../lib/node/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./../lib/node/index.d.mts\",\n        \"default\": \"./../lib/node/index.mjs\"\n      },\n      \"node\": {\n        \"require\": \"./../lib/node/index.js\",\n        \"import\": \"./../lib/node/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./../lib/node/index.d.mts\",\n        \"default\": \"./../lib/node/index.mjs\"\n      },\n      \"browser\": null,\n      \"react-native\": null,\n      \"default\": {\n        \"types\": \"./../lib/node/index.d.ts\",\n        \"default\": \"./../lib/node/index.js\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"msw\",\n  \"version\": \"2.12.13\",\n  \"description\": \"Seamless REST/GraphQL API mocking library for browser and Node.js.\",\n  \"type\": \"commonjs\",\n  \"main\": \"./lib/core/index.js\",\n  \"module\": \"./lib/core/index.mjs\",\n  \"types\": \"./lib/core/index.d.ts\",\n  \"packageManager\": \"pnpm@9.15.0\",\n  \"exports\": {\n    \".\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"react-native\": {\n        \"import\": {\n          \"types\": \"./lib/core/index.d.mts\",\n          \"default\": \"./lib/core/index.mjs\"\n        },\n        \"default\": {\n          \"types\": \"./lib/core/index.d.ts\",\n          \"default\": \"./lib/core/index.js\"\n        }\n      },\n      \"import\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/index.d.ts\",\n        \"default\": \"./lib/core/index.js\"\n      }\n    },\n    \"./browser\": {\n      \"module-sync\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"browser\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"node\": null,\n      \"react-native\": null,\n      \"default\": {\n        \"types\": \"./lib/browser/index.d.ts\",\n        \"default\": \"./lib/browser/index.js\"\n      }\n    },\n    \"./node\": {\n      \"module-sync\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"node\": {\n        \"require\": \"./lib/node/index.js\",\n        \"import\": \"./lib/node/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"browser\": null,\n      \"react-native\": null,\n      \"default\": {\n        \"types\": \"./lib/node/index.d.ts\",\n        \"default\": \"./lib/node/index.js\"\n      }\n    },\n    \"./native\": {\n      \"browser\": null,\n      \"react-native\": {\n        \"import\": {\n          \"types\": \"./lib/native/index.d.mts\",\n          \"default\": \"./lib/native/index.mjs\"\n        },\n        \"default\": {\n          \"types\": \"./lib/native/index.d.ts\",\n          \"default\": \"./lib/native/index.js\"\n        }\n      },\n      \"import\": {\n        \"types\": \"./lib/native/index.d.mts\",\n        \"default\": \"./lib/native/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/native/index.d.ts\",\n        \"default\": \"./lib/native/index.js\"\n      }\n    },\n    \"./core/http\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/http.d.ts\",\n        \"default\": \"./lib/core/http.js\"\n      }\n    },\n    \"./core/graphql\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/graphql.d.ts\",\n        \"default\": \"./lib/core/graphql.js\"\n      }\n    },\n    \"./core/ws\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/ws.d.ts\",\n        \"default\": \"./lib/core/ws.js\"\n      }\n    },\n    \"./mockServiceWorker.js\": \"./lib/mockServiceWorker.js\",\n    \"./package.json\": \"./package.json\"\n  },\n  \"bin\": {\n    \"msw\": \"cli/index.js\"\n  },\n  \"engines\": {\n    \"node\": \">=18\"\n  },\n  \"scripts\": {\n    \"start\": \"tsup --watch\",\n    \"clean\": \"rimraf ./lib\",\n    \"lint\": \"eslint \\\"{cli,src,test}/**/*.ts\\\"\",\n    \"build\": \"pnpm clean && cross-env NODE_ENV=production tsup && pnpm patch:dts\",\n    \"patch:dts\": \"node \\\"./config/scripts/patch-ts.js\\\"\",\n    \"publint\": \"publint\",\n    \"test\": \"pnpm test:unit && pnpm test:node && pnpm test:browser && pnpm test:native\",\n    \"test:unit\": \"vitest\",\n    \"test:node\": \"vitest --config=./test/node/vitest.config.ts\",\n    \"test:native\": \"vitest --config=./test/native/vitest.config.ts\",\n    \"test:browser\": \"playwright test -c ./test/browser/playwright.config.ts\",\n    \"test:modules:node\": \"vitest run --config=./test/modules/node/vitest.config.ts\",\n    \"test:modules:browser\": \"playwright test -c ./test/modules/browser/playwright.config.ts\",\n    \"test:e2e\": \"vitest run --config=./test/e2e/vitest.config.ts\",\n    \"test:ts\": \"vitest --config=./test/typings/vitest.config.ts\",\n    \"prepare\": \"pnpm simple-git-hooks init\",\n    \"prepack\": \"pnpm build\",\n    \"release\": \"release publish\",\n    \"postinstall\": \"node -e \\\"import('./config/scripts/postinstall.js').catch(() => void 0)\\\"\",\n    \"knip\": \"knip\"\n  },\n  \"lint-staged\": {\n    \"**/*.ts\": [\n      \"eslint --fix\"\n    ],\n    \"**/*.{ts,json}\": [\n      \"prettier --write\"\n    ]\n  },\n  \"homepage\": \"https://mswjs.io\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/mswjs/msw.git\"\n  },\n  \"author\": {\n    \"name\": \"Artem Zakharchenko\",\n    \"url\": \"https://github.com/kettanaito\"\n  },\n  \"license\": \"MIT\",\n  \"funding\": \"https://github.com/sponsors/mswjs\",\n  \"files\": [\n    \"config/package.json\",\n    \"config/constants.js\",\n    \"config/scripts/postinstall.js\",\n    \"cli\",\n    \"lib\",\n    \"src\",\n    \"browser\",\n    \"node\",\n    \"native\",\n    \"LICENSE.md\",\n    \"README.md\"\n  ],\n  \"keywords\": [\n    \"api\",\n    \"mock\",\n    \"mocking\",\n    \"worker\",\n    \"prototype\",\n    \"server\",\n    \"service\",\n    \"handler\",\n    \"testing\",\n    \"front-end\",\n    \"back-end\"\n  ],\n  \"sideEffects\": false,\n  \"dependencies\": {\n    \"@inquirer/confirm\": \"^5.0.0\",\n    \"@mswjs/interceptors\": \"^0.41.2\",\n    \"@open-draft/deferred-promise\": \"^2.2.0\",\n    \"@types/statuses\": \"^2.0.6\",\n    \"cookie\": \"^1.0.2\",\n    \"graphql\": \"^16.12.0\",\n    \"headers-polyfill\": \"^4.0.2\",\n    \"is-node-process\": \"^1.2.0\",\n    \"outvariant\": \"^1.4.3\",\n    \"path-to-regexp\": \"^6.3.0\",\n    \"picocolors\": \"^1.1.1\",\n    \"rettime\": \"^0.10.1\",\n    \"statuses\": \"^2.0.2\",\n    \"strict-event-emitter\": \"^0.5.1\",\n    \"tough-cookie\": \"^6.0.0\",\n    \"type-fest\": \"^5.2.0\",\n    \"until-async\": \"^3.0.2\",\n    \"yargs\": \"^17.7.2\"\n  },\n  \"devDependencies\": {\n    \"@commitlint/cli\": \"^20.1.0\",\n    \"@commitlint/config-conventional\": \"^20.0.0\",\n    \"@epic-web/test-server\": \"^0.1.6\",\n    \"@eslint/eslintrc\": \"^3.3.1\",\n    \"@eslint/js\": \"^9.39.1\",\n    \"@fastify/websocket\": \"^11.2.0\",\n    \"@graphql-typed-document-node/core\": \"^3.2.0\",\n    \"@open-draft/test-server\": \"^0.4.2\",\n    \"@ossjs/release\": \"^0.10.1\",\n    \"@playwright/test\": \"^1.50.1\",\n    \"@types/express\": \"^5.0.5\",\n    \"@types/json-bigint\": \"^1.0.4\",\n    \"@types/node\": \"~20.19.25\",\n    \"@types/serviceworker\": \"^0.0.167\",\n    \"@typescript-eslint/eslint-plugin\": \"^8.47.0\",\n    \"@typescript-eslint/parser\": \"^8.47.0\",\n    \"@web/dev-server\": \"^0.4.6\",\n    \"axios\": \"^1.13.5\",\n    \"babel-minify\": \"^0.5.1\",\n    \"commitizen\": \"^4.3.1\",\n    \"cross-env\": \"^10.1.0\",\n    \"cross-fetch\": \"^4.1.0\",\n    \"cz-conventional-changelog\": \"3.3.0\",\n    \"esbuild\": \"^0.27.0\",\n    \"esbuild-loader\": \"^4.4.0\",\n    \"eslint\": \"^9.39.1\",\n    \"eslint-config-prettier\": \"^10.1.8\",\n    \"eslint-plugin-prettier\": \"^5.5.4\",\n    \"express\": \"^5.1.0\",\n    \"fastify\": \"^5.6.2\",\n    \"fs-teardown\": \"^0.3.0\",\n    \"glob\": \"^13.0.0\",\n    \"jsdom\": \"^25.0.1\",\n    \"json-bigint\": \"^1.0.0\",\n    \"knip\": \"^5.70.1\",\n    \"lint-staged\": \"^15.2.10\",\n    \"msw\": \"workspace:*\",\n    \"page-with\": \"^0.6.1\",\n    \"prettier\": \"^3.6.2\",\n    \"publint\": \"^0.3.15\",\n    \"regenerator-runtime\": \"^0.14.1\",\n    \"rimraf\": \"^6.1.2\",\n    \"simple-git-hooks\": \"^2.13.1\",\n    \"tsup\": \"^8.5.1\",\n    \"typescript\": \"^5.9.3\",\n    \"typescript-eslint\": \"^8.47.0\",\n    \"undici\": \"^7.16.0\",\n    \"url-loader\": \"^4.1.1\",\n    \"vitest\": \"^4.0.13\",\n    \"vitest-environment-miniflare\": \"^2.14.4\",\n    \"webpack\": \"^5.95.0\",\n    \"webpack-http-server\": \"^0.5.0\"\n  },\n  \"peerDependencies\": {\n    \"typescript\": \">= 4.8.x\"\n  },\n  \"peerDependenciesMeta\": {\n    \"typescript\": {\n      \"optional\": true\n    }\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    }\n  },\n  \"simple-git-hooks\": {\n    \"pre-commit\": \"pnpm lint-staged\",\n    \"prepare-commit-msg\": \"grep -qE '^[^#]' .git/COMMIT_EDITMSG || (exec < /dev/tty && pnpm cz --hook || true)\",\n    \"commit-msg\": \"pnpm commitlint --edit $1\"\n  }\n}\n"
  },
  {
    "path": "release.config.json",
    "content": "{\n  \"$schema\": \"./node_modules/@ossjs/release/schema.json\",\n  \"profiles\": [\n    {\n      \"name\": \"latest\",\n      \"use\": \"NPM_CONFIG_PROVENANCE=true pnpm publish --no-git-checks\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/browser/global.browser.d.ts",
    "content": "declare const SERVICE_WORKER_CHECKSUM: string\n"
  },
  {
    "path": "src/browser/index.ts",
    "content": "export { setupWorker } from './setupWorker/setupWorker'\nexport type { SetupWorker, StartOptions } from './setupWorker/glossary'\nexport { SetupWorkerApi } from './setupWorker/setupWorker'\n"
  },
  {
    "path": "src/browser/setupWorker/glossary.ts",
    "content": "import { Emitter } from 'strict-event-emitter'\nimport type { HttpRequestEventMap, Interceptor } from '@mswjs/interceptors'\nimport type { DeferredPromise } from '@open-draft/deferred-promise'\nimport {\n  LifeCycleEventEmitter,\n  LifeCycleEventsMap,\n  SharedOptions,\n} from '~/core/sharedOptions'\nimport { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { RequiredDeep } from '~/core/typeUtils'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { WorkerChannel } from '../utils/workerChannel'\n\nexport interface StringifiedResponse extends ResponseInit {\n  body: string | ArrayBuffer | ReadableStream<Uint8Array> | null\n}\n\nexport type SetupWorkerInternalContext = {\n  isMockingEnabled: boolean\n  workerStoppedAt?: number\n  startOptions: RequiredDeep<StartOptions>\n  workerPromise: DeferredPromise<ServiceWorker>\n  registration: ServiceWorkerRegistration | undefined\n  getRequestHandlers: () => Array<RequestHandler | WebSocketHandler>\n  emitter: Emitter<LifeCycleEventsMap>\n  keepAliveInterval?: number\n  workerChannel: WorkerChannel\n  fallbackInterceptor?: Interceptor<HttpRequestEventMap>\n}\n\nexport type ServiceWorkerInstanceTuple = [\n  ServiceWorker | null,\n  ServiceWorkerRegistration,\n]\n\nexport type FindWorker = (\n  scriptUrl: string,\n  mockServiceWorkerUrl: string,\n) => boolean\n\nexport interface StartOptions extends SharedOptions {\n  /**\n   * Service Worker registration options.\n   */\n  serviceWorker?: {\n    /**\n     * Custom url to the worker script.\n     * @default \"/mockServiceWorker.js\"\n     */\n    url?: string\n    options?: RegistrationOptions\n  }\n\n  /**\n   * Disables the logging of the intercepted requests\n   * into browser's console.\n   * @default false\n   */\n  quiet?: boolean\n\n  /**\n   * Defers any network requests until the Service Worker\n   * instance is activated.\n   * @default true\n   */\n  waitUntilReady?: boolean\n\n  /**\n   * A custom lookup function to find a Mock Service Worker in the list\n   * of all registered Service Workers on the page.\n   */\n  findWorker?: FindWorker\n}\n\nexport type StartReturnType = Promise<ServiceWorkerRegistration | undefined>\n\nexport type StartHandler = (\n  options: RequiredDeep<StartOptions>,\n  initialOptions: StartOptions,\n) => StartReturnType\n\nexport type StopHandler = () => void\n\nexport interface SetupWorker {\n  /**\n   * Registers and activates the mock Service Worker.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/start `worker.start()` API reference}\n   */\n  start: (options?: StartOptions) => StartReturnType\n\n  /**\n   * Stops requests interception for the current client.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/stop `worker.stop()` API reference}\n   */\n  stop: StopHandler\n\n  /**\n   * Prepends given request handlers to the list of existing handlers.\n   * @param {RequestHandler[]} handlers List of runtime request handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/use `worker.use()` API reference}\n   */\n  use: (...handlers: Array<RequestHandler | WebSocketHandler>) => void\n\n  /**\n   * Marks all request handlers that respond using `res.once()` as unused.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/restore-handlers `worker.restoreHandlers()` API reference}\n   */\n  restoreHandlers: () => void\n\n  /**\n   * Resets request handlers to the initial list given to the `setupWorker` call, or to the explicit next request handlers list, if given.\n   * @param {RequestHandler[]} nextHandlers List of the new initial request handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/reset-handlers `worker.resetHandlers()` API reference}\n   */\n  resetHandlers: (\n    ...nextHandlers: Array<RequestHandler | WebSocketHandler>\n  ) => void\n\n  /**\n   * Returns a readonly list of currently active request handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-worker/list-handlers `worker.listHandlers()` API reference}\n   */\n  listHandlers(): ReadonlyArray<RequestHandler | WebSocketHandler>\n\n  /**\n   * Life-cycle events.\n   * Life-cycle events allow you to subscribe to the internal library events occurring during the request/response handling.\n   *\n   * @see {@link https://mswjs.io/docs/api/life-cycle-events Life-cycle Events API reference}\n   */\n  events: LifeCycleEventEmitter<LifeCycleEventsMap>\n}\n"
  },
  {
    "path": "src/browser/setupWorker/setupWorker.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { setupWorker } from './setupWorker'\n\ntest('returns an error when run in a Node.js environment', () => {\n  expect(setupWorker).toThrow(\n    '[MSW] Failed to execute `setupWorker` in a non-browser environment',\n  )\n})\n"
  },
  {
    "path": "src/browser/setupWorker/setupWorker.ts",
    "content": "import { invariant } from 'outvariant'\nimport { isNodeProcess } from 'is-node-process'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport type {\n  SetupWorkerInternalContext,\n  StartReturnType,\n  StartOptions,\n  SetupWorker,\n} from './glossary'\nimport { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { DEFAULT_START_OPTIONS } from './start/utils/prepareStartHandler'\nimport { createStartHandler } from './start/createStartHandler'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport { SetupApi } from '~/core/SetupApi'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport type { LifeCycleEventsMap } from '~/core/sharedOptions'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { attachWebSocketLogger } from '~/core/ws/utils/attachWebSocketLogger'\nimport { WorkerChannel } from '../utils/workerChannel'\nimport { createFallbackRequestListener } from './start/createFallbackRequestListener'\nimport { printStartMessage } from './start/utils/printStartMessage'\nimport { printStopMessage } from './stop/utils/printStopMessage'\nimport { supportsServiceWorker } from '../utils/supports'\n\nexport class SetupWorkerApi\n  extends SetupApi<LifeCycleEventsMap>\n  implements SetupWorker\n{\n  private context: SetupWorkerInternalContext\n\n  constructor(...handlers: Array<RequestHandler | WebSocketHandler>) {\n    super(...handlers)\n\n    invariant(\n      !isNodeProcess(),\n      devUtils.formatMessage(\n        'Failed to execute `setupWorker` in a non-browser environment. Consider using `setupServer` for Node.js environment instead.',\n      ),\n    )\n\n    this.context = this.createWorkerContext()\n  }\n\n  private createWorkerContext(): SetupWorkerInternalContext {\n    const workerPromise = new DeferredPromise<ServiceWorker>()\n\n    return {\n      // Mocking is not considered enabled until the worker\n      // signals back the successful activation event.\n      isMockingEnabled: false,\n      startOptions: null as any,\n      workerPromise,\n      registration: undefined,\n      getRequestHandlers: () => {\n        return this.handlersController.currentHandlers()\n      },\n      emitter: this.emitter,\n      workerChannel: new WorkerChannel({\n        worker: workerPromise,\n      }),\n    }\n  }\n\n  public async start(options: StartOptions = {}): StartReturnType {\n    if ('waitUntilReady' in options) {\n      devUtils.warn(\n        'The \"waitUntilReady\" option has been deprecated. Please remove it from this \"worker.start()\" call. Follow the recommended Browser integration (https://mswjs.io/docs/integrations/browser) to eliminate any race conditions between the Service Worker registration and any requests made by your application on initial render.',\n      )\n    }\n\n    // Warn the developer on multiple \"worker.start()\" calls.\n    // While this will not affect the worker in any way,\n    // it likely indicates an issue with the developer's code.\n    if (this.context.isMockingEnabled) {\n      devUtils.warn(\n        `Found a redundant \"worker.start()\" call. Note that starting the worker while mocking is already enabled will have no effect. Consider removing this \"worker.start()\" call.`,\n      )\n      return this.context.registration\n    }\n\n    this.context.workerStoppedAt = undefined\n\n    this.context.startOptions = mergeRight(\n      DEFAULT_START_OPTIONS,\n      options,\n    ) as SetupWorkerInternalContext['startOptions']\n\n    // Enable the WebSocket interception.\n    handleWebSocketEvent({\n      getUnhandledRequestStrategy: () => {\n        return this.context.startOptions.onUnhandledRequest\n      },\n      getHandlers: () => {\n        return this.handlersController.currentHandlers()\n      },\n      onMockedConnection: (connection) => {\n        if (!this.context.startOptions.quiet) {\n          // Attach the logger for mocked connections since\n          // those won't be visible in the browser's devtools.\n          attachWebSocketLogger(connection)\n        }\n      },\n      onPassthroughConnection() {},\n    })\n    webSocketInterceptor.apply()\n\n    this.subscriptions.push(() => {\n      webSocketInterceptor.dispose()\n    })\n\n    // Use a fallback interception algorithm in the environments\n    // where the Service Worker API isn't supported.\n    if (!supportsServiceWorker()) {\n      const fallbackInterceptor = createFallbackRequestListener(\n        this.context,\n        this.context.startOptions,\n      )\n\n      this.subscriptions.push(() => {\n        fallbackInterceptor.dispose()\n      })\n\n      this.context.isMockingEnabled = true\n\n      printStartMessage({\n        message: 'Mocking enabled (fallback mode).',\n        quiet: this.context.startOptions.quiet,\n      })\n\n      return undefined\n    }\n\n    const startHandler = createStartHandler(this.context)\n    const registration = await startHandler(this.context.startOptions, options)\n\n    this.context.isMockingEnabled = true\n\n    return registration\n  }\n\n  public stop(): void {\n    super.dispose()\n\n    if (!this.context.isMockingEnabled) {\n      devUtils.warn(\n        'Found a redundant \"worker.stop()\" call. Notice that stopping the worker after it has already been stopped has no effect. Consider removing this \"worker.stop()\" call.',\n      )\n      return\n    }\n\n    this.context.isMockingEnabled = false\n    this.context.workerStoppedAt = Date.now()\n    this.context.emitter.removeAllListeners()\n\n    if (supportsServiceWorker()) {\n      this.context.workerChannel.removeAllListeners('RESPONSE')\n      window.clearInterval(this.context.keepAliveInterval)\n    }\n\n    // Post the internal stop message on the window\n    // to let any logic know when the worker has stopped.\n    // E.g. the WebSocket client manager needs this to know\n    // when to clear its in-memory clients list.\n    window.postMessage({ type: 'msw/worker:stop' })\n\n    printStopMessage({\n      quiet: this.context.startOptions?.quiet,\n    })\n  }\n}\n\n/**\n * Sets up a requests interception in the browser with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-worker `setupWorker()` API reference}\n */\nexport function setupWorker(\n  ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupWorker {\n  return new SetupWorkerApi(...handlers)\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/createFallbackRequestListener.ts",
    "content": "import {\n  Interceptor,\n  BatchInterceptor,\n  HttpRequestEventMap,\n} from '@mswjs/interceptors'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { SetupWorkerInternalContext, StartOptions } from '../glossary'\nimport type { RequiredDeep } from '~/core/typeUtils'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport { isHandlerKind } from '~/core/utils/internal/isHandlerKind'\n\nexport function createFallbackRequestListener(\n  context: SetupWorkerInternalContext,\n  options: RequiredDeep<StartOptions>,\n): Interceptor<HttpRequestEventMap> {\n  const interceptor = new BatchInterceptor({\n    name: 'fallback',\n    interceptors: [new FetchInterceptor(), new XMLHttpRequestInterceptor()],\n  })\n\n  interceptor.on('request', async ({ request, requestId, controller }) => {\n    const requestCloneForLogs = request.clone()\n\n    const response = await handleRequest(\n      request,\n      requestId,\n      context.getRequestHandlers().filter(isHandlerKind('RequestHandler')),\n      options,\n      context.emitter,\n      {\n        resolutionContext: {\n          quiet: options.quiet,\n        },\n        onMockedResponse(_, { handler, parsedResult }) {\n          if (!options.quiet) {\n            context.emitter.once('response:mocked', ({ response }) => {\n              handler.log({\n                request: requestCloneForLogs,\n                response,\n                parsedResult,\n              })\n            })\n          }\n        },\n      },\n    )\n\n    if (response) {\n      controller.respondWith(response)\n    }\n  })\n\n  interceptor.on(\n    'response',\n    ({ response, isMockedResponse, request, requestId }) => {\n      context.emitter.emit(\n        isMockedResponse ? 'response:mocked' : 'response:bypass',\n        {\n          response,\n          request,\n          requestId,\n        },\n      )\n    },\n  )\n\n  interceptor.apply()\n\n  return interceptor\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/createRequestListener.ts",
    "content": "import { Emitter } from 'rettime'\nimport { StartOptions, SetupWorkerInternalContext } from '../glossary'\nimport { deserializeRequest } from '../../utils/deserializeRequest'\nimport { supportsReadableStreamTransfer } from '../../utils/supports'\nimport { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport { RequiredDeep } from '~/core/typeUtils'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport { toResponseInit } from '~/core/utils/toResponseInit'\nimport { isHandlerKind } from '~/core/utils/internal/isHandlerKind'\n\nconst SUPPORTS_READABLE_STREAM_TRANSFER = supportsReadableStreamTransfer()\n\nexport const createRequestListener = (\n  context: SetupWorkerInternalContext,\n  options: RequiredDeep<StartOptions>,\n): Emitter.ListenerType<typeof context.workerChannel, 'REQUEST'> => {\n  return async (event) => {\n    // Treat any incoming requests from the worker as passthrough\n    // if `worker.stop()` has been called for this client.\n    if (\n      !context.isMockingEnabled &&\n      context.workerStoppedAt &&\n      event.data.interceptedAt > context.workerStoppedAt\n    ) {\n      event.postMessage('PASSTHROUGH')\n      return\n    }\n\n    const requestId = event.data.id\n    const request = deserializeRequest(event.data)\n    const requestCloneForLogs = request.clone()\n\n    // Make this the first request clone before the\n    // request resolution pipeline even starts.\n    // Store the clone in cache so the first matching\n    // request handler would skip the cloning phase.\n    const requestClone = request.clone()\n    RequestHandler.cache.set(request, requestClone)\n\n    try {\n      await handleRequest(\n        request,\n        requestId,\n        context.getRequestHandlers().filter(isHandlerKind('RequestHandler')),\n        options,\n        context.emitter,\n        {\n          resolutionContext: {\n            quiet: options.quiet,\n          },\n          onPassthroughResponse() {\n            event.postMessage('PASSTHROUGH')\n          },\n          async onMockedResponse(response, { handler, parsedResult }) {\n            // Clone the mocked response so its body could be read\n            // to buffer to be sent to the worker and also in the\n            // \".log()\" method of the request handler.\n            const responseClone = response.clone()\n            const responseCloneForLogs = response.clone()\n            const responseInit = toResponseInit(response)\n\n            /**\n             * @note Safari doesn't support transferring a \"ReadableStream\".\n             * Check that the browser supports that before sending it to the worker.\n             */\n            if (SUPPORTS_READABLE_STREAM_TRANSFER) {\n              const responseStreamOrNull = response.body\n\n              event.postMessage(\n                'MOCK_RESPONSE',\n                {\n                  ...responseInit,\n                  body: responseStreamOrNull,\n                },\n                responseStreamOrNull ? [responseStreamOrNull] : undefined,\n              )\n            } else {\n              /**\n               * @note If we are here, this means the current environment doesn't\n               * support \"ReadableStream\" as transferable. In that case,\n               * attempt to read the non-empty response body as ArrayBuffer, if it's not empty.\n               * @see https://github.com/mswjs/msw/issues/1827\n               */\n              const responseBufferOrNull =\n                response.body === null\n                  ? null\n                  : await responseClone.arrayBuffer()\n\n              event.postMessage('MOCK_RESPONSE', {\n                ...responseInit,\n                body: responseBufferOrNull,\n              })\n            }\n\n            if (!options.quiet) {\n              context.emitter.once('response:mocked', () => {\n                handler.log({\n                  request: requestCloneForLogs,\n                  response: responseCloneForLogs,\n                  parsedResult,\n                })\n              })\n            }\n          },\n        },\n      )\n    } catch (error) {\n      if (error instanceof Error) {\n        devUtils.error(\n          `Uncaught exception in the request handler for \"%s %s\":\n\n%s\n\nThis exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/http/mocking-responses/error-responses`,\n          request.method,\n          request.url,\n          error.stack ?? error,\n        )\n\n        // Treat all other exceptions in a request handler as unintended,\n        // alerting that there is a problem that needs fixing.\n        event.postMessage('MOCK_RESPONSE', {\n          status: 500,\n          statusText: 'Request Handler Error',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            name: error.name,\n            message: error.message,\n            stack: error.stack,\n          }),\n        })\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/createResponseListener.ts",
    "content": "import { FetchResponse } from '@mswjs/interceptors'\nimport type { Emitter } from 'rettime'\nimport type { SetupWorkerInternalContext } from '../glossary'\nimport { deserializeRequest } from '../../utils/deserializeRequest'\n\nexport function createResponseListener(\n  context: SetupWorkerInternalContext,\n): Emitter.ListenerType<typeof context.workerChannel, 'RESPONSE'> {\n  return (event) => {\n    const responseMessage = event.data\n    const request = deserializeRequest(responseMessage.request)\n\n    /**\n     * CORS requests with `mode: \"no-cors\"` result in \"opaque\" responses.\n     * That kind of responses cannot be manipulated in JavaScript due\n     * to the security considerations.\n     * @see https://fetch.spec.whatwg.org/#concept-filtered-response-opaque\n     * @see https://github.com/mswjs/msw/issues/529\n     */\n    if (responseMessage.response.type?.includes('opaque')) {\n      return\n    }\n\n    const response =\n      responseMessage.response.status === 0\n        ? Response.error()\n        : new FetchResponse(\n            /**\n             * Responses may be streams here, but when we create a response object\n             * with null-body status codes, like 204, 205, 304 Response will\n             * throw when passed a non-null body, so ensure it's null here\n             * for those codes\n             */\n            FetchResponse.isResponseWithBody(responseMessage.response.status)\n              ? responseMessage.response.body\n              : null,\n            {\n              ...responseMessage.response,\n              /**\n               * Set response URL if it's not set already.\n               * @see https://github.com/mswjs/msw/issues/2030\n               * @see https://developer.mozilla.org/en-US/docs/Web/API/Response/url\n               */\n              url: request.url,\n            },\n          )\n\n    context.emitter.emit(\n      responseMessage.isMockedResponse ? 'response:mocked' : 'response:bypass',\n      {\n        requestId: responseMessage.request.id,\n        request,\n        response,\n      },\n    )\n  }\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/createStartHandler.ts",
    "content": "import { devUtils } from '~/core/utils/internal/devUtils'\nimport { getWorkerInstance } from './utils/getWorkerInstance'\nimport { enableMocking } from './utils/enableMocking'\nimport type { SetupWorkerInternalContext, StartHandler } from '../glossary'\nimport { createRequestListener } from './createRequestListener'\nimport { checkWorkerIntegrity } from '../../utils/checkWorkerIntegrity'\nimport { createResponseListener } from './createResponseListener'\nimport { validateWorkerScope } from './utils/validateWorkerScope'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\nexport const createStartHandler = (\n  context: SetupWorkerInternalContext,\n): StartHandler => {\n  return function start(options, customOptions) {\n    const startWorkerInstance = async () => {\n      // Remove all previously existing event listeners.\n      // This way none of the listeners persists between Fast refresh\n      // of the application's code.\n      context.workerChannel.removeAllListeners()\n\n      // Handle requests signaled by the worker.\n      context.workerChannel.on(\n        'REQUEST',\n        createRequestListener(context, options),\n      )\n\n      // Handle responses signaled by the worker.\n      context.workerChannel.on('RESPONSE', createResponseListener(context))\n\n      const instance = await getWorkerInstance(\n        options.serviceWorker.url,\n        options.serviceWorker.options,\n        options.findWorker,\n      )\n\n      const [worker, registration] = instance\n\n      if (!worker) {\n        const missingWorkerMessage = customOptions?.findWorker\n          ? devUtils.formatMessage(\n              `Failed to locate the Service Worker registration using a custom \"findWorker\" predicate.\n\nPlease ensure that the custom predicate properly locates the Service Worker registration at \"%s\".\nMore details: https://mswjs.io/docs/api/setup-worker/start#findworker\n`,\n              options.serviceWorker.url,\n            )\n          : devUtils.formatMessage(\n              `Failed to locate the Service Worker registration.\n\nThis most likely means that the worker script URL \"%s\" cannot resolve against the actual public hostname (%s). This may happen if your application runs behind a proxy, or has a dynamic hostname.\n\nPlease consider using a custom \"serviceWorker.url\" option to point to the actual worker script location, or a custom \"findWorker\" option to resolve the Service Worker registration manually. More details: https://mswjs.io/docs/api/setup-worker/start`,\n              options.serviceWorker.url,\n              location.host,\n            )\n\n        throw new Error(missingWorkerMessage)\n      }\n\n      context.workerPromise.resolve(worker)\n      context.registration = registration\n\n      window.addEventListener('beforeunload', () => {\n        if (worker.state !== 'redundant') {\n          // Notify the Service Worker that this client has closed.\n          // Internally, it's similar to disabling the mocking, only\n          // client close event has a handler that self-terminates\n          // the Service Worker when there are no open clients.\n          context.workerChannel.postMessage('CLIENT_CLOSED')\n        }\n\n        // Make sure we're always clearing the interval - there are reports that not doing this can\n        // cause memory leaks in headless browser environments.\n        window.clearInterval(context.keepAliveInterval)\n\n        // Notify others about this client disconnecting.\n        // E.g. this will purge the in-memory WebSocket clients since\n        // starting the worker again will assign them new IDs.\n        window.postMessage({ type: 'msw/worker:stop' })\n      })\n\n      // Check if the active Service Worker has been generated\n      // by the currently installed version of MSW.\n      await checkWorkerIntegrity(context).catch((error) => {\n        devUtils.error(\n          'Error while checking the worker script integrity. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below.',\n        )\n        console.error(error)\n      })\n\n      context.keepAliveInterval = window.setInterval(\n        () => context.workerChannel.postMessage('KEEPALIVE_REQUEST'),\n        5000,\n      )\n\n      // Warn the user when loading the page that lies outside\n      // of the worker's scope.\n      validateWorkerScope(registration, context.startOptions)\n\n      return registration\n    }\n\n    const workerRegistration = startWorkerInstance().then(\n      async (registration) => {\n        const pendingInstance = registration.installing || registration.waiting\n\n        if (pendingInstance) {\n          const activationPromise = new DeferredPromise<void>()\n\n          pendingInstance.addEventListener('statechange', () => {\n            if (pendingInstance.state === 'activated') {\n              activationPromise.resolve()\n            }\n          })\n\n          // Wait until the worker is activated.\n          // Assume the worker is already activated if there's no pending registration\n          // (i.e. when reloading the page after a successful activation).\n          await activationPromise\n        }\n\n        // Print the activation message only after the worker has been activated.\n        await enableMocking(context, options).catch((error) => {\n          devUtils.error(\n            'Failed to enable mocking. Please report this on GitHub (https://github.com/mswjs/msw/issues) and include the original error below.',\n          )\n          throw error\n        })\n\n        return registration\n      },\n    )\n\n    return workerRegistration\n  }\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/enableMocking.ts",
    "content": "import { DeferredPromise } from '@open-draft/deferred-promise'\nimport type { StartOptions, SetupWorkerInternalContext } from '../../glossary'\nimport { printStartMessage } from './printStartMessage'\n\n/**\n * Signals the worker to enable the interception of requests.\n */\nexport function enableMocking(\n  context: SetupWorkerInternalContext,\n  options: StartOptions,\n): Promise<boolean> {\n  const mockingEnabledPromise = new DeferredPromise<boolean>()\n\n  context.workerChannel.postMessage('MOCK_ACTIVATE')\n  context.workerChannel.once('MOCKING_ENABLED', async (event) => {\n    context.isMockingEnabled = true\n    const worker = await context.workerPromise\n\n    printStartMessage({\n      quiet: options.quiet,\n      workerScope: context.registration?.scope,\n      workerUrl: worker.scriptURL,\n      client: event.data.client,\n    })\n\n    mockingEnabledPromise.resolve(true)\n  })\n\n  return mockingEnabledPromise\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/getWorkerByRegistration.ts",
    "content": "import { FindWorker } from '../../glossary'\n\n/**\n * Attempts to resolve a Service Worker instance from a given registration,\n * regardless of its state (active, installing, waiting).\n */\nexport function getWorkerByRegistration(\n  registration: ServiceWorkerRegistration,\n  absoluteWorkerUrl: string,\n  findWorker: FindWorker,\n): ServiceWorker | null {\n  const allStates = [\n    registration.active,\n    registration.installing,\n    registration.waiting,\n  ]\n  const relevantStates = allStates.filter((state): state is ServiceWorker => {\n    return state != null\n  })\n  const worker = relevantStates.find((worker) => {\n    return findWorker(worker.scriptURL, absoluteWorkerUrl)\n  })\n\n  return worker || null\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/getWorkerInstance.ts",
    "content": "import { until } from 'until-async'\nimport { devUtils } from '~/core/utils/internal/devUtils'\nimport { getAbsoluteWorkerUrl } from '../../../utils/getAbsoluteWorkerUrl'\nimport { getWorkerByRegistration } from './getWorkerByRegistration'\nimport { ServiceWorkerInstanceTuple, FindWorker } from '../../glossary'\n\n/**\n * Returns an active Service Worker instance.\n * When not found, registers a new Service Worker.\n */\nexport const getWorkerInstance = async (\n  url: string,\n  options: RegistrationOptions = {},\n  findWorker: FindWorker,\n): Promise<ServiceWorkerInstanceTuple> => {\n  // Resolve the absolute Service Worker URL.\n  const absoluteWorkerUrl = getAbsoluteWorkerUrl(url)\n\n  const mockRegistrations = await navigator.serviceWorker\n    .getRegistrations()\n    .then((registrations) =>\n      registrations.filter((registration) =>\n        getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n      ),\n    )\n  if (!navigator.serviceWorker.controller && mockRegistrations.length > 0) {\n    // Reload the page when it has associated workers, but no active controller.\n    // The absence of a controller can mean either:\n    // - page has no Service Worker associated with it\n    // - page has been hard-reloaded and its workers won't be used until the next reload.\n    // Since we've checked that there are registrations associated with this page,\n    // at this point we are sure it's hard reload that falls into this clause.\n    location.reload()\n  }\n\n  const [existingRegistration] = mockRegistrations\n\n  if (existingRegistration) {\n    // Schedule the worker update in the background.\n    // Update ensures the existing worker is up-to-date.\n    existingRegistration.update()\n\n    // Return the worker reference immediately.\n    return [\n      getWorkerByRegistration(\n        existingRegistration,\n        absoluteWorkerUrl,\n        findWorker,\n      ),\n      existingRegistration,\n    ]\n  }\n\n  // When the Service Worker wasn't found, register it anew and return the reference.\n  const [registrationError, registrationResult] = await until<\n    Error,\n    ServiceWorkerInstanceTuple\n  >(async () => {\n    const registration = await navigator.serviceWorker.register(url, options)\n    return [\n      // Compare existing worker registration by its worker URL,\n      // to prevent irrelevant workers to resolve here (such as Codesandbox worker).\n      getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),\n      registration,\n    ]\n  })\n\n  // Handle Service Worker registration errors.\n  if (registrationError) {\n    const isWorkerMissing = registrationError.message.includes('(404)')\n\n    // Produce a custom error message when given a non-existing Service Worker url.\n    // Suggest developers to check their setup.\n    if (isWorkerMissing) {\n      const scopeUrl = new URL(options?.scope || '/', location.href)\n\n      throw new Error(\n        devUtils.formatMessage(`\\\nFailed to register a Service Worker for scope ('${scopeUrl.href}') with script ('${absoluteWorkerUrl}'): Service Worker script does not exist at the given path.\n\nDid you forget to run \"npx msw init <PUBLIC_DIR>\"?\n\nLearn more about creating the Service Worker script: https://mswjs.io/docs/cli/init`),\n      )\n    }\n\n    // Fallback error message for any other registration errors.\n    throw new Error(\n      devUtils.formatMessage(\n        'Failed to register the Service Worker:\\n\\n%s',\n        registrationError.message,\n      ),\n    )\n  }\n\n  return registrationResult\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/prepareStartHandler.test.ts",
    "content": "import { SetupWorkerInternalContext, StartOptions } from '../../glossary'\nimport {\n  DEFAULT_START_OPTIONS,\n  resolveStartOptions,\n  prepareStartHandler,\n} from './prepareStartHandler'\n\ndescribe('resolveStartOptions', () => {\n  test('returns default options given no custom start options', () => {\n    expect(resolveStartOptions()).toEqual(DEFAULT_START_OPTIONS)\n    expect(resolveStartOptions(undefined)).toEqual(DEFAULT_START_OPTIONS)\n    expect(resolveStartOptions({})).toEqual(DEFAULT_START_OPTIONS)\n  })\n\n  test('deeply merges the default and custom start options', () => {\n    expect(\n      resolveStartOptions({\n        quiet: true,\n        serviceWorker: {\n          url: './custom.js',\n        },\n      }),\n    ).toEqual({\n      ...DEFAULT_START_OPTIONS,\n      quiet: true,\n      serviceWorker: {\n        url: './custom.js',\n        options: null,\n      },\n    })\n  })\n})\n\ndescribe('prepareStartHandler', () => {\n  test('exposes resolved start options to the generated star handler', () => {\n    const createStartHandler = vi.fn()\n    const context: SetupWorkerInternalContext = {} as any\n    const startHandler = prepareStartHandler(createStartHandler, context)\n    expect(startHandler).toBeInstanceOf(Function)\n\n    const initialOptions: StartOptions = {\n      quiet: true,\n      serviceWorker: {\n        url: './custom.js',\n      },\n    }\n    const resolvedOptions = resolveStartOptions(initialOptions)\n    startHandler(initialOptions)\n\n    // Calls the handler creator with both resolved and initial options.\n    expect(createStartHandler).toHaveBeenCalledWith(\n      resolvedOptions,\n      initialOptions,\n    )\n\n    // Sets the resolved options on the internal context.\n    expect(context).toHaveProperty('startOptions', resolvedOptions)\n  })\n})\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/prepareStartHandler.ts",
    "content": "import { RequiredDeep } from '~/core/typeUtils'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport {\n  SetupWorker,\n  SetupWorkerInternalContext,\n  StartHandler,\n  StartOptions,\n} from '../../glossary'\n\nexport const DEFAULT_START_OPTIONS: RequiredDeep<StartOptions> = {\n  serviceWorker: {\n    url: '/mockServiceWorker.js',\n    options: null as any,\n  },\n  quiet: false,\n  waitUntilReady: true,\n  onUnhandledRequest: 'warn',\n  findWorker(scriptURL, mockServiceWorkerUrl) {\n    return scriptURL === mockServiceWorkerUrl\n  },\n}\n\n/**\n * Returns resolved worker start options, merging the default options\n * with the given custom options.\n */\nexport function resolveStartOptions(\n  initialOptions?: StartOptions,\n): RequiredDeep<StartOptions> {\n  return mergeRight(\n    DEFAULT_START_OPTIONS,\n    initialOptions || {},\n  ) as RequiredDeep<StartOptions>\n}\n\nexport function prepareStartHandler(\n  handler: StartHandler,\n  context: SetupWorkerInternalContext,\n): SetupWorker['start'] {\n  return (initialOptions) => {\n    context.startOptions = resolveStartOptions(initialOptions)\n    return handler(context.startOptions, initialOptions || {})\n  }\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/printStartMessage.test.ts",
    "content": "import { printStartMessage } from './printStartMessage'\n\nbeforeEach(() => {\n  vi.spyOn(console, 'groupCollapsed').mockImplementation(() => void 0)\n  vi.spyOn(console, 'log').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.restoreAllMocks()\n})\n\ntest('prints out a default start message into console', () => {\n  printStartMessage({\n    workerScope: 'http://localhost:3000/',\n    workerUrl: 'http://localhost:3000/worker.js',\n  })\n\n  expect(console.groupCollapsed).toHaveBeenCalledWith(\n    '%c[MSW] Mocking enabled.',\n    expect.anything(),\n  )\n\n  // Includes a link to the documentation.\n  expect(console.log).toHaveBeenCalledWith(\n    '%cDocumentation: %chttps://mswjs.io/docs',\n    expect.anything(),\n    expect.anything(),\n  )\n\n  // Includes a link to the GitHub issues page.\n  expect(console.log).toHaveBeenCalledWith(\n    'Found an issue? https://github.com/mswjs/msw/issues',\n  )\n\n  // Includes service worker scope.\n  expect(console.log).toHaveBeenCalledWith(\n    'Worker scope:',\n    'http://localhost:3000/',\n  )\n\n  // Includes service worker script location.\n  expect(console.log).toHaveBeenCalledWith(\n    'Worker script URL:',\n    'http://localhost:3000/worker.js',\n  )\n})\n\ntest('supports printing a custom start message', () => {\n  printStartMessage({ message: 'Custom start message' })\n\n  expect(console.groupCollapsed).toHaveBeenCalledWith(\n    '%c[MSW] Custom start message',\n    expect.anything(),\n  )\n})\n\ntest('does not print any messages when log level is quiet', () => {\n  printStartMessage({ quiet: true })\n\n  expect(console.groupCollapsed).not.toHaveBeenCalled()\n  expect(console.log).not.toHaveBeenCalled()\n})\n\ntest('prints a worker scope in the start message', () => {\n  printStartMessage({\n    workerScope: 'http://localhost:3000/user',\n  })\n\n  expect(console.log).toHaveBeenCalledWith(\n    'Worker scope:',\n    'http://localhost:3000/user',\n  )\n})\n\ntest('prints a worker script url in the start message', () => {\n  printStartMessage({\n    workerUrl: 'http://localhost:3000/mockServiceWorker.js',\n  })\n\n  expect(console.log).toHaveBeenCalledWith(\n    'Worker script URL:',\n    'http://localhost:3000/mockServiceWorker.js',\n  )\n})\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/printStartMessage.ts",
    "content": "import type { ServiceWorkerIncomingEventsMap } from '../../glossary'\nimport { devUtils } from '~/core/utils/internal/devUtils'\n\ninterface PrintStartMessageArgs {\n  quiet?: boolean\n  message?: string\n  workerUrl?: string\n  workerScope?: string\n  client?: ServiceWorkerIncomingEventsMap['MOCKING_ENABLED']['client']\n}\n\n/**\n * Prints a worker activation message in the browser's console.\n */\nexport function printStartMessage(args: PrintStartMessageArgs = {}) {\n  if (args.quiet) {\n    return\n  }\n\n  const message = args.message || 'Mocking enabled.'\n\n  console.groupCollapsed(\n    `%c${devUtils.formatMessage(message)}`,\n    'color:orangered;font-weight:bold;',\n  )\n  // eslint-disable-next-line no-console\n  console.log(\n    '%cDocumentation: %chttps://mswjs.io/docs',\n    'font-weight:bold',\n    'font-weight:normal',\n  )\n  // eslint-disable-next-line no-console\n  console.log('Found an issue? https://github.com/mswjs/msw/issues')\n\n  if (args.workerUrl) {\n    // eslint-disable-next-line no-console\n    console.log('Worker script URL:', args.workerUrl)\n  }\n\n  if (args.workerScope) {\n    // eslint-disable-next-line no-console\n    console.log('Worker scope:', args.workerScope)\n  }\n\n  if (args.client) {\n    // eslint-disable-next-line no-console\n    console.log('Client ID: %s (%s)', args.client.id, args.client.frameType)\n  }\n\n  console.groupEnd()\n}\n"
  },
  {
    "path": "src/browser/setupWorker/start/utils/validateWorkerScope.ts",
    "content": "import { devUtils } from '~/core/utils/internal/devUtils'\nimport { StartOptions } from '../../glossary'\n\nexport function validateWorkerScope(\n  registration: ServiceWorkerRegistration,\n  options?: StartOptions,\n): void {\n  if (!options?.quiet && !location.href.startsWith(registration.scope)) {\n    devUtils.warn(\n      `\\\nCannot intercept requests on this page because it's outside of the worker's scope (\"${registration.scope}\"). If you wish to mock API requests on this page, you must resolve this scope issue.\n\n- (Recommended) Register the worker at the root level (\"/\") of your application.\n- Set the \"Service-Worker-Allowed\" response header to allow out-of-scope workers.\\\n`,\n    )\n  }\n}\n"
  },
  {
    "path": "src/browser/setupWorker/stop/utils/printStopMessage.test.ts",
    "content": "import { printStopMessage } from './printStopMessage'\n\nbeforeAll(() => {\n  vi.spyOn(global.console, 'log').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  vi.restoreAllMocks()\n})\n\ntest('prints a stop message to the console', () => {\n  printStopMessage()\n  expect(console.log).toHaveBeenCalledWith(\n    '%c[MSW] Mocking disabled.',\n    'color:orangered;font-weight:bold;',\n  )\n})\n\ntest('does not print any message when log level is quiet', () => {\n  printStopMessage({ quiet: true })\n  expect(console.log).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "src/browser/setupWorker/stop/utils/printStopMessage.ts",
    "content": "import { devUtils } from '~/core/utils/internal/devUtils'\n\nexport function printStopMessage(args: { quiet?: boolean } = {}): void {\n  if (args.quiet) {\n    return\n  }\n\n  // eslint-disable-next-line no-console\n  console.log(\n    `%c${devUtils.formatMessage('Mocking disabled.')}`,\n    'color:orangered;font-weight:bold;',\n  )\n}\n"
  },
  {
    "path": "src/browser/tsconfig.browser.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.browser.json\",\n  \"compilerOptions\": {\n    \"composite\": false\n  }\n}\n"
  },
  {
    "path": "src/browser/tsconfig.browser.json",
    "content": "{\n  \"extends\": \"../tsconfig.src.json\",\n  \"compilerOptions\": {\n    // Expose browser-specific libraries only for the\n    // source code under the \"src/browser\" directory.\n    \"lib\": [\"DOM\", \"WebWorker\", \"DOM.Iterable\"]\n  },\n  \"include\": [\"../../global.d.ts\", \"./global.browser.d.ts\", \"./**/*.ts\"]\n}\n"
  },
  {
    "path": "src/browser/utils/checkWorkerIntegrity.ts",
    "content": "import { devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupWorkerInternalContext } from '../setupWorker/glossary'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\n/**\n * Check whether the registered Service Worker has been\n * generated by the installed version of the library.\n * Prints a warning message if the worker scripts mismatch.\n */\nexport function checkWorkerIntegrity(\n  context: SetupWorkerInternalContext,\n): Promise<void> {\n  const integrityCheckPromise = new DeferredPromise<void>()\n\n  // Request the integrity checksum from the registered worker.\n  context.workerChannel.postMessage('INTEGRITY_CHECK_REQUEST')\n  context.workerChannel.once('INTEGRITY_CHECK_RESPONSE', (event) => {\n    const { checksum, packageVersion } = event.data\n\n    // Compare the response from the Service Worker and the\n    // global variable set during the build.\n\n    // The integrity is validated based on the worker script's checksum\n    // that's derived from its minified content during the build.\n    // The \"SERVICE_WORKER_CHECKSUM\" global variable is injected by the build.\n    if (checksum !== SERVICE_WORKER_CHECKSUM) {\n      devUtils.warn(\n        `The currently registered Service Worker has been generated by a different version of MSW (${packageVersion}) and may not be fully compatible with the installed version.\n\nIt's recommended you update your worker script by running this command:\n\n  \\u2022 npx msw init <PUBLIC_DIR>\n\nYou can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,\n      )\n    }\n\n    integrityCheckPromise.resolve()\n  })\n\n  return integrityCheckPromise\n}\n"
  },
  {
    "path": "src/browser/utils/deserializeRequest.ts",
    "content": "import { pruneGetRequestBody } from './pruneGetRequestBody'\nimport type { ServiceWorkerIncomingRequest } from '../setupWorker/glossary'\n\n/**\n * Converts a given request received from the Service Worker\n * into a Fetch `Request` instance.\n */\nexport function deserializeRequest(\n  serializedRequest: ServiceWorkerIncomingRequest,\n): Request {\n  return new Request(serializedRequest.url, {\n    ...serializedRequest,\n    body: pruneGetRequestBody(serializedRequest),\n  })\n}\n"
  },
  {
    "path": "src/browser/utils/getAbsoluteWorkerUrl.test.ts",
    "content": "// @vitest-environment jsdom\nimport { getAbsoluteWorkerUrl } from './getAbsoluteWorkerUrl'\n\nconst rawLocation = window.location\n\nafterAll(() => {\n  Object.defineProperty(window, 'location', {\n    value: rawLocation,\n  })\n})\n\nit('returns absolute worker url relatively to the root', () => {\n  expect(getAbsoluteWorkerUrl('./worker.js')).toBe('http://localhost/worker.js')\n})\n\nit('returns an absolute worker url relatively to the current path', () => {\n  Object.defineProperty(window, 'location', {\n    value: {\n      href: 'http://localhost/path/to/page',\n    },\n  })\n\n  expect(getAbsoluteWorkerUrl('./worker.js')).toBe(\n    'http://localhost/path/to/worker.js',\n  )\n\n  // Leading slash must still resolve to the root.\n  expect(getAbsoluteWorkerUrl('/worker.js')).toBe('http://localhost/worker.js')\n})\n"
  },
  {
    "path": "src/browser/utils/getAbsoluteWorkerUrl.ts",
    "content": "/**\n * Returns an absolute Service Worker URL based on the given\n * relative URL (known during the registration).\n */\nexport function getAbsoluteWorkerUrl(workerUrl: string): string {\n  return new URL(workerUrl, location.href).href\n}\n"
  },
  {
    "path": "src/browser/utils/pruneGetRequestBody.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { TextEncoder } from 'util'\nimport { pruneGetRequestBody } from './pruneGetRequestBody'\n\ntest('sets empty GET request body to undefined', () => {\n  expect(\n    pruneGetRequestBody({\n      method: 'GET',\n    }),\n  ).toBeUndefined()\n\n  expect(\n    pruneGetRequestBody({\n      method: 'GET',\n      // There's no such thing as a GET request with a body.\n      body: new ArrayBuffer(5),\n    }),\n  ).toBeUndefined()\n})\n\ntest('sets HEAD request body to undefined', () => {\n  expect(\n    pruneGetRequestBody({\n      method: 'HEAD',\n    }),\n  ).toBeUndefined()\n\n  expect(\n    pruneGetRequestBody({\n      method: 'HEAD',\n      body: new ArrayBuffer(5),\n    }),\n  ).toBeUndefined()\n})\n\ntest('ignores requests of the other methods than GET', () => {\n  const body = new TextEncoder().encode('hello world')\n  expect(\n    pruneGetRequestBody({\n      method: 'POST',\n      body,\n    }),\n  ).toEqual(body)\n\n  expect(\n    pruneGetRequestBody({\n      method: 'PUT',\n      body,\n    }),\n  ).toEqual(body)\n})\n"
  },
  {
    "path": "src/browser/utils/pruneGetRequestBody.ts",
    "content": "import type { ServiceWorkerIncomingRequest } from '../setupWorker/glossary'\n\ntype Input = Pick<ServiceWorkerIncomingRequest, 'method' | 'body'>\n\n/**\n * Ensures that an empty GET request body is always represented as `undefined`.\n */\nexport function pruneGetRequestBody(\n  request: Input,\n): ServiceWorkerIncomingRequest['body'] {\n  // Force HEAD/GET request body to always be empty.\n  // The worker reads any request's body as ArrayBuffer,\n  // and you cannot re-construct a GET/HEAD Request\n  // with an ArrayBuffer, even if empty. Also note that\n  // \"request.body\" is always undefined in the worker.\n  if (['HEAD', 'GET'].includes(request.method)) {\n    return undefined\n  }\n\n  return request.body\n}\n"
  },
  {
    "path": "src/browser/utils/supports.ts",
    "content": "/**\n * Checks if the Service Worker API is supproted and available\n * in the current browsing context.\n */\nexport function supportsServiceWorker(): boolean {\n  return (\n    typeof navigator !== 'undefined' &&\n    'serviceWorker' in navigator &&\n    typeof location !== 'undefined' &&\n    location.protocol !== 'file:'\n  )\n}\n\n/**\n * Returns a boolean indicating whether the current browser\n * supports `ReadableStream` as a `Transferable` when posting\n * messages.\n */\nexport function supportsReadableStreamTransfer() {\n  try {\n    const stream = new ReadableStream({\n      start: (controller) => controller.close(),\n    })\n    const message = new MessageChannel()\n    message.port1.postMessage(stream, [stream])\n    return true\n  } catch {\n    return false\n  }\n}\n"
  },
  {
    "path": "src/browser/utils/workerChannel.ts",
    "content": "import { invariant } from 'outvariant'\nimport { Emitter, TypedEvent } from 'rettime'\nimport { isObject } from '~/core/utils/internal/isObject'\nimport type { StringifiedResponse } from '../setupWorker/glossary'\nimport { supportsServiceWorker } from '../utils/supports'\n\nexport interface WorkerChannelOptions {\n  worker: Promise<ServiceWorker>\n}\n\nexport type WorkerChannelEventMap = {\n  REQUEST: WorkerEvent<IncomingWorkerRequest>\n  RESPONSE: WorkerEvent<IncomingWorkerResponse>\n  MOCKING_ENABLED: WorkerEvent<{\n    client: {\n      id: string\n      frameType: string\n    }\n  }>\n  INTEGRITY_CHECK_RESPONSE: WorkerEvent<{\n    packageVersion: string\n    checksum: string\n  }>\n  KEEPALIVE_RESPONSE: TypedEvent<never>\n}\n\n/**\n * Request representation received from the worker message event.\n */\nexport interface IncomingWorkerRequest\n  extends Omit<\n    Request,\n    | 'text'\n    | 'body'\n    | 'json'\n    | 'blob'\n    | 'arrayBuffer'\n    | 'formData'\n    | 'clone'\n    | 'signal'\n    | 'isHistoryNavigation'\n    | 'isReloadNavigation'\n  > {\n  /**\n   * Unique ID of the request generated once the request is\n   * intercepted by the \"fetch\" event in the Service Worker.\n   */\n  id: string\n  interceptedAt: number\n  body?: ArrayBuffer | null\n}\n\ntype IncomingWorkerResponse = {\n  isMockedResponse: boolean\n  request: IncomingWorkerRequest\n  response: Pick<\n    Response,\n    'type' | 'ok' | 'status' | 'statusText' | 'body' | 'headers' | 'redirected'\n  >\n}\n\nexport type WorkerEventResponse = {\n  MOCK_RESPONSE: [\n    data: StringifiedResponse,\n    transfer?: [ReadableStream<Uint8Array>],\n  ]\n  PASSTHROUGH: []\n}\n\nconst SUPPORTS_SERVICE_WORKER = supportsServiceWorker()\n\nexport class WorkerEvent<\n  DataType,\n  ReturnType = any,\n  EventType extends string = string,\n> extends TypedEvent<DataType, ReturnType, EventType> {\n  #workerEvent: MessageEvent\n\n  constructor(workerEvent: MessageEvent) {\n    const type = workerEvent.data.type as EventType\n    const data = workerEvent.data.payload as DataType\n\n    /**\n     * @note This is the only place we're mapping { type, payload }\n     * message structure of the worker. The client references the\n     * payload via `event.data`.\n     */\n    super(\n      // @ts-expect-error Troublesome `TypedEvent` extension.\n      type,\n      { data },\n    )\n    this.#workerEvent = workerEvent\n  }\n\n  get ports() {\n    return this.#workerEvent.ports\n  }\n\n  /**\n   * Reply directly to this event using its `MessagePort`.\n   */\n  public postMessage<Type extends keyof WorkerEventResponse>(\n    type: Type,\n    ...rest: WorkerEventResponse[Type]\n  ): void {\n    this.#workerEvent.ports[0].postMessage(\n      { type, data: rest[0] },\n      { transfer: rest[1] },\n    )\n  }\n}\n\n/**\n * Map of the events that can be sent to the Service Worker\n * from any execution context.\n */\ntype OutgoingWorkerEvents =\n  | 'MOCK_ACTIVATE'\n  | 'INTEGRITY_CHECK_REQUEST'\n  | 'KEEPALIVE_REQUEST'\n  | 'CLIENT_CLOSED'\n\nexport class WorkerChannel extends Emitter<WorkerChannelEventMap> {\n  constructor(protected readonly options: WorkerChannelOptions) {\n    super()\n\n    if (!SUPPORTS_SERVICE_WORKER) {\n      return\n    }\n\n    navigator.serviceWorker.addEventListener('message', async (event) => {\n      const worker = await this.options.worker\n\n      if (event.source != null && event.source !== worker) {\n        return\n      }\n\n      if (event.data && isObject(event.data) && 'type' in event.data) {\n        this.emit(new WorkerEvent<any, any, any>(event))\n      }\n    })\n  }\n\n  /**\n   * Send data to the Service Worker controlling this client.\n   * This triggers the `message` event listener on ServiceWorkerGlobalScope.\n   */\n  public postMessage(type: OutgoingWorkerEvents): void {\n    invariant(\n      SUPPORTS_SERVICE_WORKER,\n      'Failed to post message on a WorkerChannel: the Service Worker API is unavailable in this context. This is likely an issue with MSW. Please report it on GitHub: https://github.com/mswjs/msw/issues',\n    )\n\n    this.options.worker.then((worker) => {\n      worker.postMessage(type)\n    })\n  }\n}\n"
  },
  {
    "path": "src/core/HttpResponse.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { TextEncoder } from 'util'\nimport { HttpResponse, kDefaultContentType } from './HttpResponse'\n\nit('creates a plain response', async () => {\n  const response = new HttpResponse(null, { status: 301 })\n  expect(response.status).toBe(301)\n  expect(response.statusText).toBe('Moved Permanently')\n  expect(response.body).toBe(null)\n  await expect(response.text()).resolves.toBe('')\n  expect(Object.fromEntries(response.headers.entries())).toEqual({})\n})\n\nit('supports non-configurable status codes', () => {\n  expect(new HttpResponse(null, { status: 101 })).toHaveProperty('status', 101)\n})\n\ndescribe('HttpResponse.text()', () => {\n  it('creates a text response', async () => {\n    const response = HttpResponse.text('hello world', { status: 201 })\n\n    expect(response.status).toBe(201)\n    expect(response.statusText).toBe('Created')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe('hello world')\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'text/plain',\n    })\n    expect(kDefaultContentType in response).toBe(true)\n  })\n\n  it('creates a text response with special characters', async () => {\n    const response = HttpResponse.text('안녕 세상', { status: 201 })\n\n    expect(response.status).toBe(201)\n    expect(response.statusText).toBe('Created')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe('안녕 세상')\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '13',\n      'content-type': 'text/plain',\n    })\n  })\n\n  it('allows overriding the \"Content-Type\" response header', async () => {\n    const response = HttpResponse.text('hello world', {\n      headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n    })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe('hello world')\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'text/plain; charset=utf-8',\n    })\n    expect(kDefaultContentType in response).toBe(false)\n  })\n\n  it('allows overriding the \"Content-Length\" response header', async () => {\n    const response = HttpResponse.text('hello world', {\n      headers: { 'Content-Length': '32' },\n    })\n\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '32',\n      'content-type': 'text/plain',\n    })\n  })\n})\n\ndescribe('HttpResponse.json()', () => {\n  it('creates a json response given an object', async () => {\n    const response = HttpResponse.json({ firstName: 'John' })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toEqual({ firstName: 'John' })\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '20',\n      'content-type': 'application/json',\n    })\n    expect(kDefaultContentType in response).toBe(true)\n  })\n\n  it('creates a json response given an object with special characters', async () => {\n    const response = HttpResponse.json({ firstName: '제로' })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toEqual({ firstName: '제로' })\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '22',\n      'content-type': 'application/json',\n    })\n  })\n\n  it('creates a json response given an array', async () => {\n    const response = HttpResponse.json([1, 2, 3])\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toEqual([1, 2, 3])\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '7',\n      'content-type': 'application/json',\n    })\n  })\n\n  it('creates a json response given a plain string', async () => {\n    const response = HttpResponse.json(`\"hello\"`)\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toBe(`\"hello\"`)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'application/json',\n    })\n  })\n\n  it('creates a json response given a number', async () => {\n    const response = HttpResponse.json(123)\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toBe(123)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '3',\n      'content-type': 'application/json',\n    })\n  })\n\n  it('creates a json response given a json ReadableStream', async () => {\n    const encoder = new TextEncoder()\n    const stream = new ReadableStream({\n      start(controller) {\n        controller.enqueue(encoder.encode(`{\"firstName`))\n        controller.enqueue(encoder.encode(`\":\"John`))\n        controller.enqueue(encoder.encode(`\"}`))\n        controller.close()\n      },\n    })\n    const response = HttpResponse.json(stream)\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    // A ReadableStream instance is not a valid body init\n    // for the \"Response.json()\" static method. It gets serialized\n    // into a plain object.\n    expect(await response.json()).toEqual({})\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '2',\n      'content-type': 'application/json',\n    })\n  })\n\n  it('allows overriding the \"Content-Type\" response header', async () => {\n    const response = HttpResponse.json(\n      { a: 1 },\n      {\n        headers: {\n          'Content-Type': 'application/hal+json',\n        },\n      },\n    )\n\n    expect(kDefaultContentType in response).toBe(false)\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    expect(await response.json()).toEqual({ a: 1 })\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '7',\n      'content-type': 'application/hal+json',\n    })\n  })\n\n  it('allows overriding the \"Content-Length\" response header', async () => {\n    const response = HttpResponse.json(\n      { a: 1 },\n      {\n        headers: { 'Content-Length': '32' },\n      },\n    )\n\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '32',\n      'content-type': 'application/json',\n    })\n  })\n})\n\ndescribe('HttpResponse.xml()', () => {\n  it('creates an xml response', async () => {\n    const response = HttpResponse.xml('<user name=\"John\" />')\n\n    expect(kDefaultContentType in response).toBe(true)\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe('<user name=\"John\" />')\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-type': 'text/xml',\n    })\n    expect(kDefaultContentType in response).toBe(true)\n  })\n\n  it('allows overriding the \"Content-Type\" response header', async () => {\n    const response = HttpResponse.xml('<user name=\"John\" />', {\n      headers: {\n        'Content-Type': 'text/xml; charset=utf-8',\n      },\n    })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe('<user name=\"John\" />')\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-type': 'text/xml; charset=utf-8',\n    })\n    expect(kDefaultContentType in response).toBe(false)\n  })\n})\n\ndescribe('HttpResponse.html()', () => {\n  it('creates an html response', async () => {\n    const response = HttpResponse.html('<p class=\"author\">Jane Doe</p>')\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe(\n      '<p class=\"author\">Jane Doe</p>',\n    )\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-type': 'text/html',\n    })\n    expect(kDefaultContentType in response).toBe(true)\n  })\n\n  it('allows overriding the \"Content-Type\" response header', async () => {\n    const response = HttpResponse.html('<p class=\"author\">Jane Doe</p>', {\n      headers: {\n        'Content-Type': 'text/html; charset=utf-8',\n      },\n    })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n    await expect(response.text()).resolves.toBe(\n      '<p class=\"author\">Jane Doe</p>',\n    )\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-type': 'text/html; charset=utf-8',\n    })\n    expect(kDefaultContentType in response).toBe(false)\n  })\n})\n\ndescribe('HttpResponse.arrayBuffer()', () => {\n  it('creates an array buffer response', async () => {\n    const buffer = new TextEncoder().encode('hello world')\n    const response = HttpResponse.arrayBuffer(buffer)\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n\n    const responseData = await response.arrayBuffer()\n    expect(responseData).toEqual(buffer.buffer)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'application/octet-stream',\n    })\n    expect(kDefaultContentType in response).toBe(true)\n  })\n\n  it('allows overriding the \"Content-Type\" response header', async () => {\n    const buffer = new TextEncoder().encode('hello world')\n    const response = HttpResponse.arrayBuffer(buffer, {\n      headers: {\n        'Content-Type': 'text/plain; charset=utf-8',\n      },\n    })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n\n    const responseData = await response.arrayBuffer()\n    expect(responseData).toEqual(buffer.buffer)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'text/plain; charset=utf-8',\n    })\n    expect(kDefaultContentType in response).toBe(false)\n  })\n\n  it('creates an array buffer response from a shared array buffer', async () => {\n    const arrayBuffer = new TextEncoder().encode('hello world')\n\n    // Copy the data from the array buffer to a shared array buffer\n    const sharedBuffer = new SharedArrayBuffer(11)\n    const sharedView = new Uint8Array(sharedBuffer)\n    sharedView.set(arrayBuffer)\n\n    const response = HttpResponse.arrayBuffer(sharedBuffer)\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n\n    const responseData = await response.arrayBuffer()\n    expect(responseData).toEqual(arrayBuffer.buffer)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'application/octet-stream',\n    })\n  })\n\n  it('allows overriding the \"Content-Type\" response header for shared array buffers', async () => {\n    const arrayBuffer = new TextEncoder().encode('hello world')\n\n    // Copy the data from the array buffer to a shared array buffer\n    const sharedBuffer = new SharedArrayBuffer(11)\n    const sharedView = new Uint8Array(sharedBuffer)\n    sharedView.set(arrayBuffer)\n\n    const response = HttpResponse.arrayBuffer(sharedBuffer, {\n      headers: {\n        'Content-Type': 'text/plain; charset=utf-8',\n      },\n    })\n\n    expect(response.status).toBe(200)\n    expect(response.statusText).toBe('OK')\n    expect(response.body).toBeInstanceOf(ReadableStream)\n\n    const responseData = await response.arrayBuffer()\n    expect(responseData).toEqual(arrayBuffer.buffer)\n    expect(Object.fromEntries(response.headers.entries())).toEqual({\n      'content-length': '11',\n      'content-type': 'text/plain; charset=utf-8',\n    })\n    expect(kDefaultContentType in response).toBe(false)\n  })\n})\n\nit('creates a form data response', async () => {\n  const formData = new FormData()\n  formData.append('firstName', 'John')\n  const response = HttpResponse.formData(formData)\n\n  expect(response.status).toBe(200)\n  expect(response.statusText).toBe('OK')\n  expect(response.body).toBeInstanceOf(ReadableStream)\n\n  const responseData = await response.formData()\n  expect(responseData.get('firstName')).toBe('John')\n  expect(Object.fromEntries(response.headers.entries())).toEqual({\n    'content-type': expect.stringContaining(\n      'multipart/form-data; boundary=----',\n    ),\n  })\n})\n"
  },
  {
    "path": "src/core/HttpResponse.ts",
    "content": "import { FetchResponse } from '@mswjs/interceptors'\nimport type { DefaultBodyType, JsonBodyType } from './handlers/RequestHandler'\nimport type { NoInfer } from './typeUtils'\nimport {\n  decorateResponse,\n  normalizeResponseInit,\n} from './utils/HttpResponse/decorators'\n\nexport interface HttpResponseInit extends ResponseInit {\n  type?: ResponseType\n}\n\nexport const bodyType: unique symbol = Symbol('bodyType')\nexport type DefaultUnsafeFetchResponse = Response & {\n  [bodyType]?: never\n}\n\nexport interface StrictRequest<BodyType extends JsonBodyType> extends Request {\n  json(): Promise<BodyType>\n  clone(): StrictRequest<BodyType>\n}\n\n/**\n * Opaque `Response` type that supports strict body type.\n *\n * @deprecated Please use {@link HttpResponse} instead.\n */\nexport type StrictResponse<BodyType extends DefaultBodyType> =\n  HttpResponse<BodyType>\n\nexport const kDefaultContentType = Symbol.for('kDefaultContentType')\n\n/**\n * A drop-in replacement for the standard `Response` class\n * to allow additional features, like mocking the response `Set-Cookie` header.\n *\n * @example\n * new HttpResponse('Hello world', { status: 201 })\n * HttpResponse.json({ name: 'John' })\n * HttpResponse.formData(form)\n *\n * @see {@link https://mswjs.io/docs/api/http-response `HttpResponse` API reference}\n */\nexport class HttpResponse<\n  BodyType extends DefaultBodyType,\n> extends FetchResponse {\n  readonly [bodyType]: BodyType = null as any\n\n  constructor(body?: NoInfer<BodyType> | null, init?: HttpResponseInit) {\n    const responseInit = normalizeResponseInit(init)\n    super(body as BodyInit, responseInit)\n    decorateResponse(this, responseInit)\n  }\n\n  static error(): HttpResponse<any> {\n    return super.error() as HttpResponse<any>\n  }\n\n  /**\n   * Create a `Response` with a `Content-Type: \"text/plain\"` body.\n   * @example\n   * HttpResponse.text('hello world')\n   * HttpResponse.text('Error', { status: 500 })\n   */\n  static text<BodyType extends string>(\n    body?: NoInfer<BodyType> | null,\n    init?: HttpResponseInit,\n  ): HttpResponse<BodyType> {\n    const responseInit = normalizeResponseInit(init)\n    const hasExplicitContentType = responseInit.headers.has('Content-Type')\n\n    if (!hasExplicitContentType) {\n      responseInit.headers.set('Content-Type', 'text/plain')\n    }\n\n    // Automatically set the \"Content-Length\" response header\n    // for non-empty text responses. This enforces consistency and\n    // brings mocked responses closer to production.\n    if (!responseInit.headers.has('Content-Length')) {\n      responseInit.headers.set(\n        'Content-Length',\n        body ? new Blob([body]).size.toString() : '0',\n      )\n    }\n\n    const response = new HttpResponse(body, responseInit)\n\n    if (!hasExplicitContentType) {\n      Object.defineProperty(response, kDefaultContentType, {\n        value: true,\n        enumerable: false,\n      })\n    }\n\n    return response\n  }\n\n  /**\n   * Create a `Response` with a `Content-Type: \"application/json\"` body.\n   * @example\n   * HttpResponse.json({ firstName: 'John' })\n   * HttpResponse.json({ error: 'Not Authorized' }, { status: 401 })\n   */\n  static json<BodyType extends JsonBodyType>(\n    body?: NoInfer<BodyType> | null | undefined,\n    init?: HttpResponseInit,\n  ): HttpResponse<BodyType> {\n    const responseInit = normalizeResponseInit(init)\n    const hasExplicitContentType = responseInit.headers.has('Content-Type')\n\n    if (!hasExplicitContentType) {\n      responseInit.headers.set('Content-Type', 'application/json')\n    }\n\n    /**\n     * @note TypeScript is incorrect here.\n     * Stringifying undefined will return undefined.\n     */\n    const responseText = JSON.stringify(body) as string | undefined\n\n    if (!responseInit.headers.has('Content-Length')) {\n      responseInit.headers.set(\n        'Content-Length',\n        responseText ? new Blob([responseText]).size.toString() : '0',\n      )\n    }\n\n    const response = new HttpResponse(responseText, responseInit)\n\n    if (!hasExplicitContentType) {\n      Object.defineProperty(response, kDefaultContentType, {\n        value: true,\n        enumerable: false,\n      })\n    }\n\n    return response as HttpResponse<BodyType>\n  }\n\n  /**\n   * Create a `Response` with a `Content-Type: \"application/xml\"` body.\n   * @example\n   * HttpResponse.xml(`<user name=\"John\" />`)\n   * HttpResponse.xml(`<article id=\"abc-123\" />`, { status: 201 })\n   */\n  static xml<BodyType extends string>(\n    body?: BodyType | null,\n    init?: HttpResponseInit,\n  ): HttpResponse<BodyType> {\n    const responseInit = normalizeResponseInit(init)\n    const hasExplicitContentType = responseInit.headers.has('Content-Type')\n\n    if (!hasExplicitContentType) {\n      responseInit.headers.set('Content-Type', 'text/xml')\n    }\n\n    const response = new HttpResponse(body, responseInit)\n\n    if (!hasExplicitContentType) {\n      Object.defineProperty(response, kDefaultContentType, {\n        value: true,\n        enumerable: false,\n      })\n    }\n\n    return response as HttpResponse<BodyType>\n  }\n\n  /**\n   * Create a `Response` with a `Content-Type: \"text/html\"` body.\n   * @example\n   * HttpResponse.html(`<p class=\"author\">Jane Doe</p>`)\n   * HttpResponse.html(`<main id=\"abc-123\">Main text</main>`, { status: 201 })\n   */\n  static html<BodyType extends string>(\n    body?: BodyType | null,\n    init?: HttpResponseInit,\n  ): HttpResponse<BodyType> {\n    const responseInit = normalizeResponseInit(init)\n    const hasExplicitContentType = responseInit.headers.has('Content-Type')\n\n    if (!hasExplicitContentType) {\n      responseInit.headers.set('Content-Type', 'text/html')\n    }\n\n    const response = new HttpResponse(body, responseInit)\n\n    if (!hasExplicitContentType) {\n      Object.defineProperty(response, kDefaultContentType, {\n        value: true,\n        enumerable: false,\n      })\n    }\n\n    return response as HttpResponse<BodyType>\n  }\n\n  /**\n   * Create a `Response` with an `ArrayBuffer` body.\n   * @example\n   * const buffer = new ArrayBuffer(3)\n   * const view = new Uint8Array(buffer)\n   * view.set([1, 2, 3])\n   *\n   * HttpResponse.arrayBuffer(buffer)\n   */\n  static arrayBuffer<BodyType extends ArrayBuffer | SharedArrayBuffer>(\n    body?: BodyType,\n    init?: HttpResponseInit,\n  ): HttpResponse<BodyType> {\n    const responseInit = normalizeResponseInit(init)\n    const hasExplicitContentType = responseInit.headers.has('Content-Type')\n\n    if (!hasExplicitContentType) {\n      responseInit.headers.set('Content-Type', 'application/octet-stream')\n    }\n\n    if (body && !responseInit.headers.has('Content-Length')) {\n      responseInit.headers.set('Content-Length', body.byteLength.toString())\n    }\n\n    const response = new HttpResponse(body, responseInit)\n\n    if (!hasExplicitContentType) {\n      Object.defineProperty(response, kDefaultContentType, {\n        value: true,\n        enumerable: false,\n      })\n    }\n\n    return response as HttpResponse<BodyType>\n  }\n\n  /**\n   * Create a `Response` with a `FormData` body.\n   * @example\n   * const data = new FormData()\n   * data.set('name', 'Alice')\n   *\n   * HttpResponse.formData(data)\n   */\n  static formData(\n    body?: FormData,\n    init?: HttpResponseInit,\n  ): HttpResponse<FormData> {\n    return new HttpResponse(body, normalizeResponseInit(init))\n  }\n}\n"
  },
  {
    "path": "src/core/SetupApi.ts",
    "content": "import { invariant } from 'outvariant'\nimport { EventMap, Emitter } from 'strict-event-emitter'\nimport { RequestHandler } from './handlers/RequestHandler'\nimport { LifeCycleEventEmitter } from './sharedOptions'\nimport { devUtils } from './utils/internal/devUtils'\nimport { pipeEvents } from './utils/internal/pipeEvents'\nimport { toReadonlyArray } from './utils/internal/toReadonlyArray'\nimport { Disposable } from './utils/internal/Disposable'\nimport type { WebSocketHandler } from './handlers/WebSocketHandler'\n\nexport abstract class HandlersController {\n  abstract prepend(\n    runtimeHandlers: Array<RequestHandler | WebSocketHandler>,\n  ): void\n  abstract reset(nextHandles: Array<RequestHandler | WebSocketHandler>): void\n  abstract currentHandlers(): Array<RequestHandler | WebSocketHandler>\n}\n\nexport class InMemoryHandlersController implements HandlersController {\n  private handlers: Array<RequestHandler | WebSocketHandler>\n\n  constructor(\n    private initialHandlers: Array<RequestHandler | WebSocketHandler>,\n  ) {\n    this.handlers = [...initialHandlers]\n  }\n\n  public prepend(\n    runtimeHandles: Array<RequestHandler | WebSocketHandler>,\n  ): void {\n    this.handlers.unshift(...runtimeHandles)\n  }\n\n  public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>): void {\n    this.handlers =\n      nextHandlers.length > 0 ? [...nextHandlers] : [...this.initialHandlers]\n  }\n\n  public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n    return this.handlers\n  }\n}\n\n/**\n * Generic class for the mock API setup.\n */\nexport abstract class SetupApi<EventsMap extends EventMap> extends Disposable {\n  protected handlersController: HandlersController\n  protected readonly emitter: Emitter<EventsMap>\n  protected readonly publicEmitter: Emitter<EventsMap>\n\n  public readonly events: LifeCycleEventEmitter<EventsMap>\n\n  constructor(...initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n    super()\n\n    invariant(\n      this.validateHandlers(initialHandlers),\n      devUtils.formatMessage(\n        `Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?`,\n      ),\n    )\n\n    this.handlersController = new InMemoryHandlersController(initialHandlers)\n\n    this.emitter = new Emitter<EventsMap>()\n    this.publicEmitter = new Emitter<EventsMap>()\n    pipeEvents(this.emitter, this.publicEmitter)\n\n    this.events = this.createLifeCycleEvents()\n\n    this.subscriptions.push(() => {\n      this.emitter.removeAllListeners()\n      this.publicEmitter.removeAllListeners()\n    })\n  }\n\n  private validateHandlers(handlers: ReadonlyArray<unknown>): boolean {\n    // Guard against incorrect call signature of the setup API.\n    return handlers.every((handler) => !Array.isArray(handler))\n  }\n\n  public use(\n    ...runtimeHandlers: Array<RequestHandler | WebSocketHandler>\n  ): void {\n    invariant(\n      this.validateHandlers(runtimeHandlers),\n      devUtils.formatMessage(\n        `Failed to call \"use()\" with the given request handlers: invalid input. Did you forget to spread the array of request handlers?`,\n      ),\n    )\n\n    this.handlersController.prepend(runtimeHandlers)\n  }\n\n  public restoreHandlers(): void {\n    this.handlersController.currentHandlers().forEach((handler) => {\n      if ('isUsed' in handler) {\n        handler.isUsed = false\n      }\n    })\n  }\n\n  public resetHandlers(\n    ...nextHandlers: Array<RequestHandler | WebSocketHandler>\n  ): void {\n    this.handlersController.reset(nextHandlers)\n  }\n\n  public listHandlers(): ReadonlyArray<RequestHandler | WebSocketHandler> {\n    return toReadonlyArray(this.handlersController.currentHandlers())\n  }\n\n  private createLifeCycleEvents(): LifeCycleEventEmitter<EventsMap> {\n    return {\n      on: (...args: any[]) => {\n        return (this.publicEmitter.on as any)(...args)\n      },\n      removeListener: (...args: any[]) => {\n        return (this.publicEmitter.removeListener as any)(...args)\n      },\n      removeAllListeners: (...args: any[]) => {\n        return this.publicEmitter.removeAllListeners(...args)\n      },\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/bypass.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { bypass } from './bypass'\n\nit('returns bypassed request given a request url string', async () => {\n  const request = bypass('https://api.example.com/resource')\n\n  // Relative URLs are rebased against the current location.\n  expect(request.method).toBe('GET')\n  expect(request.url).toBe('https://api.example.com/resource')\n  expect(Array.from(request.headers)).toEqual([['accept', 'msw/passthrough']])\n})\n\nit('returns bypassed request given a request url', async () => {\n  const request = bypass(new URL('/resource', 'https://api.example.com'))\n\n  expect(request.url).toBe('https://api.example.com/resource')\n  expect(Array.from(request.headers)).toEqual([['accept', 'msw/passthrough']])\n})\n\nit('returns bypassed request given request instance', async () => {\n  const original = new Request('http://localhost/resource', {\n    method: 'POST',\n    headers: {\n      accept: '*/*',\n      'X-My-Header': 'value',\n    },\n    body: 'hello world',\n  })\n  const request = bypass(original)\n\n  expect(request.method).toBe('POST')\n  expect(request.url).toBe('http://localhost/resource')\n\n  const bypassedRequestBody = await request.text()\n  expect(original.bodyUsed).toBe(false)\n\n  expect(bypassedRequestBody).toEqual(await original.text())\n  expect(Array.from(request.headers)).toEqual([\n    ['accept', '*/*, msw/passthrough'],\n    ['content-type', 'text/plain;charset=UTF-8'],\n    ['x-my-header', 'value'],\n  ])\n})\n\nit('allows modifying the bypassed request instance', async () => {\n  const original = new Request('http://localhost/resource', {\n    method: 'POST',\n    body: 'hello world',\n  })\n  const request = bypass(original, {\n    method: 'PUT',\n    headers: { 'x-modified-header': 'yes' },\n  })\n\n  expect(request.method).toBe('PUT')\n  expect(Array.from(request.headers)).toEqual([\n    ['accept', 'msw/passthrough'],\n    ['x-modified-header', 'yes'],\n  ])\n  expect(original.bodyUsed).toBe(false)\n  expect(request.bodyUsed).toBe(false)\n\n  expect(await request.text()).toBe('hello world')\n  expect(original.bodyUsed).toBe(false)\n})\n\nit('supports bypassing \"keepalive: true\" requests', async () => {\n  const original = new Request('http://localhost/resource', {\n    method: 'POST',\n    keepalive: true,\n  })\n  const request = bypass(original)\n\n  expect(request.method).toBe('POST')\n  expect(request.url).toBe('http://localhost/resource')\n  expect(request.body).toBeNull()\n  expect(Array.from(request.headers)).toEqual([['accept', 'msw/passthrough']])\n})\n"
  },
  {
    "path": "src/core/bypass.ts",
    "content": "import { invariant } from 'outvariant'\n\nexport type BypassRequestInput = string | URL | Request\n\n/**\n * Creates a `Request` instance that will always be ignored by MSW.\n *\n * @example\n * import { bypass } from 'msw'\n *\n * fetch(bypass('/resource'))\n * fetch(bypass(new URL('/resource', 'https://example.com)))\n * fetch(bypass(new Request('https://example.com/resource')))\n *\n * @see {@link https://mswjs.io/docs/api/bypass `bypass()` API reference}\n */\nexport function bypass(input: BypassRequestInput, init?: RequestInit): Request {\n  // Always create a new Request instance.\n  // This way, the \"init\" modifications will propagate\n  // to the bypass request instance automatically.\n  const request = new Request(\n    // If given a Request instance, clone it not to exhaust\n    // the original request's body.\n    input instanceof Request ? input.clone() : input,\n    init,\n  )\n\n  invariant(\n    !request.bodyUsed,\n    'Failed to create a bypassed request to \"%s %s\": given request instance already has its body read. Make sure to clone the intercepted request if you wish to read its body before bypassing it.',\n    request.method,\n    request.url,\n  )\n\n  const requestClone = request.clone()\n\n  /**\n   * Send the internal request header that would instruct MSW\n   * to perform this request as-is, ignoring any matching handlers.\n   * @note Use the `accept` header to support scenarios when the\n   * request cannot have headers (e.g. `sendBeacon` requests).\n   */\n  requestClone.headers.append('accept', 'msw/passthrough')\n\n  return requestClone\n}\n"
  },
  {
    "path": "src/core/delay.ts",
    "content": "import { isNodeProcess } from 'is-node-process'\nimport { hasRefCounted } from './utils/internal/hasRefCounted'\n\nexport const SET_TIMEOUT_MAX_ALLOWED_INT = 2147483647\nexport const MIN_SERVER_RESPONSE_TIME = 100\nexport const MAX_SERVER_RESPONSE_TIME = 400\nexport const NODE_SERVER_RESPONSE_TIME = 5\n\nfunction getRealisticResponseTime(): number {\n  if (isNodeProcess()) {\n    return NODE_SERVER_RESPONSE_TIME\n  }\n\n  return Math.floor(\n    Math.random() * (MAX_SERVER_RESPONSE_TIME - MIN_SERVER_RESPONSE_TIME) +\n      MIN_SERVER_RESPONSE_TIME,\n  )\n}\n\nexport type DelayMode = 'real' | 'infinite'\n\n/**\n * Delays the response by the given duration (ms).\n *\n * @example\n * await delay() // emulate realistic server response time\n * await delay(1200) // delay response by 1200ms\n * await delay('infinite') // delay response infinitely\n *\n * @see {@link https://mswjs.io/docs/api/delay `delay()` API reference}\n */\nexport async function delay(\n  durationOrMode?: DelayMode | number,\n): Promise<void> {\n  let delayTime: number\n\n  if (typeof durationOrMode === 'string') {\n    switch (durationOrMode) {\n      case 'infinite': {\n        // Using `Infinity` as a delay value executes the response timeout immediately.\n        // Instead, use the maximum allowed integer for `setTimeout`.\n        delayTime = SET_TIMEOUT_MAX_ALLOWED_INT\n        break\n      }\n      case 'real': {\n        delayTime = getRealisticResponseTime()\n        break\n      }\n      default: {\n        throw new Error(\n          `Failed to delay a response: unknown delay mode \"${durationOrMode}\". Please make sure you provide one of the supported modes (\"real\", \"infinite\") or a number.`,\n        )\n      }\n    }\n  } else if (typeof durationOrMode === 'undefined') {\n    // Use random realistic server response time when no explicit delay duration was provided.\n    delayTime = getRealisticResponseTime()\n  } else {\n    // Guard against passing values like `Infinity` or `Number.MAX_VALUE`\n    // as the response delay duration. They don't produce the result you may expect.\n    if (durationOrMode > SET_TIMEOUT_MAX_ALLOWED_INT) {\n      throw new Error(\n        `Failed to delay a response: provided delay duration (${durationOrMode}) exceeds the maximum allowed duration for \"setTimeout\" (${SET_TIMEOUT_MAX_ALLOWED_INT}). This will cause the response to be returned immediately. Please use a number within the allowed range to delay the response by exact duration, or consider the \"infinite\" delay mode to delay the response indefinitely.`,\n      )\n    }\n\n    delayTime = durationOrMode\n  }\n\n  return new Promise((resolve) => {\n    const timeoutId = setTimeout(resolve, delayTime)\n\n    if (\n      delayTime === SET_TIMEOUT_MAX_ALLOWED_INT &&\n      isNodeProcess() &&\n      hasRefCounted(timeoutId)\n    ) {\n      // Prevent the process from hanging if this is the only active ref.\n      timeoutId.unref()\n    }\n  })\n}\n"
  },
  {
    "path": "src/core/getResponse.test.ts",
    "content": "// @vitest-environment node\nimport { http } from './http'\nimport { getResponse } from './getResponse'\n\nit('returns undefined given empty headers array', async () => {\n  await expect(\n    getResponse([], new Request('http://localhost/')),\n  ).resolves.toBeUndefined()\n})\n\nit('returns undefined given no matching handlers', async () => {\n  await expect(\n    getResponse(\n      [http.get('/product', () => void 0)],\n      new Request('http://localhost/user'),\n    ),\n  ).resolves.toBeUndefined()\n})\n\nit('returns undefined given a matching handler that returned no response', async () => {\n  await expect(\n    getResponse(\n      [http.get('*/user', () => void 0)],\n      new Request('http://localhost/user'),\n    ),\n  ).resolves.toBeUndefined()\n})\n\nit('returns undefined given a matching handler that returned explicit undefined', async () => {\n  await expect(\n    getResponse(\n      [http.get('*/user', () => undefined)],\n      new Request('http://localhost/user'),\n    ),\n  ).resolves.toBeUndefined()\n})\n\nit('returns the response returned from a matching handler', async () => {\n  const response = await getResponse(\n    [http.get('*/user', () => Response.json({ name: 'John' }))],\n    new Request('http://localhost/user'),\n  )\n\n  expect(response?.status).toBe(200)\n  expect(response?.headers.get('Content-Type')).toBe('application/json')\n  await expect(response?.json()).resolves.toEqual({ name: 'John' })\n})\n\nit('returns the response from the first matching handler if multiple match', async () => {\n  const response = await getResponse(\n    [\n      http.get('*/user', () => Response.json({ name: 'John' })),\n      http.get('*/user', () => Response.json({ name: 'Kate' })),\n    ],\n    new Request('http://localhost/user'),\n  )\n\n  expect(response?.status).toBe(200)\n  expect(response?.headers.get('Content-Type')).toBe('application/json')\n  await expect(response?.json()).resolves.toEqual({ name: 'John' })\n})\n\nit('supports custom base url', async () => {\n  const response = await getResponse(\n    [http.get('/resource', () => new Response('hello world'))],\n    new Request('https://localhost:3000/resource'),\n    {\n      baseUrl: 'https://localhost:3000/',\n    },\n  )\n\n  expect(response?.status).toBe(200)\n  await expect(response?.text()).resolves.toBe('hello world')\n})\n"
  },
  {
    "path": "src/core/getResponse.ts",
    "content": "import { createRequestId } from '@mswjs/interceptors'\nimport type { RequestHandler } from './handlers/RequestHandler'\nimport {\n  executeHandlers,\n  type ResponseResolutionContext,\n} from './utils/executeHandlers'\n\n/**\n * Finds a response for the given request instance\n * in the array of request handlers.\n * @param handlers The array of request handlers.\n * @param request The `Request` instance.\n * @param resolutionContext Request resolution options.\n * @returns {Response} A mocked response, if any.\n */\nexport const getResponse = async (\n  handlers: Array<RequestHandler>,\n  request: Request,\n  resolutionContext?: ResponseResolutionContext,\n): Promise<Response | undefined> => {\n  const result = await executeHandlers({\n    request,\n    requestId: createRequestId(),\n    handlers,\n    resolutionContext,\n  })\n\n  return result?.response\n}\n"
  },
  {
    "path": "src/core/graphql.test.ts",
    "content": "import { graphql } from './graphql'\n\ntest('exports supported GraphQL operation types', () => {\n  expect(graphql).toBeDefined()\n  expect(Object.keys(graphql)).toEqual([\n    'query',\n    'mutation',\n    'operation',\n    'link',\n  ])\n})\n"
  },
  {
    "path": "src/core/graphql.ts",
    "content": "import type { OperationTypeNode } from 'graphql'\nimport {\n  ResponseResolver,\n  RequestHandlerOptions,\n} from './handlers/RequestHandler'\nimport {\n  GraphQLHandler,\n  GraphQLVariables,\n  GraphQLOperationType,\n  GraphQLResolverExtras,\n  GraphQLResponseBody,\n  GraphQLQuery,\n  GraphQLPredicate,\n} from './handlers/GraphQLHandler'\nimport type { Path } from './utils/matching/matchRequestUrl'\n\nexport type GraphQLRequestHandler = <\n  Query extends GraphQLQuery = GraphQLQuery,\n  Variables extends GraphQLVariables = GraphQLVariables,\n>(\n  predicate: GraphQLPredicate<Query, Variables>,\n  resolver: GraphQLResponseResolver<\n    [Query] extends [never] ? GraphQLQuery : Query,\n    Variables\n  >,\n  options?: RequestHandlerOptions,\n) => GraphQLHandler\n\nexport type GraphQLOperationHandler = <\n  Query extends GraphQLQuery = GraphQLQuery,\n  Variables extends GraphQLVariables = GraphQLVariables,\n>(\n  resolver: GraphQLResponseResolver<\n    [Query] extends [never] ? GraphQLQuery : Query,\n    Variables\n  >,\n  options?: RequestHandlerOptions,\n) => GraphQLHandler\n\nexport type GraphQLResponseResolver<\n  Query extends GraphQLQuery = GraphQLQuery,\n  Variables extends GraphQLVariables = GraphQLVariables,\n> = ResponseResolver<\n  GraphQLResolverExtras<Variables>,\n  null,\n  GraphQLResponseBody<[Query] extends [never] ? GraphQLQuery : Query>\n>\n\nfunction createScopedGraphQLHandler(\n  operationType: GraphQLOperationType,\n  url: Path,\n): GraphQLRequestHandler {\n  return (predicate, resolver, options = {}) => {\n    return new GraphQLHandler(operationType, predicate, url, resolver, options)\n  }\n}\n\nfunction createGraphQLOperationHandler(url: Path): GraphQLOperationHandler {\n  return (resolver, options) => {\n    return new GraphQLHandler('all', new RegExp('.*'), url, resolver, options)\n  }\n}\n\nexport interface GraphQLLinkHandlers {\n  query: GraphQLRequestHandler\n  mutation: GraphQLRequestHandler\n  operation: GraphQLOperationHandler\n}\n\n/**\n * A namespace to intercept and mock GraphQL operations\n *\n * @example\n * graphql.query('GetUser', resolver)\n * graphql.mutation('DeletePost', resolver)\n *\n * @see {@link https://mswjs.io/docs/api/graphql `graphql` API reference}\n */\nexport const graphql = {\n  /**\n   * Intercepts a GraphQL query by a given name.\n   *\n   * @example\n   * graphql.query('GetUser', () => {\n   *   return HttpResponse.json({ data: { user: { name: 'John' } } })\n   * })\n   *\n   * @see {@link https://mswjs.io/docs/api/graphql#graphqlqueryqueryname-resolver `graphql.query()` API reference}\n   */\n  query: createScopedGraphQLHandler('query' as OperationTypeNode, '*'),\n\n  /**\n   * Intercepts a GraphQL mutation by its name.\n   *\n   * @example\n   * graphql.mutation('SavePost', () => {\n   *   return HttpResponse.json({ data: { post: { id: 'abc-123 } } })\n   * })\n   *\n   * @see {@link https://mswjs.io/docs/api/graphql#graphqlmutationmutationname-resolver `graphql.query()` API reference}\n   *\n   */\n  mutation: createScopedGraphQLHandler('mutation' as OperationTypeNode, '*'),\n\n  /**\n   * Intercepts any GraphQL operation, regardless of its type or name.\n   *\n   * @example\n   * graphql.operation(() => {\n   *   return HttpResponse.json({ data: { name: 'John' } })\n   * })\n   *\n   * @see {@link https://mswjs.io/docs/api/graphql#graphqloperationresolver `graphql.operation()` API reference}\n   */\n  operation: createGraphQLOperationHandler('*'),\n\n  /**\n   * Intercepts GraphQL operations scoped by the given URL.\n   *\n   * @example\n   * const github = graphql.link('https://api.github.com/graphql')\n   * github.query('GetRepo', resolver)\n   *\n   * @see {@link https://mswjs.io/docs/api/graphql#graphqllinkurl `graphql.link()` API reference}\n   */\n  link(url: Path): GraphQLLinkHandlers {\n    return {\n      operation: createGraphQLOperationHandler(url),\n      query: createScopedGraphQLHandler('query' as OperationTypeNode, url),\n      mutation: createScopedGraphQLHandler(\n        'mutation' as OperationTypeNode,\n        url,\n      ),\n    }\n  },\n}\n"
  },
  {
    "path": "src/core/handlers/GraphQLHandler.test.ts",
    "content": "// @vitest-environment jsdom\nimport { createRequestId, encodeBuffer } from '@mswjs/interceptors'\nimport { OperationTypeNode, parse } from 'graphql'\nimport {\n  GraphQLHandler,\n  GraphQLRequestBody,\n  GraphQLResolverExtras,\n  isDocumentNode,\n} from './GraphQLHandler'\nimport { HttpResponse } from '../HttpResponse'\nimport { ResponseResolver } from './RequestHandler'\n\nconst resolver: ResponseResolver<GraphQLResolverExtras<{ userId: string }>> = ({\n  variables,\n}) => {\n  return HttpResponse.json({\n    data: {\n      user: {\n        id: variables.userId,\n      },\n    },\n  })\n}\n\nfunction createGetGraphQLRequest(\n  body: GraphQLRequestBody<any>,\n  graphqlEndpoint = 'https://example.com',\n) {\n  const requestUrl = new URL(graphqlEndpoint)\n  requestUrl.searchParams.set('query', body?.query)\n  requestUrl.searchParams.set('variables', JSON.stringify(body?.variables))\n  return new Request(requestUrl)\n}\n\nfunction createPostGraphQLRequest(\n  body: GraphQLRequestBody<any>,\n  graphqlEndpoint = 'https://example.com',\n) {\n  return new Request(new URL(graphqlEndpoint), {\n    method: 'POST',\n    headers: new Headers({ 'Content-Type': 'application/json' }),\n    body: encodeBuffer(JSON.stringify(body)),\n  })\n}\n\nconst GET_USER = `\n  query GetUser {\n    user {\n      id\n    }\n  }\n`\n\nconst LOGIN = `\n  mutation Login {\n    user {\n      id\n    }\n  }\n`\n\ndescribe('info', () => {\n  it('exposes request handler information for query', () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n\n    expect(handler.info.header).toEqual('query GetUser (origin: *)')\n    expect(handler.info.operationType).toEqual('query')\n    expect(handler.info.operationName).toEqual('GetUser')\n  })\n\n  it('exposes request handler information for mutation', () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.MUTATION,\n      'Login',\n      '*',\n      resolver,\n    )\n\n    expect(handler.info.header).toEqual('mutation Login (origin: *)')\n    expect(handler.info.operationType).toEqual('mutation')\n    expect(handler.info.operationName).toEqual('Login')\n  })\n\n  it('parses a query operation name from a given DocumentNode', () => {\n    const node = parse(`\n      query GetUser {\n        user {\n          firstName\n        }\n      }\n    `)\n\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      node,\n      '*',\n      resolver,\n    )\n\n    expect(handler.info).toHaveProperty('header', 'query GetUser (origin: *)')\n    expect(handler.info).toHaveProperty('operationType', 'query')\n    expect(handler.info).toHaveProperty('operationName', 'GetUser')\n  })\n\n  it('parses a mutation operation name from a given DocumentNode', () => {\n    const node = parse(`\n      mutation Login {\n        user {\n          id\n        }\n      }\n    `)\n    const handler = new GraphQLHandler(\n      OperationTypeNode.MUTATION,\n      node,\n      '*',\n      resolver,\n    )\n\n    expect(handler.info).toHaveProperty('header', 'mutation Login (origin: *)')\n    expect(handler.info).toHaveProperty('operationType', 'mutation')\n    expect(handler.info).toHaveProperty('operationName', 'Login')\n  })\n\n  it('throws an exception given a DocumentNode with a mismatched operation type', () => {\n    const node = parse(`\n      mutation CreateUser {\n        user {\n          firstName\n        }\n      }\n    `)\n\n    expect(\n      () => new GraphQLHandler(OperationTypeNode.QUERY, node, '*', resolver),\n    ).toThrow(\n      'Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected \"query\" but got \"mutation\").',\n    )\n  })\n})\n\ndescribe('parse', () => {\n  describe('query', () => {\n    it('parses a query without variables (GET)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createGetGraphQLRequest({\n        query: GET_USER,\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: undefined,\n      })\n    })\n\n    it('parses a query with variables (GET)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createGetGraphQLRequest({\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n    })\n\n    it('parses a query without variables (POST)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createPostGraphQLRequest({\n        query: GET_USER,\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: undefined,\n      })\n    })\n\n    it('parses a query with variables (POST)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createPostGraphQLRequest({\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n    })\n  })\n\n  describe('mutation', () => {\n    it('parses a mutation without variables (GET)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.MUTATION,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createGetGraphQLRequest({\n        query: LOGIN,\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'mutation',\n        operationName: 'Login',\n        query: LOGIN,\n        variables: undefined,\n      })\n    })\n\n    it('parses a mutation with variables (GET)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.MUTATION,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createGetGraphQLRequest({\n        query: LOGIN,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'mutation',\n        operationName: 'Login',\n        query: LOGIN,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n    })\n\n    it('parses a mutation without variables (POST)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.MUTATION,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createPostGraphQLRequest({\n        query: LOGIN,\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'mutation',\n        operationName: 'Login',\n        query: LOGIN,\n        variables: undefined,\n      })\n    })\n\n    it('parses a mutation with variables (POST)', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.MUTATION,\n        'GetUser',\n        '*',\n        resolver,\n      )\n      const request = createPostGraphQLRequest({\n        query: LOGIN,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n\n      expect(await handler.parse({ request })).toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {\n            '0': 'https://example.com/',\n          },\n        },\n        operationType: 'mutation',\n        operationName: 'Login',\n        query: LOGIN,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n    })\n  })\n\n  describe('with endpoint configuration', () => {\n    it('parses the request and parses grapqhl properties from it when the graphql.link endpoint matches', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        'https://mswjs.com/graphql',\n        resolver,\n      )\n\n      await expect(\n        handler.parse({\n          request: createGetGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://mswjs.com/graphql',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {},\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n\n      await expect(\n        handler.parse({\n          request: createPostGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://mswjs.com/graphql',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: true,\n          params: {},\n        },\n        operationType: 'query',\n        operationName: 'GetUser',\n        query: GET_USER,\n        variables: {\n          userId: 'abc-123',\n        },\n      })\n    })\n\n    it('parses a request but does not parse graphql properties from it graphql.link hostname does not match', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        'https://mswjs.com/graphql',\n        resolver,\n      )\n\n      await expect(\n        handler.parse({\n          request: createGetGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://example.com/graphql',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: false,\n          params: {},\n        },\n      })\n\n      await expect(\n        handler.parse({\n          request: createPostGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://example.com/graphql',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: false,\n          params: {},\n        },\n      })\n    })\n\n    it('parses a request but does not parse graphql properties from it graphql.link pathname does not match', async () => {\n      const handler = new GraphQLHandler(\n        OperationTypeNode.QUERY,\n        'GetUser',\n        'https://mswjs.com/graphql',\n        resolver,\n      )\n\n      await expect(\n        handler.parse({\n          request: createGetGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://mswjs.com/some/other/endpoint',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: false,\n          params: {},\n        },\n      })\n\n      await expect(\n        handler.parse({\n          request: createPostGraphQLRequest(\n            {\n              query: GET_USER,\n              variables: {\n                userId: 'abc-123',\n              },\n            },\n            'https://mswjs.com/some/other/endpoint',\n          ),\n        }),\n      ).resolves.toEqual({\n        cookies: {},\n        match: {\n          matches: false,\n          params: {},\n        },\n      })\n    })\n  })\n})\n\ndescribe('predicate', () => {\n  it('respects operation type', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n    const alienRequest = createPostGraphQLRequest({\n      query: LOGIN,\n    })\n\n    expect(\n      await handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).toBe(true)\n    expect(\n      await handler.predicate({\n        request: alienRequest,\n        parsedResult: await handler.parse({ request: alienRequest }),\n      }),\n    ).toBe(false)\n  })\n\n  it('respects operation name', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n    const alienRequest = createPostGraphQLRequest({\n      query: `\n          query GetAllUsers {\n            user {\n              id\n            }\n          }\n        `,\n    })\n\n    await expect(\n      handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).resolves.toBe(true)\n    await expect(\n      handler.predicate({\n        request: alienRequest,\n        parsedResult: await handler.parse({ request: alienRequest }),\n      }),\n    ).resolves.toBe(false)\n  })\n\n  it('allows anonymous GraphQL operations when using \"all\" expected operation type', async () => {\n    const handler = new GraphQLHandler('all', new RegExp('.*'), '*', resolver)\n    const request = createPostGraphQLRequest({\n      query: `\n        query {\n          anonymousQuery {\n            query\n            variables\n          }\n        }\n      `,\n    })\n\n    await expect(\n      handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).resolves.toBe(true)\n  })\n\n  it('respects custom endpoint', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      'https://api.github.com/graphql',\n      resolver,\n    )\n    const request = createPostGraphQLRequest(\n      {\n        query: GET_USER,\n      },\n      'https://api.github.com/graphql',\n    )\n    const alienRequest = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n\n    await expect(\n      handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).resolves.toBe(true)\n    await expect(\n      handler.predicate({\n        request: alienRequest,\n        parsedResult: await handler.parse({ request: alienRequest }),\n      }),\n    ).resolves.toBe(false)\n  })\n\n  it('supports custom predicate function', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      ({ query }) => {\n        return query.includes('password')\n      },\n      /.+/,\n      resolver,\n    )\n\n    {\n      const request = createPostGraphQLRequest({\n        query: `query GetUser { user { password } }`,\n      })\n\n      await expect(\n        handler.predicate({\n          request,\n          parsedResult: await handler.parse({ request }),\n        }),\n      ).resolves.toBe(true)\n    }\n\n    {\n      const request = createPostGraphQLRequest({\n        query: `query GetUser { user { nonMatching } }`,\n      })\n\n      await expect(\n        handler.predicate({\n          request,\n          parsedResult: await handler.parse({ request }),\n        }),\n      ).resolves.toBe(false)\n    }\n  })\n})\n\ndescribe('test', () => {\n  it('respects operation type', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n    const alienRequest = createPostGraphQLRequest({\n      query: LOGIN,\n    })\n\n    expect(await handler.test({ request })).toBe(true)\n    expect(await handler.test({ request: alienRequest })).toBe(false)\n  })\n\n  it('respects operation name', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n    const alienRequest = createPostGraphQLRequest({\n      query: `\n          query GetAllUsers {\n            user {\n              id\n            }\n          }\n        `,\n    })\n\n    await expect(handler.test({ request })).resolves.toBe(true)\n    await expect(handler.test({ request: alienRequest })).resolves.toBe(false)\n  })\n\n  it('respects custom endpoint', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      'https://api.github.com/graphql',\n      resolver,\n    )\n    const request = createPostGraphQLRequest(\n      {\n        query: GET_USER,\n      },\n      'https://api.github.com/graphql',\n    )\n    const alienRequest = createPostGraphQLRequest({\n      query: GET_USER,\n    })\n\n    await expect(handler.test({ request })).resolves.toBe(true)\n    await expect(handler.test({ request: alienRequest })).resolves.toBe(false)\n  })\n})\n\ndescribe('run', () => {\n  it('returns a mocked response given a matching query', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: GET_USER,\n      variables: {\n        userId: 'abc-123',\n      },\n    })\n    const requestId = createRequestId()\n    const result = await handler.run({ request, requestId })\n\n    expect(result!.handler).toEqual(handler)\n    expect(result!.parsedResult).toEqual({\n      cookies: {},\n      match: {\n        matches: true,\n        params: {\n          '0': 'https://example.com/',\n        },\n      },\n      operationType: 'query',\n      operationName: 'GetUser',\n      query: GET_USER,\n      variables: {\n        userId: 'abc-123',\n      },\n    })\n    expect(result!.request.method).toBe('POST')\n    expect(result!.request.url).toBe('https://example.com/')\n    await expect(result!.request.json()).resolves.toEqual({\n      query: GET_USER,\n      variables: { userId: 'abc-123' },\n    })\n    expect(result!.response?.status).toBe(200)\n    expect(result!.response?.statusText).toBe('OK')\n    await expect(result!.response?.json()).resolves.toEqual({\n      data: { user: { id: 'abc-123' } },\n    })\n  })\n\n  it('returns null given a non-matching query', async () => {\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      'GetUser',\n      '*',\n      resolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: LOGIN,\n    })\n    const requestId = createRequestId()\n    const result = await handler.run({ request, requestId })\n\n    expect(result).toBeNull()\n  })\n})\n\ndescribe('isDocumentNode', () => {\n  it('returns true given a valid DocumentNode', () => {\n    const node = parse(`\n      query GetUser {\n        user {\n          login\n        }\n      }\n    `)\n\n    expect(isDocumentNode(node)).toEqual(true)\n  })\n\n  it('returns false given an arbitrary input', () => {\n    expect(isDocumentNode(null)).toEqual(false)\n    expect(isDocumentNode(undefined)).toEqual(false)\n    expect(isDocumentNode('')).toEqual(false)\n    expect(isDocumentNode('value')).toEqual(false)\n    expect(isDocumentNode(/value/)).toEqual(false)\n  })\n})\n\ndescribe('request', () => {\n  it('has parsed operationName', async () => {\n    const matchAllResolver = vi.fn()\n    const handler = new GraphQLHandler(\n      OperationTypeNode.QUERY,\n      /.*/,\n      '*',\n      matchAllResolver,\n    )\n    const request = createPostGraphQLRequest({\n      query: `\n        query GetAllUsers {\n          user {\n            id\n          }\n        }\n      `,\n    })\n\n    const requestId = createRequestId()\n    await handler.run({ request, requestId })\n\n    expect(matchAllResolver).toHaveBeenCalledTimes(1)\n    expect(matchAllResolver.mock.calls[0][0]).toHaveProperty(\n      'operationName',\n      'GetAllUsers',\n    )\n  })\n})\n"
  },
  {
    "path": "src/core/handlers/GraphQLHandler.ts",
    "content": "import { invariant } from 'outvariant'\nimport {\n  parse,\n  type DocumentNode,\n  type GraphQLError,\n  type OperationTypeNode,\n} from 'graphql'\nimport {\n  DefaultBodyType,\n  RequestHandler,\n  RequestHandlerDefaultInfo,\n  RequestHandlerExecutionResult,\n  RequestHandlerOptions,\n  ResponseResolver,\n} from './RequestHandler'\nimport { getTimestamp } from '../utils/logging/getTimestamp'\nimport { getStatusCodeColor } from '../utils/logging/getStatusCodeColor'\nimport { serializeRequest } from '../utils/logging/serializeRequest'\nimport { serializeResponse } from '../utils/logging/serializeResponse'\nimport { Match, matchRequestUrl, Path } from '../utils/matching/matchRequestUrl'\nimport {\n  ParsedGraphQLRequest,\n  GraphQLMultipartRequestBody,\n  parseGraphQLRequest,\n  parseDocumentNode,\n  ParsedGraphQLQuery,\n} from '../utils/internal/parseGraphQLRequest'\nimport { toPublicUrl } from '../utils/request/toPublicUrl'\nimport { devUtils } from '../utils/internal/devUtils'\nimport { getAllRequestCookies } from '../utils/request/getRequestCookies'\nimport { ResponseResolutionContext } from 'src/iife'\nimport { kDefaultContentType, StrictRequest } from '../HttpResponse'\nimport { getAllAcceptedMimeTypes } from '../utils/request/getAllAcceptedMimeTypes'\n\nexport interface DocumentTypeDecoration<\n  Result = { [key: string]: any },\n  Variables = { [key: string]: any },\n> {\n  __apiType?: (variables: Variables) => Result\n  __resultType?: Result\n  __variablesType?: Variables\n}\n\nexport type GraphQLOperationType = OperationTypeNode | 'all'\nexport type GraphQLHandlerNameSelector = DocumentNode | RegExp | string\n\nexport type GraphQLQuery = Record<string, any> | null\nexport type GraphQLVariables = Record<string, any>\n\nexport interface GraphQLHandlerInfo extends RequestHandlerDefaultInfo {\n  operationType: GraphQLOperationType\n  operationName: GraphQLHandlerNameSelector | GraphQLCustomPredicate\n}\n\nexport type GraphQLRequestParsedResult = {\n  match: Match\n  cookies: Record<string, string>\n} & (\n  | ParsedGraphQLRequest<GraphQLVariables>\n  /**\n   * An empty version of the ParsedGraphQLRequest\n   * which simplifies the return type of the resolver\n   * when the request is to a non-matching endpoint\n   */\n  | {\n      operationType?: undefined\n      operationName?: undefined\n      query?: undefined\n      variables?: undefined\n    }\n)\n\nexport type GraphQLResolverExtras<Variables extends GraphQLVariables> = {\n  query: string\n  operationName: string\n  variables: Variables\n  cookies: Record<string, string>\n}\n\nexport type GraphQLRequestBody<VariablesType extends GraphQLVariables> =\n  | GraphQLJsonRequestBody<VariablesType>\n  | GraphQLMultipartRequestBody\n  | Record<string, any>\n  | undefined\n\nexport interface GraphQLJsonRequestBody<Variables extends GraphQLVariables> {\n  query: string\n  variables?: Variables\n}\n\nexport type GraphQLResponseBody<BodyType extends DefaultBodyType> =\n  | {\n      data?: BodyType | null\n      errors?: readonly Partial<GraphQLError>[] | null\n      extensions?: Record<string, any>\n    }\n  | null\n  | undefined\n\nexport type GraphQLCustomPredicate = (args: {\n  request: Request\n  query: string\n  operationType: GraphQLOperationType\n  operationName: string\n  variables: GraphQLVariables\n  cookies: Record<string, string>\n}) => GraphQLCustomPredicateResult | Promise<GraphQLCustomPredicateResult>\n\nexport type GraphQLCustomPredicateResult = boolean | { matches: boolean }\n\nexport type GraphQLPredicate<Query = any, Variables = any> =\n  | GraphQLHandlerNameSelector\n  | DocumentTypeDecoration<Query, Variables>\n  | GraphQLCustomPredicate\n\nexport function isDocumentNode(\n  value: DocumentNode | any,\n): value is DocumentNode {\n  if (value == null) {\n    return false\n  }\n\n  return typeof value === 'object' && 'kind' in value && 'definitions' in value\n}\n\nfunction isDocumentTypeDecoration(\n  value: unknown,\n): value is DocumentTypeDecoration<any, any> {\n  return value instanceof String\n}\n\nexport class GraphQLHandler extends RequestHandler<\n  GraphQLHandlerInfo,\n  GraphQLRequestParsedResult,\n  GraphQLResolverExtras<any>\n> {\n  private endpoint: Path\n\n  static parsedRequestCache = new WeakMap<\n    Request,\n    ParsedGraphQLRequest<GraphQLVariables>\n  >()\n\n  static #parseOperationName(\n    predicate: GraphQLPredicate,\n    operationType: GraphQLOperationType,\n  ): GraphQLHandlerInfo['operationName'] {\n    const getOperationName = (node: ParsedGraphQLQuery): string => {\n      invariant(\n        node.operationType === operationType,\n        'Failed to create a GraphQL handler: provided a DocumentNode with a mismatched operation type (expected \"%s\" but got \"%s\").',\n        operationType,\n        node.operationType,\n      )\n\n      invariant(\n        node.operationName,\n        'Failed to create a GraphQL handler: provided a DocumentNode without operation name',\n      )\n\n      return node.operationName\n    }\n\n    if (isDocumentNode(predicate)) {\n      return getOperationName(parseDocumentNode(predicate))\n    }\n\n    if (isDocumentTypeDecoration(predicate)) {\n      const documentNode = parse(predicate.toString())\n\n      invariant(\n        isDocumentNode(documentNode),\n        'Failed to create a GraphQL handler: given TypedDocumentString (%s) does not produce a valid DocumentNode',\n        predicate,\n      )\n\n      return getOperationName(parseDocumentNode(documentNode))\n    }\n\n    return predicate\n  }\n\n  constructor(\n    operationType: GraphQLOperationType,\n    predicate: GraphQLPredicate,\n    endpoint: Path,\n    resolver: ResponseResolver<GraphQLResolverExtras<any>, any, any>,\n    options?: RequestHandlerOptions,\n  ) {\n    const operationName = GraphQLHandler.#parseOperationName(\n      predicate,\n      operationType,\n    )\n\n    const displayOperationName =\n      typeof operationName === 'function' ? '[custom predicate]' : operationName\n\n    const header =\n      operationType === 'all'\n        ? `${operationType} (origin: ${endpoint.toString()})`\n        : `${operationType}${displayOperationName ? ` ${displayOperationName}` : ''} (origin: ${endpoint.toString()})`\n\n    super({\n      info: {\n        header,\n        operationType,\n        operationName: GraphQLHandler.#parseOperationName(\n          predicate,\n          operationType,\n        ),\n      },\n      resolver,\n      options,\n    })\n\n    this.endpoint = endpoint\n  }\n\n  /**\n   * Parses the request body, once per request, cached across all\n   * GraphQL handlers. This is done to avoid multiple parsing of the\n   * request body, which each requires a clone of the request.\n   */\n  async parseGraphQLRequestOrGetFromCache(\n    request: Request,\n  ): Promise<ParsedGraphQLRequest<GraphQLVariables>> {\n    if (!GraphQLHandler.parsedRequestCache.has(request)) {\n      GraphQLHandler.parsedRequestCache.set(\n        request,\n        await parseGraphQLRequest(request).catch((error) => {\n          console.error(error)\n          return undefined\n        }),\n      )\n    }\n\n    return GraphQLHandler.parsedRequestCache.get(request)\n  }\n\n  async parse(args: { request: Request }): Promise<GraphQLRequestParsedResult> {\n    /**\n     * If the request doesn't match a specified endpoint, there's no\n     * need to parse it since there's no case where we would handle this\n     */\n    const match = matchRequestUrl(new URL(args.request.url), this.endpoint)\n    const cookies = getAllRequestCookies(args.request)\n\n    if (!match.matches) {\n      return {\n        match,\n        cookies,\n      }\n    }\n\n    const parsedResult = await this.parseGraphQLRequestOrGetFromCache(\n      args.request,\n    )\n\n    if (typeof parsedResult === 'undefined') {\n      return {\n        match,\n        cookies,\n      }\n    }\n\n    return {\n      match,\n      cookies,\n      query: parsedResult.query,\n      operationType: parsedResult.operationType,\n      operationName: parsedResult.operationName,\n      variables: parsedResult.variables,\n    }\n  }\n\n  async predicate(args: {\n    request: Request\n    parsedResult: GraphQLRequestParsedResult\n  }): Promise<boolean> {\n    if (args.parsedResult.operationType === undefined) {\n      return false\n    }\n\n    if (!args.parsedResult.operationName && this.info.operationType !== 'all') {\n      const publicUrl = toPublicUrl(args.request.url)\n\n      devUtils.warn(`\\\nFailed to intercept a GraphQL request at \"${args.request.method} ${publicUrl}\": anonymous GraphQL operations are not supported.\n\nConsider naming this operation or using \"graphql.operation()\" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/#graphqloperationresolver`)\n      return false\n    }\n\n    const hasMatchingOperationType =\n      this.info.operationType === 'all' ||\n      args.parsedResult.operationType === this.info.operationType\n\n    /**\n     * Check if the operation name matches the outgoing GraphQL request.\n     * @note Unlike the HTTP handler, the custom predicate functions are invoked\n     * during predicate, not parsing, because GraphQL request parsing happens first,\n     * and non-GraphQL requests are filtered out automatically.\n     */\n    const hasMatchingOperationName = await this.matchOperationName({\n      request: args.request,\n      parsedResult: args.parsedResult,\n    })\n\n    return (\n      args.parsedResult.match.matches &&\n      hasMatchingOperationType &&\n      hasMatchingOperationName\n    )\n  }\n\n  public async run(args: {\n    request: StrictRequest<any>\n    requestId: string\n    resolutionContext?: ResponseResolutionContext\n  }): Promise<RequestHandlerExecutionResult<GraphQLRequestParsedResult> | null> {\n    const result = await super.run(args)\n\n    if (result?.response == null) {\n      return result\n    }\n\n    if (!(kDefaultContentType in result.response)) {\n      return result\n    }\n\n    const acceptedMimeTypes = getAllAcceptedMimeTypes(\n      args.request.headers.get('accept'),\n    )\n\n    if (acceptedMimeTypes.length === 0) {\n      return result\n    }\n\n    const graphqlResponseIndex = acceptedMimeTypes.indexOf(\n      'application/graphql-response+json',\n    )\n    const jsonIndex = acceptedMimeTypes.indexOf('application/json')\n\n    /**\n     * Use the \"application/graphql-response+json\" response content type\n     * only when the client accepts it AND prefers it over \"application/json\"\n     * (i.e. it appears earlier in the precedence-sorted list, or \"application/json\"\n     * is not listed at all).\n     * @see https://github.com/graphql/graphql-over-http/blob/4d1df1fb829ec2dd3ecbf3c6aa4025bd356c270d/spec/GraphQLOverHTTP.md#accept\n     */\n    if (\n      graphqlResponseIndex !== -1 &&\n      (jsonIndex === -1 || graphqlResponseIndex <= jsonIndex)\n    ) {\n      result.response.headers.set(\n        'content-type',\n        'application/graphql-response+json',\n      )\n    }\n\n    return result\n  }\n\n  private async matchOperationName(args: {\n    request: Request\n    parsedResult: GraphQLRequestParsedResult\n  }): Promise<boolean> {\n    if (typeof this.info.operationName === 'function') {\n      const customPredicateResult = await this.info.operationName({\n        request: args.request,\n        ...this.extendResolverArgs({\n          request: args.request,\n          parsedResult: args.parsedResult,\n        }),\n      })\n\n      /**\n       * @note Keep the { matches } signature in case we decide to support path parameters\n       * in GraphQL handlers. If that happens, the custom predicate would have to be moved\n       * to the parsing phase, the same as we have for the HttpHandler, and the user will\n       * have a possibility to return parsed path parameters from the custom predicate.\n       */\n      return typeof customPredicateResult === 'boolean'\n        ? customPredicateResult\n        : customPredicateResult.matches\n    }\n\n    if (this.info.operationName instanceof RegExp) {\n      return this.info.operationName.test(args.parsedResult.operationName || '')\n    }\n\n    return args.parsedResult.operationName === this.info.operationName\n  }\n\n  protected extendResolverArgs(args: {\n    request: Request\n    parsedResult: GraphQLRequestParsedResult\n  }) {\n    return {\n      query: args.parsedResult.query || '',\n      operationType: args.parsedResult.operationType!,\n      operationName: args.parsedResult.operationName || '',\n      variables: args.parsedResult.variables || {},\n      cookies: args.parsedResult.cookies,\n    }\n  }\n\n  async log(args: {\n    request: Request\n    response: Response\n    parsedResult: GraphQLRequestParsedResult\n  }) {\n    const loggedRequest = await serializeRequest(args.request)\n    const loggedResponse = await serializeResponse(args.response)\n    const statusColor = getStatusCodeColor(loggedResponse.status)\n    const requestInfo = args.parsedResult.operationName\n      ? `${args.parsedResult.operationType} ${args.parsedResult.operationName}`\n      : `anonymous ${args.parsedResult.operationType}`\n\n    console.groupCollapsed(\n      devUtils.formatMessage(\n        `${getTimestamp()} ${requestInfo} (%c${loggedResponse.status} ${\n          loggedResponse.statusText\n        }%c)`,\n      ),\n      `color:${statusColor}`,\n      'color:inherit',\n    )\n    // eslint-disable-next-line no-console\n    console.log('Request:', loggedRequest)\n    // eslint-disable-next-line no-console\n    console.log('Handler:', this)\n    // eslint-disable-next-line no-console\n    console.log('Response:', loggedResponse)\n    console.groupEnd()\n  }\n}\n"
  },
  {
    "path": "src/core/handlers/HttpHandler.test.ts",
    "content": "// @vitest-environment jsdom\nimport { createRequestId } from '@mswjs/interceptors'\nimport { HttpHandler, HttpRequestResolverExtras } from './HttpHandler'\nimport { HttpResponse } from '..'\nimport { ResponseResolver } from './RequestHandler'\n\nconst resolver: ResponseResolver<\n  HttpRequestResolverExtras<{ userId: string }>\n> = ({ params }) => {\n  return HttpResponse.json({ userId: params.userId })\n}\n\ndescribe('info', () => {\n  it('exposes request handler information', () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n\n    expect(handler.info.header).toEqual('GET /user/:userId')\n    expect(handler.info.method).toEqual('GET')\n    expect(handler.info.path).toEqual('/user/:userId')\n    expect(handler.isUsed).toBe(false)\n  })\n})\n\ndescribe('parse', () => {\n  it('parses a URL given a matching request', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const request = new Request(new URL('/user/abc-123', location.href))\n\n    expect(await handler.parse({ request })).toEqual({\n      match: {\n        matches: true,\n        params: {\n          userId: 'abc-123',\n        },\n      },\n      cookies: {},\n    })\n  })\n\n  it('parses a URL and ignores the request method', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const request = new Request(new URL('/user/def-456', location.href), {\n      method: 'POST',\n    })\n\n    expect(await handler.parse({ request })).toEqual({\n      match: {\n        matches: true,\n        params: {\n          userId: 'def-456',\n        },\n      },\n      cookies: {},\n    })\n  })\n\n  it('returns negative match result given a non-matching request', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const request = new Request(new URL('/login', location.href))\n\n    expect(await handler.parse({ request })).toEqual({\n      match: {\n        matches: false,\n        params: {},\n      },\n      cookies: {},\n    })\n  })\n})\n\ndescribe('predicate', () => {\n  it('returns true given a matching request', async () => {\n    const handler = new HttpHandler('POST', '/login', resolver)\n    const request = new Request(new URL('/login', location.href), {\n      method: 'POST',\n    })\n\n    await expect(\n      handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).resolves.toBe(true)\n  })\n\n  it('supports RegExp as the request method', async () => {\n    const handler = new HttpHandler(/.+/, '/login', resolver)\n    const requests = [\n      new Request(new URL('/login', location.href)),\n      new Request(new URL('/login', location.href), { method: 'POST' }),\n      new Request(new URL('/login', location.href), { method: 'DELETE' }),\n    ]\n\n    for (const request of requests) {\n      await expect(\n        handler.predicate({\n          request,\n          parsedResult: await handler.parse({ request }),\n        }),\n      ).resolves.toBe(true)\n    }\n  })\n\n  it('returns false given a non-matching request', async () => {\n    const handler = new HttpHandler('POST', '/login', resolver)\n    const request = new Request(new URL('/user/abc-123', location.href))\n\n    await expect(\n      handler.predicate({\n        request,\n        parsedResult: await handler.parse({ request }),\n      }),\n    ).resolves.toBe(false)\n  })\n\n  it('supports custom predicate function', async () => {\n    const handler = new HttpHandler(\n      'GET',\n      ({ request }) => {\n        return new URL(request.url).searchParams.get('a') === '1'\n      },\n      resolver,\n    )\n\n    {\n      const request = new Request(new URL('/login?a=1', location.href))\n      await expect(\n        handler.predicate({\n          request,\n          parsedResult: await handler.parse({ request }),\n        }),\n      ).resolves.toBe(true)\n    }\n\n    {\n      const request = new Request(new URL('/login', location.href))\n      await expect(\n        handler.predicate({\n          request,\n          parsedResult: await handler.parse({ request }),\n        }),\n      ).resolves.toBe(false)\n    }\n  })\n})\n\ndescribe('test', () => {\n  it('returns true given a matching request', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const firstTest = await handler.test({\n      request: new Request(new URL('/user/abc-123', location.href)),\n    })\n    const secondTest = await handler.test({\n      request: new Request(new URL('/user/def-456', location.href)),\n    })\n\n    expect(firstTest).toBe(true)\n    expect(secondTest).toBe(true)\n  })\n\n  it('returns false given a non-matching request', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const firstTest = await handler.test({\n      request: new Request(new URL('/login', location.href)),\n    })\n    const secondTest = await handler.test({\n      request: new Request(new URL('/user/', location.href)),\n    })\n    const thirdTest = await handler.test({\n      request: new Request(new URL('/user/abc-123/extra', location.href)),\n    })\n\n    expect(firstTest).toBe(false)\n    expect(secondTest).toBe(false)\n    expect(thirdTest).toBe(false)\n  })\n})\n\ndescribe('run', () => {\n  it('returns a mocked response given a matching request', async () => {\n    const handler = new HttpHandler('GET', '/user/:userId', resolver)\n    const request = new Request(new URL('/user/abc-123', location.href))\n    const requestId = createRequestId()\n    const result = await handler.run({ request, requestId })\n\n    expect(result!.handler).toEqual(handler)\n    expect(result!.parsedResult).toEqual({\n      match: {\n        matches: true,\n        params: {\n          userId: 'abc-123',\n        },\n      },\n      cookies: {},\n    })\n    expect(result!.request.method).toBe('GET')\n    expect(result!.request.url).toBe('http://localhost/user/abc-123')\n    expect(result!.response?.status).toBe(200)\n    expect(result!.response?.statusText).toBe('OK')\n    await expect(result?.response?.json()).resolves.toEqual({\n      userId: 'abc-123',\n    })\n  })\n\n  it('returns null given a non-matching request', async () => {\n    const handler = new HttpHandler('POST', '/login', resolver)\n    const result = await handler.run({\n      request: new Request(new URL('/users', location.href)),\n      requestId: createRequestId(),\n    })\n\n    expect(result).toBeNull()\n  })\n\n  it('returns an empty \"params\" object given request with no URL parameters', async () => {\n    const handler = new HttpHandler('GET', '/users', resolver)\n    const result = await handler.run({\n      request: new Request(new URL('/users', location.href)),\n      requestId: createRequestId(),\n    })\n\n    expect(result?.parsedResult?.match?.params).toEqual({})\n  })\n\n  it('exhausts resolver until its generator completes', async () => {\n    const handler = new HttpHandler('GET', '/users', function* () {\n      let count = 0\n\n      while (count < 5) {\n        count += 1\n        yield HttpResponse.text('pending')\n      }\n\n      return HttpResponse.text('complete')\n    })\n\n    const run = async () => {\n      const result = await handler.run({\n        request: new Request(new URL('/users', location.href)),\n        requestId: createRequestId(),\n      })\n      return result?.response?.text()\n    }\n\n    await expect(run()).resolves.toBe('pending')\n    await expect(run()).resolves.toBe('pending')\n    await expect(run()).resolves.toBe('pending')\n    await expect(run()).resolves.toBe('pending')\n    await expect(run()).resolves.toBe('pending')\n    await expect(run()).resolves.toBe('complete')\n    await expect(run()).resolves.toBe('complete')\n  })\n})\n"
  },
  {
    "path": "src/core/handlers/HttpHandler.ts",
    "content": "import { ResponseResolutionContext } from '../utils/executeHandlers'\nimport { devUtils } from '../utils/internal/devUtils'\nimport { isStringEqual } from '../utils/internal/isStringEqual'\nimport { getStatusCodeColor } from '../utils/logging/getStatusCodeColor'\nimport { getTimestamp } from '../utils/logging/getTimestamp'\nimport { serializeRequest } from '../utils/logging/serializeRequest'\nimport { serializeResponse } from '../utils/logging/serializeResponse'\nimport {\n  matchRequestUrl,\n  Match,\n  Path,\n  PathParams,\n} from '../utils/matching/matchRequestUrl'\nimport { toPublicUrl } from '../utils/request/toPublicUrl'\nimport { getAllRequestCookies } from '../utils/request/getRequestCookies'\nimport { cleanUrl } from '../utils/url/cleanUrl'\nimport {\n  RequestHandler,\n  RequestHandlerDefaultInfo,\n  RequestHandlerOptions,\n  ResponseResolver,\n} from './RequestHandler'\n\nexport type HttpHandlerMethod = string | RegExp\n\nexport interface HttpHandlerInfo extends RequestHandlerDefaultInfo {\n  method: HttpHandlerMethod\n  path: HttpRequestPredicate<PathParams>\n}\n\nexport enum HttpMethods {\n  HEAD = 'HEAD',\n  GET = 'GET',\n  POST = 'POST',\n  PUT = 'PUT',\n  PATCH = 'PATCH',\n  OPTIONS = 'OPTIONS',\n  DELETE = 'DELETE',\n}\n\nexport type RequestQuery = {\n  [queryName: string]: string\n}\n\nexport type HttpRequestParsedResult = {\n  match: Match\n  cookies: Record<string, string>\n}\n\nexport type HttpRequestResolverExtras<Params extends PathParams> = {\n  params: Params\n  cookies: Record<string, string>\n}\n\nexport type HttpCustomPredicate<Params extends PathParams> = (args: {\n  request: Request\n  cookies: Record<string, string>\n}) =>\n  | HttpCustomPredicateResult<Params>\n  | Promise<HttpCustomPredicateResult<Params>>\n\nexport type HttpCustomPredicateResult<Params extends PathParams> =\n  | boolean\n  | {\n      matches: boolean\n      params: Params\n    }\n\nexport type HttpRequestPredicate<Params extends PathParams> =\n  | Path\n  | HttpCustomPredicate<Params>\n\n/**\n * Request handler for HTTP requests.\n * Provides request matching based on method and URL.\n */\nexport class HttpHandler extends RequestHandler<\n  HttpHandlerInfo,\n  HttpRequestParsedResult,\n  HttpRequestResolverExtras<any>\n> {\n  constructor(\n    method: HttpHandlerMethod,\n    predicate: HttpRequestPredicate<PathParams>,\n    resolver: ResponseResolver<HttpRequestResolverExtras<any>, any, any>,\n    options?: RequestHandlerOptions,\n  ) {\n    const displayPath =\n      typeof predicate === 'function' ? '[custom predicate]' : predicate\n\n    super({\n      info: {\n        header: `${method}${displayPath ? ` ${displayPath}` : ''}`,\n        path: predicate,\n        method,\n      },\n      resolver,\n      options,\n    })\n\n    this.checkRedundantQueryParameters()\n  }\n\n  private checkRedundantQueryParameters() {\n    const { method, path } = this.info\n\n    if (!path || path instanceof RegExp || typeof path === 'function') {\n      return\n    }\n\n    const url = cleanUrl(path)\n\n    // Bypass request handler URLs that have no redundant characters.\n    if (url === path) {\n      return\n    }\n\n    devUtils.warn(\n      `Found a redundant usage of query parameters in the request handler URL for \"${method} ${path}\". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`,\n    )\n  }\n\n  async parse(args: {\n    request: Request\n    resolutionContext?: ResponseResolutionContext\n  }) {\n    const url = new URL(args.request.url)\n    const cookies = getAllRequestCookies(args.request)\n\n    /**\n     * Handle custom predicate functions.\n     * @note Invoke this during parsing so the user can parse the path parameters\n     * manually. Otherwise, `params` is always an empty object, which isn't nice.\n     */\n    if (typeof this.info.path === 'function') {\n      const customPredicateResult = await this.info.path({\n        request: args.request,\n        cookies,\n      })\n\n      const match =\n        typeof customPredicateResult === 'boolean'\n          ? {\n              matches: customPredicateResult,\n              params: {},\n            }\n          : customPredicateResult\n\n      return {\n        match,\n        cookies,\n      }\n    }\n\n    const match = this.info.path\n      ? matchRequestUrl(url, this.info.path, args.resolutionContext?.baseUrl)\n      : { matches: false, params: {} }\n\n    return {\n      match,\n      cookies,\n    }\n  }\n\n  async predicate(args: {\n    request: Request\n    parsedResult: HttpRequestParsedResult\n    resolutionContext?: ResponseResolutionContext\n  }) {\n    const hasMatchingMethod = this.matchMethod(args.request.method)\n    const hasMatchingUrl = args.parsedResult.match.matches\n    return hasMatchingMethod && hasMatchingUrl\n  }\n\n  private matchMethod(actualMethod: string): boolean {\n    return this.info.method instanceof RegExp\n      ? this.info.method.test(actualMethod)\n      : isStringEqual(this.info.method, actualMethod)\n  }\n\n  protected extendResolverArgs(args: {\n    request: Request\n    parsedResult: HttpRequestParsedResult\n  }) {\n    return {\n      params: args.parsedResult.match?.params || {},\n      cookies: args.parsedResult.cookies,\n    }\n  }\n\n  async log(args: { request: Request; response: Response }) {\n    const publicUrl = toPublicUrl(args.request.url)\n    const loggedRequest = await serializeRequest(args.request)\n    const loggedResponse = await serializeResponse(args.response)\n    const statusColor = getStatusCodeColor(loggedResponse.status)\n\n    console.groupCollapsed(\n      devUtils.formatMessage(\n        `${getTimestamp()} ${args.request.method} ${publicUrl} (%c${\n          loggedResponse.status\n        } ${loggedResponse.statusText}%c)`,\n      ),\n      `color:${statusColor}`,\n      'color:inherit',\n    )\n    // eslint-disable-next-line no-console\n    console.log('Request', loggedRequest)\n    // eslint-disable-next-line no-console\n    console.log('Handler:', this)\n    // eslint-disable-next-line no-console\n    console.log('Response', loggedResponse)\n    console.groupEnd()\n  }\n}\n"
  },
  {
    "path": "src/core/handlers/RequestHandler.ts",
    "content": "import { getCallFrame } from '../utils/internal/getCallFrame'\nimport {\n  AsyncIterable,\n  Iterable,\n  isIterable,\n} from '../utils/internal/isIterable'\nimport type { ResponseResolutionContext } from '../utils/executeHandlers'\nimport type { MaybePromise } from '../typeUtils'\nimport {\n  StrictRequest,\n  HttpResponse,\n  DefaultUnsafeFetchResponse,\n} from '../HttpResponse'\nimport type { HandlerKind } from './common'\nimport type { GraphQLRequestBody } from './GraphQLHandler'\n\nexport type DefaultRequestMultipartBody = Record<\n  string,\n  string | File | Array<string | File>\n>\n\nexport type DefaultBodyType =\n  | Record<string, any>\n  | DefaultRequestMultipartBody\n  | string\n  | number\n  | boolean\n  | null\n  | undefined\n\nexport type JsonBodyType =\n  | Record<string, any>\n  | string\n  | number\n  | boolean\n  | null\n  | undefined\n\nexport interface RequestHandlerDefaultInfo {\n  header: string\n}\n\nexport interface RequestHandlerInternalInfo {\n  callFrame?: string\n}\n\nexport type ResponseResolverReturnType<\n  ResponseBodyType extends DefaultBodyType = undefined,\n> =\n  // If ResponseBodyType is a union and one of the types is `undefined`,\n  // allow plain Response as the type.\n  | ([ResponseBodyType] extends [undefined]\n      ? Response\n      : /**\n         * Treat GraphQL response body type as a special case.\n         * For esome reason, making the default HttpResponse<T> | DefaultUnsafeFetchResponse\n         * union breaks the body type inference for HTTP requests.\n         * @see https://github.com/mswjs/msw/issues/2130\n         */\n        ResponseBodyType extends GraphQLRequestBody<any>\n        ? HttpResponse<ResponseBodyType> | DefaultUnsafeFetchResponse\n        : HttpResponse<ResponseBodyType>)\n  | undefined\n  | void\n\nexport type MaybeAsyncResponseResolverReturnType<\n  ResponseBodyType extends DefaultBodyType,\n> = MaybePromise<ResponseResolverReturnType<ResponseBodyType>>\n\nexport type AsyncResponseResolverReturnType<\n  ResponseBodyType extends DefaultBodyType,\n> = MaybePromise<\n  | ResponseResolverReturnType<ResponseBodyType>\n  | Iterable<\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>,\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>,\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>\n    >\n  | AsyncIterable<\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>,\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>,\n      MaybeAsyncResponseResolverReturnType<ResponseBodyType>\n    >\n>\n\nexport type ResponseResolverInfo<\n  ResolverExtraInfo extends Record<string, unknown>,\n  RequestBodyType extends DefaultBodyType = DefaultBodyType,\n> = {\n  request: StrictRequest<RequestBodyType>\n  requestId: string\n} & ResolverExtraInfo\n\nexport type ResponseResolver<\n  ResolverExtraInfo extends Record<string, unknown> = Record<string, unknown>,\n  RequestBodyType extends DefaultBodyType = DefaultBodyType,\n  ResponseBodyType extends DefaultBodyType = undefined,\n> = (\n  info: ResponseResolverInfo<ResolverExtraInfo, RequestBodyType>,\n) => AsyncResponseResolverReturnType<ResponseBodyType>\n\nexport interface RequestHandlerArgs<\n  HandlerInfo,\n  HandlerOptions extends RequestHandlerOptions,\n> {\n  info: HandlerInfo\n  resolver: ResponseResolver<any>\n  options?: HandlerOptions\n}\n\nexport interface RequestHandlerOptions {\n  once?: boolean\n}\n\nexport interface RequestHandlerExecutionResult<\n  ParsedResult extends object | undefined,\n> {\n  handler: RequestHandler\n  parsedResult?: ParsedResult\n  request: Request\n  requestId: string\n  response?: Response\n}\n\nexport abstract class RequestHandler<\n  HandlerInfo extends RequestHandlerDefaultInfo = RequestHandlerDefaultInfo,\n  ParsedResult extends Record<string, any> | undefined = any,\n  ResolverExtras extends Record<string, unknown> = any,\n  HandlerOptions extends RequestHandlerOptions = RequestHandlerOptions,\n> {\n  static cache = new WeakMap<\n    StrictRequest<DefaultBodyType>,\n    StrictRequest<DefaultBodyType>\n  >()\n\n  private readonly __kind: HandlerKind\n\n  public info: HandlerInfo & RequestHandlerInternalInfo\n  /**\n   * Indicates whether this request handler has been used\n   * (its resolver has successfully executed).\n   */\n  public isUsed: boolean\n\n  protected resolver: ResponseResolver<ResolverExtras, any, any>\n  private resolverIterator?:\n    | Iterator<\n        MaybeAsyncResponseResolverReturnType<any>,\n        MaybeAsyncResponseResolverReturnType<any>,\n        MaybeAsyncResponseResolverReturnType<any>\n      >\n    | AsyncIterator<\n        MaybeAsyncResponseResolverReturnType<any>,\n        MaybeAsyncResponseResolverReturnType<any>,\n        MaybeAsyncResponseResolverReturnType<any>\n      >\n  private resolverIteratorResult?: Response | HttpResponse<any>\n  private options?: HandlerOptions\n\n  constructor(args: RequestHandlerArgs<HandlerInfo, HandlerOptions>) {\n    this.resolver = args.resolver\n    this.options = args.options\n\n    const callFrame = getCallFrame(new Error())\n\n    this.info = {\n      ...args.info,\n      callFrame,\n    }\n\n    this.isUsed = false\n    this.__kind = 'RequestHandler'\n  }\n\n  /**\n   * Determine if the intercepted request should be mocked.\n   */\n  abstract predicate(args: {\n    request: Request\n    parsedResult: ParsedResult\n    resolutionContext?: ResponseResolutionContext\n  }): boolean | Promise<boolean>\n\n  /**\n   * Print out the successfully handled request.\n   */\n  abstract log(args: {\n    request: Request\n    response: Response\n    parsedResult: ParsedResult\n  }): void\n\n  /**\n   * Parse the intercepted request to extract additional information from it.\n   * Parsed result is then exposed to other methods of this request handler.\n   */\n  async parse(_args: {\n    request: Request\n    resolutionContext?: ResponseResolutionContext\n  }): Promise<ParsedResult> {\n    return {} as ParsedResult\n  }\n\n  /**\n   * Test if this handler matches the given request.\n   *\n   * This method is not used internally but is exposed\n   * as a convenience method for consumers writing custom\n   * handlers.\n   */\n  public async test(args: {\n    request: Request\n    resolutionContext?: ResponseResolutionContext\n  }): Promise<boolean> {\n    const parsedResult = await this.parse({\n      request: args.request,\n      resolutionContext: args.resolutionContext,\n    })\n\n    return this.predicate({\n      request: args.request,\n      parsedResult,\n      resolutionContext: args.resolutionContext,\n    })\n  }\n\n  protected extendResolverArgs(_args: {\n    request: Request\n    parsedResult: ParsedResult\n  }): ResolverExtras {\n    return {} as ResolverExtras\n  }\n\n  // Clone the request instance before it's passed to the handler phases\n  // and the response resolver so we can always read it for logging.\n  // We only clone it once per request to avoid unnecessary overhead.\n  private cloneRequestOrGetFromCache(\n    request: StrictRequest<DefaultBodyType>,\n  ): StrictRequest<DefaultBodyType> {\n    const existingClone = RequestHandler.cache.get(request)\n\n    if (typeof existingClone !== 'undefined') {\n      return existingClone\n    }\n\n    const clonedRequest = request.clone()\n    RequestHandler.cache.set(request, clonedRequest)\n\n    return clonedRequest\n  }\n\n  /**\n   * Execute this request handler and produce a mocked response\n   * using the given resolver function.\n   */\n  public async run(args: {\n    request: StrictRequest<any>\n    requestId: string\n    resolutionContext?: ResponseResolutionContext\n  }): Promise<RequestHandlerExecutionResult<ParsedResult> | null> {\n    if (this.isUsed && this.options?.once) {\n      return null\n    }\n\n    // Clone the request.\n    // If this is the first time MSW handles this request, a fresh clone\n    // will be created and cached. Upon further handling of the same request,\n    // the request clone from the cache will be reused to prevent abundant\n    // \"abort\" listeners and save up resources on cloning.\n    const requestClone = this.cloneRequestOrGetFromCache(args.request)\n\n    const parsedResult = await this.parse({\n      request: args.request,\n      resolutionContext: args.resolutionContext,\n    })\n    const shouldInterceptRequest = await this.predicate({\n      request: args.request,\n      parsedResult,\n      resolutionContext: args.resolutionContext,\n    })\n\n    if (!shouldInterceptRequest) {\n      return null\n    }\n\n    // Re-check isUsed, in case another request hit this handler while we were\n    // asynchronously parsing the request.\n    if (this.isUsed && this.options?.once) {\n      return null\n    }\n\n    // Preemptively mark the handler as used.\n    // Generators will undo this because only when the resolver reaches the\n    // \"done\" state of the generator that it considers the handler used.\n    this.isUsed = true\n\n    // Create a response extraction wrapper around the resolver\n    // since it can be both an async function and a generator.\n    const executeResolver = this.wrapResolver(this.resolver)\n\n    const resolverExtras = this.extendResolverArgs({\n      request: args.request,\n      parsedResult,\n    })\n\n    const mockedResponsePromise = (\n      executeResolver({\n        ...resolverExtras,\n        requestId: args.requestId,\n        request: args.request,\n      }) as Promise<Response>\n    ).catch((errorOrResponse) => {\n      // Allow throwing a Response instance in a response resolver.\n      if (errorOrResponse instanceof Response) {\n        return errorOrResponse\n      }\n\n      // Otherwise, throw the error as-is.\n      throw errorOrResponse\n    })\n\n    const mockedResponse = await mockedResponsePromise\n\n    const executionResult = this.createExecutionResult({\n      // Pass the cloned request to the result so that logging\n      // and other consumers could read its body once more.\n      request: requestClone,\n      requestId: args.requestId,\n      response: mockedResponse,\n      parsedResult,\n    })\n\n    return executionResult\n  }\n\n  private wrapResolver(\n    resolver: ResponseResolver<ResolverExtras>,\n  ): ResponseResolver<ResolverExtras> {\n    return async (info): Promise<ResponseResolverReturnType<any>> => {\n      if (!this.resolverIterator) {\n        const result = await resolver(info)\n\n        if (!isIterable(result)) {\n          return result\n        }\n\n        this.resolverIterator =\n          Symbol.iterator in result\n            ? result[Symbol.iterator]()\n            : result[Symbol.asyncIterator]()\n      }\n\n      // Opt-out from marking this handler as used.\n      this.isUsed = false\n\n      const { done, value } = await this.resolverIterator.next()\n      const nextResponse = await value\n\n      if (nextResponse) {\n        this.resolverIteratorResult = nextResponse.clone()\n      }\n\n      if (done) {\n        // A one-time generator resolver stops affecting the network\n        // only after it's been completely exhausted.\n        this.isUsed = true\n\n        // Clone the previously stored response so it can be read\n        // when receiving it repeatedly from the \"done\" generator.\n        return this.resolverIteratorResult?.clone()\n      }\n\n      return nextResponse\n    }\n  }\n\n  private createExecutionResult(args: {\n    request: Request\n    requestId: string\n    parsedResult: ParsedResult\n    response?: Response\n  }): RequestHandlerExecutionResult<ParsedResult> {\n    return {\n      handler: this,\n      request: args.request,\n      requestId: args.requestId,\n      response: args.response,\n      parsedResult: args.parsedResult,\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/handlers/WebSocketHandler.test.ts",
    "content": "import { WebSocketHandler } from './WebSocketHandler'\n\ndescribe('parse', () => {\n  it('matches an exact url', () => {\n    expect(\n      new WebSocketHandler('ws://localhost:3000').parse({\n        url: new URL('ws://localhost:3000'),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n  })\n\n  it('ignores trailing slash', () => {\n    expect(\n      new WebSocketHandler('ws://localhost:3000').parse({\n        url: new URL('ws://localhost:3000/'),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n\n    expect(\n      new WebSocketHandler('ws://localhost:3000/').parse({\n        url: new URL('ws://localhost:3000/'),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n  })\n\n  it('supports path parameters', () => {\n    expect(\n      new WebSocketHandler('ws://localhost:3000/:serviceName').parse({\n        url: new URL('ws://localhost:3000/auth'),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {\n          serviceName: 'auth',\n        },\n      },\n    })\n  })\n\n  it('ignores \"/socket.io/\" prefix in the client url', () => {\n    expect(\n      new WebSocketHandler('ws://localhost:3000').parse({\n        url: new URL(\n          'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',\n        ),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n\n    expect(\n      new WebSocketHandler('ws://localhost:3000/non-matching').parse({\n        url: new URL(\n          'ws://localhost:3000/socket.io/?EIO=4&transport=websocket',\n        ),\n      }),\n    ).toEqual({\n      match: {\n        matches: false,\n        params: {},\n      },\n    })\n  })\n\n  it('preserves non-prefix \"/socket.io/\" path segment', () => {\n    /**\n     * @note It is highly unlikely but we still shouldn't modify the\n     * WebSocket client URL if it contains a user-defined \"socket.io\" segment.\n     */\n    expect(\n      new WebSocketHandler('ws://localhost:3000/clients/socket.io/123').parse({\n        url: new URL('ws://localhost:3000/clients/socket.io/123'),\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n\n    expect(\n      new WebSocketHandler('ws://localhost:3000').parse({\n        url: new URL('ws://localhost:3000/clients/socket.io/123'),\n      }),\n    ).toEqual({\n      match: {\n        matches: false,\n        params: {},\n      },\n    })\n  })\n\n  it('supports a custom resolution context (base url)', () => {\n    expect(\n      new WebSocketHandler('/api/ws').parse({\n        url: new URL('ws://localhost:3000/api/ws'),\n        resolutionContext: {\n          baseUrl: 'ws://localhost:3000/',\n        },\n      }),\n    ).toEqual({\n      match: {\n        matches: true,\n        params: {},\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "src/core/handlers/WebSocketHandler.ts",
    "content": "import { Emitter } from 'strict-event-emitter'\nimport { createRequestId, resolveWebSocketUrl } from '@mswjs/interceptors'\nimport type {\n  WebSocketClientConnectionProtocol,\n  WebSocketConnectionData,\n  WebSocketServerConnectionProtocol,\n} from '@mswjs/interceptors/WebSocket'\nimport {\n  type Match,\n  type Path,\n  type PathParams,\n  matchRequestUrl,\n} from '../utils/matching/matchRequestUrl'\nimport { getCallFrame } from '../utils/internal/getCallFrame'\nimport type { HandlerKind } from './common'\n\ntype WebSocketHandlerParsedResult = {\n  match: Match\n}\n\nexport type WebSocketHandlerEventMap = {\n  connection: [args: WebSocketHandlerConnection]\n}\n\nexport interface WebSocketHandlerConnection {\n  client: WebSocketClientConnectionProtocol\n  server: WebSocketServerConnectionProtocol\n  info: WebSocketConnectionData['info']\n  params: PathParams\n}\n\nexport interface WebSocketResolutionContext {\n  baseUrl?: string\n}\n\nexport const kEmitter = Symbol('kEmitter')\nexport const kSender = Symbol('kSender')\nconst kStopPropagationPatched = Symbol('kStopPropagationPatched')\nconst KOnStopPropagation = Symbol('KOnStopPropagation')\n\nexport class WebSocketHandler {\n  private readonly __kind: HandlerKind\n\n  public id: string\n  public callFrame?: string\n\n  protected [kEmitter]: Emitter<WebSocketHandlerEventMap>\n\n  constructor(protected readonly url: Path) {\n    this.id = createRequestId()\n\n    this[kEmitter] = new Emitter()\n    this.callFrame = getCallFrame(new Error())\n    this.__kind = 'EventHandler'\n  }\n\n  public parse(args: {\n    url: URL\n    resolutionContext?: WebSocketResolutionContext\n  }): WebSocketHandlerParsedResult {\n    const clientUrl = new URL(args.url)\n\n    // Resolve the WebSocket handler path:\n    // - Plain string URLs resolved as per the specification (via Interceptors).\n    // - String URLs starting with a wildcard are preserved (prepending a scheme there will break them).\n    // - RegExp paths are preserved.\n    const resolvedHandlerUrl =\n      this.url instanceof RegExp || this.url.startsWith('*')\n        ? this.url\n        : this.#resolveWebSocketUrl(this.url, args.resolutionContext?.baseUrl)\n\n    /**\n     * @note Remove the Socket.IO path prefix from the WebSocket\n     * client URL. This is an exception to keep the users from\n     * including the implementation details in their handlers.\n     */\n    clientUrl.pathname = clientUrl.pathname.replace(/^\\/socket.io\\//, '/')\n\n    const match = matchRequestUrl(\n      clientUrl,\n      resolvedHandlerUrl,\n      args.resolutionContext?.baseUrl,\n    )\n\n    return {\n      match,\n    }\n  }\n\n  public predicate(args: {\n    url: URL\n    parsedResult: WebSocketHandlerParsedResult\n  }): boolean {\n    return args.parsedResult.match.matches\n  }\n\n  public async run(\n    connection: Omit<WebSocketHandlerConnection, 'params'>,\n    resolutionContext?: WebSocketResolutionContext,\n  ): Promise<boolean> {\n    const parsedResult = this.parse({\n      url: connection.client.url,\n      resolutionContext,\n    })\n\n    if (!this.predicate({ url: connection.client.url, parsedResult })) {\n      return false\n    }\n\n    const resolvedConnection: WebSocketHandlerConnection = {\n      ...connection,\n      params: parsedResult.match.params || {},\n    }\n\n    return this.connect(resolvedConnection)\n  }\n\n  protected connect(connection: WebSocketHandlerConnection): boolean {\n    // Support `event.stopPropagation()` for various client/server events.\n    connection.client.addEventListener(\n      'message',\n      createStopPropagationListener(this),\n    )\n    connection.client.addEventListener(\n      'close',\n      createStopPropagationListener(this),\n    )\n\n    connection.server.addEventListener(\n      'open',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'message',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'error',\n      createStopPropagationListener(this),\n    )\n    connection.server.addEventListener(\n      'close',\n      createStopPropagationListener(this),\n    )\n\n    // Emit the connection event on the handler.\n    // This is what the developer adds listeners for.\n    return this[kEmitter].emit('connection', connection)\n  }\n\n  #resolveWebSocketUrl(url: string, baseUrl?: string): string {\n    const resolvedUrl = resolveWebSocketUrl(\n      baseUrl\n        ? /**\n           * @note Resolve against the base URL preemtively because `resolveWebSocketUrl` only\n           * resolves against `location.href`, which is missing in Node.js. Base URL allows\n           * the handler to accept a relative URL in Node.js.\n           */\n          new URL(url, baseUrl)\n        : url,\n    )\n\n    /**\n     * @note Omit the trailing slash.\n     * While the browser always produces a trailing slash at the end of a WebSocket URL,\n     * having it in as the handler's predicate would mean it is *required* in the actual URL.\n     */\n    return resolvedUrl.replace(/\\/$/, '')\n  }\n}\n\nfunction createStopPropagationListener(handler: WebSocketHandler) {\n  return function stopPropagationListener(event: Event) {\n    const propagationStoppedAt = Reflect.get(event, 'kPropagationStoppedAt') as\n      | string\n      | undefined\n\n    if (propagationStoppedAt && handler.id !== propagationStoppedAt) {\n      event.stopImmediatePropagation()\n      return\n    }\n\n    Object.defineProperty(event, KOnStopPropagation, {\n      value(this: WebSocketHandler) {\n        Object.defineProperty(event, 'kPropagationStoppedAt', {\n          value: handler.id,\n        })\n      },\n      configurable: true,\n    })\n\n    // Since the same event instance is shared between all client/server objects,\n    // make sure to patch its `stopPropagation` method only once.\n    if (!Reflect.get(event, kStopPropagationPatched)) {\n      event.stopPropagation = new Proxy(event.stopPropagation, {\n        apply: (target, thisArg, args) => {\n          Reflect.get(event, KOnStopPropagation)?.call(handler)\n          return Reflect.apply(target, thisArg, args)\n        },\n      })\n\n      Object.defineProperty(event, kStopPropagationPatched, {\n        value: true,\n        // If something else attempts to redefine this, throw.\n        configurable: false,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/handlers/common.ts",
    "content": "export type HandlerKind = 'RequestHandler' | 'EventHandler'\n"
  },
  {
    "path": "src/core/http.test.ts",
    "content": "import { http } from './http'\n\ntest('exports all REST API methods', () => {\n  expect(http).toBeDefined()\n  expect(Object.keys(http)).toEqual([\n    'all',\n    'head',\n    'get',\n    'post',\n    'put',\n    'delete',\n    'patch',\n    'options',\n  ])\n})\n"
  },
  {
    "path": "src/core/http.ts",
    "content": "import {\n  DefaultBodyType,\n  RequestHandlerOptions,\n  ResponseResolver,\n} from './handlers/RequestHandler'\nimport {\n  HttpMethods,\n  HttpHandler,\n  HttpRequestResolverExtras,\n  HttpRequestPredicate,\n} from './handlers/HttpHandler'\nimport type { PathParams } from './utils/matching/matchRequestUrl'\n\nexport type HttpRequestHandler = <\n  Params extends PathParams<keyof Params> = PathParams,\n  RequestBodyType extends DefaultBodyType = DefaultBodyType,\n  // Response body type MUST be undefined by default.\n  // This is how we can distinguish between a handler that\n  // returns plain \"Response\" and the one returning \"HttpResponse\"\n  // to enforce a stricter response body type.\n  ResponseBodyType extends DefaultBodyType = undefined,\n>(\n  predicate: HttpRequestPredicate<Params>,\n  resolver: HttpResponseResolver<Params, RequestBodyType, ResponseBodyType>,\n  options?: RequestHandlerOptions,\n) => HttpHandler\n\nexport type HttpResponseResolver<\n  Params extends PathParams<keyof Params> = PathParams,\n  RequestBodyType extends DefaultBodyType = DefaultBodyType,\n  ResponseBodyType extends DefaultBodyType = DefaultBodyType,\n> = ResponseResolver<\n  HttpRequestResolverExtras<Params>,\n  RequestBodyType,\n  ResponseBodyType\n>\n\nfunction createHttpHandler<Method extends HttpMethods | RegExp>(\n  method: Method,\n): HttpRequestHandler {\n  return (predicate, resolver, options = {}) => {\n    return new HttpHandler(method, predicate, resolver, options)\n  }\n}\n\n/**\n * A namespace to intercept and mock HTTP requests.\n *\n * @example\n * http.get('/user', resolver)\n * http.post('/post/:id', resolver)\n *\n * @see {@link https://mswjs.io/docs/api/http `http` API reference}\n */\nexport const http = {\n  all: createHttpHandler(/.+/),\n  head: createHttpHandler(HttpMethods.HEAD),\n  get: createHttpHandler(HttpMethods.GET),\n  post: createHttpHandler(HttpMethods.POST),\n  put: createHttpHandler(HttpMethods.PUT),\n  delete: createHttpHandler(HttpMethods.DELETE),\n  patch: createHttpHandler(HttpMethods.PATCH),\n  options: createHttpHandler(HttpMethods.OPTIONS),\n}\n"
  },
  {
    "path": "src/core/index.ts",
    "content": "import { checkGlobals } from './utils/internal/checkGlobals'\n\nexport { SetupApi } from './SetupApi'\n\n/* HTTP handlers */\nexport { RequestHandler } from './handlers/RequestHandler'\nexport { http } from './http'\nexport { HttpHandler, HttpMethods } from './handlers/HttpHandler'\nexport { graphql } from './graphql'\nexport { GraphQLHandler } from './handlers/GraphQLHandler'\n\n/* WebSocket handler */\nexport { ws, type WebSocketLink } from './ws'\nexport {\n  WebSocketHandler,\n  type WebSocketHandlerEventMap,\n  type WebSocketHandlerConnection,\n} from './handlers/WebSocketHandler'\n\n/* Server-Sent Events */\nexport {\n  sse,\n  type ServerSentEventRequestHandler,\n  type ServerSentEventResolver,\n  type ServerSentEventResolverExtras,\n  type ServerSentEventMessage,\n} from './sse'\n\nimport type { HttpHandler } from './handlers/HttpHandler'\nimport type { GraphQLHandler } from './handlers/GraphQLHandler'\nimport type { WebSocketHandler } from './handlers/WebSocketHandler'\n\nexport type AnyHandler = HttpHandler | GraphQLHandler | WebSocketHandler\n\n/* Utils */\nexport { matchRequestUrl } from './utils/matching/matchRequestUrl'\nexport { handleRequest, type HandleRequestOptions } from './utils/handleRequest'\nexport {\n  onUnhandledRequest,\n  type UnhandledRequestStrategy,\n  type UnhandledRequestCallback,\n} from './utils/request/onUnhandledRequest'\nexport { getResponse } from './getResponse'\nexport { cleanUrl } from './utils/url/cleanUrl'\n\n/**\n * Type definitions.\n */\n\nexport type { SharedOptions, LifeCycleEventsMap } from './sharedOptions'\n\nexport type {\n  ResponseResolver,\n  ResponseResolverReturnType,\n  AsyncResponseResolverReturnType,\n  RequestHandlerOptions,\n  DefaultBodyType,\n  DefaultRequestMultipartBody,\n  JsonBodyType,\n  ResponseResolverInfo,\n} from './handlers/RequestHandler'\n\nexport type {\n  RequestQuery,\n  HttpRequestParsedResult,\n  HttpHandlerInfo,\n  HttpRequestResolverExtras,\n  HttpHandlerMethod,\n  HttpCustomPredicate,\n} from './handlers/HttpHandler'\nexport type { HttpRequestHandler, HttpResponseResolver } from './http'\n\nexport type {\n  GraphQLQuery,\n  GraphQLVariables,\n  GraphQLRequestBody,\n  GraphQLResponseBody,\n  GraphQLJsonRequestBody,\n  GraphQLOperationType,\n  GraphQLCustomPredicate,\n} from './handlers/GraphQLHandler'\nexport type {\n  GraphQLRequestHandler,\n  GraphQLOperationHandler,\n  GraphQLResponseResolver,\n  GraphQLLinkHandlers,\n} from './graphql'\n\nexport type { WebSocketData, WebSocketEventListener } from './ws'\n\nexport type { Path, PathParams, Match } from './utils/matching/matchRequestUrl'\nexport type { ParsedGraphQLRequest } from './utils/internal/parseGraphQLRequest'\nexport type { ResponseResolutionContext } from './utils/executeHandlers'\n\nexport {\n  HttpResponse,\n  type HttpResponseInit,\n  type StrictRequest,\n  type StrictResponse,\n} from './HttpResponse'\nexport { delay, type DelayMode } from './delay'\nexport { bypass } from './bypass'\nexport { passthrough } from './passthrough'\nexport { isCommonAssetRequest } from './isCommonAssetRequest'\n\n// Validate environmental globals before executing any code.\n// This ensures that the library gives user-friendly errors\n// when ran in the environments that require additional polyfills\n// from the end user.\ncheckGlobals()\n"
  },
  {
    "path": "src/core/isCommonAssetRequest.ts",
    "content": "/**\n * Determines if the given request is a static asset request.\n * Useful when deciding which unhandled requests to ignore.\n * @note Despite being ignored, you can still intercept and mock\n * static assets by creating request handlers for them.\n *\n * @example\n * import { isCommonAssetRequest } from 'msw'\n *\n * await worker.start({\n *   onUnhandledRequest(request, print) {\n *     if (!isCommonAssetRequest(request)) {\n *       print.warning()\n *     }\n *   }\n * })\n */\nexport function isCommonAssetRequest(request: Request): boolean {\n  const url = new URL(request.url)\n\n  // Ignore certain protocols.\n  if (url.protocol === 'file:') {\n    return true\n  }\n\n  // Ignore static assets hosts.\n  if (/(fonts\\.googleapis\\.com)/.test(url.hostname)) {\n    return true\n  }\n\n  // Ignore node modules served over HTTP.\n  if (/node_modules/.test(url.pathname)) {\n    return true\n  }\n\n  // Ignore internal Vite requests, like \"/@vite/client\".\n  if (url.pathname.includes('@vite')) {\n    return true\n  }\n\n  // Ignore common static assets.\n  return /\\.(s?css|less|m?jsx?|m?tsx?|html|ttf|otf|woff|woff2|eot|gif|jpe?g|png|avif|webp|svg|mp4|webm|ogg|mov|mp3|wav|ogg|flac|aac|pdf|txt|csv|json|xml|md|zip|tar|gz|rar|7z)$/i.test(\n    url.pathname,\n  )\n}\n"
  },
  {
    "path": "src/core/passthrough.test.ts",
    "content": "// @vitest-environment node\nimport { passthrough } from './passthrough'\n\nit('creates a 302 response with the intention header', () => {\n  const response = passthrough()\n\n  expect(response).toBeInstanceOf(Response)\n  expect(response.status).toBe(302)\n  expect(response.statusText).toBe('Passthrough')\n  expect(response.headers.get('x-msw-intention')).toBe('passthrough')\n})\n"
  },
  {
    "path": "src/core/passthrough.ts",
    "content": "import type { HttpResponse } from './HttpResponse'\n\n/**\n * Performs the intercepted request as-is.\n *\n * This stops request handler lookup so no other handlers\n * can affect this request past this point.\n * Unlike `bypass()`, this will not trigger an additional request.\n *\n * @example\n * http.get('/resource', () => {\n *   return passthrough()\n * })\n *\n * @see {@link https://mswjs.io/docs/api/passthrough `passthrough()` API reference}\n */\nexport function passthrough(): HttpResponse<any> {\n  return new Response(null, {\n    status: 302,\n    statusText: 'Passthrough',\n    headers: {\n      'x-msw-intention': 'passthrough',\n    },\n  }) as HttpResponse<any>\n}\n"
  },
  {
    "path": "src/core/sharedOptions.ts",
    "content": "import type { Emitter } from 'strict-event-emitter'\nimport type { UnhandledRequestStrategy } from './utils/request/onUnhandledRequest'\n\nexport interface SharedOptions {\n  /**\n   * Specifies how to react to a request that has no corresponding\n   * request handler. Warns on unhandled requests by default.\n   *\n   * @example worker.start({ onUnhandledRequest: 'bypass' })\n   * @example worker.start({ onUnhandledRequest: 'warn' })\n   * @example server.listen({ onUnhandledRequest: 'error' })\n   */\n  onUnhandledRequest?: UnhandledRequestStrategy\n}\n\nexport type LifeCycleEventsMap = {\n  'request:start': [\n    args: {\n      request: Request\n      requestId: string\n    },\n  ]\n  'request:match': [\n    args: {\n      request: Request\n      requestId: string\n    },\n  ]\n  'request:unhandled': [\n    args: {\n      request: Request\n      requestId: string\n    },\n  ]\n  'request:end': [\n    args: {\n      request: Request\n      requestId: string\n    },\n  ]\n  'response:mocked': [\n    args: {\n      response: Response\n      request: Request\n      requestId: string\n    },\n  ]\n  'response:bypass': [\n    args: {\n      response: Response\n      request: Request\n      requestId: string\n    },\n  ]\n  unhandledException: [\n    args: {\n      error: Error\n      request: Request\n      requestId: string\n    },\n  ]\n}\n\nexport type LifeCycleEventEmitter<\n  EventsMap extends Record<string | symbol, any>,\n> = Pick<Emitter<EventsMap>, 'on' | 'removeListener' | 'removeAllListeners'>\n"
  },
  {
    "path": "src/core/sse.ts",
    "content": "import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport type { ResponseResolver } from './handlers/RequestHandler'\nimport {\n  HttpHandler,\n  type HttpRequestResolverExtras,\n  type HttpRequestParsedResult,\n} from './handlers/HttpHandler'\nimport type { ResponseResolutionContext } from '~/core/utils/executeHandlers'\nimport type { Path, PathParams } from './utils/matching/matchRequestUrl'\nimport { delay } from './delay'\nimport { getTimestamp } from './utils/logging/getTimestamp'\nimport { devUtils } from './utils/internal/devUtils'\nimport { colors } from './ws/utils/attachWebSocketLogger'\nimport { toPublicUrl } from './utils/request/toPublicUrl'\n\ntype EventMapConstraint = {\n  message?: unknown\n  [key: string]: unknown\n  [key: symbol | number]: never\n}\n\nexport type ServerSentEventResolverExtras<\n  EventMap extends EventMapConstraint,\n  Params extends PathParams,\n> = HttpRequestResolverExtras<Params> & {\n  client: ServerSentEventClient<EventMap>\n  server: ServerSentEventServer\n}\n\nexport type ServerSentEventResolver<\n  EventMap extends EventMapConstraint,\n  Params extends PathParams,\n> = ResponseResolver<ServerSentEventResolverExtras<EventMap, Params>, any, any>\n\nexport type ServerSentEventRequestHandler = <\n  EventMap extends EventMapConstraint = { message: unknown },\n  Params extends PathParams<keyof Params> = PathParams,\n  RequestPath extends Path = Path,\n>(\n  path: RequestPath,\n  resolver: ServerSentEventResolver<EventMap, Params>,\n) => HttpHandler\n\nexport type ServerSentEventMessage<\n  EventMap extends EventMapConstraint = { message: unknown },\n> =\n  | ToEventDiscriminatedUnion<EventMap & { message: unknown }>\n  | {\n      id?: never\n      event?: never\n      data?: never\n      retry: number\n    }\n\n/**\n * Intercept Server-Sent Events (SSE).\n *\n * @example\n * sse('http://localhost:4321', ({ client }) => {\n *   client.send({ data: 'hello world' })\n * })\n *\n * @see {@link https://mswjs.io/docs/sse/ Mocking Server-Sent Events}\n * @see {@link https://mswjs.io/docs/api/sse `sse()` API reference}\n */\nexport const sse: ServerSentEventRequestHandler = (path, resolver) => {\n  return new ServerSentEventHandler(path, resolver)\n}\n\nconst SSE_RESPONSE_INIT: ResponseInit = {\n  headers: {\n    'content-type': 'text/event-stream',\n    'cache-control': 'no-cache',\n    connection: 'keep-alive',\n  },\n}\n\nclass ServerSentEventHandler<\n  EventMap extends EventMapConstraint,\n> extends HttpHandler {\n  #emitter: Emitter<ServerSentEventClientEventMap>\n\n  constructor(path: Path, resolver: ServerSentEventResolver<EventMap, any>) {\n    invariant(\n      typeof EventSource !== 'undefined',\n      'Failed to construct a Server-Sent Event handler for path \"%s\": the EventSource API is not supported in this environment',\n      path,\n    )\n\n    super('GET', path, async (info) => {\n      const stream = new ReadableStream({\n        start: async (controller) => {\n          const client = new ServerSentEventClient<EventMap>({\n            controller,\n            emitter: this.#emitter,\n          })\n          const server = new ServerSentEventServer({\n            request: info.request,\n            client,\n          })\n\n          await resolver({\n            ...info,\n            client,\n            server,\n          })\n        },\n      })\n\n      return new Response(stream, SSE_RESPONSE_INIT)\n    })\n\n    this.#emitter = new Emitter<ServerSentEventClientEventMap>()\n  }\n\n  async predicate(args: {\n    request: Request\n    parsedResult: HttpRequestParsedResult\n    resolutionContext?: ResponseResolutionContext\n  }) {\n    if (args.request.headers.get('accept') !== 'text/event-stream') {\n      return false\n    }\n\n    const matches = await super.predicate(args)\n\n    if (matches && !args.resolutionContext?.quiet) {\n      /**\n       * @note Log the intercepted request early.\n       * Normally, the `this.log()` method is called when the handler returns a response.\n       * For SSE, call that method earlier so the logs are in correct order.\n       */\n      await super.log({\n        request: args.request,\n        /**\n         * @note Construct a placeholder response since SSE response\n         * is being streamed and cannot be cloned/consumed for logging.\n         */\n        response: new Response('[streaming]', SSE_RESPONSE_INIT),\n      })\n\n      this.#attachClientLogger(args.request, this.#emitter)\n    }\n\n    return matches\n  }\n\n  async log(_args: { request: Request; response: Response }): Promise<void> {\n    /**\n     * @note Skip the default `this.log()` logic so that when this handler is logged\n     * upon handling the request, nothing is printed (we log SSE requests early).\n     */\n    return\n  }\n\n  #attachClientLogger(\n    request: Request,\n    emitter: Emitter<ServerSentEventClientEventMap>,\n  ): void {\n    const publicUrl = toPublicUrl(request.url)\n\n    /* eslint-disable no-console */\n    emitter.on('message', (payload) => {\n      console.groupCollapsed(\n        devUtils.formatMessage(\n          `${getTimestamp()} SSE %s %c⇣%c ${payload.event}`,\n        ),\n        publicUrl,\n        `color:${colors.mocked}`,\n        'color:inherit',\n      )\n      console.log(payload.frames)\n      console.groupEnd()\n    })\n\n    emitter.on('error', () => {\n      console.groupCollapsed(\n        devUtils.formatMessage(`${getTimestamp()} SSE %s %c\\u00D7%c error`),\n        publicUrl,\n        `color: ${colors.system}`,\n        'color:inherit',\n      )\n      console.log('Handler:', this)\n      console.groupEnd()\n    })\n\n    emitter.on('close', () => {\n      console.groupCollapsed(\n        devUtils.formatMessage(`${getTimestamp()} SSE %s %c■%c close`),\n        publicUrl,\n        `colors:${colors.system}`,\n        'color:inherit',\n      )\n      console.log('Handler:', this)\n      console.groupEnd()\n    })\n    /* eslint-enable no-console */\n  }\n}\n\ntype Values<T> = T[keyof T]\ntype Identity<T> = { [K in keyof T]: T[K] } & unknown\ntype ToEventDiscriminatedUnion<T> = Values<{\n  [K in keyof T]: Identity<\n    (K extends 'message'\n      ? {\n          id?: string\n          event?: K\n          data?: T[K]\n          retry?: never\n        }\n      : {\n          id?: string\n          event: K\n          data?: T[K]\n          retry?: never\n        }) &\n      // Make the `data` field conditionally required through an intersection.\n      (undefined extends T[K] ? unknown : { data: unknown })\n  >\n}>\n\ntype ServerSentEventClientEventMap = {\n  message: [\n    payload: {\n      id?: string\n      event: string\n      data?: unknown\n      frames: Array<string>\n    },\n  ]\n  error: []\n  close: []\n}\n\nclass ServerSentEventClient<\n  EventMap extends EventMapConstraint = { message: unknown },\n> {\n  #encoder: TextEncoder\n  #controller: ReadableStreamDefaultController\n  #emitter: Emitter<ServerSentEventClientEventMap>\n\n  constructor(args: {\n    controller: ReadableStreamDefaultController\n    emitter: Emitter<ServerSentEventClientEventMap>\n  }) {\n    this.#encoder = new TextEncoder()\n    this.#controller = args.controller\n    this.#emitter = args.emitter\n  }\n\n  /**\n   * Sends the given payload to the intercepted `EventSource`.\n   */\n  public send(payload: ServerSentEventMessage<EventMap>): void {\n    if ('retry' in payload && payload.retry != null) {\n      this.#sendRetry(payload.retry)\n      return\n    }\n\n    this.#sendMessage({\n      id: payload.id,\n      event: payload.event,\n      data:\n        typeof payload.data === 'object'\n          ? JSON.stringify(payload.data)\n          : payload.data,\n    })\n  }\n\n  /**\n   * Dispatches the given event on the intercepted `EventSource`.\n   */\n  public dispatchEvent(event: Event) {\n    if (event instanceof MessageEvent) {\n      /**\n       * @note Use the internal send mechanism to skip normalization\n       * of the message data (already normalized by the server).\n       */\n      this.#sendMessage({\n        id: event.lastEventId || undefined,\n        event: event.type === 'message' ? undefined : event.type,\n        data: event.data,\n      })\n      return\n    }\n\n    if (event.type === 'error') {\n      this.error()\n      return\n    }\n\n    if (event.type === 'close') {\n      this.close()\n      return\n    }\n  }\n\n  /**\n   * Errors the underlying `EventSource`, closing the connection with an error.\n   * This is equivalent to aborting the connection and will produce a `TypeError: Failed to fetch`\n   * error.\n   */\n  public error(): void {\n    this.#controller.error()\n    this.#emitter.emit('error')\n  }\n\n  /**\n   * Closes the underlying `EventSource`, closing the connection.\n   */\n  public close(): void {\n    this.#controller.close()\n    this.#emitter.emit('close')\n  }\n\n  #sendRetry(retry: number): void {\n    if (typeof retry === 'number') {\n      this.#controller.enqueue(this.#encoder.encode(`retry:${retry}\\n\\n`))\n    }\n  }\n\n  #sendMessage(message: {\n    id?: string\n    event?: unknown\n    data: unknown | undefined\n  }): void {\n    const frames: Array<string> = []\n\n    if (message.id) {\n      frames.push(`id:${message.id}`)\n    }\n\n    if (message.event) {\n      frames.push(`event:${message.event.toString()}`)\n    }\n\n    if (message.data != null) {\n      /**\n       * Split data on line terminators (LF, CR, or CRLF) and translate them to individual frames.\n       * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n       * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n       */\n      for (const line of message.data.toString().split(/\\r\\n|\\r|\\n/)) {\n        frames.push(`data:${line}`)\n      }\n    }\n\n    frames.push('', '')\n\n    this.#controller.enqueue(this.#encoder.encode(frames.join('\\n')))\n\n    this.#emitter.emit('message', {\n      id: message.id,\n      event: message.event?.toString() || 'message',\n      data: message.data,\n      frames,\n    })\n  }\n}\n\nclass ServerSentEventServer {\n  #request: Request\n  #client: ServerSentEventClient<ServerSentEventClientEventMap>\n\n  constructor(args: { request: Request; client: ServerSentEventClient<any> }) {\n    this.#request = args.request\n    this.#client = args.client\n  }\n\n  /**\n   * Establishes the actual connection for this SSE request\n   * and returns the `EventSource` instance.\n   */\n  public connect(): EventSource {\n    const source = new ObservableEventSource(this.#request.url, {\n      withCredentials: this.#request.credentials === 'include',\n      headers: {\n        /**\n         * @note Mark this request as passthrough so it doesn't trigger\n         * an infinite loop matching against the existing request handler.\n         */\n        accept: 'msw/passthrough',\n      },\n    })\n\n    source[kOnAnyMessage] = (event) => {\n      Object.defineProperties(event, {\n        target: {\n          value: this,\n          enumerable: true,\n          writable: true,\n          configurable: true,\n        },\n      })\n\n      // Schedule the server-to-client forwarding for the next tick\n      // so the user can prevent the message event.\n      queueMicrotask(() => {\n        if (!event.defaultPrevented) {\n          this.#client.dispatchEvent(event)\n        }\n      })\n    }\n\n    // Forward stream errors from the actual server to the client.\n    source.addEventListener('error', (event) => {\n      Object.defineProperties(event, {\n        target: {\n          value: this,\n          enumerable: true,\n          writable: true,\n          configurable: true,\n        },\n      })\n\n      queueMicrotask(() => {\n        // Allow the user to opt-out from this forwarding.\n        if (!event.defaultPrevented) {\n          this.#client.dispatchEvent(event)\n        }\n      })\n    })\n\n    return source\n  }\n}\n\ninterface ObservableEventSourceInit extends EventSourceInit {\n  headers?: HeadersInit\n}\n\ntype EventHandler<EventType extends Event> = (\n  this: EventSource,\n  event: EventType,\n) => any\n\nconst kRequest = Symbol('kRequest')\nconst kReconnectionTime = Symbol('kReconnectionTime')\nconst kLastEventId = Symbol('kLastEventId')\nconst kAbortController = Symbol('kAbortController')\nconst kOnOpen = Symbol('kOnOpen')\nconst kOnMessage = Symbol('kOnMessage')\nconst kOnAnyMessage = Symbol('kOnAnyMessage')\nconst kOnError = Symbol('kOnError')\n\nclass ObservableEventSource extends EventTarget implements EventSource {\n  static readonly CONNECTING = 0\n  static readonly OPEN = 1\n  static readonly CLOSED = 2\n\n  public readonly CONNECTING = ObservableEventSource.CONNECTING\n  public readonly OPEN = ObservableEventSource.OPEN\n  public readonly CLOSED = ObservableEventSource.CLOSED\n\n  public readyState: number\n  public url: string\n  public withCredentials: boolean\n\n  private [kRequest]: Request\n  private [kReconnectionTime]: number\n  private [kLastEventId]: string\n  private [kAbortController]: AbortController\n  private [kOnOpen]: EventHandler<Event> | null = null\n  private [kOnMessage]: EventHandler<MessageEvent> | null = null\n  private [kOnAnyMessage]: EventHandler<MessageEvent> | null = null\n  private [kOnError]: EventHandler<Event> | null = null\n\n  constructor(url: string | URL, init?: ObservableEventSourceInit) {\n    super()\n\n    this.url = new URL(url).href\n    this.withCredentials = init?.withCredentials ?? false\n\n    this.readyState = this.CONNECTING\n\n    // Support custom request init.\n    const headers = new Headers(init?.headers || {})\n    headers.append('accept', 'text/event-stream')\n\n    this[kAbortController] = new AbortController()\n    this[kReconnectionTime] = 2000\n    this[kLastEventId] = ''\n    this[kRequest] = new Request(this.url, {\n      method: 'GET',\n      headers,\n      credentials: this.withCredentials ? 'include' : 'omit',\n      signal: this[kAbortController].signal,\n    })\n\n    this.connect()\n  }\n\n  get onopen(): EventHandler<Event> | null {\n    return this[kOnOpen]\n  }\n\n  set onopen(handler: EventHandler<Event>) {\n    if (this[kOnOpen]) {\n      this.removeEventListener('open', this[kOnOpen])\n    }\n    this[kOnOpen] = handler.bind(this)\n    this.addEventListener('open', this[kOnOpen])\n  }\n\n  get onmessage(): EventHandler<MessageEvent> | null {\n    return this[kOnMessage]\n  }\n  set onmessage(handler: EventHandler<MessageEvent>) {\n    if (this[kOnMessage]) {\n      this.removeEventListener('message', { handleEvent: this[kOnMessage] })\n    }\n    this[kOnMessage] = handler.bind(this)\n    this.addEventListener('message', { handleEvent: this[kOnMessage] })\n  }\n\n  get onerror(): EventHandler<Event> | null {\n    return this[kOnError]\n  }\n  set oneerror(handler: EventHandler<Event>) {\n    if (this[kOnError]) {\n      this.removeEventListener('error', { handleEvent: this[kOnError] })\n    }\n    this[kOnError] = handler.bind(this)\n    this.addEventListener('error', { handleEvent: this[kOnError] })\n  }\n\n  public addEventListener<K extends keyof EventSourceEventMap>(\n    type: K,\n    listener: EventHandler<EventSourceEventMap[K]>,\n    options?: boolean | AddEventListenerOptions,\n  ): void\n  public addEventListener(\n    type: string,\n    listener: EventHandler<MessageEvent>,\n    options?: boolean | AddEventListenerOptions,\n  ): void\n  public addEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions,\n  ): void\n\n  public addEventListener(\n    type: string,\n    listener: EventHandler<MessageEvent> | EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions,\n  ): void {\n    super.addEventListener(\n      type,\n      listener as EventListenerOrEventListenerObject,\n      options,\n    )\n  }\n\n  public removeEventListener<K extends keyof EventSourceEventMap>(\n    type: K,\n    listener: (this: EventSource, ev: EventSourceEventMap[K]) => any,\n    options?: boolean | EventListenerOptions,\n  ): void\n  public removeEventListener(\n    type: string,\n    listener: (this: EventSource, event: MessageEvent) => any,\n    options?: boolean | EventListenerOptions,\n  ): void\n  public removeEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | EventListenerOptions,\n  ): void\n\n  public removeEventListener(\n    type: string,\n    listener: EventHandler<MessageEvent> | EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions,\n  ): void {\n    super.removeEventListener(\n      type,\n      listener as EventListenerOrEventListenerObject,\n      options,\n    )\n  }\n\n  public dispatchEvent(event: Event): boolean {\n    return super.dispatchEvent(event)\n  }\n\n  public close(): void {\n    this[kAbortController].abort()\n    this.readyState = this.CLOSED\n  }\n\n  private async connect() {\n    await fetch(this[kRequest])\n      .then((response) => {\n        this.processResponse(response)\n      })\n      .catch(() => {\n        // Fail the connection on request errors instead of\n        // throwing a generic \"Failed to fetch\" error.\n        this.failConnection()\n      })\n  }\n\n  private processResponse(response: Response): void {\n    if (!response.body) {\n      this.failConnection()\n      return\n    }\n\n    if (isNetworkError(response)) {\n      this.reestablishConnection()\n      return\n    }\n\n    if (\n      response.status !== 200 ||\n      response.headers.get('content-type') !== 'text/event-stream'\n    ) {\n      this.failConnection()\n      return\n    }\n\n    this.announceConnection()\n    this.interpretResponseBody(response)\n  }\n\n  private announceConnection(): void {\n    queueMicrotask(() => {\n      if (this.readyState !== this.CLOSED) {\n        this.readyState = this.OPEN\n        this.dispatchEvent(new Event('open'))\n      }\n    })\n  }\n\n  private interpretResponseBody(response: Response): void {\n    const parsingStream = new EventSourceParsingStream({\n      message: (message) => {\n        if (message.id) {\n          this[kLastEventId] = message.id\n        }\n\n        if (message.retry) {\n          this[kReconnectionTime] = message.retry\n        }\n\n        const messageEvent = new MessageEvent(\n          message.event ? message.event : 'message',\n          {\n            data: message.data,\n            origin: this[kRequest].url,\n            lastEventId: this[kLastEventId],\n            cancelable: true,\n          },\n        )\n\n        this[kOnAnyMessage]?.(messageEvent)\n        this.dispatchEvent(messageEvent)\n      },\n      abort: () => {\n        throw new Error('Stream abort is not implemented')\n      },\n      close: () => {\n        this.failConnection()\n      },\n    })\n\n    response\n      .body!.pipeTo(parsingStream)\n      .then(() => {\n        this.processResponseEndOfBody(response)\n      })\n      .catch(() => {\n        this.failConnection()\n      })\n  }\n\n  private processResponseEndOfBody(response: Response): void {\n    if (!isNetworkError(response)) {\n      this.reestablishConnection()\n    }\n  }\n\n  private async reestablishConnection(): Promise<void> {\n    queueMicrotask(() => {\n      if (this.readyState === this.CLOSED) {\n        return\n      }\n\n      this.readyState = this.CONNECTING\n      this.dispatchEvent(new Event('error'))\n    })\n\n    await delay(this[kReconnectionTime])\n\n    queueMicrotask(async () => {\n      if (this.readyState !== this.CONNECTING) {\n        return\n      }\n\n      if (this[kLastEventId] !== '') {\n        this[kRequest].headers.set('last-event-id', this[kLastEventId])\n      }\n\n      await this.connect()\n    })\n  }\n\n  private failConnection(): void {\n    queueMicrotask(() => {\n      if (this.readyState !== this.CLOSED) {\n        this.readyState = this.CLOSED\n        this.dispatchEvent(new Event('error'))\n      }\n    })\n  }\n}\n\n/**\n * Checks if the given `Response` instance is a network error.\n * @see https://fetch.spec.whatwg.org/#concept-network-error\n */\nfunction isNetworkError(response: Response): boolean {\n  return (\n    response.type === 'error' &&\n    response.status === 0 &&\n    response.statusText === '' &&\n    Array.from(response.headers.entries()).length === 0 &&\n    response.body === null\n  )\n}\n\nconst enum ControlCharacters {\n  NewLine = 10,\n  CarriageReturn = 13,\n  Space = 32,\n  Colon = 58,\n}\n\ninterface EventSourceMessage {\n  id?: string\n  event?: string\n  data?: string\n  retry?: number\n}\n\nclass EventSourceParsingStream extends WritableStream {\n  private decoder: TextDecoder\n\n  private buffer?: Uint8Array\n  private position: number\n  private fieldLength?: number\n  private discardTrailingNewline = false\n\n  private message: EventSourceMessage = {\n    id: undefined,\n    event: undefined,\n    data: undefined,\n    retry: undefined,\n  }\n\n  constructor(\n    private underlyingSink: {\n      message: (message: EventSourceMessage) => void\n      abort?: (reason: any) => void\n      close?: () => void\n    },\n  ) {\n    super({\n      write: (chunk) => {\n        this.processResponseBodyChunk(chunk)\n      },\n      abort: (reason) => {\n        this.underlyingSink.abort?.(reason)\n      },\n      close: () => {\n        this.underlyingSink.close?.()\n      },\n    })\n\n    this.decoder = new TextDecoder()\n    this.position = 0\n  }\n\n  private resetMessage(): void {\n    this.message = {\n      id: undefined,\n      event: undefined,\n      data: undefined,\n      retry: undefined,\n    }\n  }\n\n  private processResponseBodyChunk(chunk: Uint8Array): void {\n    if (this.buffer == null) {\n      this.buffer = chunk\n      this.position = 0\n      this.fieldLength = -1\n    } else {\n      const nextBuffer = new Uint8Array(this.buffer.length + chunk.length)\n      nextBuffer.set(this.buffer)\n      nextBuffer.set(chunk, this.buffer.length)\n      this.buffer = nextBuffer\n    }\n\n    const bufferLength = this.buffer.length\n    let lineStart = 0\n\n    while (this.position < bufferLength) {\n      if (this.discardTrailingNewline) {\n        if (this.buffer[this.position] === ControlCharacters.NewLine) {\n          lineStart = ++this.position\n        }\n\n        this.discardTrailingNewline = false\n      }\n\n      let lineEnd = -1\n\n      for (; this.position < bufferLength && lineEnd === -1; ++this.position) {\n        switch (this.buffer[this.position]) {\n          case ControlCharacters.Colon: {\n            if (this.fieldLength === -1) {\n              this.fieldLength = this.position - lineStart\n            }\n            break\n          }\n\n          case ControlCharacters.CarriageReturn: {\n            this.discardTrailingNewline = true\n            break\n          }\n\n          case ControlCharacters.NewLine: {\n            lineEnd = this.position\n            break\n          }\n        }\n      }\n\n      if (lineEnd === -1) {\n        break\n      }\n\n      this.processLine(\n        this.buffer.subarray(lineStart, lineEnd),\n        this.fieldLength!,\n      )\n\n      lineStart = this.position\n      this.fieldLength = -1\n    }\n\n    if (lineStart === bufferLength) {\n      this.buffer = undefined\n    } else if (lineStart !== 0) {\n      this.buffer = this.buffer.subarray(lineStart)\n      this.position -= lineStart\n    }\n  }\n\n  private processLine(line: Uint8Array, fieldLength: number): void {\n    // New line indicates the end of the message. Dispatch it.\n    if (line.length === 0) {\n      // Prevent dispatching the message if the data is an empty string.\n      // That is a no-op per spec.\n      if (this.message.data === undefined) {\n        this.message.event = undefined\n        return\n      }\n\n      this.underlyingSink.message(this.message)\n      this.resetMessage()\n      return\n    }\n\n    // Otherwise, keep accumulating message fields until the new line.\n    if (fieldLength > 0) {\n      const field = this.decoder.decode(line.subarray(0, fieldLength))\n      const valueOffset =\n        fieldLength +\n        (line[fieldLength + 1] === ControlCharacters.Space ? 2 : 1)\n      const value = this.decoder.decode(line.subarray(valueOffset))\n\n      switch (field) {\n        case 'data': {\n          this.message.data = this.message.data\n            ? this.message.data + '\\n' + value\n            : value\n          break\n        }\n\n        case 'event': {\n          this.message.event = value\n          break\n        }\n\n        case 'id': {\n          this.message.id = value\n          break\n        }\n\n        case 'retry': {\n          const retry = parseInt(value, 10)\n\n          if (!isNaN(retry)) {\n            this.message.retry = retry\n          }\n          break\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/typeUtils.ts",
    "content": "type Fn = (...arg: any[]) => any\n\nexport type MaybePromise<T> = T | Promise<T>\n\nexport type RequiredDeep<\n  Type,\n  U extends Record<string, unknown> | Fn | undefined = undefined,\n> = Type extends Fn\n  ? Type\n  : /**\n     * @note The \"Fn\" type satisfies the predicate below.\n     * It must always come first, before the Record check.\n     */\n    Type extends Record<string, any>\n    ? {\n        [Key in keyof Type]-?: NonNullable<Type[Key]> extends NonNullable<U>\n          ? NonNullable<Type[Key]>\n          : RequiredDeep<NonNullable<Type[Key]>, U>\n      }\n    : Type\n\n/**\n * @fixme Remove this once TS 5.4 is the lowest supported version.\n * Because \"NoInfer\" is a built-in type utility there.\n */\nexport type NoInfer<T> = [T][T extends any ? 0 : never]\n"
  },
  {
    "path": "src/core/utils/HttpResponse/decorators.ts",
    "content": "import statuses from '../../../shims/statuses'\nimport { Headers as HeadersPolyfill } from 'headers-polyfill'\nimport type { HttpResponseInit } from '../../HttpResponse'\n\nconst { message } = statuses\n\nexport const kSetCookie = Symbol('kSetCookie')\n\nexport interface HttpResponseDecoratedInit extends HttpResponseInit {\n  status: number\n  statusText: string\n  headers: Headers\n}\n\nexport function normalizeResponseInit(\n  init: HttpResponseInit = {},\n): HttpResponseDecoratedInit {\n  const status = init?.status || 200\n  const statusText = init?.statusText || message[status] || ''\n  const headers = new Headers(init?.headers)\n\n  return {\n    ...init,\n    headers,\n    status,\n    statusText,\n  }\n}\n\nexport function decorateResponse(\n  response: Response,\n  init: HttpResponseDecoratedInit,\n): Response {\n  // Allow to mock the response type.\n  if (init.type) {\n    Object.defineProperty(response, 'type', {\n      value: init.type,\n      enumerable: true,\n      writable: false,\n    })\n  }\n\n  const responseCookies = init.headers.get('set-cookie')\n\n  if (responseCookies) {\n    // Record the raw \"Set-Cookie\" response header provided\n    // in the HeadersInit. This is later used to store these cookies\n    // in cookie jar and return the right cookies in the \"cookies\"\n    // response resolver argument.\n    Object.defineProperty(response, kSetCookie, {\n      value: responseCookies,\n      enumerable: false,\n      writable: false,\n    })\n\n    // Cookie forwarding is only relevant in the browser.\n    if (typeof document !== 'undefined') {\n      // Write the mocked response cookies to the document.\n      // Use `headers-polyfill` to get the Set-Cookie header value correctly.\n      // This is an alternative until TypeScript 5.2\n      // and Node.js v20 become the minimum supported version\n      // and getSetCookie in Headers can be used directly.\n      const responseCookiePairs = HeadersPolyfill.prototype.getSetCookie.call(\n        init.headers,\n      )\n\n      for (const cookieString of responseCookiePairs) {\n        // No need to parse the cookie headers because it's defined\n        // as the valid cookie string to begin with.\n        document.cookie = cookieString\n      }\n    }\n  }\n\n  return response\n}\n"
  },
  {
    "path": "src/core/utils/cookieStore.ts",
    "content": "import { isNodeProcess } from 'is-node-process'\nimport { invariant } from 'outvariant'\nimport {\n  Cookie,\n  CookieJar,\n  MemoryCookieStore,\n  type MemoryCookieStoreIndex,\n} from 'tough-cookie'\nimport { jsonParse } from './internal/jsonParse'\n\nclass CookieStore {\n  #storageKey = '__msw-cookie-store__'\n  #jar: CookieJar\n  #memoryStore: MemoryCookieStore\n\n  constructor() {\n    if (!isNodeProcess()) {\n      invariant(\n        typeof localStorage !== 'undefined',\n        'Failed to create a CookieStore: `localStorage` is not available in this environment. This is likely an issue with your environment, which has been detected as browser (or browser-like) environment and must implement global browser APIs correctly.',\n      )\n    }\n\n    this.#memoryStore = new MemoryCookieStore()\n    this.#memoryStore.idx = this.getCookieStoreIndex()\n    this.#jar = new CookieJar(this.#memoryStore)\n  }\n\n  public getCookies(url: string): Array<Cookie> {\n    return this.#jar.getCookiesSync(url)\n  }\n\n  public async setCookie(cookieName: string, url: string): Promise<void> {\n    await this.#jar.setCookie(cookieName, url)\n    this.persist()\n  }\n\n  private getCookieStoreIndex(): MemoryCookieStoreIndex {\n    if (\n      typeof localStorage === 'undefined' ||\n      typeof localStorage.getItem !== 'function'\n    ) {\n      return {}\n    }\n\n    const cookiesString = localStorage.getItem(this.#storageKey)\n    if (cookiesString == null) {\n      return {}\n    }\n\n    const rawCookies = jsonParse<Array<Record<string, unknown>>>(cookiesString)\n    if (rawCookies == null) {\n      return {}\n    }\n\n    const cookies: MemoryCookieStoreIndex = {}\n\n    for (const rawCookie of rawCookies) {\n      const cookie = Cookie.fromJSON(rawCookie)\n\n      if (cookie != null && cookie.domain != null && cookie.path != null) {\n        cookies[cookie.domain] ||= {}\n        cookies[cookie.domain][cookie.path] ||= {}\n        cookies[cookie.domain][cookie.path][cookie.key] = cookie\n      }\n    }\n\n    return cookies\n  }\n\n  private persist(): void {\n    if (\n      typeof localStorage === 'undefined' ||\n      typeof localStorage.setItem !== 'function'\n    ) {\n      return\n    }\n\n    const data = []\n    const { idx } = this.#memoryStore\n\n    for (const domain in idx) {\n      for (const path in idx[domain]) {\n        for (const key in idx[domain][path]) {\n          data.push(idx[domain][path][key].toJSON())\n        }\n      }\n    }\n\n    localStorage.setItem(this.#storageKey, JSON.stringify(data))\n  }\n}\n\nexport const cookieStore = new CookieStore()\n"
  },
  {
    "path": "src/core/utils/executeHandlers.ts",
    "content": "import {\n  RequestHandler,\n  type RequestHandlerExecutionResult,\n} from '../handlers/RequestHandler'\n\nexport interface HandlersExecutionResult {\n  handler: RequestHandler\n  parsedResult?: any\n  response?: Response\n}\n\nexport interface ResponseResolutionContext {\n  /**\n   * A base url to use when resolving relative urls.\n   * @note This is primarily used by the `@mswjs/http-middleware`\n   * to resolve relative urls in the context of the running server\n   */\n  baseUrl?: string\n  quiet?: boolean\n}\n\n/**\n * Executes the list of request handlers against the given request.\n * Returns the execution result object containing any matching request\n * handler and any mocked response it returned.\n */\nexport const executeHandlers = async <Handlers extends Array<RequestHandler>>({\n  request,\n  requestId,\n  handlers,\n  resolutionContext,\n}: {\n  request: Request\n  requestId: string\n  handlers: Handlers\n  resolutionContext?: ResponseResolutionContext\n}): Promise<HandlersExecutionResult | null> => {\n  let matchingHandler: RequestHandler | null = null\n  let result: RequestHandlerExecutionResult<any> | null = null\n\n  for (const handler of handlers) {\n    result = await handler.run({ request, requestId, resolutionContext })\n\n    // If the handler produces some result for this request,\n    // it automatically becomes matching.\n    if (result !== null) {\n      matchingHandler = handler\n    }\n\n    // Stop the lookup if this handler returns a mocked response.\n    // If it doesn't, it will still be considered the last matching\n    // handler until any of them returns a response. This way we can\n    // distinguish between fallthrough handlers without responses\n    // and the lack of a matching handler.\n    if (result?.response) {\n      break\n    }\n  }\n\n  if (matchingHandler) {\n    return {\n      handler: matchingHandler,\n      parsedResult: result?.parsedResult,\n      response: result?.response,\n    }\n  }\n\n  return null\n}\n"
  },
  {
    "path": "src/core/utils/handleRequest.test.ts",
    "content": "// @vitest-environment jsdom\nimport { Emitter } from 'strict-event-emitter'\nimport { createRequestId } from '@mswjs/interceptors'\nimport { LifeCycleEventsMap, SharedOptions } from '../sharedOptions'\nimport { RequestHandler } from '../handlers/RequestHandler'\nimport { http } from '../http'\nimport { handleRequest, HandleRequestOptions } from './handleRequest'\nimport { RequiredDeep } from '../typeUtils'\nimport { HttpResponse } from '../HttpResponse'\nimport { passthrough } from '../passthrough'\n\nconst options: RequiredDeep<SharedOptions> = {\n  onUnhandledRequest: vi.fn(),\n}\nconst handleRequestOptions: Partial<Record<keyof HandleRequestOptions, any>> = {\n  onPassthroughResponse: vi.fn(),\n  onMockedResponse: vi.fn(),\n}\n\nfunction setup() {\n  const emitter = new Emitter<LifeCycleEventsMap>()\n  const listener = vi.fn()\n\n  const createMockListener = (name: string) => {\n    return (...args: any) => {\n      listener(name, ...args)\n    }\n  }\n\n  emitter.on('request:start', createMockListener('request:start'))\n  emitter.on('request:match', createMockListener('request:match'))\n  emitter.on('request:unhandled', createMockListener('request:unhandled'))\n  emitter.on('request:end', createMockListener('request:end'))\n  emitter.on('response:mocked', createMockListener('response:mocked'))\n  emitter.on('response:bypass', createMockListener('response:bypass'))\n\n  const events = listener.mock.calls\n  return { emitter, events }\n}\n\nbeforeEach(() => {\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\ntest('returns undefined for a request with the \"accept: msw/passthrough\" header equal to \"bypass\"', async () => {\n  const { emitter, events } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'), {\n    headers: new Headers({\n      accept: 'msw/passthrough',\n    }),\n  })\n  const handlers: Array<RequestHandler> = []\n\n  const result = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).toBeUndefined()\n  expect(events).toEqual([\n    ['request:start', { request, requestId }],\n    ['request:end', { request, requestId }],\n  ])\n  expect(options.onUnhandledRequest).not.toHaveBeenCalled()\n  expect(handleRequestOptions.onPassthroughResponse).toHaveBeenNthCalledWith(\n    1,\n    request,\n  )\n  expect(handleRequestOptions.onMockedResponse).not.toHaveBeenCalled()\n})\n\ntest('does not bypass a request with \"accept: msw/*\" header set to arbitrary value', async () => {\n  const { emitter } = setup()\n\n  const request = new Request(new URL('http://localhost/user'), {\n    headers: new Headers({\n      accept: 'msw/invalid',\n    }),\n  })\n  const handlers: Array<RequestHandler> = [\n    http.get('/user', () => {\n      return HttpResponse.text('hello world')\n    }),\n  ]\n\n  const result = await handleRequest(\n    request,\n    createRequestId(),\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).not.toBeUndefined()\n  expect(options.onUnhandledRequest).not.toHaveBeenCalled()\n  expect(handleRequestOptions.onMockedResponse).toHaveBeenCalledTimes(1)\n})\n\ntest('reports request as unhandled when it has no matching request handlers', async () => {\n  const { emitter, events } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'))\n  const handlers: Array<RequestHandler> = []\n\n  const result = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).toBeUndefined()\n  expect(events).toEqual([\n    ['request:start', { request, requestId }],\n    ['request:unhandled', { request, requestId }],\n    ['request:end', { request, requestId }],\n  ])\n  expect(options.onUnhandledRequest).toHaveBeenNthCalledWith(1, request, {\n    warning: expect.any(Function),\n    error: expect.any(Function),\n  })\n  expect(handleRequestOptions.onPassthroughResponse).toHaveBeenNthCalledWith(\n    1,\n    request,\n  )\n  expect(handleRequestOptions.onMockedResponse).not.toHaveBeenCalled()\n})\n\ntest('returns undefined on a request handler that returns no response', async () => {\n  const { emitter, events } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'))\n  const handlers: Array<RequestHandler> = [\n    http.get('/user', () => {\n      // Intentionally blank response resolver.\n      return\n    }),\n  ]\n\n  const result = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).toBeUndefined()\n  expect(events).toEqual([\n    ['request:start', { request, requestId }],\n    ['request:end', { request, requestId }],\n  ])\n  expect(options.onUnhandledRequest).not.toHaveBeenCalled()\n  expect(handleRequestOptions.onPassthroughResponse).toHaveBeenNthCalledWith(\n    1,\n    request,\n  )\n  expect(handleRequestOptions.onMockedResponse).not.toHaveBeenCalled()\n\n  /**\n   * @note Returning undefined from a resolver no longer prints a warning.\n   */\n  expect(console.warn).toHaveBeenCalledTimes(0)\n})\n\ntest('returns the mocked response for a request with a matching request handler', async () => {\n  const { emitter, events } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'))\n  const mockedResponse = HttpResponse.json({ firstName: 'John' })\n  const handlers: Array<RequestHandler> = [\n    http.get('/user', () => {\n      return mockedResponse\n    }),\n  ]\n  const lookupResult = {\n    handler: handlers[0],\n    response: mockedResponse,\n    request,\n    parsedResult: {\n      match: { matches: true, params: {} },\n      cookies: {},\n    },\n  }\n\n  const result = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).toEqual(mockedResponse)\n  expect(events).toEqual([\n    ['request:start', { request, requestId }],\n    ['request:match', { request, requestId }],\n    ['request:end', { request, requestId }],\n  ])\n  expect(handleRequestOptions.onPassthroughResponse).not.toHaveBeenCalled()\n\n  expect(handleRequestOptions.onMockedResponse).toHaveBeenCalledTimes(1)\n  const [mockedResponseParam, lookupResultParam] =\n    handleRequestOptions.onMockedResponse.mock.calls[0]\n\n  expect(mockedResponseParam.status).toBe(mockedResponse.status)\n  expect(mockedResponseParam.statusText).toBe(mockedResponse.statusText)\n  expect(Object.fromEntries(mockedResponseParam.headers.entries())).toEqual(\n    Object.fromEntries(mockedResponse.headers.entries()),\n  )\n\n  expect(lookupResultParam).toEqual({\n    handler: lookupResult.handler,\n    parsedResult: lookupResult.parsedResult,\n    response: expect.objectContaining({\n      status: lookupResult.response.status,\n      statusText: lookupResult.response.statusText,\n    }),\n  })\n})\n\nit('returns undefined without warning on a passthrough request', async () => {\n  const { emitter, events } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'))\n  const handlers: Array<RequestHandler> = [\n    http.get('/user', () => {\n      return passthrough()\n    }),\n  ]\n\n  const result = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(result).toBeUndefined()\n  expect(events).toEqual([\n    ['request:start', { request, requestId }],\n    ['request:end', { request, requestId }],\n  ])\n  expect(options.onUnhandledRequest).not.toHaveBeenCalled()\n  expect(handleRequestOptions.onPassthroughResponse).toHaveBeenNthCalledWith(\n    1,\n    request,\n  )\n  expect(handleRequestOptions.onMockedResponse).not.toHaveBeenCalled()\n})\n\nit('calls the handler with the requestId', async () => {\n  const { emitter } = setup()\n\n  const requestId = createRequestId()\n  const request = new Request(new URL('http://localhost/user'))\n  const handlerFn = vi.fn()\n  const handlers: Array<RequestHandler> = [http.get('/user', handlerFn)]\n\n  await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(handlerFn).toHaveBeenCalledWith(expect.objectContaining({ requestId }))\n})\n\nit('marks the first matching one-time handler as used', async () => {\n  const { emitter } = setup()\n\n  const oneTimeHandler = http.get(\n    '/resource',\n    () => {\n      return HttpResponse.text('One-time')\n    },\n    { once: true },\n  )\n  const anotherHandler = http.get('/resource', () => {\n    return HttpResponse.text('Another')\n  })\n  const handlers: Array<RequestHandler> = [oneTimeHandler, anotherHandler]\n\n  const requestId = createRequestId()\n  const request = new Request('http://localhost/resource')\n  const firstResult = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(await firstResult?.text()).toBe('One-time')\n  expect(oneTimeHandler.isUsed).toBe(true)\n  expect(anotherHandler.isUsed).toBe(false)\n\n  const secondResult = await handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(await secondResult?.text()).toBe('Another')\n  expect(anotherHandler.isUsed).toBe(true)\n  expect(oneTimeHandler.isUsed).toBe(true)\n})\n\nit('does not mark non-matching one-time handlers as used', async () => {\n  const { emitter } = setup()\n\n  const oneTimeHandler = http.get(\n    '/resource',\n    () => {\n      return HttpResponse.text('One-time')\n    },\n    { once: true },\n  )\n  const anotherHandler = http.get(\n    '/another',\n    () => {\n      return HttpResponse.text('Another')\n    },\n    { once: true },\n  )\n  const handlers: Array<RequestHandler> = [oneTimeHandler, anotherHandler]\n\n  const requestId = createRequestId()\n  const firstResult = await handleRequest(\n    new Request('http://localhost/another'),\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(await firstResult?.text()).toBe('Another')\n  expect(oneTimeHandler.isUsed).toBe(false)\n  expect(anotherHandler.isUsed).toBe(true)\n\n  const secondResult = await handleRequest(\n    new Request('http://localhost/resource'),\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  expect(await secondResult?.text()).toBe('One-time')\n  expect(anotherHandler.isUsed).toBe(true)\n  expect(oneTimeHandler.isUsed).toBe(true)\n})\n\nit('handles parallel requests with one-time handlers', async () => {\n  const { emitter } = setup()\n\n  const oneTimeHandler = http.get(\n    '/resource',\n    () => {\n      return HttpResponse.text('One-time')\n    },\n    { once: true },\n  )\n  const anotherHandler = http.get('/resource', () => {\n    return HttpResponse.text('Another')\n  })\n  const handlers: Array<RequestHandler> = [oneTimeHandler, anotherHandler]\n\n  const requestId = createRequestId()\n  const request = new Request('http://localhost/resource')\n  const firstResultPromise = handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n  const secondResultPromise = handleRequest(\n    request,\n    requestId,\n    handlers,\n    options,\n    emitter,\n    handleRequestOptions,\n  )\n\n  const firstResult = await firstResultPromise\n  const secondResult = await secondResultPromise\n\n  expect(await firstResult?.text()).toBe('One-time')\n  expect(await secondResult?.text()).toBe('Another')\n  expect(oneTimeHandler.isUsed).toBe(true)\n  expect(anotherHandler.isUsed).toBe(true)\n})\n\ndescribe('[Private] - resolutionContext - used for extensions', () => {\n  describe('#baseUrl', () => {\n    test('when defined, handle requests to that base url only defining pathnames in the handler', async () => {\n      const { emitter } = setup()\n\n      const baseUrl = 'http://this-base-url-works.com'\n      const handleRequestOptionsWithBaseUrl: HandleRequestOptions = {\n        ...handleRequestOptions,\n        resolutionContext: { baseUrl },\n      }\n\n      const handler = http.get('/resource', () => {\n        return HttpResponse.text('Mocked response')\n      })\n\n      const handlers: Array<RequestHandler> = [handler]\n\n      const requestId = createRequestId()\n      const request = new Request(new URL('/resource', baseUrl))\n      const response = await handleRequest(\n        request,\n        requestId,\n        handlers,\n        options,\n        emitter,\n        handleRequestOptionsWithBaseUrl,\n      )\n\n      expect(await response?.text()).toBe('Mocked response')\n    })\n\n    test('when defined, do not handle requests to different base urls when defining pathnames in the handler', async () => {\n      const { emitter } = setup()\n\n      const baseUrl = 'http://this-base-url-works.com'\n      const handleRequestOptionsWithBaseUrl: HandleRequestOptions = {\n        ...handleRequestOptions,\n        resolutionContext: { baseUrl },\n      }\n\n      const handler = http.get('/resource', () => {\n        return HttpResponse.text('Mocked response')\n      })\n\n      const handlers: Array<RequestHandler> = [handler]\n\n      const requestId = createRequestId()\n      const request = new Request(\n        new URL('/resource', `http://not-the-base-url.com`),\n      )\n      const response = await handleRequest(\n        request,\n        requestId,\n        handlers,\n        options,\n        emitter,\n        handleRequestOptionsWithBaseUrl,\n      )\n\n      expect(response).toBeUndefined()\n    })\n  })\n})\n\ndescribe('handler with custom predicate', () => {\n  test('matches if custom predicate returns true', async () => {\n    const { emitter, events } = setup()\n\n    const requestId = createRequestId()\n    const request = new Request(new URL('http://localhost/login'), {\n      method: 'POST',\n      body: JSON.stringify({ username: 'test', password: 'password' }),\n      headers: { 'Content-Type': 'application/json' },\n    })\n    const handlers: Array<RequestHandler> = [\n      http.post(\n        async ({ request }) => {\n          const body = await request.clone().json()\n          return body.username === 'test' && body.password === 'password'\n        },\n        () =>\n          HttpResponse.json({\n            success: true,\n          }),\n      ),\n    ]\n\n    const result = await handleRequest(\n      request,\n      requestId,\n      handlers,\n      options,\n      emitter,\n      handleRequestOptions,\n    )\n\n    expect(result).toBeDefined()\n    expect(await result?.json()).toStrictEqual({ success: true })\n    expect(events).toEqual([\n      ['request:start', { request, requestId }],\n      ['request:match', { request, requestId }],\n      ['request:end', { request, requestId }],\n    ])\n    expect(handleRequestOptions.onMockedResponse).toHaveBeenCalledTimes(1)\n  })\n\n  test('does not match if custom predicate returns false', async () => {\n    const { emitter, events } = setup()\n\n    const requestId = createRequestId()\n    const request = new Request(new URL('http://localhost/login'), {\n      method: 'POST',\n      body: JSON.stringify({ username: 'test', password: 'passwordd' }),\n      headers: { 'Content-Type': 'application/json' },\n    })\n    const handlers: Array<RequestHandler> = [\n      http.post(\n        async ({ request }) => {\n          const body = await request.clone().json()\n          return body.username === 'test' && body.password === 'password'\n        },\n        () =>\n          HttpResponse.json({\n            success: true,\n          }),\n      ),\n    ]\n\n    const result = await handleRequest(\n      request,\n      requestId,\n      handlers,\n      options,\n      emitter,\n      handleRequestOptions,\n    )\n\n    expect(result).toBeUndefined()\n    expect(events).toEqual([\n      ['request:start', { request, requestId }],\n      ['request:unhandled', { request, requestId }],\n      ['request:end', { request, requestId }],\n    ])\n    expect(options.onUnhandledRequest).toHaveBeenCalledTimes(1)\n    expect(handleRequestOptions.onPassthroughResponse).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "src/core/utils/handleRequest.ts",
    "content": "import { until } from 'until-async'\nimport { Emitter } from 'strict-event-emitter'\nimport { LifeCycleEventsMap, SharedOptions } from '../sharedOptions'\nimport { RequiredDeep } from '../typeUtils'\nimport type { RequestHandler } from '../handlers/RequestHandler'\nimport {\n  type HandlersExecutionResult,\n  type ResponseResolutionContext,\n  executeHandlers,\n} from './executeHandlers'\nimport { onUnhandledRequest } from './request/onUnhandledRequest'\nimport { storeResponseCookies } from './request/storeResponseCookies'\n\nexport interface HandleRequestOptions {\n  /**\n   * `resolutionContext` is not part of the general public api\n   * but is exposed to aid in creating extensions like\n   * `@mswjs/http-middleware`.\n   */\n  resolutionContext?: ResponseResolutionContext\n\n  /**\n   * Invoked whenever a request is performed as-is.\n   */\n  onPassthroughResponse?(request: Request): void\n\n  /**\n   * Invoked when the mocked response is ready to be sent.\n   */\n  onMockedResponse?(\n    response: Response,\n    handler: RequiredDeep<HandlersExecutionResult>,\n  ): void\n}\n\nexport async function handleRequest(\n  request: Request,\n  requestId: string,\n  handlers: Array<RequestHandler>,\n  options: RequiredDeep<SharedOptions>,\n  emitter: Emitter<LifeCycleEventsMap>,\n  handleRequestOptions?: HandleRequestOptions,\n): Promise<Response | undefined> {\n  emitter.emit('request:start', { request, requestId })\n\n  // Perform requests wrapped in \"bypass()\" as-is.\n  if (request.headers.get('accept')?.includes('msw/passthrough')) {\n    emitter.emit('request:end', { request, requestId })\n    handleRequestOptions?.onPassthroughResponse?.(request)\n    return\n  }\n\n  // Resolve a mocked response from the list of request handlers.\n  const [lookupError, lookupResult] = await until(() => {\n    return executeHandlers({\n      request,\n      requestId,\n      handlers,\n      resolutionContext: handleRequestOptions?.resolutionContext,\n    })\n  })\n\n  if (lookupError) {\n    // Allow developers to react to unhandled exceptions in request handlers.\n    emitter.emit('unhandledException', {\n      error: lookupError,\n      request,\n      requestId,\n    })\n    throw lookupError\n  }\n\n  // If the handler lookup returned nothing, no request handler was found\n  // matching this request. Report the request as unhandled.\n  if (!lookupResult) {\n    await onUnhandledRequest(request, options.onUnhandledRequest)\n    emitter.emit('request:unhandled', { request, requestId })\n    emitter.emit('request:end', { request, requestId })\n    handleRequestOptions?.onPassthroughResponse?.(request)\n    return\n  }\n\n  const { response } = lookupResult\n\n  // When the handled request returned no mocked response, warn the developer,\n  // as it may be an oversight on their part. Perform the request as-is.\n  if (!response) {\n    emitter.emit('request:end', { request, requestId })\n    handleRequestOptions?.onPassthroughResponse?.(request)\n    return\n  }\n\n  // Perform the request as-is when the developer explicitly returned \"req.passthrough()\".\n  // This produces no warning as the request was handled.\n  if (\n    response.status === 302 &&\n    response.headers.get('x-msw-intention') === 'passthrough'\n  ) {\n    emitter.emit('request:end', { request, requestId })\n    handleRequestOptions?.onPassthroughResponse?.(request)\n    return\n  }\n\n  // Store all the received response cookies in the cookie jar.\n  await storeResponseCookies(request, response)\n\n  emitter.emit('request:match', { request, requestId })\n\n  const requiredLookupResult =\n    lookupResult as RequiredDeep<HandlersExecutionResult>\n\n  handleRequestOptions?.onMockedResponse?.(response, requiredLookupResult)\n\n  emitter.emit('request:end', { request, requestId })\n\n  return response\n}\n"
  },
  {
    "path": "src/core/utils/internal/Disposable.ts",
    "content": "export type DisposableSubscription = () => void\n\nexport class Disposable {\n  protected subscriptions: Array<DisposableSubscription> = []\n\n  public dispose() {\n    let subscription: DisposableSubscription | undefined\n    while ((subscription = this.subscriptions.shift())) {\n      subscription()\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/checkGlobals.ts",
    "content": "import { invariant } from 'outvariant'\nimport { devUtils } from './devUtils'\n\nexport function checkGlobals() {\n  /**\n   * MSW expects the \"URL\" constructor to be defined.\n   * It's not present in React Native so suggest a polyfill\n   * instead of failing silently.\n   * @see https://github.com/mswjs/msw/issues/1408\n   */\n  invariant(\n    typeof URL !== 'undefined',\n    devUtils.formatMessage(\n      `Global \"URL\" class is not defined. This likely means that you're running MSW in an environment that doesn't support all Node.js standard API (e.g. React Native). If that's the case, please use an appropriate polyfill for the \"URL\" class, like \"react-native-url-polyfill\".`,\n    ),\n  )\n}\n"
  },
  {
    "path": "src/core/utils/internal/devUtils.test.ts",
    "content": "import { InternalError } from './devUtils'\n\ndescribe(InternalError, () => {\n  it('creates an InternalError instance', () => {\n    const error = new InternalError('Message')\n\n    expect(error.name).toBe('InternalError')\n    expect(error.message).toBe('Message')\n    expect(error.toString()).toBe('InternalError: Message')\n    expect(error.stack).toMatch(/\\w+/)\n  })\n\n  it('passes the identity check', () => {\n    const error = new InternalError('Message')\n    expect(error instanceof InternalError).toBe(true)\n    expect(error instanceof Error).toBe(true)\n\n    const extraneousError = new Error('Message')\n    expect(extraneousError).not.toBeInstanceOf(InternalError)\n  })\n})\n"
  },
  {
    "path": "src/core/utils/internal/devUtils.ts",
    "content": "import { format } from 'outvariant'\n\nconst LIBRARY_PREFIX = '[MSW]'\n\n/**\n * Formats a given message by appending the library's prefix string.\n */\nfunction formatMessage(message: string, ...positionals: any[]): string {\n  const interpolatedMessage = format(message, ...positionals)\n  return `${LIBRARY_PREFIX} ${interpolatedMessage}`\n}\n\n/**\n * Prints a library-specific warning.\n */\nfunction warn(message: string, ...positionals: any[]): void {\n  console.warn(formatMessage(message, ...positionals))\n}\n\n/**\n * Prints a library-specific error.\n */\nfunction error(message: string, ...positionals: any[]): void {\n  console.error(formatMessage(message, ...positionals))\n}\n\nexport const devUtils = {\n  formatMessage,\n  warn,\n  error,\n}\n\n/**\n * Internal error instance.\n * Used to differentiate the library errors that must be forwarded\n * to the user from the unhandled exceptions. Use this if you don't\n * wish for the error to be coerced to a 500 fallback response.\n */\nexport class InternalError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = 'InternalError'\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/getCallFrame.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { getCallFrame } from './getCallFrame'\n\nclass ErrorWithStack extends Error {\n  constructor(stack: string[] | undefined | null) {\n    super('')\n    this.stack = stack?.join('\\n')\n  }\n}\n\ntest('supports Node.js (Linux, MacOS) error stack', () => {\n  const linuxError = new ErrorWithStack([\n    'Error: ',\n    '    at getCallFrame (/Users/mock/github/msw/lib/node/index.js:3735:22)',\n    '    at Object.get (/Users/mock/github/msw/lib/node/index.js:3776:29)',\n    '    at Object.<anonymous> (/Users/mock/github/msw/test/msw-api/setup-server/listHandlers.test.ts:13:8)', // <-- this one\n    '    at Runtime._execModule (/Users/mock/github/msw/node_modules/jest-runtime/build/index.js:1299:24)',\n    '    at Runtime._loadModule (/Users/mock/github/msw/node_modules/jest-runtime/build/index.js:898:12)',\n    '    at Runtime.requireModule (/Users/mock/github/msw/node_modules/jest-runtime/build/index.js:746:10)',\n    '    at jasmine2 (/Users/mock/github/msw/node_modules/jest-jasmine2/build/index.js:230:13)',\n    '    at runTestInternal (/Users/mock/github/msw/node_modules/jest-runner/build/runTest.js:380:22)',\n    '    at runTest (/Users/mock/github/msw/node_modules/jest-runner/build/runTest.js:472:34)',\n  ])\n  expect(getCallFrame(linuxError)).toEqual(\n    '/Users/mock/github/msw/test/msw-api/setup-server/listHandlers.test.ts:13:8',\n  )\n\n  const macOsError = new ErrorWithStack([\n    'Error: ',\n    '    at getCallFrame (/Users/mock/git/msw/lib/node/index.js:3735:22)',\n    '    at graphQLRequestHandler (/Users/mock/git/msw/lib/node/index.js:7071:25)',\n    '    at Object.query (/Users/mock/git/msw/lib/node/index.js:7182:18)',\n    '    at Object.<anonymous> (/Users/mock/git/msw/test/msw-api/setup-server/listHandlers.test.ts:14:11)', // <-- this one\n    '    at Runtime._execModule (/Users/mock/git/msw/node_modules/jest-runtime/build/index.js:1299:24)',\n    '    at Runtime._loadModule (/Users/mock/git/msw/node_modules/jest-runtime/build/index.js:898:12)',\n    '    at Runtime.requireModule (/Users/mock/git/msw/node_modules/jest-runtime/build/index.js:746:10)',\n    '    at jasmine2 (/Users/mock/git/msw/node_modules/jest-jasmine2/build/index.js:230:13)',\n    '    at runTestInternal (/Users/mock/git/msw/node_modules/jest-runner/build/runTest.js:380:22)',\n    '    at runTest (/Users/mock/git/msw/node_modules/jest-runner/build/runTest.js:472:34)',\n  ])\n\n  expect(getCallFrame(macOsError)).toEqual(\n    '/Users/mock/git/msw/test/msw-api/setup-server/listHandlers.test.ts:14:11',\n  )\n})\n\ntest('supports Node.js (Windows) error stack', () => {\n  const error = new ErrorWithStack([\n    'Error: ',\n    '    at getCallFrame (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\lib\\\\node\\\\index.js:3735:22)',\n    '    at graphQLRequestHandler (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\lib\\\\node\\\\index.js:7071:25)',\n    '    at Object.query (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\lib\\\\node\\\\index.js:7182:18)',\n    '    at Object.<anonymous> (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\test\\\\msw-api\\\\setup-server\\\\listHandlers.test.ts:75:13)', // <-- this one\n    '    at Object.asyncJestTest (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\node_modules\\\\jest-jasmine2\\\\build\\\\jasmineAsyncInstall.js:106:37)',\n    '    at C:\\\\Users\\\\mock\\\\git\\\\msw\\\\node_modules\\\\jest-jasmine2\\\\build\\\\queueRunner.js:45:12',\n    '    at new Promise (<anonymous>)',\n    '    at mapper (C:\\\\Users\\\\mock\\\\git\\\\msw\\\\node_modules\\\\jest-jasmine2\\\\build\\\\queueRunner.js:28:19)',\n    '    at C:\\\\Users\\\\mock\\\\git\\\\msw\\\\node_modules\\\\jest-jasmine2\\\\build\\\\queueRunner.js:75:41',\n  ])\n\n  expect(getCallFrame(error)).toBe(\n    'C:\\\\Users\\\\mock\\\\git\\\\msw\\\\test\\\\msw-api\\\\setup-server\\\\listHandlers.test.ts:75:13',\n  )\n})\n\ntest('supports Chrome and Edge error stack', () => {\n  const error = new ErrorWithStack([\n    'Error',\n    '    at getCallFrame (webpack:///./lib/browser/getCallFrame-deps.js?:272:20)',\n    '    at Object.eval [as get] (webpack:///./lib/browser/rest-deps.js?:1402:90)',\n    '    at eval (webpack:///./test/msw-api/setup-worker/listHandlers.mocks.ts?:6:113)', // <-- this one\n    '    at Module../test/msw-api/setup-worker/listHandlers.mocks.ts (http://localhost:59464/main.js:1376:1)',\n    '    at __webpack_require__ (http://localhost:59464/main.js:790:30)',\n    '    at fn (http://localhost:59464/main.js:101:20)',\n    '    at eval (webpack:///multi_(webpack)-dev-server/client?:4:18)',\n    '    at Object.0 (http://localhost:59464/main.js:1399:1)',\n    '    at __webpack_require__ (http://localhost:59464/main.js:790:30)',\n    '    at http://localhost:59464/main.js:857:37',\n  ])\n\n  expect(getCallFrame(error)).toBe(\n    'webpack:///./test/msw-api/setup-worker/listHandlers.mocks.ts?:6:113',\n  )\n})\n\ntest('supports Firefox (MacOS, Windows) error stack', () => {\n  const error = new ErrorWithStack([\n    'getCallFrame@webpack:///./lib/browser/getCallFrame-deps.js?:272:20',\n    'createRestHandler/<@webpack:///./lib/browser/rest-deps.js?:1402:90',\n    '@webpack:///./test/msw-api/setup-worker/listHandlers.mocks.ts?:6:113', // <-- this one\n    './test/msw-api/setup-worker/listHandlers.mocks.ts@http://localhost:59464/main.js:1376:1',\n    '__webpack_require__@http://localhost:59464/main.js:790:30',\n    'fn@http://localhost:59464/main.js:101:20',\n    '@webpack:///multi_(webpack)-dev-server/client?:4:18',\n    '0@http://localhost:59464/main.js:1399:1',\n    '__webpack_require__@http://localhost:59464/main.js:790:30',\n    '@http://localhost:59464/main.js:857:37',\n  ])\n\n  expect(getCallFrame(error)).toBe(\n    'webpack:///./test/msw-api/setup-worker/listHandlers.mocks.ts?:6:113',\n  )\n})\n\ntest('supports Safari (MacOS) error stack', () => {\n  const errorOne = new ErrorWithStack([\n    'getCallFrame',\n    '',\n    'eval code',\n    'eval@[native code]',\n    './test/msw-api/setup-worker/listHandlers.mocks.ts@http://localhost:59464/main.js:1376:5', // <-- this one\n    '__webpack_require__@http://localhost:59464/main.js:790:34',\n    'fn@http://localhost:59464/main.js:101:39',\n    'eval code',\n    'eval@[native code]',\n    'http://localhost:59464/main.js:1399:5',\n    '__webpack_require__@http://localhost:59464/main.js:790:34',\n    'http://localhost:59464/main.js:857:37',\n    'global code@http://localhost:59464/main.js:858:12',\n  ])\n\n  expect(getCallFrame(errorOne)).toBe(\n    './test/msw-api/setup-worker/listHandlers.mocks.ts@http://localhost:59464/main.js:1376:5',\n  )\n\n  const errorTwo = new ErrorWithStack([\n    'getCallFrame',\n    'graphQLRequestHandler',\n    'eval code',\n    'eval@[native code]',\n    './test/msw-api/setup-worker/listHandlers.mocks.ts@http://localhost:56460/main.js:1376:5', // <-- this one\n    '__webpack_require__@http://localhost:56460/main.js:790:34',\n    'fn@http://localhost:56460/main.js:101:39',\n    'eval code',\n    'eval@[native code]',\n    'http://localhost:56460/main.js:1399:5',\n    '__webpack_require__@http://localhost:56460/main.js:790:34',\n    'http://localhost:56460/main.js:857:37',\n    'global code@http://localhost:56460/main.js:858:12',\n  ])\n\n  expect(getCallFrame(errorTwo)).toBe(\n    './test/msw-api/setup-worker/listHandlers.mocks.ts@http://localhost:56460/main.js:1376:5',\n  )\n})\n\ntest('handles the undefined stack trace', () => {\n  expect(() => getCallFrame(new ErrorWithStack(undefined))).not.toThrow(\n    TypeError,\n  )\n  expect(() => getCallFrame(new ErrorWithStack(null))).not.toThrow(TypeError)\n})\n"
  },
  {
    "path": "src/core/utils/internal/getCallFrame.ts",
    "content": "// Ignore the source files traces for local testing.\nconst SOURCE_FRAME = /[/\\\\]msw[/\\\\]src[/\\\\](.+)/\n\nconst BUILD_FRAME =\n  /(node_modules)?[/\\\\]lib[/\\\\](core|browser|node|native|iife)[/\\\\]|^[^/\\\\]*$/\n\n/**\n * Return the stack trace frame of a function's invocation.\n */\nexport function getCallFrame(error: Error) {\n  // In <IE11, new Error may return an undefined stack\n  const stack = error.stack\n\n  if (!stack) {\n    return\n  }\n\n  const frames: string[] = stack.split('\\n').slice(1)\n\n  // Get the first frame that doesn't reference the library's internal trace.\n  // Assume that frame is the invocation frame.\n  const declarationFrame = frames.find((frame) => {\n    return !(SOURCE_FRAME.test(frame) || BUILD_FRAME.test(frame))\n  })\n\n  if (!declarationFrame) {\n    return\n  }\n\n  // Extract file reference from the stack frame.\n  const declarationPath = declarationFrame\n    .replace(/\\s*at [^()]*\\(([^)]+)\\)/, '$1')\n    .replace(/^@/, '')\n  return declarationPath\n}\n"
  },
  {
    "path": "src/core/utils/internal/hasRefCounted.test.ts",
    "content": "import { hasRefCounted } from './hasRefCounted'\n\nit('returns true for objects with ref and unref methods', () => {\n  expect(\n    hasRefCounted({\n      ref() {},\n      unref() {},\n    }),\n  ).toBe(true)\n})\n\nit('returns false for a non-refcounted object', () => {\n  expect(hasRefCounted({})).toBe(false)\n  expect(hasRefCounted({ ref() {} })).toBe(false)\n  expect(hasRefCounted({ unref() {} })).toBe(false)\n})\n"
  },
  {
    "path": "src/core/utils/internal/hasRefCounted.ts",
    "content": "export function hasRefCounted<T extends object>(\n  value: T,\n): value is T & NodeJS.RefCounted {\n  return (\n    typeof Reflect.get(value, 'ref') === 'function' &&\n    typeof Reflect.get(value, 'unref') === 'function'\n  )\n}\n"
  },
  {
    "path": "src/core/utils/internal/isHandlerKind.test.ts",
    "content": "import { GraphQLHandler } from '../../handlers/GraphQLHandler'\nimport { HttpHandler } from '../../handlers/HttpHandler'\nimport { RequestHandler } from '../../handlers/RequestHandler'\nimport { WebSocketHandler } from '../../handlers/WebSocketHandler'\nimport { isHandlerKind } from './isHandlerKind'\n\nit('returns true if expected a request handler and given a request handler', () => {\n  expect(\n    isHandlerKind('RequestHandler')(new HttpHandler('*', '*', () => {})),\n  ).toBe(true)\n\n  expect(\n    isHandlerKind('RequestHandler')(\n      new GraphQLHandler('all', '*', '*', () => {}),\n    ),\n  ).toBe(true)\n})\n\nit('returns true if expected a request handler and given a custom request handler', () => {\n  class MyHandler extends RequestHandler {\n    constructor() {\n      super({ info: { header: '*' }, resolver: () => {} })\n    }\n    predicate = () => false\n    log() {}\n  }\n\n  expect(isHandlerKind('RequestHandler')(new MyHandler())).toBe(true)\n})\n\nit('returns false if expected a request handler but given event handler', () => {\n  expect(isHandlerKind('RequestHandler')(new WebSocketHandler('*'))).toBe(false)\n})\n\nit('returns false if expected a request handler but given arbitrary object', () => {\n  expect(isHandlerKind('RequestHandler')(undefined)).toBe(false)\n  expect(isHandlerKind('RequestHandler')(null)).toBe(false)\n  expect(isHandlerKind('RequestHandler')({})).toBe(false)\n  expect(isHandlerKind('RequestHandler')([])).toBe(false)\n  expect(isHandlerKind('RequestHandler')(123)).toBe(false)\n  expect(isHandlerKind('RequestHandler')('hello')).toBe(false)\n})\n\nit('returns true if expected an event handler and given an event handler', () => {\n  expect(isHandlerKind('EventHandler')(new WebSocketHandler('*'))).toBe(true)\n})\n\nit('returns true if expected an event handler and given a custom event handler', () => {\n  class MyEventHandler extends WebSocketHandler {\n    constructor() {\n      super('*')\n    }\n  }\n  expect(isHandlerKind('EventHandler')(new MyEventHandler())).toBe(true)\n})\n\nit('returns false if expected an event handler but given arbitrary object', () => {\n  expect(isHandlerKind('EventHandler')(undefined)).toBe(false)\n  expect(isHandlerKind('EventHandler')(null)).toBe(false)\n  expect(isHandlerKind('EventHandler')({})).toBe(false)\n  expect(isHandlerKind('EventHandler')([])).toBe(false)\n  expect(isHandlerKind('EventHandler')(123)).toBe(false)\n  expect(isHandlerKind('EventHandler')('hello')).toBe(false)\n})\n"
  },
  {
    "path": "src/core/utils/internal/isHandlerKind.ts",
    "content": "import type { HandlerKind } from '../../handlers/common'\nimport type { RequestHandler } from '../../handlers/RequestHandler'\nimport type { WebSocketHandler } from '../../handlers/WebSocketHandler'\n\n/**\n * A filter function that ensures that the provided argument\n * is a handler of the given kind. This helps differentiate\n * between different kinds of handlers, e.g. request and event handlers.\n */\nexport function isHandlerKind<K extends HandlerKind>(kind: K) {\n  return (\n    input: unknown,\n  ): input is K extends 'EventHandler' ? WebSocketHandler : RequestHandler => {\n    return (\n      input != null &&\n      typeof input === 'object' &&\n      '__kind' in input &&\n      input.__kind === kind\n    )\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/isIterable.test.ts",
    "content": "import { isIterable } from './isIterable'\n\ntest('returns true given an iterator', () => {\n  expect(\n    isIterable(\n      (function* () {\n        yield 2\n      })(),\n    ),\n  ).toEqual(true)\n})\n\ntest('returns false given a regular function', () => {\n  expect(\n    isIterable(\n      (function () {\n        return null\n      })(),\n    ),\n  ).toEqual(false)\n\n  expect(isIterable((() => null)())).toEqual(false)\n})\n"
  },
  {
    "path": "src/core/utils/internal/isIterable.ts",
    "content": "/**\n * This is the same as TypeScript's `Iterable`, but with all three type parameters.\n * @todo Remove once TypeScript 5.6 is the minimum.\n */\nexport interface Iterable<T, TReturn, TNext> {\n  [Symbol.iterator](): Iterator<T, TReturn, TNext>\n}\n\n/**\n * This is the same as TypeScript's `AsyncIterable`, but with all three type parameters.\n * @todo Remove once TypeScript 5.6 is the minimum.\n */\nexport interface AsyncIterable<T, TReturn, TNext> {\n  [Symbol.asyncIterator](): AsyncIterator<T, TReturn, TNext>\n}\n\n/**\n * Determines if the given function is an iterator.\n */\nexport function isIterable<IteratorType>(\n  fn: any,\n): fn is\n  | Iterable<IteratorType, IteratorType, IteratorType>\n  | AsyncIterable<IteratorType, IteratorType, IteratorType> {\n  if (!fn) {\n    return false\n  }\n\n  return (\n    Reflect.has(fn, Symbol.iterator) || Reflect.has(fn, Symbol.asyncIterator)\n  )\n}\n"
  },
  {
    "path": "src/core/utils/internal/isObject.test.ts",
    "content": "import { isObject } from './isObject'\n\ntest('returns true given an object', () => {\n  expect(isObject({})).toBe(true)\n  expect(isObject({ a: 1 })).toBe(true)\n})\n\ntest('returns false given a non-object value', () => {\n  expect(isObject(1)).toBe(false)\n  expect(isObject('string')).toBe(false)\n  expect(isObject([])).toBe(false)\n  expect(\n    isObject(function () {\n      return 2\n    }),\n  ).toBe(false)\n  expect(isObject(false)).toBe(false)\n  expect(isObject(undefined)).toBe(false)\n  expect(isObject(null)).toBe(false)\n})\n"
  },
  {
    "path": "src/core/utils/internal/isObject.ts",
    "content": "/**\n * Determines if the given value is an object.\n */\nexport function isObject(value: any): value is Record<string, any> {\n  return value != null && typeof value === 'object' && !Array.isArray(value)\n}\n"
  },
  {
    "path": "src/core/utils/internal/isStringEqual.test.ts",
    "content": "import { isStringEqual } from './isStringEqual'\n\ndescribe('isStringEqual', () => {\n  describe('given two uppercase strings', () => {\n    describe('and the strings are equal', () => {\n      it('should return true', () => {\n        expect(isStringEqual('GET', 'GET')).toBe(true)\n      })\n    })\n\n    describe('and the strings are not equal', () => {\n      it('should return false', () => {\n        expect(isStringEqual('GET', 'POST')).toBe(false)\n      })\n    })\n  })\n\n  describe('given two lowercase strings', () => {\n    describe('and the strings are equal', () => {\n      it('should return true', () => {\n        expect(isStringEqual('get', 'get')).toBe(true)\n      })\n    })\n\n    describe('and the strings are not equal', () => {\n      it('should return false', () => {\n        expect(isStringEqual('get', 'post')).toBe(false)\n      })\n    })\n  })\n\n  describe('given two strings cased differently', () => {\n    describe('and the strings are equal', () => {\n      it('should return true', () => {\n        expect(isStringEqual('get', 'GET')).toBe(true)\n      })\n    })\n\n    describe('and the strings are not equal', () => {\n      it('should return false', () => {\n        expect(isStringEqual('get', 'POST')).toBe(false)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "src/core/utils/internal/isStringEqual.ts",
    "content": "/**\n * Performs a case-insensitive comparison of two given strings.\n */\nexport function isStringEqual(actual: string, expected: string): boolean {\n  return actual.toLowerCase() === expected.toLowerCase()\n}\n"
  },
  {
    "path": "src/core/utils/internal/jsonParse.test.ts",
    "content": "import { jsonParse } from './jsonParse'\n\ntest('parses a given valid JSON string', () => {\n  expect(jsonParse(`{\"property\":\"value\"}`)).toEqual({\n    property: 'value',\n  })\n})\n\ntest('returns undefined without an error given an invalid JSON string', () => {\n  const parse = () => jsonParse(`{\"property:val\"ue$}`)\n  expect(parse).not.toThrow()\n  expect(parse()).toBeUndefined()\n})\n"
  },
  {
    "path": "src/core/utils/internal/jsonParse.ts",
    "content": "/**\n * Parses a given value into a JSON.\n * Does not throw an exception on an invalid JSON string.\n */\nexport function jsonParse<ValueType extends Record<string, any>>(\n  value: any,\n): ValueType | undefined {\n  try {\n    return JSON.parse(value)\n  } catch {\n    return undefined\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/mergeRight.test.ts",
    "content": "import { mergeRight } from './mergeRight'\n\ntest('shallowly merges two given objects', () => {\n  expect(mergeRight({ a: 1, b: 2 }, { b: 3, c: 4 })).toEqual({\n    a: 1,\n    b: 3,\n    c: 4,\n  })\n})\n\ntest('deeply merges two given objects', () => {\n  expect(\n    mergeRight(\n      {\n        a: 'string',\n        b: [1, 2],\n        c: {\n          d: 2,\n        },\n      },\n      {\n        a: 'another-string',\n        b: [3],\n        c: {\n          e: 'five',\n          f: {\n            g: true,\n          },\n        },\n      },\n    ),\n  ).toEqual({\n    a: 'another-string',\n    b: [1, 2, 3],\n    c: {\n      d: 2,\n      e: 'five',\n      f: {\n        g: true,\n      },\n    },\n  })\n})\n"
  },
  {
    "path": "src/core/utils/internal/mergeRight.ts",
    "content": "import { isObject } from './isObject'\n\n/**\n * Deeply merges two given objects with the right one\n * having a priority during property assignment.\n */\nexport function mergeRight(\n  left: Record<string, any>,\n  right: Record<string, any>,\n) {\n  return Object.entries(right).reduce(\n    (result, [key, rightValue]) => {\n      const leftValue = result[key]\n\n      if (Array.isArray(leftValue) && Array.isArray(rightValue)) {\n        result[key] = leftValue.concat(rightValue)\n        return result\n      }\n\n      if (isObject(leftValue) && isObject(rightValue)) {\n        result[key] = mergeRight(leftValue, rightValue)\n        return result\n      }\n\n      result[key] = rightValue\n      return result\n    },\n    Object.assign({}, left),\n  )\n}\n"
  },
  {
    "path": "src/core/utils/internal/parseGraphQLRequest.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { encodeBuffer } from '@mswjs/interceptors'\nimport { OperationTypeNode } from 'graphql'\nimport {\n  ParsedGraphQLRequest,\n  parseGraphQLRequest,\n} from './parseGraphQLRequest'\n\ntest('returns true given a GraphQL-compatible request', async () => {\n  const getRequest = new Request(\n    new URL(\n      'http://localhost:8080/graphql?query=mutation Login { user { id } }',\n    ),\n  )\n  expect(await parseGraphQLRequest(getRequest)).toEqual<\n    ParsedGraphQLRequest<any>\n  >({\n    operationType: OperationTypeNode.MUTATION,\n    operationName: 'Login',\n    query: `mutation Login { user { id } }`,\n    variables: undefined,\n  })\n\n  const postRequest = new Request(new URL('http://localhost:8080/graphql'), {\n    method: 'POST',\n    headers: new Headers({ 'Content-Type': 'application/json' }),\n    body: encodeBuffer(\n      JSON.stringify({\n        query: `query GetUser { user { firstName } }`,\n      }),\n    ),\n  })\n\n  expect(await parseGraphQLRequest(postRequest)).toEqual<\n    ParsedGraphQLRequest<any>\n  >({\n    operationType: OperationTypeNode.QUERY,\n    operationName: 'GetUser',\n    query: `query GetUser { user { firstName } }`,\n    variables: undefined,\n  })\n})\n\ntest('throws an exception given an invalid GraphQL request', async () => {\n  const getRequest = new Request(\n    new URL('http://localhost:8080/graphql?query=mutation Login() { user { {}'),\n  )\n\n  await expect(parseGraphQLRequest(getRequest)).rejects.toThrowError(\n    '[MSW] Failed to intercept a GraphQL request to \"GET http://localhost:8080/graphql\": cannot parse query. See the error message from the parser below.',\n  )\n\n  const postRequest = new Request(new URL('http://localhost:8080/graphql'), {\n    method: 'POST',\n    headers: new Headers({ 'Content-Type': 'application/json' }),\n    body: encodeBuffer(\n      JSON.stringify({\n        query: `query GetUser() { user {{}`,\n      }),\n    ),\n  })\n\n  await expect(parseGraphQLRequest(postRequest)).rejects.toThrowError(\n    '[MSW] Failed to intercept a GraphQL request to \"POST http://localhost:8080/graphql\": cannot parse query. See the error message from the parser below.\\n\\nSyntax Error: Expected \"$\", found \")\".',\n  )\n})\n\ntest('returns false given a GraphQL-incompatible request', async () => {\n  const getRequest = new Request(new URL('http://localhost:8080/graphql'), {\n    headers: new Headers({ 'Content-Type': 'application/json' }),\n  })\n  expect(await parseGraphQLRequest(getRequest)).toBeUndefined()\n\n  const postRequest = new Request(new URL('http://localhost:8080/graphql'), {\n    method: 'POST',\n    headers: new Headers({ 'Content-Type': 'application/json' }),\n    body: encodeBuffer(\n      JSON.stringify({\n        queryUser: true,\n      }),\n    ),\n  })\n  expect(await parseGraphQLRequest(postRequest)).toBeUndefined()\n})\n\ntest('does not read the original request body', async () => {\n  const request = new Request(new URL('http://localhost/api'), {\n    method: 'POST',\n    body: JSON.stringify({ payload: 'value' }),\n  })\n\n  await parseGraphQLRequest(request)\n\n  // Must not read the original request body because GraphQL parsing\n  // is an internal operation that must not lock the body stream.\n  expect(request.bodyUsed).toBe(false)\n})\n"
  },
  {
    "path": "src/core/utils/internal/parseGraphQLRequest.ts",
    "content": "import type {\n  DocumentNode,\n  OperationDefinitionNode,\n  OperationTypeNode,\n} from 'graphql'\nimport type { GraphQLVariables } from '../../handlers/GraphQLHandler'\nimport { toPublicUrl } from '../request/toPublicUrl'\nimport { devUtils } from './devUtils'\nimport { jsonParse } from './jsonParse'\nimport { parseMultipartData } from './parseMultipartData'\n\ninterface GraphQLInput {\n  query: string | null\n  variables?: GraphQLVariables\n}\n\nexport interface ParsedGraphQLQuery {\n  operationType: OperationTypeNode\n  operationName?: string\n}\n\nexport type ParsedGraphQLRequest<\n  VariablesType extends GraphQLVariables = GraphQLVariables,\n> =\n  | (ParsedGraphQLQuery & {\n      query: string\n      variables?: VariablesType\n    })\n  | undefined\n\nexport function parseDocumentNode(node: DocumentNode): ParsedGraphQLQuery {\n  const operationDef = node.definitions.find((definition) => {\n    return definition.kind === 'OperationDefinition'\n  }) as OperationDefinitionNode\n\n  return {\n    operationType: operationDef?.operation,\n    operationName: operationDef?.name?.value,\n  }\n}\n\nasync function parseQuery(query: string): Promise<ParsedGraphQLQuery | Error> {\n  /**\n   * @note Use `require` to get the \"graphql\" module here.\n   * It has to be scoped to this function because this module leaks to the\n   * root export. It has to be `require` because tools like Jest have trouble\n   * handling dynamic imports. It gets replaced with a dynamic import on build time.\n   */\n  // eslint-disable-next-line @typescript-eslint/no-require-imports\n  const { parse } = require('graphql')\n\n  try {\n    const ast = parse(query)\n    return parseDocumentNode(ast)\n  } catch (error) {\n    return error as Error\n  }\n}\n\nexport type GraphQLParsedOperationsMap = Record<string, string[]>\nexport type GraphQLMultipartRequestBody = {\n  operations: string\n  map?: string\n} & {\n  [fileName: string]: File\n}\n\nfunction extractMultipartVariables<VariablesType extends GraphQLVariables>(\n  variables: VariablesType,\n  map: GraphQLParsedOperationsMap,\n  files: Record<string, File>,\n) {\n  const operations = { variables }\n\n  for (const [key, pathArray] of Object.entries(map)) {\n    if (!(key in files)) {\n      throw new Error(`Given files do not have a key '${key}' .`)\n    }\n\n    for (const dotPath of pathArray) {\n      const [lastPath, ...reversedPaths] = dotPath.split('.').reverse()\n      const paths = reversedPaths.reverse()\n      let target: Record<string, any> = operations\n\n      for (const path of paths) {\n        if (!(path in target)) {\n          throw new Error(`Property '${path}' is not in operations.`)\n        }\n\n        target = target[path]\n      }\n\n      target[lastPath] = files[key]\n    }\n  }\n\n  return operations.variables\n}\n\nasync function getGraphQLInput(request: Request): Promise<GraphQLInput | null> {\n  switch (request.method) {\n    case 'GET': {\n      const url = new URL(request.url)\n      const query = url.searchParams.get('query')\n      const variables = url.searchParams.get('variables') || ''\n\n      return {\n        query,\n        variables: jsonParse(variables),\n      }\n    }\n\n    case 'POST': {\n      // Clone the request so we could read its body without locking\n      // the body stream to the downward consumers.\n      const requestClone = request.clone()\n\n      // Handle multipart body GraphQL operations.\n      if (\n        request.headers.get('content-type')?.includes('multipart/form-data')\n      ) {\n        const responseJson = parseMultipartData<GraphQLMultipartRequestBody>(\n          await requestClone.text(),\n          request.headers,\n        )\n\n        if (!responseJson) {\n          return null\n        }\n\n        const { operations, map, ...files } = responseJson\n        const parsedOperations =\n          jsonParse<{ query?: string; variables?: GraphQLVariables }>(\n            operations,\n          ) || {}\n\n        if (!parsedOperations.query) {\n          return null\n        }\n\n        const parsedMap = jsonParse<GraphQLParsedOperationsMap>(map || '') || {}\n        const variables = parsedOperations.variables\n          ? extractMultipartVariables(\n              parsedOperations.variables,\n              parsedMap,\n              files,\n            )\n          : {}\n\n        return {\n          query: parsedOperations.query,\n          variables,\n        }\n      }\n\n      // Handle plain POST GraphQL operations.\n      const requestJson: {\n        query: string\n        variables?: GraphQLVariables\n        operations?: any /** @todo Annotate this */\n      } = await requestClone.json().catch(() => null)\n\n      if (requestJson?.query) {\n        const { query, variables } = requestJson\n\n        return {\n          query,\n          variables,\n        }\n      }\n      return null\n    }\n\n    default:\n      return null\n  }\n}\n\n/**\n * Determines if a given request can be considered a GraphQL request.\n * Does not parse the query and does not guarantee its validity.\n */\nexport async function parseGraphQLRequest(\n  request: Request,\n): Promise<ParsedGraphQLRequest> {\n  const input = await getGraphQLInput(request)\n\n  if (!input || !input.query) {\n    return\n  }\n\n  const { query, variables } = input\n  const parsedResult = await parseQuery(query)\n\n  if (parsedResult instanceof Error) {\n    const requestPublicUrl = toPublicUrl(request.url)\n\n    throw new Error(\n      devUtils.formatMessage(\n        'Failed to intercept a GraphQL request to \"%s %s\": cannot parse query. See the error message from the parser below.\\n\\n%s',\n        request.method,\n        requestPublicUrl,\n        parsedResult.message,\n      ),\n    )\n  }\n\n  return {\n    query: input.query,\n    operationType: parsedResult.operationType,\n    operationName: parsedResult.operationName,\n    variables,\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/parseMultipartData.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { parseMultipartData } from './parseMultipartData'\n\ntest('parses a given valid multipart string', async () => {\n  expect.assertions(3)\n  await testMultipartDataWithContentType(\n    'multipart/form-data; boundary=WebKitFormBoundaryvZ1cVXWyK0ilQdab',\n  )\n})\n\ntest('parses a given valid multipart string given non-pretty content-type', async () => {\n  expect.assertions(3)\n  // node-fetch will serialize content-type in this format, which is valid according to HTTP\n  // https://github.com/node-fetch/node-fetch/blob/d8fc32d6b29bd43d1ad377e80b3e439fe37f2904/test/main.js#L1438\n  await testMultipartDataWithContentType(\n    'multipart/form-data;boundary=WebKitFormBoundaryvZ1cVXWyK0ilQdab',\n  )\n})\n\ntest('parses a given valid multipart string given content-type with extra spaces', async () => {\n  expect.assertions(3)\n  await testMultipartDataWithContentType(\n    'multipart/form-data;   boundary=WebKitFormBoundaryvZ1cVXWyK0ilQdab',\n  )\n})\n\nasync function testMultipartDataWithContentType(\n  contentType: string,\n): Promise<void> {\n  const body = `\\\n------WebKitFormBoundaryvZ1cVXWyK0ilQdab\\r\nContent-Disposition: form-data; name=\"file\"; filename=\"file1.txt\"\\r\nContent-Type: application/octet-stream\\r\n\\r\nfile content\\r\n------WebKitFormBoundaryvZ1cVXWyK0ilQdab\\r\nContent-Disposition: form-data; name=\"text\"\\r\n\\r\ntext content\\r\n------WebKitFormBoundaryvZ1cVXWyK0ilQdab\\r\nContent-Disposition: form-data; name=\"text2\"\\r\n\\r\nanother text content\\r\n------WebKitFormBoundaryvZ1cVXWyK0ilQdab\\r\nContent-Disposition: form-data; name=\"text2\"\\r\n\\r\n\\r\nanother text content 2\\r\n\\r\n------WebKitFormBoundaryvZ1cVXWyK0ilQdab--`\n  const headers = new Headers({\n    'content-type': contentType,\n  })\n  const parsed = parseMultipartData(body, headers)\n\n  // Workaround: JSDOM does not have `Blob.text` implementation.\n  // see https://github.com/jsdom/jsdom/issues/2555\n  expect(parsed).toHaveProperty('file.name', 'file1.txt')\n\n  expect(parsed).toHaveProperty('text', 'text content')\n  expect(parsed).toHaveProperty('text2', [\n    'another text content',\n    '\\r\\nanother text content 2\\r\\n',\n  ])\n}\n\ntest('returns undefined without an error given an invalid multipart string', () => {\n  const headers = new Headers({\n    'content-type': 'multipart/form-data; boundary=dummyBoundary',\n  })\n  const parse = () => parseMultipartData(`{\"invalid\": [\"multipart\"]}`, headers)\n  expect(parse).not.toThrow()\n  expect(parse()).toBeUndefined()\n})\n"
  },
  {
    "path": "src/core/utils/internal/parseMultipartData.ts",
    "content": "import { stringToHeaders } from 'headers-polyfill'\nimport { DefaultRequestMultipartBody } from '../../handlers/RequestHandler'\n\ninterface ParsedContentHeaders {\n  name: string\n  filename?: string\n  contentType: string\n}\n\ninterface ContentDispositionDirective {\n  [key: string]: string | undefined\n  name: string\n  filename?: string\n  'form-data': string\n}\n\nfunction parseContentHeaders(headersString: string): ParsedContentHeaders {\n  const headers = stringToHeaders(headersString)\n  const contentType = headers.get('content-type') || 'text/plain'\n  const disposition = headers.get('content-disposition')\n\n  if (!disposition) {\n    throw new Error('\"Content-Disposition\" header is required.')\n  }\n\n  const directives = disposition.split(';').reduce((acc, chunk) => {\n    const [name, ...rest] = chunk.trim().split('=')\n    acc[name] = rest.join('=')\n    return acc\n  }, {} as ContentDispositionDirective)\n\n  const name = directives.name?.slice(1, -1)\n  const filename = directives.filename?.slice(1, -1)\n\n  return {\n    name,\n    filename,\n    contentType,\n  }\n}\n\n/**\n * Parses a given string as a multipart/form-data.\n * Does not throw an exception on an invalid multipart string.\n */\nexport function parseMultipartData<T extends DefaultRequestMultipartBody>(\n  data: string,\n  headers?: Headers,\n): T | undefined {\n  const contentType = headers?.get('content-type')\n\n  if (!contentType) {\n    return undefined\n  }\n\n  const [, ...directives] = contentType.split(/; */)\n  const boundary = directives\n    .filter((d) => d.startsWith('boundary='))\n    .map((s) => s.replace(/^boundary=/, ''))[0]\n\n  if (!boundary) {\n    return undefined\n  }\n\n  const boundaryRegExp = new RegExp(\n    `--+${boundary.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`,\n  )\n  const fields = data\n    .split(boundaryRegExp)\n    .filter((chunk) => chunk.startsWith('\\r\\n') && chunk.endsWith('\\r\\n'))\n    .map((chunk) => chunk.trimStart().replace(/\\r\\n$/, ''))\n\n  if (!fields.length) {\n    return undefined\n  }\n\n  const parsedBody: DefaultRequestMultipartBody = {}\n\n  try {\n    for (const field of fields) {\n      const [contentHeaders, ...rest] = field.split('\\r\\n\\r\\n')\n      const contentBody = rest.join('\\r\\n\\r\\n')\n      const { contentType, filename, name } =\n        parseContentHeaders(contentHeaders)\n\n      const value =\n        filename === undefined\n          ? contentBody\n          : new File([contentBody], filename, { type: contentType })\n\n      const parsedValue = parsedBody[name]\n\n      if (parsedValue === undefined) {\n        parsedBody[name] = value\n      } else if (Array.isArray(parsedValue)) {\n        parsedBody[name] = [...parsedValue, value]\n      } else {\n        parsedBody[name] = [parsedValue, value]\n      }\n    }\n\n    return parsedBody as T\n  } catch {\n    return undefined\n  }\n}\n"
  },
  {
    "path": "src/core/utils/internal/pipeEvents.test.ts",
    "content": "import { Emitter } from 'strict-event-emitter'\nimport { pipeEvents } from './pipeEvents'\n\nit('pipes events from the source emitter to the destination emitter', () => {\n  const source = new Emitter()\n  const destination = new Emitter()\n  pipeEvents(source, destination)\n\n  const callback = vi.fn()\n  destination.on('hello', callback)\n\n  source.emit('hello', 'world', { data: true })\n  expect(callback).toHaveBeenNthCalledWith(1, 'world', { data: true })\n})\n"
  },
  {
    "path": "src/core/utils/internal/pipeEvents.ts",
    "content": "import { Emitter, EventMap } from 'strict-event-emitter'\n\n/**\n * Pipes all emitted events from one emitter to another.\n */\nexport function pipeEvents<Events extends EventMap>(\n  source: Emitter<Events>,\n  destination: Emitter<Events>,\n): void {\n  const rawEmit: typeof source.emit & { _isPiped?: boolean } = source.emit\n\n  if (rawEmit._isPiped) {\n    return\n  }\n\n  const sourceEmit: typeof source.emit & { _isPiped?: boolean } =\n    function sourceEmit(this: typeof source, event, ...data) {\n      destination.emit(event, ...data)\n      return rawEmit.call(this, event, ...data)\n    }\n\n  sourceEmit._isPiped = true\n\n  source.emit = sourceEmit\n}\n"
  },
  {
    "path": "src/core/utils/internal/requestHandlerUtils.ts",
    "content": "import { RequestHandler } from '../../handlers/RequestHandler'\n\nexport function use(\n  currentHandlers: Array<RequestHandler>,\n  ...handlers: Array<RequestHandler>\n): void {\n  currentHandlers.unshift(...handlers)\n}\n\nexport function restoreHandlers(handlers: Array<RequestHandler>): void {\n  handlers.forEach((handler) => {\n    handler.isUsed = false\n  })\n}\n\nexport function resetHandlers(\n  initialHandlers: Array<RequestHandler>,\n  ...nextHandlers: Array<RequestHandler>\n) {\n  return nextHandlers.length > 0 ? [...nextHandlers] : [...initialHandlers]\n}\n"
  },
  {
    "path": "src/core/utils/internal/toReadonlyArray.test.ts",
    "content": "import { toReadonlyArray } from './toReadonlyArray'\n\nit('creates a copy of an array', () => {\n  expect(toReadonlyArray([1, 2, 3])).toEqual([1, 2, 3])\n})\n\nit('does not affect the source array', () => {\n  const source = ['a', 'b', 'c']\n  toReadonlyArray(source)\n\n  expect(source.push('d')).toBe(4)\n  expect(source).toEqual(['a', 'b', 'c', 'd'])\n})\n\nit('forbids modifying the array copy', () => {\n  const source = [1, 2, 3]\n  const copy = toReadonlyArray(source)\n\n  expect(() => {\n    // @ts-expect-error Intentional runtime misusage.\n    copy[2] = 1\n  }).toThrow(/Cannot assign to read only property '\\d+' of object/)\n\n  expect(() => {\n    // @ts-expect-error Intentional runtime misusage.\n    copy.push(4)\n  }).toThrow(/Cannot add property \\d+, object is not extensible/)\n\n  expect(source).toEqual([1, 2, 3])\n})\n"
  },
  {
    "path": "src/core/utils/internal/toReadonlyArray.ts",
    "content": "/**\n * Creates an immutable copy of the given array.\n */\nexport function toReadonlyArray<T>(source: Array<T>): ReadonlyArray<T> {\n  const clone = [...source] as Array<T>\n  Object.freeze(clone)\n  return clone\n}\n"
  },
  {
    "path": "src/core/utils/internal/tryCatch.test.ts",
    "content": "import { tryCatch } from './tryCatch'\n\ntest('returns the function payload', () => {\n  const result = tryCatch(() => 'hello')\n  expect(result).toEqual('hello')\n})\n\ntest('silences exceptions by default', () => {\n  const result = tryCatch(() => {\n    throw new Error('Exception')\n  })\n\n  expect(result).toBeUndefined()\n})\n\ntest('executes a custom callback function when an exception occurs', async () => {\n  await new Promise<void>((resolve) => {\n    tryCatch(\n      () => {\n        throw new Error('Exception')\n      },\n      (error) => {\n        expect(error).toBeInstanceOf(Error)\n        expect(error.message).toEqual('Exception')\n        resolve()\n      },\n    )\n  })\n})\n"
  },
  {
    "path": "src/core/utils/internal/tryCatch.ts",
    "content": "export function tryCatch<Fn extends (...args: any[]) => any>(\n  fn: Fn,\n  onException?: (error: Error) => void,\n): ReturnType<Fn> | undefined {\n  try {\n    const result = fn()\n    return result\n  } catch (error) {\n    onException?.(error as Error)\n  }\n}\n"
  },
  {
    "path": "src/core/utils/logging/getStatusCodeColor.test.ts",
    "content": "import { getStatusCodeColor } from './getStatusCodeColor'\n\ntest('returns a green color for status codes lower than 300', () => {\n  expect(getStatusCodeColor(100)).toBe('#69AB32')\n  expect(getStatusCodeColor(200)).toBe('#69AB32')\n  expect(getStatusCodeColor(204)).toBe('#69AB32')\n})\n\ntest('returns a yellow color for status codes between 201 and 400', () => {\n  expect(getStatusCodeColor(300)).toBe('#F0BB4B')\n  expect(getStatusCodeColor(304)).toBe('#F0BB4B')\n})\n\ntest('returns a red color for status codes higher than 400', () => {\n  expect(getStatusCodeColor(400)).toBe('#E95F5D')\n  expect(getStatusCodeColor(404)).toBe('#E95F5D')\n  expect(getStatusCodeColor(500)).toBe('#E95F5D')\n})\n\ntest('returns a red color for unknown status code', () => {\n  expect(getStatusCodeColor(700)).toBe('#E95F5D')\n})\n"
  },
  {
    "path": "src/core/utils/logging/getStatusCodeColor.ts",
    "content": "export enum StatusCodeColor {\n  Success = '#69AB32',\n  Warning = '#F0BB4B',\n  Danger = '#E95F5D',\n}\n\n/**\n * Returns a HEX color for a given response status code number.\n */\nexport function getStatusCodeColor(status: number): StatusCodeColor {\n  if (status < 300) {\n    return StatusCodeColor.Success\n  }\n\n  if (status < 400) {\n    return StatusCodeColor.Warning\n  }\n\n  return StatusCodeColor.Danger\n}\n"
  },
  {
    "path": "src/core/utils/logging/getTimestamp.test.ts",
    "content": "import { getTimestamp } from './getTimestamp'\n\nbeforeAll(() => {\n  vi.useFakeTimers()\n})\n\nafterAll(() => {\n  vi.useRealTimers()\n})\n\ntest('returns a timestamp string of the invocation time', () => {\n  vi.setSystemTime(new Date('2024-01-01 12:4:8'))\n  const timestamp = getTimestamp()\n  expect(timestamp).toBe('12:04:08')\n})\n\ntest('returns a timestamp with milliseconds', () => {\n  vi.setSystemTime(new Date('2024-01-01 12:4:8'))\n  expect(getTimestamp({ milliseconds: true })).toBe('12:04:08.000')\n\n  vi.setSystemTime(new Date('2024-01-01 12:4:8.000'))\n  expect(getTimestamp({ milliseconds: true })).toBe('12:04:08.000')\n\n  vi.setSystemTime(new Date('2024-01-01 12:4:8.4'))\n  expect(getTimestamp({ milliseconds: true })).toBe('12:04:08.400')\n\n  vi.setSystemTime(new Date('2024-01-01 12:4:8.123'))\n  expect(getTimestamp({ milliseconds: true })).toBe('12:04:08.123')\n\n  vi.setSystemTime(new Date('2024-01-01 12:00:00'))\n  expect(getTimestamp({ milliseconds: true })).toBe('12:00:00.000')\n})\n"
  },
  {
    "path": "src/core/utils/logging/getTimestamp.ts",
    "content": "interface GetTimestampOptions {\n  milliseconds?: boolean\n}\n\n/**\n * Returns a timestamp string in a \"HH:MM:SS\" format.\n */\nexport function getTimestamp(options?: GetTimestampOptions): string {\n  const now = new Date()\n  const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`\n\n  if (options?.milliseconds) {\n    return `${timestamp}.${now.getMilliseconds().toString().padStart(3, '0')}`\n  }\n\n  return timestamp\n}\n"
  },
  {
    "path": "src/core/utils/logging/serializeRequest.test.ts",
    "content": "import { encodeBuffer } from '@mswjs/interceptors'\nimport { serializeRequest } from './serializeRequest'\n\ntest('serializes given Request instance into a plain object', async () => {\n  const request = await serializeRequest(\n    new Request(new URL('http://test.mswjs.io/user'), {\n      method: 'POST',\n      headers: new Headers({\n        'Content-Type': 'text/plain',\n        'X-Header': 'secret',\n      }),\n      body: encodeBuffer('text-body'),\n    }),\n  )\n\n  expect(request.method).toBe('POST')\n  expect(request.url.href).toBe('http://test.mswjs.io/user')\n  expect(request.headers).toEqual({\n    'content-type': 'text/plain',\n    'x-header': 'secret',\n  })\n  expect(request.body).toBe('text-body')\n})\n"
  },
  {
    "path": "src/core/utils/logging/serializeRequest.ts",
    "content": "export interface LoggedRequest {\n  url: URL\n  method: string\n  headers: Record<string, string>\n  body: string\n}\n\n/**\n * Formats a mocked request for introspection in browser's console.\n */\nexport async function serializeRequest(\n  request: Request,\n): Promise<LoggedRequest> {\n  const requestClone = request.clone()\n  const requestText = await requestClone.text()\n\n  return {\n    url: new URL(request.url),\n    method: request.method,\n    headers: Object.fromEntries(request.headers.entries()),\n    body: requestText,\n  }\n}\n"
  },
  {
    "path": "src/core/utils/logging/serializeResponse.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { encodeBuffer } from '@mswjs/interceptors'\nimport { serializeResponse } from './serializeResponse'\n\nit('serializes response without body', async () => {\n  const result = await serializeResponse(new Response(null))\n\n  expect(result.status).toBe(200)\n  expect(result.statusText).toBe('OK')\n  expect(result.headers).toEqual({})\n  expect(result.body).toBe('')\n})\n\nit('serializes a plain text response', async () => {\n  const result = await serializeResponse(\n    new Response('hello world', {\n      status: 201,\n      statusText: 'Created',\n      headers: {\n        'Content-Type': 'text/plain',\n      },\n    }),\n  )\n\n  expect(result.status).toBe(201)\n  expect(result.statusText).toBe('Created')\n  expect(result.headers).toEqual({\n    'content-type': 'text/plain',\n  })\n  expect(result.body).toBe('hello world')\n})\n\nit('serializes a JSON response', async () => {\n  const response = new Response(JSON.stringify({ users: ['John'] }), {\n    headers: {\n      'Content-Type': 'application/json',\n    },\n  })\n  const result = await serializeResponse(response)\n\n  expect(result.headers).toEqual({\n    'content-type': 'application/json',\n  })\n  expect(result.body).toBe(JSON.stringify({ users: ['John'] }))\n})\n\nit('serializes a ArrayBuffer response', async () => {\n  const data = encodeBuffer('hello world')\n  const response = new Response(data)\n  const result = await serializeResponse(response)\n\n  expect(result.body).toBe('hello world')\n})\n\nit('serializes a Blob response', async () => {\n  const response = new Response(new Blob(['hello world']))\n  const result = await serializeResponse(response)\n\n  expect(result.body).toBe('hello world')\n})\n\nit('serializes a FormData response', async () => {\n  const data = new FormData()\n  data.set('firstName', 'Alice')\n  data.set('age', '32')\n  const response = new Response(data)\n  const result = await serializeResponse(response)\n\n  expect(result.body).toContain(\n    `Content-Disposition: form-data; name=\"firstName\"\\r\\n\\r\\nAlice`,\n  )\n  expect(result.body).toContain(\n    `Content-Disposition: form-data; name=\"age\"\\r\\n\\r\\n32`,\n  )\n})\n"
  },
  {
    "path": "src/core/utils/logging/serializeResponse.ts",
    "content": "import statuses from '../../../shims/statuses'\n\nconst { message } = statuses\n\nexport interface SerializedResponse {\n  status: number\n  statusText: string\n  headers: Record<string, any>\n  body: string\n}\n\nexport async function serializeResponse(\n  response: Response,\n): Promise<SerializedResponse> {\n  const responseClone = response.clone()\n  const responseText = await responseClone.text()\n\n  // Normalize the response status and status text when logging\n  // since the default Response instance doesn't infer status texts\n  // from status codes. This has no effect on the actual response instance.\n  const responseStatus = responseClone.status || 200\n  const responseStatusText =\n    responseClone.statusText || message[responseStatus] || 'OK'\n\n  return {\n    status: responseStatus,\n    statusText: responseStatusText,\n    headers: Object.fromEntries(responseClone.headers.entries()),\n    body: responseText,\n  }\n}\n"
  },
  {
    "path": "src/core/utils/matching/matchRequestUrl.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { coercePath, matchRequestUrl } from './matchRequestUrl'\n\ndescribe('matchRequestUrl', () => {\n  test('returns true when matches against an exact URL', () => {\n    expect(\n      matchRequestUrl(\n        new URL('https://test.mswjs.io'),\n        'https://test.mswjs.io',\n      ),\n    ).toEqual({\n      matches: true,\n      params: {},\n    })\n  })\n\n  test('returns true when matched against a wildcard', () => {\n    expect(matchRequestUrl(new URL('https://test.mswjs.io'), '*')).toEqual({\n      matches: true,\n      params: {\n        '0': 'https://test.mswjs.io/',\n      },\n    })\n  })\n\n  test('returns true when matched against a RegExp', () => {\n    expect(\n      matchRequestUrl(new URL('https://test.mswjs.io'), /test\\.mswjs\\.io/),\n    ).toEqual({\n      matches: true,\n      params: {},\n    })\n  })\n\n  test('returns path parameters when matched', () => {\n    expect(\n      matchRequestUrl(\n        new URL('https://test.mswjs.io/user/abc-123'),\n        'https://test.mswjs.io/user/:userId',\n      ),\n    ).toEqual({\n      matches: true,\n      params: {\n        userId: 'abc-123',\n      },\n    })\n  })\n\n  test('decodes path parameters', () => {\n    const url = 'http://example.com:5001/example'\n\n    expect(\n      matchRequestUrl(\n        new URL(`https://test.mswjs.io/reflect-url/${encodeURIComponent(url)}`),\n        'https://test.mswjs.io/reflect-url/:url',\n      ),\n    ).toEqual({\n      matches: true,\n      params: {\n        url,\n      },\n    })\n  })\n\n  test('returns false when does not match against the request URL', () => {\n    expect(\n      matchRequestUrl(new URL('https://test.mswjs.io'), 'https://google.com'),\n    ).toEqual({\n      matches: false,\n      params: {},\n    })\n  })\n\n  test('returns true when matching optional path parameters', () => {\n    expect(\n      matchRequestUrl(\n        new URL('https://test.mswjs.io/user/123'),\n        'https://test.mswjs.io/user/:userId?',\n      ),\n    ).toEqual({\n      matches: true,\n      params: {\n        userId: '123',\n      },\n    })\n  })\n\n  test('returns true for matching WebSocket URL', () => {\n    expect(\n      matchRequestUrl(new URL('ws://test.mswjs.io'), 'ws://test.mswjs.io'),\n    ).toEqual({\n      matches: true,\n      params: {},\n    })\n    expect(\n      matchRequestUrl(new URL('wss://test.mswjs.io'), 'wss://test.mswjs.io'),\n    ).toEqual({\n      matches: true,\n      params: {},\n    })\n  })\n\n  test('returns false for non-matching WebSocket URL', () => {\n    expect(\n      matchRequestUrl(new URL('ws://test.mswjs.io'), 'ws://foo.mswjs.io'),\n    ).toEqual({\n      matches: false,\n      params: {},\n    })\n    expect(\n      matchRequestUrl(new URL('wss://test.mswjs.io'), 'wss://completely.diff'),\n    ).toEqual({\n      matches: false,\n      params: {},\n    })\n  })\n\n  test('returns path parameters when matched a WebSocket URL', () => {\n    expect(\n      matchRequestUrl(\n        new URL('wss://test.mswjs.io'),\n        'wss://:service.mswjs.io',\n      ),\n    ).toEqual({\n      matches: true,\n      params: {\n        service: 'test',\n      },\n    })\n  })\n})\n\ndescribe('coercePath', () => {\n  test('escapes the colon in protocol', () => {\n    expect(coercePath('https://example.com')).toEqual('https\\\\://example.com')\n    expect(coercePath('https://example.com/:userId')).toEqual(\n      'https\\\\://example.com/:userId',\n    )\n    expect(coercePath('http://localhost:3000')).toEqual(\n      'http\\\\://localhost\\\\:3000',\n    )\n  })\n\n  test('escapes the colon before the port number', () => {\n    expect(coercePath('localhost:8080')).toEqual('localhost\\\\:8080')\n    expect(coercePath('http://127.0.0.1:8080')).toEqual(\n      'http\\\\://127.0.0.1\\\\:8080',\n    )\n    expect(coercePath('https://example.com:1234')).toEqual(\n      'https\\\\://example.com\\\\:1234',\n    )\n\n    expect(coercePath('localhost:8080/:5678')).toEqual('localhost\\\\:8080/:5678')\n    expect(coercePath('https://example.com:8080/:5678')).toEqual(\n      'https\\\\://example.com\\\\:8080/:5678',\n    )\n  })\n\n  test('replaces wildcard with an unnnamed capturing group', () => {\n    expect(coercePath('*')).toEqual('(.*)')\n    expect(coercePath('**')).toEqual('(.*)')\n    expect(coercePath('/us*')).toEqual('/us(.*)')\n    expect(coercePath('/user/*')).toEqual('/user/(.*)')\n    expect(coercePath('https://example.com/user/*')).toEqual(\n      'https\\\\://example.com/user/(.*)',\n    )\n    expect(coercePath('https://example.com/us*')).toEqual(\n      'https\\\\://example.com/us(.*)',\n    )\n  })\n\n  test('preserves path parameter modifiers', () => {\n    expect(coercePath(':name*')).toEqual(':name*')\n    expect(coercePath('/foo/:name*')).toEqual('/foo/:name*')\n    expect(coercePath('/foo/**:name*')).toEqual('/foo/(.*):name*')\n    expect(coercePath('**/foo/*/:name*')).toEqual('(.*)/foo/(.*)/:name*')\n    expect(coercePath('/foo/:first/bar/:second*/*')).toEqual(\n      '/foo/:first/bar/:second*/(.*)',\n    )\n  })\n})\n"
  },
  {
    "path": "src/core/utils/matching/matchRequestUrl.ts",
    "content": "import { match } from 'path-to-regexp'\nimport { getCleanUrl } from '@mswjs/interceptors'\nimport { normalizePath } from './normalizePath'\n\nexport type Path = string | RegExp\nexport type PathParams<KeyType extends keyof any = string> = {\n  [ParamName in KeyType]?: string | ReadonlyArray<string>\n}\n\nexport interface Match {\n  matches: boolean\n  params?: PathParams\n}\n\n/**\n * Coerce a path supported by MSW into a path\n * supported by \"path-to-regexp\".\n */\nexport function coercePath(path: string): string {\n  return (\n    path\n      /**\n       * Replace wildcards (\"*\") with unnamed capturing groups\n       * because \"path-to-regexp\" doesn't support wildcards.\n       * Ignore path parameter' modifiers (i.e. \":name*\").\n       */\n      .replace(\n        /([:a-zA-Z_-]*)(\\*{1,2})+/g,\n        (_, parameterName: string | undefined, wildcard: string) => {\n          const expression = '(.*)'\n\n          if (!parameterName) {\n            return expression\n          }\n\n          return parameterName.startsWith(':')\n            ? `${parameterName}${wildcard}`\n            : `${parameterName}${expression}`\n        },\n      )\n      /**\n       * Escape the port so that \"path-to-regexp\" can match\n       * absolute URLs including port numbers.\n       */\n      .replace(/([^/])(:)(?=\\d+)/, '$1\\\\$2')\n      /**\n       * Escape the protocol so that \"path-to-regexp\" could match\n       * absolute URL.\n       * @see https://github.com/pillarjs/path-to-regexp/issues/259\n       */\n      .replace(/^([^/]+)(:)(?=\\/\\/)/, '$1\\\\$2')\n  )\n}\n\n/**\n * Returns the result of matching given request URL against a mask.\n */\nexport function matchRequestUrl(url: URL, path: Path, baseUrl?: string): Match {\n  const normalizedPath = normalizePath(path, baseUrl)\n  const cleanPath =\n    typeof normalizedPath === 'string'\n      ? coercePath(normalizedPath)\n      : normalizedPath\n\n  const cleanUrl = getCleanUrl(url)\n  const result = match(cleanPath, { decode: decodeURIComponent })(cleanUrl)\n  const params = (result && (result.params as PathParams)) || {}\n\n  return {\n    matches: result !== false,\n    params,\n  }\n}\n\nexport function isPath(value: unknown): value is Path {\n  return typeof value === 'string' || value instanceof RegExp\n}\n"
  },
  {
    "path": "src/core/utils/matching/normalizePath.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { normalizePath } from './normalizePath'\n\ntest('returns RegExp as-is', () => {\n  const path = /s/\n  expect(normalizePath(path)).toEqual(path)\n})\n\ntest('returns a clean absolute URL as-is', () => {\n  const path = 'https://test.mswjs.io/path'\n  expect(normalizePath(path)).toEqual(path)\n})\n\ntest('returns a relative URL as-is given a string path', () => {\n  const path = '/relative/url'\n  expect(normalizePath(path)).toEqual(path)\n})\n\ntest('rebases a relative URL against a custom base URL', () => {\n  const path = '/relative/url'\n  expect(normalizePath(path, 'https://test.mswjs.io')).toEqual(\n    'https://test.mswjs.io/relative/url',\n  )\n})\n\ntest('removes query parameters and hashes from an absolute URL', () => {\n  expect(normalizePath('https://test.mswjs.io/user?query=123')).toEqual(\n    'https://test.mswjs.io/user',\n  )\n  expect(normalizePath('https://test.mswjs.io/user#some')).toEqual(\n    'https://test.mswjs.io/user',\n  )\n  expect(normalizePath('https://test.mswjs.io/user?query=123#some')).toEqual(\n    'https://test.mswjs.io/user',\n  )\n})\n\ntest('removes query parameters and hashes from a relative URL', () => {\n  expect(normalizePath('/user?query=123')).toEqual('/user')\n  expect(normalizePath('/user#some')).toEqual('/user')\n  expect(normalizePath('/user?query=123#some')).toEqual('/user')\n})\n"
  },
  {
    "path": "src/core/utils/matching/normalizePath.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { normalizePath } from './normalizePath'\n\ntest('returns RegExp as-is', () => {\n  const path = /\\/user\\/(.+?)\\//\n  expect(normalizePath(path)).toEqual(path)\n})\n\ntest('returns a clean absolute URL as-is', () => {\n  const path = 'https://test.mswjs.io/user'\n  expect(normalizePath(path)).toEqual(path)\n})\n\ntest('rebases a relative URL against the current location', () => {\n  const path = '/relative/url'\n  expect(normalizePath(path)).toBe(`${location.origin}/relative/url`)\n})\n\ntest('rebases a relative URL against a custom base URL', () => {\n  const path = '/relative/url'\n  expect(normalizePath(path, 'https://test.mswjs.io')).toEqual(\n    'https://test.mswjs.io/relative/url',\n  )\n})\n\ntest('removes query parameters and hashes from an absolute URL', () => {\n  const path = 'https://test.mswjs.io/user?query=123#some'\n  expect(normalizePath(path)).toEqual('https://test.mswjs.io/user')\n})\n\ntest('removes query parameters and hashes from a relative URL', () => {\n  expect(normalizePath('/user?query=123')).toEqual(`${location.origin}/user`)\n  expect(normalizePath('/user#some')).toEqual(`${location.origin}/user`)\n  expect(normalizePath('/user?query=123#some')).toEqual(\n    `${location.origin}/user`,\n  )\n})\n\ntest('returns a path pattern string as-is', () => {\n  expect(normalizePath(':api/user')).toEqual('http://localhost/:api/user')\n  expect(normalizePath('*/resource/*')).toEqual('*/resource/*')\n})\n\ntest('removes query parameters and hashes from a path pattern string', () => {\n  expect(normalizePath(':api/user?query=123#some')).toEqual(\n    'http://localhost/:api/user',\n  )\n})\n\ntest('preserves optional path parameters', () => {\n  expect(normalizePath('/user/:userId?')).toEqual(\n    'http://localhost/user/:userId?',\n  )\n})\n"
  },
  {
    "path": "src/core/utils/matching/normalizePath.ts",
    "content": "import type { Path } from './matchRequestUrl'\nimport { cleanUrl } from '../url/cleanUrl'\nimport { getAbsoluteUrl } from '../url/getAbsoluteUrl'\n\n/**\n * Normalizes a given request handler path:\n * - Preserves RegExp.\n * - Removes query parameters and hashes.\n * - Rebases relative URLs against the \"baseUrl\" or the current location.\n * - Preserves relative URLs in Node.js, unless specified otherwise.\n * - Preserves optional path parameters.\n */\nexport function normalizePath(path: Path, baseUrl?: string): Path {\n  // RegExp paths do not need normalization.\n  if (path instanceof RegExp) {\n    return path\n  }\n\n  const maybeAbsoluteUrl = getAbsoluteUrl(path, baseUrl)\n\n  return cleanUrl(maybeAbsoluteUrl)\n}\n"
  },
  {
    "path": "src/core/utils/request/getAllAcceptedMimeTypes.test.ts",
    "content": "import { getAllAcceptedMimeTypes } from './getAllAcceptedMimeTypes'\n\nit('returns an empty array for null accept header', () => {\n  expect(getAllAcceptedMimeTypes(null)).toEqual([])\n})\n\nit('returns a single mime type as-is', () => {\n  expect(getAllAcceptedMimeTypes('application/json')).toEqual([\n    'application/json',\n  ])\n})\n\nit('returns multiple mime types in order', () => {\n  expect(getAllAcceptedMimeTypes('text/html, application/json')).toEqual([\n    'text/html',\n    'application/json',\n  ])\n})\n\nit('sorts by quality value (q parameter)', () => {\n  expect(\n    getAllAcceptedMimeTypes('text/plain;q=0.5, application/json;q=0.9'),\n  ).toEqual(['application/json', 'text/plain'])\n})\n\nit('excludes types with q=0', () => {\n  expect(getAllAcceptedMimeTypes('text/html, text/plain;q=0')).toEqual([\n    'text/html',\n  ])\n})\n\nit('returns an empty array when all types have q=0', () => {\n  expect(getAllAcceptedMimeTypes('text/html;q=0, text/plain;q=0')).toEqual([])\n})\n\nit('treats missing q as q=1 (default)', () => {\n  expect(getAllAcceptedMimeTypes('text/plain;q=0.5, application/json')).toEqual(\n    ['application/json', 'text/plain'],\n  )\n})\n\nit('sorts by specificity when quality is equal (type/subtype > type/* > */*)', () => {\n  expect(getAllAcceptedMimeTypes('*/*, text/*, text/html')).toEqual([\n    'text/html',\n    'text/*',\n    '*/*',\n  ])\n})\n\nit('sorts by parameter count when quality and specificity are equal', () => {\n  expect(\n    getAllAcceptedMimeTypes(\n      'text/plain;format=fixed;charset=utf-8, text/plain;charset=utf-8',\n    ),\n  ).toEqual(['text/plain', 'text/plain'])\n})\n\nit('applies full precedence: quality > specificity > parameter count', () => {\n  expect(\n    getAllAcceptedMimeTypes(\n      'text/*;q=0.8, application/json, text/html;q=0.8, */*;q=0.1',\n    ),\n  ).toEqual(['application/json', 'text/html', 'text/*', '*/*'])\n})\n\nit('handles whitespace around values', () => {\n  expect(\n    getAllAcceptedMimeTypes('  text/html  ,  application/json ; q=0.9  '),\n  ).toEqual(['text/html', 'application/json'])\n})\n\nit('handles a realistic browser accept header', () => {\n  expect(\n    getAllAcceptedMimeTypes(\n      'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8',\n    ),\n  ).toEqual(['text/html', 'application/xhtml+xml', 'application/xml', '*/*'])\n})\n\nit('handles the graphql-over-http accept header', () => {\n  expect(\n    getAllAcceptedMimeTypes(\n      'application/graphql-response+json, application/json',\n    ),\n  ).toEqual(['application/graphql-response+json', 'application/json'])\n})\n"
  },
  {
    "path": "src/core/utils/request/getAllAcceptedMimeTypes.ts",
    "content": "/**\n * Returns all accepted mime types, ordered by precedence as defined\n * in [RFC 7231 Section 5.3.2](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2).\n *\n * Precedence rules (highest to lowest):\n * 1. Quality value (`q` parameter, default 1).\n * 2. Specificity: `type/subtype` > `type/*` > `*\\/*`.\n * 3. Number of media type parameters (more = more specific).\n *\n * Types with `q=0` are excluded (explicitly not acceptable).\n */\nexport function getAllAcceptedMimeTypes(\n  acceptHeader: string | null,\n): Array<string> {\n  if (acceptHeader == null) {\n    return []\n  }\n\n  const accepted: Array<{\n    type: string\n    quality: number\n    specificity: number\n    parameterCount: number\n  }> = []\n\n  for (const part of acceptHeader.split(',')) {\n    const [type, ...params] = part.split(';').map((v) => v.trim())\n\n    let quality = 1\n    let parameterCount = 0\n\n    for (const param of params) {\n      const [key, value] = param.split('=').map((v) => v.trim())\n\n      if (key === 'q') {\n        quality = Number(value)\n      } else {\n        parameterCount++\n      }\n    }\n\n    // RFC 7231: a quality value of 0 indicates \"not acceptable\".\n    if (quality === 0) {\n      continue\n    }\n\n    const [mediaType, mediaSubtype] = type.split('/')\n    const specificity = mediaType === '*' ? 0 : mediaSubtype === '*' ? 1 : 2\n\n    accepted.push({ type, quality, specificity, parameterCount })\n  }\n\n  if (!accepted.length) {\n    return []\n  }\n\n  return accepted\n    .sort((left, right) => {\n      if (right.quality !== left.quality) {\n        return right.quality - left.quality\n      }\n\n      if (right.specificity !== left.specificity) {\n        return right.specificity - left.specificity\n      }\n\n      return right.parameterCount - left.parameterCount\n    })\n    .map((entry) => entry.type)\n}\n"
  },
  {
    "path": "src/core/utils/request/getRequestCookies.ts",
    "content": "import {\n  parse as parseCookie,\n  serialize as serializeCookie,\n} from '../../../shims/cookie'\nimport { cookieStore } from '../cookieStore'\n\nfunction parseCookies(input: string): Record<string, string> {\n  const parsedCookies = parseCookie(input)\n  const cookies: Record<string, string> = {}\n\n  for (const cookieName in parsedCookies) {\n    if (typeof parsedCookies[cookieName] !== 'undefined') {\n      cookies[cookieName] = parsedCookies[cookieName]\n    }\n  }\n\n  return cookies\n}\n\nfunction getAllDocumentCookies() {\n  return parseCookies(document.cookie)\n}\n\nfunction getDocumentCookies(request: Request): Record<string, string> {\n  if (typeof document === 'undefined' || typeof location === 'undefined') {\n    return {}\n  }\n\n  switch (request.credentials) {\n    case 'same-origin': {\n      const requestUrl = new URL(request.url)\n\n      // Return document cookies only when requested a resource\n      // from the same origin as the current document.\n      return location.origin === requestUrl.origin\n        ? getAllDocumentCookies()\n        : {}\n    }\n\n    case 'include': {\n      // Return all document cookies.\n      return getAllDocumentCookies()\n    }\n\n    default: {\n      return {}\n    }\n  }\n}\n\nexport function getAllRequestCookies(request: Request): Record<string, string> {\n  /**\n   * @note While the \"cookie\" header is a forbidden header field\n   * in the browser, you can read it in Node.js. We need to respect\n   * it for mocking in Node.js.\n   */\n  const requestCookieHeader = request.headers.get('cookie')\n  const cookiesFromHeaders = requestCookieHeader\n    ? parseCookies(requestCookieHeader)\n    : {}\n\n  const cookiesFromDocument = getDocumentCookies(request)\n\n  // Forward the document cookies to the request headers.\n  for (const name in cookiesFromDocument) {\n    request.headers.append(\n      'cookie',\n      serializeCookie(name, cookiesFromDocument[name]),\n    )\n  }\n\n  const cookiesFromStore = cookieStore.getCookies(request.url)\n  const storedCookiesObject = Object.fromEntries(\n    cookiesFromStore.map((cookie) => [cookie.key, cookie.value]),\n  )\n\n  // Forward the raw stored cookies to request headers\n  // so they contain metadata like \"expires\", \"secure\", etc.\n  for (const cookie of cookiesFromStore) {\n    request.headers.append('cookie', cookie.toString())\n  }\n\n  return {\n    ...cookiesFromDocument,\n    ...storedCookiesObject,\n    ...cookiesFromHeaders,\n  }\n}\n"
  },
  {
    "path": "src/core/utils/request/onUnhandledRequest.node.test.ts",
    "content": "// @vitest-environment node\nimport { onUnhandledRequest } from './onUnhandledRequest'\n\nconst fixtures = {\n  warningWithoutSuggestions: (url = `/api`) => `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET ${url}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n  warningWithResponseBody: (url = `/api`) => `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • POST ${url}\n\n  • Request body: {\"variables\":{\"id\":\"abc-123\"},\"query\":\"query UserName($id: String!) { user(id: $id) { name } }\"}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n\n  errorWithoutSuggestions: `\\\n[MSW] Error: intercepted a request without a matching request handler:\n\n  • GET /api\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n}\n\nbeforeAll(() => {\n  vi.spyOn(console, 'warn').mockImplementation(() => void 0)\n  vi.spyOn(console, 'error').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.clearAllMocks()\n})\n\nafterAll(() => {\n  vi.restoreAllMocks()\n})\n\ntest('prints with an absolute URL and search params', async () => {\n  await onUnhandledRequest(\n    new Request(new URL('https://mswjs.io/api?foo=boo')),\n    'warn',\n  )\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(`https://mswjs.io/api?foo=boo`),\n  )\n\n  await onUnhandledRequest(\n    new Request(new URL('http://localhost/api?foo=boo')),\n    'warn',\n  )\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(`http://localhost/api?foo=boo`),\n  )\n})\n"
  },
  {
    "path": "src/core/utils/request/onUnhandledRequest.test.ts",
    "content": "// @vitest-environment jsdom\nimport {\n  onUnhandledRequest,\n  UnhandledRequestCallback,\n} from './onUnhandledRequest'\n\nconst fixtures = {\n  warningWithoutSuggestions: (url = `/api`) => `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET ${url}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n  warningWithResponseBody: (url = `/api`) => `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • POST ${url}\n\n  • Request body: {\"variables\":{\"id\":\"abc-123\"},\"query\":\"query UserName($id: String!) { user(id: $id) { name } }\"}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n\n  errorWithoutSuggestions: `\\\n[MSW] Error: intercepted a request without a matching request handler:\n\n  • GET /api\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n}\n\nbeforeEach(() => {\n  vi.spyOn(console, 'warn').mockImplementation(() => void 0)\n  vi.spyOn(console, 'error').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.restoreAllMocks()\n})\n\ntest('supports the \"bypass\" request strategy', async () => {\n  await onUnhandledRequest(\n    new Request(new URL('http://localhost/api')),\n    'bypass',\n  )\n\n  expect(console.warn).not.toHaveBeenCalled()\n  expect(console.error).not.toHaveBeenCalled()\n})\n\ntest('supports the \"warn\" request strategy', async () => {\n  await onUnhandledRequest(new Request(new URL('http://localhost/api')), 'warn')\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(),\n  )\n})\n\ntest('supports the \"warn\" request strategy with request body', async () => {\n  await onUnhandledRequest(\n    new Request(new URL('http://localhost/api'), {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        variables: {\n          id: 'abc-123',\n        },\n        query: 'query UserName($id: String!) { user(id: $id) { name } }',\n      }),\n    }),\n  )\n\n  expect(console.warn).toHaveBeenCalledWith(fixtures.warningWithResponseBody())\n})\n\ntest('supports the \"error\" request strategy', async () => {\n  await expect(\n    onUnhandledRequest(new Request(new URL('http://localhost/api')), 'error'),\n  ).rejects.toThrow(\n    '[MSW] Cannot bypass a request when using the \"error\" strategy for the \"onUnhandledRequest\" option.',\n  )\n\n  expect(console.error).toHaveBeenCalledWith(fixtures.errorWithoutSuggestions)\n})\n\ntest('supports a custom callback function', async () => {\n  const callback = vi.fn<UnhandledRequestCallback>((request) => {\n    console.warn(`callback: ${request.method} ${request.url}`)\n  })\n  const request = new Request(new URL('/user', 'http://localhost:3000'))\n  await onUnhandledRequest(request, callback)\n\n  expect(callback).toHaveBeenCalledTimes(1)\n  expect(callback).toHaveBeenCalledWith(request, {\n    warning: expect.any(Function),\n    error: expect.any(Function),\n  })\n\n  // Check that the custom logic in the callback was called.\n  expect(console.warn).toHaveBeenCalledWith(\n    `callback: GET http://localhost:3000/user`,\n  )\n})\n\ntest('supports calling default strategies from the custom callback function', async () => {\n  const callback = vi.fn<UnhandledRequestCallback>((request, print) => {\n    // Call the default \"error\" strategy.\n    print.error()\n  })\n  const request = new Request(new URL('http://localhost/api'))\n  await expect(onUnhandledRequest(request, callback)).rejects.toThrow(\n    `[MSW] Cannot bypass a request when using the \"error\" strategy for the \"onUnhandledRequest\" option.`,\n  )\n\n  expect(callback).toHaveBeenCalledTimes(1)\n  expect(callback).toHaveBeenCalledWith(request, {\n    warning: expect.any(Function),\n    error: expect.any(Function),\n  })\n\n  // Check that the default strategy was called.\n  expect(console.error).toHaveBeenCalledWith(fixtures.errorWithoutSuggestions)\n})\n\ntest('does not print any suggestions given no handlers to suggest', async () => {\n  await onUnhandledRequest(new Request(new URL('http://localhost/api')), 'warn')\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(),\n  )\n})\n\ntest('throws an exception given unknown request strategy', async () => {\n  await expect(\n    onUnhandledRequest(\n      new Request(new URL('http://localhost/api')),\n      // @ts-expect-error Intentional unknown strategy.\n      'invalid-strategy',\n    ),\n  ).rejects.toThrow(\n    '[MSW] Failed to react to an unhandled request: unknown strategy \"invalid-strategy\". Please provide one of the supported strategies (\"bypass\", \"warn\", \"error\") or a custom callback function as the value of the \"onUnhandledRequest\" option.',\n  )\n})\n\ntest('prints with a relative URL and search params', async () => {\n  await onUnhandledRequest(\n    new Request(new URL('http://localhost/api?foo=boo')),\n    'warn',\n  )\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(`/api?foo=boo`),\n  )\n})\n\ntest('prints with an absolute URL and search params', async () => {\n  await onUnhandledRequest(\n    new Request(new URL('https://mswjs.io/api?foo=boo')),\n    'warn',\n  )\n\n  expect(console.warn).toHaveBeenCalledWith(\n    fixtures.warningWithoutSuggestions(`https://mswjs.io/api?foo=boo`),\n  )\n})\n\ntest('ignores common static assets when using the \"warn\" strategy', async () => {\n  await Promise.allSettled([\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/main.css')),\n      'warn',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/index.mjs')),\n      'warn',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/node_modules/abc-123')),\n      'warn',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://fonts.googleapis.com/some-font')),\n      'warn',\n    ),\n  ])\n\n  expect(console.warn).not.toHaveBeenCalled()\n})\n\ntest('ignores common static assets when using the \"error\" strategy', async () => {\n  await Promise.allSettled([\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/main.css')),\n      'error',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/index.mjs')),\n      'error',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://example.com/node_modules/abc-123')),\n      'error',\n    ),\n    onUnhandledRequest(\n      new Request(new URL('https://fonts.googleapis.com/some-font')),\n      'error',\n    ),\n  ])\n\n  expect(console.error).not.toHaveBeenCalled()\n})\n\ntest('exposes common static assets to the explicit callback', async () => {\n  let callbackRequest!: Request\n  await onUnhandledRequest(\n    new Request(new URL('https://example.com/main.css')),\n    (request) => {\n      callbackRequest = request\n    },\n  )\n\n  expect(callbackRequest).toBeInstanceOf(Request)\n  expect(callbackRequest.url).toBe('https://example.com/main.css')\n})\n"
  },
  {
    "path": "src/core/utils/request/onUnhandledRequest.ts",
    "content": "import { toPublicUrl } from './toPublicUrl'\nimport { InternalError, devUtils } from '../internal/devUtils'\nimport { isCommonAssetRequest } from '../../isCommonAssetRequest'\n\nexport interface UnhandledRequestPrint {\n  warning(): void\n  error(): void\n}\n\nexport type UnhandledRequestCallback = (\n  request: Request,\n  print: UnhandledRequestPrint,\n) => void\n\nexport type UnhandledRequestStrategy =\n  | 'bypass'\n  | 'warn'\n  | 'error'\n  | UnhandledRequestCallback\n\nexport async function onUnhandledRequest(\n  request: Request,\n  strategy: UnhandledRequestStrategy = 'warn',\n): Promise<void> {\n  const url = new URL(request.url)\n  const publicUrl = toPublicUrl(url) + url.search\n\n  const requestBody =\n    request.method === 'HEAD' || request.method === 'GET'\n      ? null\n      : await request.clone().text()\n  const messageDetails = `\\n\\n  \\u2022 ${request.method} ${publicUrl}\\n\\n${requestBody ? `  \\u2022 Request body: ${requestBody}\\n\\n` : ''}`\n  const unhandledRequestMessage = `intercepted a request without a matching request handler:${messageDetails}If you still wish to intercept this unhandled request, please create a request handler for it.\\nRead more: https://mswjs.io/docs/http/intercepting-requests`\n\n  function applyStrategy(strategy: UnhandledRequestStrategy) {\n    switch (strategy) {\n      case 'error': {\n        // Print a developer-friendly error.\n        devUtils.error('Error: %s', unhandledRequestMessage)\n\n        // Throw an exception to halt request processing and not perform the original request.\n        throw new InternalError(\n          devUtils.formatMessage(\n            'Cannot bypass a request when using the \"error\" strategy for the \"onUnhandledRequest\" option.',\n          ),\n        )\n      }\n\n      case 'warn': {\n        devUtils.warn('Warning: %s', unhandledRequestMessage)\n        break\n      }\n\n      case 'bypass':\n        break\n\n      default:\n        throw new InternalError(\n          devUtils.formatMessage(\n            'Failed to react to an unhandled request: unknown strategy \"%s\". Please provide one of the supported strategies (\"bypass\", \"warn\", \"error\") or a custom callback function as the value of the \"onUnhandledRequest\" option.',\n            strategy,\n          ),\n        )\n    }\n  }\n\n  if (typeof strategy === 'function') {\n    strategy(request, {\n      warning: applyStrategy.bind(null, 'warn'),\n      error: applyStrategy.bind(null, 'error'),\n    })\n    return\n  }\n\n  // Ignore common static asset requests when using a built-in strategy.\n  // There's a slight overhead here because this utility will create a request URL\n  // instance again despite us having done so previously in this function.\n  if (!isCommonAssetRequest(request)) {\n    applyStrategy(strategy)\n  }\n}\n"
  },
  {
    "path": "src/core/utils/request/storeResponseCookies.ts",
    "content": "import { cookieStore } from '../cookieStore'\nimport { kSetCookie } from '../HttpResponse/decorators'\n\nexport async function storeResponseCookies(\n  request: Request,\n  response: Response,\n): Promise<void> {\n  // Grab the raw \"Set-Cookie\" response header provided\n  // in the HeadersInit for this mocked response.\n  const responseCookies = Reflect.get(response, kSetCookie) as\n    | string\n    | undefined\n\n  if (responseCookies) {\n    await cookieStore.setCookie(responseCookies, request.url)\n  }\n}\n"
  },
  {
    "path": "src/core/utils/request/toPublicUrl.node.test.ts",
    "content": "// @vitest-environment node\nimport { toPublicUrl } from './toPublicUrl'\n\ntest('returns an absolute request URL without search params', () => {\n  expect(toPublicUrl(new URL('https://test.mswjs.io/path'))).toBe(\n    'https://test.mswjs.io/path',\n  )\n\n  expect(toPublicUrl(new URL('http://192.168.0.10/path'))).toBe(\n    'http://192.168.0.10/path',\n  )\n\n  expect(\n    toPublicUrl(new URL('http://localhost/path?foo=bar')),\n    'Must not return relative URL in Node.js',\n  ).toBe('http://localhost/path')\n})\n"
  },
  {
    "path": "src/core/utils/request/toPublicUrl.test.ts",
    "content": "// @vitest-environment jsdom\nimport { toPublicUrl } from './toPublicUrl'\n\ntest('returns an absolute request URL without search params', () => {\n  expect(toPublicUrl(new URL('https://test.mswjs.io/path'))).toBe(\n    'https://test.mswjs.io/path',\n  )\n\n  expect(toPublicUrl(new URL('http://localhost/path'))).toBe('/path')\n\n  expect(toPublicUrl(new URL('http://localhost/path?foo=bar'))).toBe('/path')\n})\n\nit('returns a relative URL given the request to the same origin', () => {\n  expect(toPublicUrl('http://localhost/user')).toBe('/user')\n})\n"
  },
  {
    "path": "src/core/utils/request/toPublicUrl.ts",
    "content": "/**\n * Returns a relative URL if the given request URL is relative\n * to the current origin. Otherwise returns an absolute URL.\n */\nexport function toPublicUrl(url: string | URL): string {\n  const urlInstance = url instanceof URL ? url : new URL(url)\n\n  if (\n    typeof location !== 'undefined' &&\n    urlInstance.origin === location.origin\n  ) {\n    return urlInstance.pathname\n  }\n\n  return urlInstance.origin + urlInstance.pathname\n}\n"
  },
  {
    "path": "src/core/utils/toResponseInit.ts",
    "content": "export function toResponseInit(response: Response): ResponseInit {\n  return {\n    status: response.status,\n    statusText: response.statusText,\n    headers: Object.fromEntries(response.headers.entries()),\n  }\n}\n"
  },
  {
    "path": "src/core/utils/url/cleanUrl.test.ts",
    "content": "import { cleanUrl } from './cleanUrl'\n\nit('removes query parameters from a URL string', () => {\n  expect(cleanUrl('/user?id=123')).toEqual('/user')\n  expect(cleanUrl('/user?id=123&id=456')).toEqual('/user')\n  expect(cleanUrl('/user?id=123&role=admin')).toEqual('/user')\n})\n\nit('removes hashes from a URL string', () => {\n  expect(cleanUrl('/user#hash')).toEqual('/user')\n  expect(cleanUrl('/user#hash-with-dashes')).toEqual('/user')\n})\n\nit('removes both query parameters and hashes from a URL string', () => {\n  expect(cleanUrl('/user?id=123#some')).toEqual('/user')\n  expect(cleanUrl('/user?id=123&role=admin#some')).toEqual('/user')\n})\n\nit('preserves optional path parameters', () => {\n  expect(cleanUrl('/user/:id?')).toEqual('/user/:id?')\n  expect(cleanUrl('/user/:id?/:messageId?')).toEqual('/user/:id?/:messageId?')\n})\n"
  },
  {
    "path": "src/core/utils/url/cleanUrl.ts",
    "content": "const REDUNDANT_CHARACTERS_EXP = /[?|#].*$/g\n\n/**\n * Removes search parameters and the fragment\n * from a given URL string.\n */\nexport function cleanUrl(path: string): string {\n  // If the path ends with an optional path parameter,\n  // return it as-is.\n  if (path.endsWith('?')) {\n    return path\n  }\n\n  // Otherwise, remove the search and fragment from it.\n  return path.replace(REDUNDANT_CHARACTERS_EXP, '')\n}\n"
  },
  {
    "path": "src/core/utils/url/getAbsoluteUrl.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { getAbsoluteUrl } from './getAbsoluteUrl'\n\nit('returns a given relative URL as-is', () => {\n  expect(getAbsoluteUrl('/reviews')).toBe('/reviews')\n})\n\nit('rebases a relative URL against a custom base URL', () => {\n  expect(getAbsoluteUrl('/user', 'https://api.github.com')).toEqual(\n    'https://api.github.com/user',\n  )\n})\nit('returns a given absolute URL as-is', () => {\n  expect(getAbsoluteUrl('https://api.mswjs.io/users')).toBe(\n    'https://api.mswjs.io/users',\n  )\n})\n"
  },
  {
    "path": "src/core/utils/url/getAbsoluteUrl.test.ts",
    "content": "// @vitest-environment jsdom\nimport { getAbsoluteUrl } from './getAbsoluteUrl'\n\nconst rawLocation = window.location\n\nafterAll(() => {\n  Object.defineProperty(window, 'location', {\n    value: rawLocation,\n  })\n})\n\nit('resolves a relative URL against the current location (default)', () => {\n  expect(getAbsoluteUrl('/reviews')).toBe('http://localhost/reviews')\n})\n\nit('supports relative URLs starting with search parameters', () => {\n  Object.defineProperty(window, 'location', {\n    value: {\n      href: 'http://localhost/nested',\n    },\n  })\n\n  expect(getAbsoluteUrl('?resourceId=abc-123')).toBe(\n    'http://localhost/nested?resourceId=abc-123',\n  )\n})\n\nit('resolves a relative URL against a custom base URL', () => {\n  expect(getAbsoluteUrl('/user', 'https://api.github.com')).toBe(\n    'https://api.github.com/user',\n  )\n})\n\nit('returns a given absolute URL as-is', () => {\n  expect(getAbsoluteUrl('https://api.mswjs.io/users')).toBe(\n    'https://api.mswjs.io/users',\n  )\n})\n\nit('returns an absolute URL given a relative path without a leading slash', () => {\n  expect(getAbsoluteUrl('users')).toBe('http://localhost/users')\n})\n\nit('returns a path with a pattern as-is', () => {\n  expect(getAbsoluteUrl(':api/user')).toBe('http://localhost/:api/user')\n  expect(getAbsoluteUrl('*/resource/*')).toBe('*/resource/*')\n})\n"
  },
  {
    "path": "src/core/utils/url/getAbsoluteUrl.ts",
    "content": "import { isAbsoluteUrl } from './isAbsoluteUrl'\n\n/**\n * Returns an absolute URL based on the given path.\n */\nexport function getAbsoluteUrl(path: string, baseUrl?: string): string {\n  // already absolute URL\n  if (isAbsoluteUrl(path)) {\n    return path\n  }\n\n  // Ignore path with pattern start with *\n  if (path.startsWith('*')) {\n    return path\n  }\n\n  // Resolve a relative request URL against a given custom \"baseUrl\"\n  // or the document baseURI (in the case of browser/browser-like environments).\n  const origin = baseUrl || (typeof location !== 'undefined' && location.href)\n\n  return origin\n    ? // Encode and decode the path to preserve escaped characters.\n      decodeURI(new URL(encodeURI(path), origin).href)\n    : path\n}\n"
  },
  {
    "path": "src/core/utils/url/isAbsoluteUrl.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { isAbsoluteUrl } from './isAbsoluteUrl'\n\nit('returns true for the \"http\" scheme', () => {\n  expect(isAbsoluteUrl('http://www.domain.com')).toEqual(true)\n})\n\nit('returns true for the \"https\" scheme', () => {\n  expect(isAbsoluteUrl('https://www.domain.com')).toEqual(true)\n})\n\nit('returns true for the \"ws\" scheme', () => {\n  expect(isAbsoluteUrl('ws://www.domain.com')).toEqual(true)\n})\n\nit('returns true for the \"ftp\" scheme', () => {\n  expect(isAbsoluteUrl('ftp://www.domain.com')).toEqual(true)\n})\n\nit('returns true for the custom scheme', () => {\n  expect(isAbsoluteUrl('web+my://www.example.com')).toEqual(true)\n})\n\nit('returns false for the relative URL', () => {\n  expect(isAbsoluteUrl('/test')).toEqual(false)\n})\n\nit('returns false for the relative URL without a leading slash', () => {\n  expect(isAbsoluteUrl('test')).toEqual(false)\n})\n"
  },
  {
    "path": "src/core/utils/url/isAbsoluteUrl.ts",
    "content": "/**\n * Determines if the given URL string is an absolute URL.\n */\nexport function isAbsoluteUrl(url: string): boolean {\n  return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url)\n}\n"
  },
  {
    "path": "src/core/ws/WebSocketClientManager.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { setMaxListeners } from 'node:events'\nimport {\n  WebSocketClientConnection,\n  WebSocketData,\n  WebSocketTransport,\n} from '@mswjs/interceptors/WebSocket'\nimport {\n  WebSocketClientManager,\n  WebSocketBroadcastChannelMessage,\n} from './WebSocketClientManager'\n\nconst channel = new BroadcastChannel('test:channel')\n\n/**\n * @note Increase the number of maximum event listeners\n * because the same channel is shared between different\n * manager instances in different tests.\n */\nsetMaxListeners(Number.MAX_SAFE_INTEGER, channel)\n\nvi.spyOn(channel, 'postMessage')\n\nconst socket = new WebSocket('ws://localhost')\n\nclass TestWebSocketTransport extends EventTarget implements WebSocketTransport {\n  send(_data: WebSocketData): void {}\n  close(_code?: number | undefined, _reason?: string | undefined): void {}\n}\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\nit('adds a client from this runtime to the list of clients', async () => {\n  const manager = new WebSocketClientManager(channel)\n  const connection = new WebSocketClientConnection(\n    socket,\n    new TestWebSocketTransport(),\n  )\n\n  await manager.addConnection(connection)\n\n  // Must add the client to the list of clients.\n  expect(Array.from(manager.clients.values())).toEqual([connection])\n})\n\nit('adds multiple clients from this runtime to the list of clients', async () => {\n  const manager = new WebSocketClientManager(channel)\n  const connectionOne = new WebSocketClientConnection(\n    socket,\n    new TestWebSocketTransport(),\n  )\n  await manager.addConnection(connectionOne)\n\n  // Must add the client to the list of clients.\n  expect(Array.from(manager.clients.values())).toEqual([connectionOne])\n\n  const connectionTwo = new WebSocketClientConnection(\n    socket,\n    new TestWebSocketTransport(),\n  )\n  await manager.addConnection(connectionTwo)\n\n  // Must add the new client to the list as well.\n  expect(Array.from(manager.clients.values())).toEqual([\n    connectionOne,\n    connectionTwo,\n  ])\n})\n\nit('replays a \"send\" event coming from another runtime', async () => {\n  const manager = new WebSocketClientManager(channel)\n  const connection = new WebSocketClientConnection(\n    socket,\n    new TestWebSocketTransport(),\n  )\n  await manager.addConnection(connection)\n  vi.spyOn(connection, 'send')\n\n  // Emulate another runtime signaling this connection to receive data.\n  channel.dispatchEvent(\n    new MessageEvent<WebSocketBroadcastChannelMessage>('message', {\n      data: {\n        type: 'extraneous:send',\n        payload: {\n          clientId: connection.id,\n          data: 'hello',\n        },\n      },\n    }),\n  )\n\n  await vi.waitFor(() => {\n    // Must execute the requested operation on the connection.\n    expect(connection.send).toHaveBeenCalledWith('hello')\n    expect(connection.send).toHaveBeenCalledTimes(1)\n  })\n})\n\nit('replays a \"close\" event coming from another runtime', async () => {\n  const manager = new WebSocketClientManager(channel)\n  const connection = new WebSocketClientConnection(\n    socket,\n    new TestWebSocketTransport(),\n  )\n  await manager.addConnection(connection)\n  vi.spyOn(connection, 'close')\n\n  // Emulate another runtime signaling this connection to close.\n  channel.dispatchEvent(\n    new MessageEvent<WebSocketBroadcastChannelMessage>('message', {\n      data: {\n        type: 'extraneous:close',\n        payload: {\n          clientId: connection.id,\n          code: 1000,\n          reason: 'Normal closure',\n        },\n      },\n    }),\n  )\n\n  await vi.waitFor(() => {\n    // Must execute the requested operation on the connection.\n    expect(connection.close).toHaveBeenCalledWith(1000, 'Normal closure')\n    expect(connection.close).toHaveBeenCalledTimes(1)\n  })\n})\n\nit('removes the extraneous message listener when the connection closes', async () => {\n  const manager = new WebSocketClientManager(channel)\n  const transport = new TestWebSocketTransport()\n  const connection = new WebSocketClientConnection(socket, transport)\n  vi.spyOn(connection, 'close').mockImplementationOnce(() => {\n    /**\n     * @note This is a nasty hack so we don't have to uncouple\n     * the connection from transport. Creating a mock transport\n     * is difficult because it relies on the `WebSocketOverride` class.\n     * All we care here is that closing the connection triggers\n     * the transport closure, which it always does.\n     */\n    transport.dispatchEvent(new Event('close'))\n  })\n  vi.spyOn(connection, 'send')\n\n  await manager.addConnection(connection)\n  connection.close()\n\n  // Signals from other runtimes have no effect on the closed connection.\n  channel.dispatchEvent(\n    new MessageEvent<WebSocketBroadcastChannelMessage>('message', {\n      data: {\n        type: 'extraneous:send',\n        payload: {\n          clientId: connection.id,\n          data: 'hello',\n        },\n      },\n    }),\n  )\n\n  expect(connection.send).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "src/core/ws/WebSocketClientManager.ts",
    "content": "import type {\n  WebSocketData,\n  WebSocketClientConnectionProtocol,\n  WebSocketClientEventMap,\n} from '@mswjs/interceptors/WebSocket'\nimport { WebSocketClientStore } from './WebSocketClientStore'\nimport { WebSocketMemoryClientStore } from './WebSocketMemoryClientStore'\nimport { WebSocketIndexedDBClientStore } from './WebSocketIndexedDBClientStore'\n\nexport type WebSocketBroadcastChannelMessage =\n  | {\n      type: 'extraneous:send'\n      payload: {\n        clientId: string\n        data: WebSocketData\n      }\n    }\n  | {\n      type: 'extraneous:close'\n      payload: {\n        clientId: string\n        code?: number\n        reason?: string\n      }\n    }\n\n/**\n * A manager responsible for accumulating WebSocket client\n * connections across different browser runtimes.\n */\nexport class WebSocketClientManager {\n  private store: WebSocketClientStore\n  private runtimeClients: Map<string, WebSocketClientConnectionProtocol>\n  private allClients: Set<WebSocketClientConnectionProtocol>\n\n  constructor(private channel: BroadcastChannel) {\n    // Store the clients in the IndexedDB in the browser,\n    // otherwise, store the clients in memory.\n    this.store =\n      typeof indexedDB !== 'undefined'\n        ? new WebSocketIndexedDBClientStore()\n        : new WebSocketMemoryClientStore()\n\n    this.runtimeClients = new Map()\n    this.allClients = new Set()\n\n    this.channel.addEventListener('message', (message) => {\n      if (message.data?.type === 'db:update') {\n        this.flushDatabaseToMemory()\n      }\n    })\n\n    if (typeof window !== 'undefined') {\n      window.addEventListener('message', async (message) => {\n        if (message.data?.type === 'msw/worker:stop') {\n          await this.removeRuntimeClients()\n        }\n      })\n    }\n  }\n\n  private async flushDatabaseToMemory() {\n    const storedClients = await this.store.getAll()\n\n    this.allClients = new Set(\n      storedClients.map((client) => {\n        const runtimeClient = this.runtimeClients.get(client.id)\n\n        /**\n         * @note For clients originating in this runtime, use their\n         * direct references. No need to wrap them in a remote connection.\n         */\n        if (runtimeClient) {\n          return runtimeClient\n        }\n\n        return new WebSocketRemoteClientConnection(\n          client.id,\n          new URL(client.url),\n          this.channel,\n        )\n      }),\n    )\n  }\n\n  private async removeRuntimeClients(): Promise<void> {\n    await this.store.deleteMany(Array.from(this.runtimeClients.keys()))\n    this.runtimeClients.clear()\n    await this.flushDatabaseToMemory()\n    this.notifyOthersAboutDatabaseUpdate()\n  }\n\n  /**\n   * All active WebSocket client connections.\n   */\n  get clients(): Set<WebSocketClientConnectionProtocol> {\n    return this.allClients\n  }\n\n  /**\n   * Notify other runtimes about the database update\n   * using the shared `BroadcastChannel` instance.\n   */\n  private notifyOthersAboutDatabaseUpdate(): void {\n    this.channel.postMessage({ type: 'db:update' })\n  }\n\n  private async addClient(\n    client: WebSocketClientConnectionProtocol,\n  ): Promise<void> {\n    await this.store.add(client)\n    // Sync the in-memory clients in this runtime with the\n    // updated database. This pulls in all the stored clients.\n    await this.flushDatabaseToMemory()\n    this.notifyOthersAboutDatabaseUpdate()\n  }\n\n  /**\n   * Adds the given `WebSocket` client connection to the set\n   * of all connections. The given connection is always the complete\n   * connection object because `addConnection()` is called only\n   * for the opened connections in the same runtime.\n   */\n  public async addConnection(\n    client: WebSocketClientConnectionProtocol,\n  ): Promise<void> {\n    // Store this client in the map of clients created in this runtime.\n    // This way, the manager can distinguish between this runtime clients\n    // and extraneous runtime clients when synchronizing clients storage.\n    this.runtimeClients.set(client.id, client)\n\n    // Add the new client to the storage.\n    await this.addClient(client)\n\n    // Handle the incoming BroadcastChannel messages from other runtimes\n    // that attempt to control this runtime (via a remote connection wrapper).\n    // E.g. another runtime calling `client.send()` for the client in this runtime.\n    const handleExtraneousMessage = (\n      message: MessageEvent<WebSocketBroadcastChannelMessage>,\n    ) => {\n      const { type, payload } = message.data\n\n      // Ignore broadcasted messages for other clients.\n      if (\n        typeof payload === 'object' &&\n        'clientId' in payload &&\n        payload.clientId !== client.id\n      ) {\n        return\n      }\n\n      switch (type) {\n        case 'extraneous:send': {\n          client.send(payload.data)\n          break\n        }\n\n        case 'extraneous:close': {\n          client.close(payload.code, payload.reason)\n          break\n        }\n      }\n    }\n\n    const abortController = new AbortController()\n\n    this.channel.addEventListener('message', handleExtraneousMessage, {\n      signal: abortController.signal,\n    })\n\n    // Once closed, this connection cannot be operated on.\n    // This must include the extraneous runtimes as well.\n    client.addEventListener('close', () => abortController.abort(), {\n      once: true,\n    })\n  }\n}\n\n/**\n * A wrapper class to operate with WebSocket client connections\n * from other runtimes. This class maintains 1-1 public API\n * compatibility to the `WebSocketClientConnection` but relies\n * on the given `BroadcastChannel` to communicate instructions\n * with the client connections from other runtimes.\n */\nexport class WebSocketRemoteClientConnection\n  implements WebSocketClientConnectionProtocol\n{\n  constructor(\n    public readonly id: string,\n    public readonly url: URL,\n    private channel: BroadcastChannel,\n  ) {}\n\n  send(data: WebSocketData): void {\n    this.channel.postMessage({\n      type: 'extraneous:send',\n      payload: {\n        clientId: this.id,\n        data,\n      },\n    } as WebSocketBroadcastChannelMessage)\n  }\n\n  close(code?: number | undefined, reason?: string | undefined): void {\n    this.channel.postMessage({\n      type: 'extraneous:close',\n      payload: {\n        clientId: this.id,\n        code,\n        reason,\n      },\n    } as WebSocketBroadcastChannelMessage)\n  }\n\n  addEventListener<EventType extends keyof WebSocketClientEventMap>(\n    _type: EventType,\n    _listener: (\n      this: WebSocket,\n      event: WebSocketClientEventMap[EventType],\n    ) => void,\n    _options?: AddEventListenerOptions | boolean,\n  ): void {\n    throw new Error(\n      'WebSocketRemoteClientConnection.addEventListener is not supported',\n    )\n  }\n\n  removeEventListener<EventType extends keyof WebSocketClientEventMap>(\n    _event: EventType,\n    _listener: (\n      this: WebSocket,\n      event: WebSocketClientEventMap[EventType],\n    ) => void,\n    _options?: EventListenerOptions | boolean,\n  ): void {\n    throw new Error(\n      'WebSocketRemoteClientConnection.removeEventListener is not supported',\n    )\n  }\n}\n"
  },
  {
    "path": "src/core/ws/WebSocketClientStore.ts",
    "content": "import type { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/WebSocket'\n\nexport interface SerializedWebSocketClient {\n  id: string\n  url: string\n}\n\nexport abstract class WebSocketClientStore {\n  public abstract add(client: WebSocketClientConnectionProtocol): Promise<void>\n\n  public abstract getAll(): Promise<Array<SerializedWebSocketClient>>\n\n  public abstract deleteMany(clientIds: Array<string>): Promise<void>\n}\n"
  },
  {
    "path": "src/core/ws/WebSocketIndexedDBClientStore.ts",
    "content": "import { DeferredPromise } from '@open-draft/deferred-promise'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/WebSocket'\nimport {\n  type SerializedWebSocketClient,\n  WebSocketClientStore,\n} from './WebSocketClientStore'\n\nconst DB_NAME = 'msw-websocket-clients'\nconst DB_STORE_NAME = 'clients'\n\nexport class WebSocketIndexedDBClientStore implements WebSocketClientStore {\n  private db: Promise<IDBDatabase>\n\n  constructor() {\n    this.db = this.createDatabase()\n  }\n\n  public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n    const promise = new DeferredPromise<void>()\n    const store = await this.getStore()\n\n    /**\n     * @note Use `.put()` instead of `.add()` to allow setting clients\n     * that already exist in the database. This can happen if a single page\n     * has multiple event handlers. Each handler will receive the \"connection\"\n     * event in parallel, and try to set that WebSocket client in the database.\n     */\n    const request = store.put({\n      id: client.id,\n      url: client.url.href,\n    } satisfies SerializedWebSocketClient)\n\n    request.onsuccess = () => {\n      promise.resolve()\n    }\n    request.onerror = () => {\n      console.error(request.error)\n      promise.reject(\n        new Error(\n          `Failed to add WebSocket client \"${client.id}\". There is likely an additional output above.`,\n        ),\n      )\n    }\n\n    return promise\n  }\n\n  public async getAll(): Promise<Array<SerializedWebSocketClient>> {\n    const promise = new DeferredPromise<Array<SerializedWebSocketClient>>()\n    const store = await this.getStore()\n    const request = store.getAll() as IDBRequest<\n      Array<SerializedWebSocketClient>\n    >\n\n    request.onsuccess = () => {\n      promise.resolve(request.result)\n    }\n    request.onerror = () => {\n      console.error(request.error)\n      promise.reject(\n        new Error(\n          `Failed to get all WebSocket clients. There is likely an additional output above.`,\n        ),\n      )\n    }\n\n    return promise\n  }\n\n  public async deleteMany(clientIds: Array<string>): Promise<void> {\n    const promise = new DeferredPromise<void>()\n    const store = await this.getStore()\n\n    for (const clientId of clientIds) {\n      store.delete(clientId)\n    }\n\n    store.transaction.oncomplete = () => {\n      promise.resolve()\n    }\n    store.transaction.onerror = () => {\n      console.error(store.transaction.error)\n      promise.reject(\n        new Error(\n          `Failed to delete WebSocket clients [${clientIds.join(', ')}]. There is likely an additional output above.`,\n        ),\n      )\n    }\n\n    return promise\n  }\n\n  private async createDatabase(): Promise<IDBDatabase> {\n    const promise = new DeferredPromise<IDBDatabase>()\n    const request = indexedDB.open(DB_NAME, 1)\n\n    request.onsuccess = ({ currentTarget }) => {\n      const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n\n      if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n        return promise.resolve(db)\n      }\n    }\n\n    request.onupgradeneeded = async ({ currentTarget }) => {\n      const db = Reflect.get(currentTarget!, 'result') as IDBDatabase\n      if (db.objectStoreNames.contains(DB_STORE_NAME)) {\n        return\n      }\n\n      const store = db.createObjectStore(DB_STORE_NAME, { keyPath: 'id' })\n      store.transaction.oncomplete = () => {\n        promise.resolve(db)\n      }\n      store.transaction.onerror = () => {\n        console.error(store.transaction.error)\n        promise.reject(\n          new Error(\n            'Failed to create WebSocket client store. There is likely an additional output above.',\n          ),\n        )\n      }\n    }\n    request.onerror = () => {\n      console.error(request.error)\n      promise.reject(\n        new Error(\n          'Failed to open an IndexedDB database. There is likely an additional output above.',\n        ),\n      )\n    }\n\n    return promise\n  }\n\n  private async getStore(): Promise<IDBObjectStore> {\n    const db = await this.db\n    return db.transaction(DB_STORE_NAME, 'readwrite').objectStore(DB_STORE_NAME)\n  }\n}\n"
  },
  {
    "path": "src/core/ws/WebSocketMemoryClientStore.ts",
    "content": "import { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/WebSocket'\nimport {\n  SerializedWebSocketClient,\n  WebSocketClientStore,\n} from './WebSocketClientStore'\n\nexport class WebSocketMemoryClientStore implements WebSocketClientStore {\n  private store: Map<string, SerializedWebSocketClient>\n\n  constructor() {\n    this.store = new Map()\n  }\n\n  public async add(client: WebSocketClientConnectionProtocol): Promise<void> {\n    this.store.set(client.id, { id: client.id, url: client.url.href })\n  }\n\n  public getAll(): Promise<Array<SerializedWebSocketClient>> {\n    return Promise.resolve(Array.from(this.store.values()))\n  }\n\n  public async deleteMany(clientIds: Array<string>): Promise<void> {\n    for (const clientId of clientIds) {\n      this.store.delete(clientId)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/ws/handleWebSocketEvent.ts",
    "content": "import type { WebSocketConnectionData } from '@mswjs/interceptors/WebSocket'\nimport { RequestHandler } from '../handlers/RequestHandler'\nimport { WebSocketHandler } from '../handlers/WebSocketHandler'\nimport { webSocketInterceptor } from './webSocketInterceptor'\nimport {\n  onUnhandledRequest,\n  UnhandledRequestStrategy,\n} from '../utils/request/onUnhandledRequest'\nimport { isHandlerKind } from '../utils/internal/isHandlerKind'\n\ninterface HandleWebSocketEventOptions {\n  getUnhandledRequestStrategy: () => UnhandledRequestStrategy\n  getHandlers: () => Array<RequestHandler | WebSocketHandler>\n  onMockedConnection: (connection: WebSocketConnectionData) => void\n  onPassthroughConnection: (onnection: WebSocketConnectionData) => void\n}\n\nexport function handleWebSocketEvent(options: HandleWebSocketEventOptions) {\n  webSocketInterceptor.on('connection', async (connection) => {\n    const handlers = options.getHandlers().filter(isHandlerKind('EventHandler'))\n\n    // Ignore this connection if the user hasn't defined any handlers.\n    if (handlers.length > 0) {\n      options?.onMockedConnection(connection)\n\n      await Promise.all(\n        handlers.map((handler) => {\n          // Iterate over the handlers and forward the connection\n          // event to WebSocket event handlers. This is equivalent\n          // to dispatching that event onto multiple listeners.\n          return handler.run(connection)\n        }),\n      )\n\n      return\n    }\n\n    // Construct a request representing this WebSocket connection.\n    const request = new Request(connection.client.url, {\n      headers: {\n        upgrade: 'websocket',\n        connection: 'upgrade',\n      },\n    })\n    await onUnhandledRequest(\n      request,\n      options.getUnhandledRequestStrategy(),\n    ).catch((error) => {\n      const errorEvent = new Event('error')\n      Object.defineProperty(errorEvent, 'cause', {\n        enumerable: true,\n        configurable: false,\n        value: error,\n      })\n      connection.client.socket.dispatchEvent(errorEvent)\n    })\n\n    options?.onPassthroughConnection(connection)\n\n    // If none of the \"ws\" handlers matched,\n    // establish the WebSocket connection as-is.\n    connection.server.connect()\n  })\n}\n"
  },
  {
    "path": "src/core/ws/utils/attachWebSocketLogger.ts",
    "content": "import type {\n  WebSocketClientConnection,\n  WebSocketConnectionData,\n  WebSocketData,\n} from '@mswjs/interceptors/WebSocket'\nimport { devUtils } from '../../utils/internal/devUtils'\nimport { getTimestamp } from '../../utils/logging/getTimestamp'\nimport { toPublicUrl } from '../../utils/request/toPublicUrl'\nimport { getMessageLength } from './getMessageLength'\nimport { getPublicData } from './getPublicData'\n\nexport const colors = {\n  system: '#3b82f6',\n  outgoing: '#22c55e',\n  incoming: '#ef4444',\n  mocked: '#ff6a33',\n}\n\nexport function attachWebSocketLogger(\n  connection: WebSocketConnectionData,\n): void {\n  const { client, server } = connection\n\n  logConnectionOpen(client)\n\n  // Log the events sent from the WebSocket client.\n  // WebSocket client connection object is written from the\n  // server's perspective so these message events are outgoing.\n  /**\n   * @todo Provide the reference to the exact event handler\n   * that called this `client.send()`.\n   */\n  client.addEventListener('message', (event) => {\n    logOutgoingClientMessage(event)\n  })\n\n  client.addEventListener('close', (event) => {\n    logConnectionClose(event)\n  })\n\n  // Log client errors (connection closures due to errors).\n  client.socket.addEventListener('error', (event) => {\n    logClientError(event)\n  })\n\n  client.send = new Proxy(client.send, {\n    apply(target, thisArg, args) {\n      const [data] = args\n      const messageEvent = new MessageEvent('message', { data })\n      Object.defineProperties(messageEvent, {\n        currentTarget: {\n          enumerable: true,\n          writable: false,\n          value: client.socket,\n        },\n        target: {\n          enumerable: true,\n          writable: false,\n          value: client.socket,\n        },\n      })\n\n      queueMicrotask(() => {\n        logIncomingMockedClientMessage(messageEvent)\n      })\n\n      return Reflect.apply(target, thisArg, args)\n    },\n  })\n\n  server.addEventListener(\n    'open',\n    () => {\n      server.addEventListener('message', (event) => {\n        logIncomingServerMessage(event)\n      })\n    },\n    { once: true },\n  )\n\n  // Log outgoing client events initiated by the event handler.\n  // The actual client never sent these but the handler did.\n  server.send = new Proxy(server.send, {\n    apply(target, thisArg, args) {\n      const [data] = args\n      const messageEvent = new MessageEvent('message', { data })\n      Object.defineProperties(messageEvent, {\n        currentTarget: {\n          enumerable: true,\n          writable: false,\n          value: server.socket,\n        },\n        target: {\n          enumerable: true,\n          writable: false,\n          value: server.socket,\n        },\n      })\n\n      logOutgoingMockedClientMessage(messageEvent)\n\n      return Reflect.apply(target, thisArg, args)\n    },\n  })\n}\n\n/**\n * Prints the WebSocket connection.\n * This is meant to be logged by every WebSocket handler\n * that intercepted this connection. This helps you see\n * what handlers observe this connection.\n */\nexport function logConnectionOpen(client: WebSocketClientConnection) {\n  const publicUrl = toPublicUrl(client.url)\n\n  console.groupCollapsed(\n    devUtils.formatMessage(`${getTimestamp()} %c▶%c ${publicUrl}`),\n    `color:${colors.system}`,\n    'color:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log('Client:', client.socket)\n  console.groupEnd()\n}\n\nfunction logConnectionClose(event: CloseEvent) {\n  const target = event.target as WebSocket\n  const publicUrl = toPublicUrl(target.url)\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c■%c ${publicUrl}`,\n    ),\n    `color:${colors.system}`,\n    'color:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n\nfunction logClientError(event: Event) {\n  const socket = event.target as WebSocket\n  const publicUrl = toPublicUrl(socket.url)\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c\\u00D7%c ${publicUrl}`,\n    ),\n    `color:${colors.system}`,\n    'color:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message.\n */\nasync function logOutgoingClientMessage(event: MessageEvent<WebSocketData>) {\n  const byteLength = getMessageLength(event.data)\n  const publicData = await getPublicData(event.data)\n  const arrow = event.defaultPrevented ? '⇡' : '⬆'\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n    ),\n    `color:${colors.outgoing}`,\n    'color:inherit',\n    'color:gray;font-weight:normal',\n    'color:inherit;font-weight:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `server.send()` in the event handler.\n */\nasync function logOutgoingMockedClientMessage(\n  event: MessageEvent<WebSocketData>,\n) {\n  const byteLength = getMessageLength(event.data)\n  const publicData = await getPublicData(event.data)\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c⬆%c ${publicData} %c${byteLength}%c`,\n    ),\n    `color:${colors.mocked}`,\n    'color:inherit',\n    'color:gray;font-weight:normal',\n    'color:inherit;font-weight:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n\n/**\n * Prints the outgoing client message initiated\n * by `client.send()` in the event handler.\n */\nasync function logIncomingMockedClientMessage(\n  event: MessageEvent<WebSocketData>,\n) {\n  const byteLength = getMessageLength(event.data)\n  const publicData = await getPublicData(event.data)\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c⬇%c ${publicData} %c${byteLength}%c`,\n    ),\n    `color:${colors.mocked}`,\n    'color:inherit',\n    'color:gray;font-weight:normal',\n    'color:inherit;font-weight:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n\nasync function logIncomingServerMessage(event: MessageEvent<WebSocketData>) {\n  const byteLength = getMessageLength(event.data)\n  const publicData = await getPublicData(event.data)\n  const arrow = event.defaultPrevented ? '⇣' : '⬇'\n\n  console.groupCollapsed(\n    devUtils.formatMessage(\n      `${getTimestamp({ milliseconds: true })} %c${arrow}%c ${publicData} %c${byteLength}%c`,\n    ),\n    `color:${colors.incoming}`,\n    'color:inherit',\n    'color:gray;font-weight:normal',\n    'color:inherit;font-weight:inherit',\n  )\n  // eslint-disable-next-line no-console\n  console.log(event)\n  console.groupEnd()\n}\n"
  },
  {
    "path": "src/core/ws/utils/getMessageLength.test.ts",
    "content": "import { getMessageLength } from './getMessageLength'\n\nit('returns the length of the string', () => {\n  expect(getMessageLength('')).toBe(0)\n  expect(getMessageLength('hello')).toBe(5)\n})\n\nit('returns the size of the Blob', () => {\n  expect(getMessageLength(new Blob())).toBe(0)\n  expect(getMessageLength(new Blob(['hello']))).toBe(5)\n})\n\nit('returns the byte length of ArrayBuffer', () => {\n  expect(getMessageLength(new ArrayBuffer(0))).toBe(0)\n  expect(getMessageLength(new ArrayBuffer(5))).toBe(5)\n})\n"
  },
  {
    "path": "src/core/ws/utils/getMessageLength.ts",
    "content": "import type { WebSocketData } from '@mswjs/interceptors/WebSocket'\nimport { isObject } from '../../utils/internal/isObject'\n\n/**\n * Returns the byte length of the given WebSocket message.\n * @example\n * getMessageLength('hello') // 5\n * getMessageLength(new Blob(['hello'])) // 5\n */\nexport function getMessageLength(data: WebSocketData): number {\n  if (data instanceof Blob) {\n    return data.size\n  }\n\n  if (isObject(data) && 'byteLength' in data) {\n    return data.byteLength\n  }\n\n  return new Blob([data as any]).size\n}\n"
  },
  {
    "path": "src/core/ws/utils/getPublicData.test.ts",
    "content": "import { getPublicData } from './getPublicData'\n\nit('returns a short string as-is', async () => {\n  expect(await getPublicData('')).toBe('')\n  expect(await getPublicData('hello')).toBe('hello')\n})\n\nit('returns a truncated long string', async () => {\n  expect(await getPublicData('this is a very long string')).toBe(\n    'this is a very long stri…',\n  )\n})\n\nit('returns a short Blob text as-is', async () => {\n  expect(await getPublicData(new Blob(['']))).toBe('Blob()')\n  expect(await getPublicData(new Blob(['hello']))).toBe('Blob(hello)')\n})\n\nit('returns a truncated long Blob text', async () => {\n  expect(await getPublicData(new Blob(['this is a very long string']))).toBe(\n    'Blob(this is a very long stri…)',\n  )\n})\n\nit('returns a short ArrayBuffer text as-is', async () => {\n  expect(await getPublicData(new TextEncoder().encode(''))).toBe(\n    'ArrayBuffer()',\n  )\n  expect(await getPublicData(new TextEncoder().encode('hello'))).toBe(\n    'ArrayBuffer(hello)',\n  )\n})\n\nit('returns a truncated ArrayBuffer text', async () => {\n  expect(\n    await getPublicData(new TextEncoder().encode('this is a very long string')),\n  ).toBe('ArrayBuffer(this is a very long stri…)')\n})\n"
  },
  {
    "path": "src/core/ws/utils/getPublicData.ts",
    "content": "import type { WebSocketData } from '@mswjs/interceptors/WebSocket'\nimport { isObject } from '../../utils/internal/isObject'\nimport { truncateMessage } from './truncateMessage'\n\nexport async function getPublicData(data: WebSocketData): Promise<string> {\n  if (data instanceof Blob) {\n    const text = await data.text()\n    return `Blob(${truncateMessage(text)})`\n  }\n\n  // Handle all ArrayBuffer-like objects.\n  if (isObject(data)) {\n    const text = new TextDecoder().decode(data as ArrayBuffer)\n    return `ArrayBuffer(${truncateMessage(text)})`\n  }\n\n  return truncateMessage(data)\n}\n"
  },
  {
    "path": "src/core/ws/utils/truncateMessage.test.ts",
    "content": "import { truncateMessage } from './truncateMessage'\n\nit('returns a short string as-is', () => {\n  expect(truncateMessage('')).toBe('')\n  expect(truncateMessage('hello')).toBe('hello')\n})\n\nit('truncates a long string', () => {\n  expect(truncateMessage('this is a very long string')).toBe(\n    'this is a very long stri…',\n  )\n})\n"
  },
  {
    "path": "src/core/ws/utils/truncateMessage.ts",
    "content": "const MAX_LENGTH = 24\n\nexport function truncateMessage(message: string): string {\n  if (message.length <= MAX_LENGTH) {\n    return message\n  }\n\n  return `${message.slice(0, MAX_LENGTH)}…`\n}\n"
  },
  {
    "path": "src/core/ws/webSocketInterceptor.ts",
    "content": "import { WebSocketInterceptor } from '@mswjs/interceptors/WebSocket'\n\nexport const webSocketInterceptor = new WebSocketInterceptor()\n"
  },
  {
    "path": "src/core/ws.test.ts",
    "content": "/**\n * @vitest-environment node-websocket\n */\nimport { ws } from './ws'\n\nit('exports the \"link()\" method', () => {\n  expect(ws).toHaveProperty('link')\n  expect(ws.link).toBeInstanceOf(Function)\n})\n\nit('throws an error when calling \"ws.link()\" without a URL argument', () => {\n  expect(() =>\n    // @ts-expect-error Intentionally invalid call.\n    ws.link(),\n  ).toThrow('Expected a WebSocket server URL but got undefined')\n})\n\nit('throws an error when given a non-path argument to \"ws.link()\"', () => {\n  expect(() =>\n    // @ts-expect-error Intentionally invalid argument.\n    ws.link(2),\n  ).toThrow('Expected a WebSocket server URL to be a valid path but got number')\n})\n"
  },
  {
    "path": "src/core/ws.ts",
    "content": "import { invariant } from 'outvariant'\nimport type {\n  WebSocketData,\n  WebSocketClientConnectionProtocol,\n} from '@mswjs/interceptors/WebSocket'\nimport {\n  WebSocketHandler,\n  kEmitter,\n  type WebSocketHandlerEventMap,\n} from './handlers/WebSocketHandler'\nimport { hasRefCounted } from './utils/internal/hasRefCounted'\nimport { Path, isPath } from './utils/matching/matchRequestUrl'\nimport { WebSocketClientManager } from './ws/WebSocketClientManager'\n\nconst webSocketChannel = new BroadcastChannel('msw:websocket-client-manager')\n\nif (hasRefCounted(webSocketChannel)) {\n  // Allows the Node.js thread to exit if it is the only active handle in the event system.\n  // https://nodejs.org/api/worker_threads.html#broadcastchannelunref\n  webSocketChannel.unref()\n}\n\nexport type WebSocketEventListener<\n  EventType extends keyof WebSocketHandlerEventMap,\n> = (...args: WebSocketHandlerEventMap[EventType]) => void\n\nexport type WebSocketLink = {\n  /**\n   * A set of all WebSocket clients connected\n   * to this link.\n   *\n   * @see {@link https://mswjs.io/docs/api/ws#clients `clients` API reference}\n   */\n  clients: Set<WebSocketClientConnectionProtocol>\n\n  /**\n   * Adds an event listener to this WebSocket link.\n   *\n   * @example\n   * const chat = ws.link('wss://chat.example.com')\n   * chat.addEventListener('connection', listener)\n   *\n   * @see {@link https://mswjs.io/docs/api/ws#onevent-listener `on()` API reference}\n   */\n  addEventListener<EventType extends keyof WebSocketHandlerEventMap>(\n    event: EventType,\n    listener: WebSocketEventListener<EventType>,\n  ): WebSocketHandler\n\n  /**\n   * Broadcasts the given data to all WebSocket clients.\n   *\n   * @example\n   * const service = ws.link('wss://example.com')\n   * service.addEventListener('connection', () => {\n   *   service.broadcast('hello, everyone!')\n   * })\n   *\n   * @see {@link https://mswjs.io/docs/api/ws#broadcastdata `broadcast()` API reference}\n   */\n  broadcast(data: WebSocketData): void\n\n  /**\n   * Broadcasts the given data to all WebSocket clients\n   * except the ones provided in the `clients` argument.\n   *\n   * @example\n   * const service = ws.link('wss://example.com')\n   * service.addEventListener('connection', ({ client }) => {\n   *   service.broadcastExcept(client, 'hi, the rest of you!')\n   * })\n   *\n   * @see {@link https://mswjs.io/docs/api/ws#broadcastexceptclients-data `broadcast()` API reference}\n   */\n  broadcastExcept(\n    clients:\n      | WebSocketClientConnectionProtocol\n      | Array<WebSocketClientConnectionProtocol>,\n    data: WebSocketData,\n  ): void\n}\n\n/**\n * Intercepts outgoing WebSocket connections to the given URL.\n *\n * @example\n * const chat = ws.link('wss://chat.example.com')\n * chat.addEventListener('connection', ({ client }) => {\n *   client.send('hello from server!')\n * })\n */\nfunction createWebSocketLinkHandler(url: Path): WebSocketLink {\n  invariant(url, 'Expected a WebSocket server URL but got undefined')\n\n  invariant(\n    isPath(url),\n    'Expected a WebSocket server URL to be a valid path but got %s',\n    typeof url,\n  )\n\n  const clientManager = new WebSocketClientManager(webSocketChannel)\n\n  return {\n    get clients() {\n      return clientManager.clients\n    },\n    addEventListener(event, listener) {\n      const handler = new WebSocketHandler(url)\n\n      // Add the connection event listener for when the\n      // handler matches and emits a connection event.\n      // When that happens, store that connection in the\n      // set of all connections for reference.\n      handler[kEmitter].on('connection', async ({ client }) => {\n        await clientManager.addConnection(client)\n      })\n\n      // The \"handleWebSocketEvent\" function will invoke\n      // the \"run()\" method on the WebSocketHandler.\n      // If the handler matches, it will emit the \"connection\"\n      // event. Attach the user-defined listener to that event.\n      handler[kEmitter].on(event, listener)\n\n      return handler\n    },\n\n    broadcast(data) {\n      // This will invoke \"send()\" on the immediate clients\n      // in this runtime and post a message to the broadcast channel\n      // to trigger send for the clients in other runtimes.\n      this.broadcastExcept([], data)\n    },\n\n    broadcastExcept(clients, data) {\n      const ignoreClients = Array.prototype\n        .concat(clients)\n        .map((client) => client.id)\n\n      clientManager.clients.forEach((otherClient) => {\n        if (!ignoreClients.includes(otherClient.id)) {\n          otherClient.send(data)\n        }\n      })\n    },\n  }\n}\n\n/**\n * A namespace to intercept and mock WebSocket connections.\n *\n * @example\n * const chat = ws.link('wss://chat.example.com')\n *\n * @see {@link https://mswjs.io/docs/api/ws `ws` API reference}\n * @see {@link https://mswjs.io/docs/basics/handling-websocket-events Handling WebSocket events}\n */\nexport const ws = {\n  link: createWebSocketLinkHandler,\n}\n\nexport { WebSocketData }\n"
  },
  {
    "path": "src/iife/index.ts",
    "content": "export * from '~/core'\nexport * from '../browser'\n"
  },
  {
    "path": "src/mockServiceWorker.js",
    "content": "/* eslint-disable */\n/* tslint:disable */\n\n/**\n * Mock Service Worker.\n * @see https://github.com/mswjs/msw\n * - Please do NOT modify this file.\n */\n\nconst PACKAGE_VERSION = '<PACKAGE_VERSION>'\nconst INTEGRITY_CHECKSUM = '<INTEGRITY_CHECKSUM>'\nconst IS_MOCKED_RESPONSE = Symbol('isMockedResponse')\nconst activeClientIds = new Set()\n\naddEventListener('install', function () {\n  self.skipWaiting()\n})\n\naddEventListener('activate', function (event) {\n  event.waitUntil(self.clients.claim())\n})\n\naddEventListener('message', async function (event) {\n  const clientId = Reflect.get(event.source || {}, 'id')\n\n  if (!clientId || !self.clients) {\n    return\n  }\n\n  const client = await self.clients.get(clientId)\n\n  if (!client) {\n    return\n  }\n\n  const allClients = await self.clients.matchAll({\n    type: 'window',\n  })\n\n  switch (event.data) {\n    case 'KEEPALIVE_REQUEST': {\n      sendToClient(client, {\n        type: 'KEEPALIVE_RESPONSE',\n      })\n      break\n    }\n\n    case 'INTEGRITY_CHECK_REQUEST': {\n      sendToClient(client, {\n        type: 'INTEGRITY_CHECK_RESPONSE',\n        payload: {\n          packageVersion: PACKAGE_VERSION,\n          checksum: INTEGRITY_CHECKSUM,\n        },\n      })\n      break\n    }\n\n    case 'MOCK_ACTIVATE': {\n      activeClientIds.add(clientId)\n\n      sendToClient(client, {\n        type: 'MOCKING_ENABLED',\n        payload: {\n          client: {\n            id: client.id,\n            frameType: client.frameType,\n          },\n        },\n      })\n      break\n    }\n\n    case 'CLIENT_CLOSED': {\n      activeClientIds.delete(clientId)\n\n      const remainingClients = allClients.filter((client) => {\n        return client.id !== clientId\n      })\n\n      // Unregister itself when there are no more clients\n      if (remainingClients.length === 0) {\n        self.registration.unregister()\n      }\n\n      break\n    }\n  }\n})\n\naddEventListener('fetch', function (event) {\n  const requestInterceptedAt = Date.now()\n\n  // Bypass navigation requests.\n  if (event.request.mode === 'navigate') {\n    return\n  }\n\n  // Opening the DevTools triggers the \"only-if-cached\" request\n  // that cannot be handled by the worker. Bypass such requests.\n  if (\n    event.request.cache === 'only-if-cached' &&\n    event.request.mode !== 'same-origin'\n  ) {\n    return\n  }\n\n  // Bypass all requests when there are no active clients.\n  // Prevents the self-unregistered worked from handling requests\n  // after it's been terminated (still remains active until the next reload).\n  if (activeClientIds.size === 0) {\n    return\n  }\n\n  const requestId = crypto.randomUUID()\n  event.respondWith(handleRequest(event, requestId, requestInterceptedAt))\n})\n\n/**\n * @param {FetchEvent} event\n * @param {string} requestId\n * @param {number} requestInterceptedAt\n */\nasync function handleRequest(event, requestId, requestInterceptedAt) {\n  const client = await resolveMainClient(event)\n  const requestCloneForEvents = event.request.clone()\n  const response = await getResponse(\n    event,\n    client,\n    requestId,\n    requestInterceptedAt,\n  )\n\n  // Send back the response clone for the \"response:*\" life-cycle events.\n  // Ensure MSW is active and ready to handle the message, otherwise\n  // this message will pend indefinitely.\n  if (client && activeClientIds.has(client.id)) {\n    const serializedRequest = await serializeRequest(requestCloneForEvents)\n\n    // Clone the response so both the client and the library could consume it.\n    const responseClone = response.clone()\n\n    sendToClient(\n      client,\n      {\n        type: 'RESPONSE',\n        payload: {\n          isMockedResponse: IS_MOCKED_RESPONSE in response,\n          request: {\n            id: requestId,\n            ...serializedRequest,\n          },\n          response: {\n            type: responseClone.type,\n            status: responseClone.status,\n            statusText: responseClone.statusText,\n            headers: Object.fromEntries(responseClone.headers.entries()),\n            body: responseClone.body,\n          },\n        },\n      },\n      responseClone.body ? [serializedRequest.body, responseClone.body] : [],\n    )\n  }\n\n  return response\n}\n\n/**\n * Resolve the main client for the given event.\n * Client that issues a request doesn't necessarily equal the client\n * that registered the worker. It's with the latter the worker should\n * communicate with during the response resolving phase.\n * @param {FetchEvent} event\n * @returns {Promise<Client | undefined>}\n */\nasync function resolveMainClient(event) {\n  const client = await self.clients.get(event.clientId)\n\n  if (activeClientIds.has(event.clientId)) {\n    return client\n  }\n\n  if (client?.frameType === 'top-level') {\n    return client\n  }\n\n  const allClients = await self.clients.matchAll({\n    type: 'window',\n  })\n\n  return allClients\n    .filter((client) => {\n      // Get only those clients that are currently visible.\n      return client.visibilityState === 'visible'\n    })\n    .find((client) => {\n      // Find the client ID that's recorded in the\n      // set of clients that have registered the worker.\n      return activeClientIds.has(client.id)\n    })\n}\n\n/**\n * @param {FetchEvent} event\n * @param {Client | undefined} client\n * @param {string} requestId\n * @param {number} requestInterceptedAt\n * @returns {Promise<Response>}\n */\nasync function getResponse(event, client, requestId, requestInterceptedAt) {\n  // Clone the request because it might've been already used\n  // (i.e. its body has been read and sent to the client).\n  const requestClone = event.request.clone()\n\n  function passthrough() {\n    // Cast the request headers to a new Headers instance\n    // so the headers can be manipulated with.\n    const headers = new Headers(requestClone.headers)\n\n    // Remove the \"accept\" header value that marked this request as passthrough.\n    // This prevents request alteration and also keeps it compliant with the\n    // user-defined CORS policies.\n    const acceptHeader = headers.get('accept')\n    if (acceptHeader) {\n      const values = acceptHeader.split(',').map((value) => value.trim())\n      const filteredValues = values.filter(\n        (value) => value !== 'msw/passthrough',\n      )\n\n      if (filteredValues.length > 0) {\n        headers.set('accept', filteredValues.join(', '))\n      } else {\n        headers.delete('accept')\n      }\n    }\n\n    return fetch(requestClone, { headers })\n  }\n\n  // Bypass mocking when the client is not active.\n  if (!client) {\n    return passthrough()\n  }\n\n  // Bypass initial page load requests (i.e. static assets).\n  // The absence of the immediate/parent client in the map of the active clients\n  // means that MSW hasn't dispatched the \"MOCK_ACTIVATE\" event yet\n  // and is not ready to handle requests.\n  if (!activeClientIds.has(client.id)) {\n    return passthrough()\n  }\n\n  // Notify the client that a request has been intercepted.\n  const serializedRequest = await serializeRequest(event.request)\n  const clientMessage = await sendToClient(\n    client,\n    {\n      type: 'REQUEST',\n      payload: {\n        id: requestId,\n        interceptedAt: requestInterceptedAt,\n        ...serializedRequest,\n      },\n    },\n    [serializedRequest.body],\n  )\n\n  switch (clientMessage.type) {\n    case 'MOCK_RESPONSE': {\n      return respondWithMock(clientMessage.data)\n    }\n\n    case 'PASSTHROUGH': {\n      return passthrough()\n    }\n  }\n\n  return passthrough()\n}\n\n/**\n * @param {Client} client\n * @param {any} message\n * @param {Array<Transferable>} transferrables\n * @returns {Promise<any>}\n */\nfunction sendToClient(client, message, transferrables = []) {\n  return new Promise((resolve, reject) => {\n    const channel = new MessageChannel()\n\n    channel.port1.onmessage = (event) => {\n      if (event.data && event.data.error) {\n        return reject(event.data.error)\n      }\n\n      resolve(event.data)\n    }\n\n    client.postMessage(message, [\n      channel.port2,\n      ...transferrables.filter(Boolean),\n    ])\n  })\n}\n\n/**\n * @param {Response} response\n * @returns {Response}\n */\nfunction respondWithMock(response) {\n  // Setting response status code to 0 is a no-op.\n  // However, when responding with a \"Response.error()\", the produced Response\n  // instance will have status code set to 0. Since it's not possible to create\n  // a Response instance with status code 0, handle that use-case separately.\n  if (response.status === 0) {\n    return Response.error()\n  }\n\n  const mockedResponse = new Response(response.body, response)\n\n  Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {\n    value: true,\n    enumerable: true,\n  })\n\n  return mockedResponse\n}\n\n/**\n * @param {Request} request\n */\nasync function serializeRequest(request) {\n  return {\n    url: request.url,\n    mode: request.mode,\n    method: request.method,\n    headers: Object.fromEntries(request.headers.entries()),\n    cache: request.cache,\n    credentials: request.credentials,\n    destination: request.destination,\n    integrity: request.integrity,\n    redirect: request.redirect,\n    referrer: request.referrer,\n    referrerPolicy: request.referrerPolicy,\n    body: await request.arrayBuffer(),\n    keepalive: request.keepalive,\n  }\n}\n"
  },
  {
    "path": "src/native/index.ts",
    "content": "import { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport { SetupServerCommonApi } from '../node/SetupServerCommonApi'\n\n/**\n * Sets up a requests interception in React Native with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport function setupServer(\n  ...handlers: Array<RequestHandler>\n): SetupServerCommonApi {\n  // Provision request interception via patching the `XMLHttpRequest` class only\n  // in React Native. There is no `http`/`https` modules in that environment.\n  return new SetupServerCommonApi(\n    [new FetchInterceptor(), new XMLHttpRequestInterceptor()],\n    handlers,\n  )\n}\n"
  },
  {
    "path": "src/node/SetupServerApi.ts",
    "content": "import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { HttpRequestEventMap, Interceptor } from '@mswjs/interceptors'\nimport { ClientRequestInterceptor } from '@mswjs/interceptors/ClientRequest'\nimport { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { HandlersController } from '~/core/SetupApi'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type { SetupServer } from './glossary'\nimport { SetupServerCommonApi } from './SetupServerCommonApi'\n\nconst store = new AsyncLocalStorage<RequestHandlersContext>()\n\ntype RequestHandlersContext = {\n  initialHandlers: Array<RequestHandler | WebSocketHandler>\n  handlers: Array<RequestHandler | WebSocketHandler>\n}\n\n/**\n * A handlers controller that utilizes `AsyncLocalStorage` in Node.js\n * to prevent the request handlers list from being a shared state\n * across multiple tests.\n */\nclass AsyncHandlersController implements HandlersController {\n  private rootContext: RequestHandlersContext\n\n  constructor(initialHandlers: Array<RequestHandler | WebSocketHandler>) {\n    this.rootContext = { initialHandlers, handlers: [] }\n  }\n\n  get context(): RequestHandlersContext {\n    return store.getStore() || this.rootContext\n  }\n\n  public prepend(runtimeHandlers: Array<RequestHandler | WebSocketHandler>) {\n    this.context.handlers.unshift(...runtimeHandlers)\n  }\n\n  public reset(nextHandlers: Array<RequestHandler | WebSocketHandler>) {\n    const context = this.context\n    context.handlers = []\n    context.initialHandlers =\n      nextHandlers.length > 0 ? nextHandlers : context.initialHandlers\n  }\n\n  public currentHandlers(): Array<RequestHandler | WebSocketHandler> {\n    const { initialHandlers, handlers } = this.context\n    return handlers.concat(initialHandlers)\n  }\n}\nexport class SetupServerApi\n  extends SetupServerCommonApi\n  implements SetupServer\n{\n  constructor(\n    handlers: Array<RequestHandler | WebSocketHandler>,\n    interceptors: Array<Interceptor<HttpRequestEventMap>> = [\n      new ClientRequestInterceptor(),\n      new XMLHttpRequestInterceptor(),\n      new FetchInterceptor(),\n    ],\n  ) {\n    super(interceptors, handlers)\n\n    this.handlersController = new AsyncHandlersController(handlers)\n  }\n\n  public boundary<Args extends Array<any>, R>(\n    callback: (...args: Args) => R,\n  ): (...args: Args) => R {\n    return (...args: Args): R => {\n      return store.run<any, any>(\n        {\n          initialHandlers: this.handlersController.currentHandlers(),\n          handlers: [],\n        },\n        callback,\n        ...args,\n      )\n    }\n  }\n\n  public close(): void {\n    super.close()\n    store.disable()\n  }\n}\n"
  },
  {
    "path": "src/node/SetupServerCommonApi.ts",
    "content": "/**\n * @note This API is extended by both \"msw/node\" and \"msw/native\"\n * so be minding about the things you import!\n */\nimport type { RequiredDeep } from 'type-fest'\nimport { invariant } from 'outvariant'\nimport {\n  BatchInterceptor,\n  InterceptorReadyState,\n  type HttpRequestEventMap,\n  type Interceptor,\n} from '@mswjs/interceptors'\nimport type { LifeCycleEventsMap, SharedOptions } from '~/core/sharedOptions'\nimport { SetupApi } from '~/core/SetupApi'\nimport { handleRequest } from '~/core/utils/handleRequest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { mergeRight } from '~/core/utils/internal/mergeRight'\nimport { InternalError, devUtils } from '~/core/utils/internal/devUtils'\nimport type { SetupServerCommon } from './glossary'\nimport { handleWebSocketEvent } from '~/core/ws/handleWebSocketEvent'\nimport { webSocketInterceptor } from '~/core/ws/webSocketInterceptor'\nimport { isHandlerKind } from '~/core/utils/internal/isHandlerKind'\n\nconst DEFAULT_LISTEN_OPTIONS: RequiredDeep<SharedOptions> = {\n  onUnhandledRequest: 'warn',\n}\n\nexport class SetupServerCommonApi\n  extends SetupApi<LifeCycleEventsMap>\n  implements SetupServerCommon\n{\n  protected readonly interceptor: BatchInterceptor<\n    Array<Interceptor<HttpRequestEventMap>>,\n    HttpRequestEventMap\n  >\n  private resolvedOptions: RequiredDeep<SharedOptions>\n\n  constructor(\n    interceptors: Array<Interceptor<HttpRequestEventMap>>,\n    handlers: Array<RequestHandler | WebSocketHandler>,\n  ) {\n    super(...handlers)\n\n    this.interceptor = new BatchInterceptor({\n      name: 'setup-server',\n      interceptors,\n    })\n\n    this.resolvedOptions = {} as RequiredDeep<SharedOptions>\n  }\n\n  /**\n   * Subscribe to all requests that are using the interceptor object\n   */\n  private init(): void {\n    this.interceptor.on(\n      'request',\n      async ({ request, requestId, controller }) => {\n        const response = await handleRequest(\n          request,\n          requestId,\n          this.handlersController\n            .currentHandlers()\n            .filter(isHandlerKind('RequestHandler')),\n          this.resolvedOptions,\n          this.emitter,\n          {\n            onPassthroughResponse(request) {\n              const acceptHeader = request.headers.get('accept')\n\n              /**\n               * @note Remove the internal bypass request header.\n               * In the browser, this is done by the worker script.\n               * In Node.js, it has to be done here.\n               */\n              if (acceptHeader) {\n                const nextAcceptHeader = acceptHeader.replace(\n                  /(,\\s+)?msw\\/passthrough/,\n                  '',\n                )\n\n                if (nextAcceptHeader) {\n                  request.headers.set('accept', nextAcceptHeader)\n                } else {\n                  request.headers.delete('accept')\n                }\n              }\n            },\n          },\n        )\n\n        if (response) {\n          controller.respondWith(response)\n        }\n\n        return\n      },\n    )\n\n    this.interceptor.on('unhandledException', ({ error }) => {\n      if (error instanceof InternalError) {\n        throw error\n      }\n    })\n\n    this.interceptor.on(\n      'response',\n      ({ response, isMockedResponse, request, requestId }) => {\n        this.emitter.emit(\n          isMockedResponse ? 'response:mocked' : 'response:bypass',\n          {\n            response,\n            request,\n            requestId,\n          },\n        )\n      },\n    )\n\n    // Preconfigure the WebSocket interception but don't enable it just yet.\n    // It will be enabled when the server starts.\n    handleWebSocketEvent({\n      getUnhandledRequestStrategy: () => {\n        return this.resolvedOptions.onUnhandledRequest\n      },\n      getHandlers: () => {\n        return this.handlersController.currentHandlers()\n      },\n      onMockedConnection: () => {},\n      onPassthroughConnection: () => {},\n    })\n  }\n\n  public listen(options: Partial<SharedOptions> = {}): void {\n    this.resolvedOptions = mergeRight(\n      DEFAULT_LISTEN_OPTIONS,\n      options,\n    ) as RequiredDeep<SharedOptions>\n\n    // Apply the interceptor when starting the server.\n    // Attach the event listeners to the interceptor here\n    // so they get re-attached whenever `.listen()` is called.\n    this.interceptor.apply()\n    this.init()\n    this.subscriptions.push(() => this.interceptor.dispose())\n\n    // Apply the WebSocket interception.\n    webSocketInterceptor.apply()\n    this.subscriptions.push(() => webSocketInterceptor.dispose())\n\n    // Assert that the interceptor has been applied successfully.\n    // Also guards us from forgetting to call \"interceptor.apply()\"\n    // as a part of the \"listen\" method.\n    invariant(\n      [InterceptorReadyState.APPLYING, InterceptorReadyState.APPLIED].includes(\n        this.interceptor.readyState,\n      ),\n      devUtils.formatMessage(\n        'Failed to start \"setupServer\": the interceptor failed to apply. This is likely an issue with the library and you should report it at \"%s\".',\n      ),\n      'https://github.com/mswjs/msw/issues/new/choose',\n    )\n  }\n\n  public close(): void {\n    this.dispose()\n  }\n}\n"
  },
  {
    "path": "src/node/glossary.ts",
    "content": "import type { PartialDeep } from 'type-fest'\nimport type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport type {\n  LifeCycleEventEmitter,\n  LifeCycleEventsMap,\n  SharedOptions,\n} from '~/core/sharedOptions'\n\nexport interface SetupServerCommon {\n  /**\n   * Starts requests interception based on the previously provided request handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/listen `server.listen()` API reference}\n   */\n  listen(options?: PartialDeep<SharedOptions>): void\n\n  /**\n   * Stops requests interception by restoring all augmented modules.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/close `server.close()` API reference}\n   */\n  close(): void\n\n  /**\n   * Prepends given request handlers to the list of existing handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/use `server.use()` API reference}\n   */\n  use(...handlers: Array<RequestHandler | WebSocketHandler>): void\n\n  /**\n   * Marks all request handlers that respond using `res.once()` as unused.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/restore-handlers `server.restore-handlers()` API reference}\n   */\n  restoreHandlers(): void\n\n  /**\n   * Resets request handlers to the initial list given to the `setupServer` call, or to the explicit next request handlers list, if given.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/reset-handlers `server.reset-handlers()` API reference}\n   */\n  resetHandlers(...nextHandlers: Array<RequestHandler | WebSocketHandler>): void\n\n  /**\n   * Returns a readonly list of currently active request handlers.\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/list-handlers `server.listHandlers()` API reference}\n   */\n  listHandlers(): ReadonlyArray<RequestHandler | WebSocketHandler>\n\n  /**\n   * Life-cycle events.\n   * Life-cycle events allow you to subscribe to the internal library events occurring during the request/response handling.\n   *\n   * @see {@link https://mswjs.io/docs/api/life-cycle-events Life-cycle Events API reference}\n   */\n  events: LifeCycleEventEmitter<LifeCycleEventsMap>\n}\n\nexport interface SetupServer extends SetupServerCommon {\n  /**\n   * Wraps the given function in a boundary. Any changes to the\n   * network behavior (e.g. adding runtime request handlers via\n   * `server.use()`) will be scoped to this boundary only.\n   * @param callback A function to run (e.g. a test)\n   *\n   * @see {@link https://mswjs.io/docs/api/setup-server/boundary `server.boundary()` API reference}\n   */\n  boundary<Args extends Array<any>, R>(\n    callback: (...args: Args) => R,\n  ): (...args: Args) => R\n}\n"
  },
  {
    "path": "src/node/index.ts",
    "content": "export type { SetupServer } from './glossary'\nexport { SetupServerApi } from './SetupServerApi'\nexport { setupServer } from './setupServer'\n"
  },
  {
    "path": "src/node/setupServer.ts",
    "content": "import type { RequestHandler } from '~/core/handlers/RequestHandler'\nimport type { WebSocketHandler } from '~/core/handlers/WebSocketHandler'\nimport { SetupServerApi } from './SetupServerApi'\n\n/**\n * Sets up a requests interception in Node.js with the given request handlers.\n * @param {RequestHandler[]} handlers List of request handlers.\n *\n * @see {@link https://mswjs.io/docs/api/setup-server `setupServer()` API reference}\n */\nexport const setupServer = (\n  ...handlers: Array<RequestHandler | WebSocketHandler>\n): SetupServerApi => {\n  return new SetupServerApi(handlers)\n}\n"
  },
  {
    "path": "src/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "src/shims/cookie.ts",
    "content": "import * as allCookie from 'cookie'\nconst cookie = (allCookie as any).default || allCookie\n\nexport const parse = cookie.parse as typeof import('cookie').parse\nexport const serialize = cookie.serialize as typeof import('cookie').serialize\n\nexport default cookie\n"
  },
  {
    "path": "src/shims/statuses.ts",
    "content": "import * as allStatuses from 'statuses'\nconst statuses = (allStatuses as any).default || allStatuses\n\nexport const message = statuses.message as typeof import('statuses').message\n\nexport default statuses\n"
  },
  {
    "path": "src/tsconfig.core.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.src.json\",\n  \"compilerOptions\": {\n    \"composite\": false\n  }\n}\n"
  },
  {
    "path": "src/tsconfig.node.build.json",
    "content": "{\n  \"extends\": \"./tsconfig.node.json\",\n  \"compilerOptions\": {\n    \"composite\": false\n  }\n}\n"
  },
  {
    "path": "src/tsconfig.node.json",
    "content": "{\n  \"extends\": \"./tsconfig.src.json\",\n  \"compilerOptions\": {\n    \"types\": [\"node\"]\n  },\n  \"include\": [\"./node\", \"./native\"],\n  \"exclude\": [\"**/*.test.ts\"]\n}\n"
  },
  {
    "path": "src/tsconfig.src.json",
    "content": "{\n  // Common configuration for everything\n  // living in the \"src\" directory.\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"composite\": true\n  },\n  \"include\": [\"../global.d.ts\", \"./**/*.ts\"],\n  \"exclude\": [\"./**/*.test.ts\"]\n}\n"
  },
  {
    "path": "src/tsconfig.worker.json",
    "content": "{\n  \"include\": [\"./mockServiceWorker.js\"],\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"noEmit\": true,\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"lib\": [\"esnext\"],\n    \"types\": [\"@types/serviceworker\"]\n  }\n}\n"
  },
  {
    "path": "test/README.md",
    "content": "# Integration tests\n\nThis directory contains a list of integration tests for the Mock Service Worker library. Our integration tests are example-driven, meaning that each test features a specific usage example and asserts its behavior. We use the [`page-with`](https://github.com/kettanaito/page-with) package to compile and run a usage example within an automated browser environment.\n\nThis directory categorizes all test suites based on the library's execution or API domain:\n\n- `/rest-api`, tests for RESTful API mocking.\n- `/graphql-api`, rests for GraphQL API mocking.\n- `/msw-api`, tests for the library's API.\n\n## Test structure\n\nExample-driven test consists of two parts:\n\n- `*.mocks.ts`, a usage example and also a code snippet to test.\n- `*.test.ts`, an actual test suite for Vitest.\n\n## Contributing\n\nPlease see the [Contribution guidelines](/CONTRIBUTING.md) for the instructions on how to run and add new tests. Thank you.\n"
  },
  {
    "path": "test/browser/graphql-api/anonymous-operation.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start()\n\nObject.assign(window, {\n  msw: {\n    worker,\n    graphql,\n    HttpResponse,\n  },\n})\n"
  },
  {
    "path": "test/browser/graphql-api/anonymous-operation.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\nimport { waitFor } from '../../support/waitFor'\n\ndeclare namespace window {\n  export const msw: {\n    worker: import('msw/browser').SetupWorkerApi\n    graphql: typeof import('msw').graphql\n    HttpResponse: typeof import('msw').HttpResponse\n  }\n}\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (req, res) => {\n    res.json({\n      data: {\n        user: {\n          id: 'abc-123',\n        },\n      },\n    })\n  })\n})\n\ntest.beforeAll(async () => {\n  await httpServer.listen()\n})\n\ntest.afterAll(async () => {\n  await httpServer.close()\n})\n\ntest('does not warn on anonymous GraphQL operation when no GraphQL handlers are present', async ({\n  loadExample,\n  query,\n  spyOnConsole,\n}) => {\n  await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  const endpointUrl = httpServer.http.url('/graphql')\n  const response = await query(endpointUrl, {\n    // Intentionally anonymous query.\n    query: gql`\n      query {\n        user {\n          id\n        }\n      }\n    `,\n  })\n\n  const json = await response.json()\n\n  // Must get the original server response.\n  expect(json).toEqual({\n    data: {\n      user: {\n        id: 'abc-123',\n      },\n    },\n  })\n\n  await waitFor(() => {\n    // Must print a generic unhandled GraphQL request warning.\n    // This has nothing to do with the operation being anonymous.\n    expect(consoleSpy.get('warning')).toEqual([\n      `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • POST ${endpointUrl}\n\n  • Request body: {\"query\":\"\\\\n      query {\\\\n        user {\\\\n          id\\\\n        }\\\\n      }\\\\n    \"}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n    ])\n  })\n})\n\ntest('warns on handled anonymous GraphQL operation', async ({\n  loadExample,\n  query,\n  spyOnConsole,\n  page,\n}) => {\n  await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  await page.evaluate(() => {\n    const { worker, graphql, HttpResponse } = window.msw\n\n    worker.use(\n      // This handler will have no effect on the anonymous operation performed.\n      graphql.query('IrrelevantQuery', () => {\n        return HttpResponse.json({\n          data: {\n            user: {\n              id: 'mocked-123',\n            },\n          },\n        })\n      }),\n    )\n  })\n\n  const endpointUrl = httpServer.http.url('/graphql')\n  const response = await query(endpointUrl, {\n    // Intentionally anonymous query.\n    // It will be handled in the \"graphql.operation()\" handler above.\n    query: gql`\n      query {\n        user {\n          id\n        }\n      }\n    `,\n  })\n\n  const json = await response.json()\n\n  // Must get the original response because the \"graphql.query()\"\n  // handler won't match an anonymous GraphQL operation.\n  expect(json).toEqual({\n    data: {\n      user: {\n        id: 'abc-123',\n      },\n    },\n  })\n\n  // Must print the warning because an anonymous operation has been performed.\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toEqual(\n      expect.arrayContaining([\n        `[MSW] Failed to intercept a GraphQL request at \"POST ${endpointUrl}\": anonymous GraphQL operations are not supported.\n\nConsider naming this operation or using \"graphql.operation()\" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/#graphqloperationresolver`,\n      ]),\n    )\n  })\n})\n\ntest('does not print a warning on anonymous GraphQL operation handled by \"graphql.operation()\"', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n  query,\n}) => {\n  await loadExample(new URL('./anonymous-operation.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  await page.evaluate(() => {\n    const { worker, graphql, HttpResponse } = window.msw\n\n    worker.use(\n      // This handler will match ANY anonymous GraphQL operation.\n      // It's a good idea to include some matching logic to differentiate\n      // between those operations. We're omitting it for testing purposes.\n      graphql.operation(() => {\n        return HttpResponse.json({\n          data: {\n            user: {\n              id: 'mocked-123',\n            },\n          },\n        })\n      }),\n    )\n  })\n\n  const endpointUrl = httpServer.http.url('/graphql')\n  const response = await query(endpointUrl, {\n    // Intentionally anonymous query.\n    // It will be handled in the \"graphql.operation()\" handler above.\n    query: gql`\n      query {\n        user {\n          id\n        }\n      }\n    `,\n  })\n\n  const json = await response.json()\n\n  // Must get the mocked response.\n  expect(json).toEqual({\n    data: {\n      user: {\n        id: 'mocked-123',\n      },\n    },\n  })\n\n  // Must not print any warnings because a permissive \"graphql.operation()\"\n  // handler was used to intercept and mock the anonymous GraphQL operation.\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/graphql-api/cookies.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  graphql.query('GetUser', () => {\n    return HttpResponse.json(\n      {\n        data: {\n          firstName: 'John',\n        },\n      },\n      {\n        headers: {\n          'Set-Cookie': 'test-cookie=value',\n        },\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/cookies.test.ts",
    "content": "import { parse as parseCookie } from '../../../src/shims/cookie'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\ntest('sets cookie on the mocked GraphQL response', async ({\n  loadExample,\n  query,\n  page,\n}) => {\n  await loadExample(new URL('./cookies.mocks.ts', import.meta.url))\n\n  const res = await query('/graphql', {\n    query: gql`\n      query GetUser {\n        firstName\n      }\n    `,\n  })\n\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(headers).not.toHaveProperty('set-cookie')\n  expect(body).toEqual({\n    data: {\n      firstName: 'John',\n    },\n  })\n\n  // Should be able to access the response cookies.\n  const cookieString = await page.evaluate(() => {\n    return document.cookie\n  })\n  const allCookies = parseCookie(cookieString)\n  expect(allCookies).toHaveProperty('test-cookie', 'value')\n})\n"
  },
  {
    "path": "test/browser/graphql-api/custom-predicate.mocks.ts",
    "content": "import { graphql } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start()\n\nwindow.msw = {\n  // @ts-expect-error\n  worker,\n  graphql,\n}\n"
  },
  {
    "path": "test/browser/graphql-api/custom-predicate.test.ts",
    "content": "import { graphql } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { gql } from '../../support/graphql'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    graphql: typeof graphql\n  }\n}\n\nconst PREDICATE_EXAMPLE = new URL(\n  './custom-predicate.mocks.ts',\n  import.meta.url,\n)\n\ntest('matches requests when the predicate function returns true', async ({\n  loadExample,\n  query,\n  page,\n}) => {\n  await loadExample(PREDICATE_EXAMPLE)\n\n  await page.evaluate(() => {\n    const { worker, graphql } = window.msw\n\n    worker.use(\n      graphql.query(\n        ({ variables }) => {\n          return variables.id === 'abc-123'\n        },\n        ({ variables }) => {\n          return Response.json({\n            data: { user: { id: variables.id } },\n          })\n        },\n      ),\n    )\n  })\n\n  const response = await query('/irrelevant', {\n    query: gql`\n      query GetUser($id: String!) {\n        user(id: $id) {\n          id\n        }\n      }\n    `,\n    variables: {\n      id: 'abc-123',\n    },\n  })\n\n  expect(response.status()).toBe(200)\n  await expect(response.json()).resolves.toEqual({\n    data: {\n      user: {\n        id: 'abc-123',\n      },\n    },\n  })\n})\n\ntest('does not match requests when the predicate function returns false', async ({\n  loadExample,\n  query,\n  page,\n}) => {\n  await loadExample(PREDICATE_EXAMPLE)\n\n  await page.evaluate(() => {\n    const { worker, graphql } = window.msw\n\n    worker.use(\n      graphql.query(\n        ({ variables }) => {\n          return variables.id === 'abc-123'\n        },\n        ({ variables }) => {\n          return Response.json({\n            data: { user: { id: variables.id } },\n          })\n        },\n      ),\n      graphql.operation(() => {\n        return Response.json({ data: { fallback: true } })\n      }),\n    )\n  })\n\n  const response = await query('/irrelevant', {\n    query: gql`\n      query GetUser($id: String!) {\n        user(id: $id) {\n          id\n        }\n      }\n    `,\n    variables: {\n      id: 'non-matching-query',\n    },\n  })\n\n  await expect(response.json()).resolves.toEqual({\n    data: {\n      fallback: true,\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/document-node.mocks.ts",
    "content": "import { parse } from 'graphql'\nimport { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst GetUser = parse(`\n  query GetUser {\n    user {\n      firstName\n    }\n  }\n`)\n\nconst Login = parse(`\n  mutation Login($username: String!) {\n    session {\n      id\n    }\n    user {\n      username\n    }\n  }\n`)\n\nconst GetSubscription = parse(`\n  query GetSubscription {\n    subscription {\n      id\n    }\n  }\n`)\n\nconst github = graphql.link('https://api.github.com/graphql')\n\nconst worker = setupWorker(\n  // \"DocumentNode\" can be used as the expected query/mutation.\n  graphql.query(GetUser, () => {\n    return HttpResponse.json({\n      data: {\n        // Note that inferring the query body and variables\n        // is impossible with the native \"DocumentNode\".\n        // Consider using tools like GraphQL Code Generator.\n        user: {\n          firstName: 'John',\n        },\n      },\n    })\n  }),\n  graphql.mutation<object, { username: string }>(Login, ({ variables }) => {\n    return HttpResponse.json({\n      data: {\n        session: {\n          id: 'abc-123',\n        },\n        user: {\n          username: variables.username,\n        },\n      },\n    })\n  }),\n  github.query(GetSubscription, () => {\n    return HttpResponse.json({\n      data: {\n        subscription: {\n          id: 123,\n        },\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/errors.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  graphql.query('Login', () => {\n    return HttpResponse.json({\n      errors: [\n        {\n          message: 'This is a mocked error',\n          locations: [\n            {\n              line: 1,\n              column: 2,\n            },\n          ],\n        },\n      ],\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/errors.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\ntest('mocks a GraphQL error response', async ({ loadExample, query }) => {\n  await loadExample(new URL('./errors.mocks.ts', import.meta.url))\n\n  const res = await query('/graphql', {\n    query: gql`\n      query Login {\n        user {\n          id\n        }\n      }\n    `,\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(body).toEqual({\n    errors: [\n      {\n        message: 'This is a mocked error',\n        locations: [\n          {\n            line: 1,\n            column: 2,\n          },\n        ],\n      },\n    ],\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/extensions.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ninterface LoginQuery {\n  user: {\n    id: number\n    name: string\n    password: string\n  }\n}\n\nconst worker = setupWorker(\n  graphql.query<LoginQuery>('Login', () => {\n    return HttpResponse.json({\n      data: {\n        user: {\n          id: 1,\n          name: 'Joe Bloggs',\n          password: 'HelloWorld!',\n        },\n      },\n      extensions: {\n        message: 'This is a mocked extension',\n        tracking: {\n          version: '0.1.2',\n          page: '/test/',\n        },\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/extensions.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\ntest('mocks a GraphQL response with both data and extensions', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(new URL('./extensions.mocks.ts', import.meta.url))\n\n  const res = await query('/graphql', {\n    query: gql`\n      query Login {\n        user {\n          id\n          name\n          password\n        }\n      }\n    `,\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    data: {\n      user: {\n        id: 1,\n        name: 'Joe Bloggs',\n        password: 'HelloWorld!',\n      },\n    },\n    extensions: {\n      message: 'This is a mocked extension',\n      tracking: {\n        version: '0.1.2',\n        page: '/test/',\n      },\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/link.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst github = graphql.link('https://api.github.com/graphql')\nconst stripe = graphql.link('https://api.stripe.com/graphql')\n\ninterface GetUserQuery {\n  user: {\n    id: string\n    username: string\n  }\n}\n\ninterface PaymentQuery {\n  bankAccount: {\n    totalFunds: number\n  }\n}\n\ninterface GetUserQuery {\n  user: {\n    id: string\n    username: string\n  }\n}\n\nconst worker = setupWorker(\n  github.query<GetUserQuery, { username: string }>(\n    'GetUser',\n    ({ variables }) => {\n      return HttpResponse.json({\n        data: {\n          user: {\n            id: '46cfe8ff-a79b-42af-9699-b56e2239d1bb',\n            username: variables.username,\n          },\n        },\n      })\n    },\n  ),\n  stripe.mutation<PaymentQuery, { amount: number }>(\n    'Payment',\n    ({ variables }) => {\n      return HttpResponse.json({\n        data: {\n          bankAccount: {\n            totalFunds: 100 + variables.amount,\n          },\n        },\n      })\n    },\n  ),\n  graphql.query<GetUserQuery, { username: string }>(\n    'GetUser',\n    ({ variables }) => {\n      return HttpResponse.json(\n        {\n          data: {\n            user: {\n              id: '46cfe8ff-a79b-42af-9699-b56e2239d1bb',\n              username: variables.username,\n            },\n          },\n        },\n        {\n          headers: {\n            'X-Request-Handler': 'fallback',\n          },\n        },\n      )\n    },\n  ),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/link.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\nconst LINK_EXAMPLE = new URL('./link.mocks.ts', import.meta.url)\n\nconst server = new HttpServer((app) => {\n  app.post('/graphql', (req, res) => {\n    res.status(500).end()\n  })\n})\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('mocks a GraphQL query to the GitHub GraphQL API', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(LINK_EXAMPLE)\n\n  const res = await query('https://api.github.com/graphql', {\n    query: gql`\n      query GetUser($username: String!) {\n        user(username: $username) {\n          id\n          username\n        }\n      }\n    `,\n    variables: {\n      username: 'john',\n    },\n  })\n\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(body).toEqual({\n    data: {\n      user: {\n        id: '46cfe8ff-a79b-42af-9699-b56e2239d1bb',\n        username: 'john',\n      },\n    },\n  })\n})\n\ntest('mocks a GraphQL mutation to the Stripe GraphQL API', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(LINK_EXAMPLE)\n\n  const res = await query('https://api.stripe.com/graphql', {\n    query: gql`\n      mutation Payment($amount: Int!) {\n        bankAccount {\n          totalFunds\n        }\n      }\n    `,\n    variables: {\n      amount: 350,\n    },\n  })\n\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(body).toEqual({\n    data: {\n      bankAccount: {\n        totalFunds: 450,\n      },\n    },\n  })\n})\n\ntest('falls through to the matching GraphQL operation to an unknown endpoint', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(LINK_EXAMPLE)\n\n  const res = await query('/graphql', {\n    query: gql`\n      query GetUser($username: String!) {\n        user(username: $username) {\n          id\n          username\n        }\n      }\n    `,\n    variables: {\n      username: 'john',\n    },\n  })\n\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(headers).toHaveProperty('x-request-handler', 'fallback')\n  expect(body).toEqual({\n    data: {\n      user: {\n        id: '46cfe8ff-a79b-42af-9699-b56e2239d1bb',\n        username: 'john',\n      },\n    },\n  })\n})\n\ntest('bypasses a GraphQL operation to an unknown endpoint', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(LINK_EXAMPLE)\n\n  const res = await query(server.http.url('/graphql'), {\n    query: gql`\n      mutation Payment($amount: Int!) {\n        bankAccount {\n          totalFunds\n        }\n      }\n    `,\n    variables: {\n      amount: 350,\n    },\n  })\n\n  expect(res.status()).toBe(500)\n})\n"
  },
  {
    "path": "test/browser/graphql-api/logging.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ninterface GetUserDetailQuery {\n  user: {\n    firstName: string\n    lastName: string\n  }\n}\n\ninterface LoginQuery {\n  user: {\n    id: string\n  }\n}\n\nconst worker = setupWorker(\n  graphql.query<GetUserDetailQuery>('GetUserDetail', () => {\n    return HttpResponse.json({\n      data: {\n        user: {\n          firstName: 'John',\n          lastName: 'Maverick',\n        },\n      },\n    })\n  }),\n  graphql.mutation<LoginQuery>('Login', () => {\n    return HttpResponse.json({\n      data: {\n        user: {\n          id: 'abc-123',\n        },\n      },\n    })\n  }),\n  graphql.operation(() => {\n    return HttpResponse.json(\n      {\n        data: {\n          ok: true,\n        },\n      },\n      {\n        status: 301,\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/logging.test.ts",
    "content": "import { StatusCodeColor } from '../../../src/core/utils/logging/getStatusCodeColor'\nimport { waitFor } from '../../support/waitFor'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\nconst LOGGING_EXAMPLE = new URL('./logging.mocks.ts', import.meta.url)\n\ntest('prints a log for a GraphQL query', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(LOGGING_EXAMPLE)\n\n  await query('/graphql', {\n    query: gql`\n      query GetUserDetail {\n        user {\n          firstName\n          lastName\n        }\n      }\n    `,\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')?.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          new RegExp(\n            `^\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} query GetUserDetail \\\\(%c200 OK%c\\\\) color:${StatusCodeColor.Success} color:inherit$`,\n          ),\n        ),\n      ]),\n    )\n  })\n})\n\ntest('prints a log for a GraphQL mutation', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(LOGGING_EXAMPLE)\n\n  await query('/graphql', {\n    query: gql`\n      mutation Login {\n        user {\n          id\n        }\n      }\n    `,\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')?.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          new RegExp(\n            `\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} mutation Login \\\\(%c200 OK%c\\\\) color:${StatusCodeColor.Success} color:inherit$`,\n          ),\n        ),\n      ]),\n    )\n  })\n})\n\ntest('prints a log for a GraphQL query intercepted via \"graphql.operation\"', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(LOGGING_EXAMPLE)\n\n  await query('/graphql', {\n    query: gql`\n      query GetLatestPosts {\n        posts {\n          title\n        }\n      }\n    `,\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')?.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          new RegExp(\n            `\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} query GetLatestPosts \\\\(%c301 Moved Permanently%c\\\\) color:${StatusCodeColor.Warning} color:inherit$`,\n          ),\n        ),\n      ]),\n    )\n  })\n})\n\ntest('prints a log for a GraphQL mutation intercepted via \"graphql.operation\"', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(LOGGING_EXAMPLE)\n\n  await query('/graphql', {\n    query: gql`\n      mutation CreatePost {\n        post {\n          id\n        }\n      }\n    `,\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')?.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          new RegExp(\n            `^\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} mutation CreatePost \\\\(%c301 Moved Permanently%c\\\\) color:${StatusCodeColor.Warning} color:inherit$`,\n          ),\n        ),\n      ]),\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/multipart-data.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  graphql.mutation<\n    {\n      multipart: {\n        file1?: string\n        file2?: string\n        files?: Array<string>\n        plainText?: string\n      }\n    },\n    {\n      file1?: File\n      file2?: File\n      files?: Array<File>\n      plainText?: string\n    }\n  >('UploadFile', async ({ variables }) => {\n    const { file1, file2, files = [], plainText } = variables\n    const filesResponse = await Promise.all(files.map((file) => file.text()))\n\n    return HttpResponse.json({\n      data: {\n        multipart: {\n          file1: await file1?.text(),\n          file2: await file2?.text(),\n          files: filesResponse,\n          plainText,\n        },\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/multipart-data.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('accepts a file from a GraphQL mutation', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(new URL('./multipart-data.mocks.ts', import.meta.url))\n\n  const UPLOAD_MUTATION = `\n    mutation UploadFile(\n      $file1: Upload\n      $file2: Upload\n      $plainText: String\n      ) {\n      multipart(\n        file1: $file1\n        file2: $file2\n        plainText: $plainText\n        ){\n        file1\n        file2\n        plainText\n      }\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: UPLOAD_MUTATION,\n    variables: {\n      file1: null,\n      file2: null,\n      files: [null, null],\n      plainText: 'text',\n    },\n    multipartOptions: {\n      map: {\n        '0': ['variables.file1', 'variables.files.0'],\n        '1': ['variables.file2', 'variables.files.1'],\n      },\n      fileContents: ['file1 content', 'file2 content'],\n    },\n  })\n\n  const body = await res.json()\n\n  expect(res.status()).toEqual(200)\n  expect(body).toEqual({\n    data: {\n      multipart: {\n        file1: 'file1 content',\n        file2: 'file2 content',\n        files: ['file1 content', 'file2 content'],\n        plainText: 'text',\n      },\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/mutation.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ninterface LogoutQuery {\n  logout: {\n    userSession: boolean\n  }\n}\n\nconst worker = setupWorker(\n  graphql.mutation<LogoutQuery>('Logout', () => {\n    return HttpResponse.json({\n      data: {\n        logout: {\n          userSession: false,\n        },\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/mutation.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\nconst MUTATION_EXAMPLE = new URL('./mutation.mocks.ts', import.meta.url)\n\nconst server = new HttpServer((app) => {\n  app.use('*', (req, res) => res.status(405).end())\n})\n\nfunction endpoint(): string {\n  return server.http.url('/graphql')\n}\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('sends a mocked response to a GraphQL mutation', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(MUTATION_EXAMPLE)\n\n  const res = await query(endpoint(), {\n    query: gql`\n      mutation Logout {\n        logout {\n          userSession\n        }\n      }\n    `,\n  })\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(body).toEqual({\n    data: {\n      logout: {\n        userSession: false,\n      },\n    },\n  })\n})\n\ntest('prints a warning when intercepted an anonymous GraphQL mutation', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(MUTATION_EXAMPLE)\n\n  const res = await query(endpoint(), {\n    query: gql`\n      mutation {\n        logout {\n          userSession\n        }\n      }\n    `,\n  })\n\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(\n        `\\\n[MSW] Failed to intercept a GraphQL request at \"POST ${endpoint()}\": anonymous GraphQL operations are not supported.\n\nConsider naming this operation or using \"graphql.operation()\" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/#graphqloperationresolver\\\n`,\n      ),\n    ]),\n  )\n\n  // The actual GraphQL server is hit.\n  expect(res.status()).toBe(405)\n})\n"
  },
  {
    "path": "test/browser/graphql-api/operation-reference.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  graphql.query('GetUser', async ({ query, variables }) => {\n    return HttpResponse.json({\n      data: {\n        query,\n        variables,\n      },\n    })\n  }),\n  graphql.mutation('Login', ({ query, variables }) => {\n    return HttpResponse.json({\n      data: {\n        query,\n        variables,\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/operation-reference.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\nconst OPERATION_REFERENCE_EXAMPLE = new URL(\n  './operation-reference.mocks.ts',\n  import.meta.url,\n)\n\ntest('allows referencing the request body in the GraphQL query handler', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(OPERATION_REFERENCE_EXAMPLE)\n\n  const GET_USER_QUERY = `\n    query GetUser($id: String!) {\n      query\n      variables\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: GET_USER_QUERY,\n    variables: {\n      id: 'abc-123',\n    },\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    data: {\n      query: GET_USER_QUERY,\n      variables: {\n        id: 'abc-123',\n      },\n    },\n  })\n})\n\ntest('allows referencing the request body in the GraphQL mutation handler', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(OPERATION_REFERENCE_EXAMPLE)\n\n  const LOGIN_MUTATION = `\n    mutation Login($username: String!, $password: String!) {\n      mutation\n      variables\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: LOGIN_MUTATION,\n    variables: {\n      username: 'john',\n      password: 'super-secret',\n    },\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    data: {\n      query: LOGIN_MUTATION,\n      variables: {\n        username: 'john',\n        password: 'super-secret',\n      },\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/operation.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  graphql.operation(async ({ query, variables }) => {\n    return HttpResponse.json({\n      data: {\n        query,\n        variables,\n      },\n    })\n  }),\n)\n\nworker.start({\n  onUnhandledRequest: 'warn',\n})\n"
  },
  {
    "path": "test/browser/graphql-api/operation.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\nconst OPERATION_EXAMPLE = new URL('./operation.mocks.ts', import.meta.url)\n\nconst server = new HttpServer((app) => {\n  app.post('/search', (req, res) => {\n    return res.json({ results: [1, 2, 3] })\n  })\n})\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('intercepts and mocks a GraphQL query', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(OPERATION_EXAMPLE)\n\n  const GET_USER_QUERY = gql`\n    query GetUser($id: String!) {\n      query\n      variables\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: GET_USER_QUERY,\n    variables: {\n      id: 'abc-123',\n    },\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    data: {\n      query: GET_USER_QUERY,\n      variables: {\n        id: 'abc-123',\n      },\n    },\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n    expect.arrayContaining([\n      expect.stringMatching(/\\[MSW\\] \\d{2}:\\d{2}:\\d{2} query GetUser 200 OK/),\n    ]),\n  )\n})\n\ntest('intercepts and mocks an anonymous GraphQL query', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(OPERATION_EXAMPLE)\n\n  const ANONYMOUS_QUERY = gql`\n    query {\n      anonymousQuery {\n        query\n        variables\n      }\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: ANONYMOUS_QUERY,\n    variables: {\n      id: 'abc-123',\n    },\n  })\n\n  expect(consoleSpy.get('warning')).toBeUndefined()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n\n  const body = await res.json()\n  expect(body).toEqual({\n    data: {\n      query: ANONYMOUS_QUERY,\n      variables: {\n        id: 'abc-123',\n      },\n    },\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n    expect.arrayContaining([\n      expect.stringMatching(/\\[MSW\\] \\d{2}:\\d{2}:\\d{2} anonymous query 200 OK/),\n    ]),\n  )\n})\n\ntest('intercepts and mocks a GraphQL mutation', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(OPERATION_EXAMPLE)\n\n  const LOGIN_MUTATION = gql`\n    mutation Login($username: String!, $password: String!) {\n      mutation\n      variables\n    }\n  `\n\n  const res = await query('/graphql', {\n    query: LOGIN_MUTATION,\n    variables: {\n      username: 'john',\n      password: 'super-secret',\n    },\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    data: {\n      query: LOGIN_MUTATION,\n      variables: {\n        username: 'john',\n        password: 'super-secret',\n      },\n    },\n  })\n})\n\ntest('propagates parsing errors from the invalid GraphQL requests', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(OPERATION_EXAMPLE)\n\n  const INVALID_QUERY = `\n    # Intentionally invalid GraphQL query.\n    query GetUser() {\n      user { id\n    }\n  `\n\n  query('/graphql', {\n    query: INVALID_QUERY,\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('error')).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining(\n          'Failed to intercept a GraphQL request to \"POST http://localhost:8080/graphql\": cannot parse query. See the error message from the parser below.\\n\\nSyntax Error: Expected \"$\", found \")\".',\n        ),\n      ]),\n    )\n  })\n})\n\ntest('bypasses seemingly compatible REST requests', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(OPERATION_EXAMPLE)\n\n  const res = await query(server.http.url('/search'), {\n    query: 'favorite books',\n  })\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    results: [1, 2, 3],\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/query.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ninterface GetUserDetailQuery {\n  user: {\n    firstName: string\n    lastName: string\n  }\n}\n\nconst worker = setupWorker(\n  graphql.query<GetUserDetailQuery>('GetUserDetail', () => {\n    return HttpResponse.json({\n      data: {\n        user: {\n          firstName: 'John',\n          lastName: 'Maverick',\n        },\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/query.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\nconst EXAMPLE_PATH = new URL('./query.mocks.ts', import.meta.url)\n\nconst server = new HttpServer((app) => {\n  app.use('*', (_, res) => res.status(405).end())\n})\n\nconst endpoint = () => {\n  return server.http.url('/graphql')\n}\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('mocks a GraphQL query issued with a GET request', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query(endpoint(), {\n    method: 'GET',\n    query: gql`\n      query GetUserDetail {\n        user {\n          firstName\n          lastName\n        }\n      }\n    `,\n  })\n\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(body).toEqual({\n    data: {\n      user: {\n        firstName: 'John',\n        lastName: 'Maverick',\n      },\n    },\n  })\n})\n\ntest('mocks a GraphQL query issued with a POST request', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query(endpoint(), {\n    method: 'POST',\n    query: gql`\n      query GetUserDetail {\n        user {\n          firstName\n          lastName\n        }\n      }\n    `,\n  })\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(body).toEqual({\n    data: {\n      user: {\n        firstName: 'John',\n        lastName: 'Maverick',\n      },\n    },\n  })\n})\n\ntest('prints a warning when intercepted an anonymous GraphQL query', async ({\n  loadExample,\n  spyOnConsole,\n  query,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query(endpoint(), {\n    query: gql`\n      query {\n        user {\n          firstName\n        }\n      }\n    `,\n  })\n\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(\n        `\\\n[MSW] Failed to intercept a GraphQL request at \"POST ${endpoint()}\": anonymous GraphQL operations are not supported.\n\nConsider naming this operation or using \"graphql.operation()\" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/#graphqloperationresolver`,\n      ),\n    ]),\n  )\n\n  // The actual GraphQL server is hit.\n  expect(res.status()).toBe(405)\n})\n"
  },
  {
    "path": "test/browser/graphql-api/response-patching.mocks.ts",
    "content": "import { graphql, bypass, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\ninterface GetUserQuery {\n  user: {\n    firstName: string\n    lastName: string\n  }\n}\n\nconst worker = setupWorker(\n  graphql.query<GetUserQuery>('GetUser', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n    const originalJson = await originalResponse.json()\n\n    return HttpResponse.json({\n      data: {\n        user: {\n          firstName: 'Christian',\n          lastName: originalJson.data?.user?.lastName,\n        },\n      },\n      errors: originalJson.errors,\n    })\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    registration: worker.start(),\n  },\n  dispatchGraphQLQuery: (uri: string) => {\n    const client = createGraphQLClient({ uri })\n\n    return client({\n      query: gql`\n        query GetUser {\n          user {\n            firstName\n            lastName\n          }\n        }\n      `,\n    })\n  },\n})\n"
  },
  {
    "path": "test/browser/graphql-api/response-patching.test.ts",
    "content": "import type { ExecutionResult } from 'graphql'\nimport { buildSchema, graphql } from 'graphql'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\nimport { gql } from '../../support/graphql'\n\ndeclare namespace window {\n  export const dispatchGraphQLQuery: (uri: string) => Promise<ExecutionResult>\n  export const msw: {\n    registration: SetupWorkerApi['start']\n  }\n}\n\n// This test server simulates a production GraphQL server\n// and uses a hard-coded `rootValue` to resolve queries\n// against the schema.\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', async (req, res) => {\n    const result = await graphql({\n      schema: buildSchema(gql`\n        type User {\n          firstName: String!\n          lastName: String!\n        }\n\n        type Query {\n          user: User!\n        }\n      `),\n      source: req.body.query,\n      rootValue: {\n        user: {\n          firstName: 'John',\n          lastName: 'Maverick',\n        },\n      },\n    })\n\n    return res.status(200).json(result)\n  })\n})\n\ntest.beforeEach(async () => {\n  await httpServer.listen()\n})\n\ntest.afterEach(async () => {\n  await httpServer.close()\n})\n\ntest('patches a GraphQL response', async ({ loadExample, page }) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n  const endpointUrl = httpServer.http.url('/graphql')\n\n  await page.evaluate(() => {\n    return window.msw.registration\n  })\n\n  const res = await page.evaluate(\n    ([url]) => {\n      return window.dispatchGraphQLQuery(url)\n    },\n    [endpointUrl],\n  )\n\n  expect(res.errors).toBeUndefined()\n  expect(res.data).toHaveProperty('user', {\n    firstName: 'Christian',\n    lastName: 'Maverick',\n  })\n})\n"
  },
  {
    "path": "test/browser/graphql-api/variables.mocks.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ninterface GetGitHubUserQuery {\n  user: {\n    username: string\n    firstName: string\n  }\n}\n\ninterface GetGitHubUserQueryVariables {\n  username: string\n}\n\ninterface DeletePostQuery {\n  deletePost: {\n    postId: string\n  }\n}\n\ninterface DeletePostQueryVariables {\n  postId: string\n}\n\ninterface GetActiveUserQuery {\n  user: {\n    id: number\n  }\n}\n\ninterface GetActiveUserQueryVariables {\n  userId: string\n}\n\nconst worker = setupWorker(\n  graphql.query<GetGitHubUserQuery, GetGitHubUserQueryVariables>(\n    'GetGithubUser',\n    ({ variables }) => {\n      const { username } = variables\n\n      return HttpResponse.json({\n        data: {\n          user: {\n            username,\n            firstName: 'John',\n          },\n        },\n      })\n    },\n  ),\n\n  graphql.mutation<DeletePostQuery, DeletePostQueryVariables>(\n    'DeletePost',\n    ({ variables }) => {\n      const { postId } = variables\n\n      return HttpResponse.json({\n        data: {\n          deletePost: {\n            postId,\n          },\n        },\n      })\n    },\n  ),\n\n  graphql.query<GetActiveUserQuery, GetActiveUserQueryVariables>(\n    'GetActiveUser',\n    ({ variables }) => {\n      // Intentionally unused variable\n      const { userId } = variables\n\n      return HttpResponse.json({\n        data: {\n          user: {\n            id: 1,\n          },\n        },\n      })\n    },\n  ),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/graphql-api/variables.test.ts",
    "content": "import { gql } from '../../support/graphql'\nimport { test, expect } from '../playwright.extend'\n\nconst EXAMPLE_PATH = new URL('./variables.mocks.ts', import.meta.url)\n\ntest('can access variables from a GraphQL query', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query('/graphql', {\n    query: gql`\n      query GetGithubUser($username: String!) {\n        user(login: $username) {\n          firstName\n          username\n        }\n      }\n    `,\n    variables: {\n      username: 'octocat',\n    },\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    data: {\n      user: {\n        firstName: 'John',\n        username: 'octocat',\n      },\n    },\n  })\n})\n\ntest('can access variables from a GraphQL mutation', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query('/graphql', {\n    query: gql`\n      mutation DeletePost($postId: String!) {\n        deletePost(id: $postId) {\n          postId\n        }\n      }\n    `,\n    variables: {\n      postId: 'abc-123',\n    },\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    data: {\n      deletePost: {\n        postId: 'abc-123',\n      },\n    },\n  })\n})\n\ntest('returns an empty object when accessing variables from a GraphQL operation without them', async ({\n  loadExample,\n  query,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await query('/graphql', {\n    query: gql`\n      query GetActiveUser {\n        user {\n          id\n        }\n      }\n    `,\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    data: {\n      user: {\n        id: 1,\n      },\n    },\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/context/delay.mocks.ts",
    "content": "import { http, delay, DelayMode, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/delay', async ({ request }) => {\n    const url = new URL(request.url)\n    const mode = url.searchParams.get('mode') as DelayMode\n    const duration = url.searchParams.get('duration')\n\n    await delay(duration ? Number(duration) : mode || undefined)\n\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/context/delay.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\nconst DELAY_EXAMPLE = new URL('./delay.mocks.ts', import.meta.url)\n\ndeclare global {\n  namespace PlaywrightTest {\n    interface Matchers<R> {\n      toRoughlyEqual(expected: number, deviation: number): R\n    }\n  }\n}\n\nexpect.extend({\n  /**\n   * Asserts a given actual number to roughly equal to the expected number,\n   * taking the maximum allowed delta `deviation` into account.\n   */\n  toRoughlyEqual(actual: number, expected: number, deviation: number) {\n    const diff = Math.abs(actual - expected)\n    const passes = diff <= deviation\n\n    if (passes) {\n      return {\n        pass: true,\n        message: () =>\n          `expected ${actual} not to be roughly equal to ${expected} (deviation: ${deviation})`,\n      }\n    }\n\n    return {\n      pass: false,\n      message: () =>\n        `expected ${actual} to be roughly equal to ${expected} (deviation: ${deviation})`,\n    }\n  },\n})\n\ntest('uses explicit server response delay', async ({ loadExample, fetch }) => {\n  await loadExample(DELAY_EXAMPLE)\n\n  const res = await fetch('/delay?duration=1200')\n  const timing = res.request().timing()\n\n  expect(timing.responseStart).toRoughlyEqual(1200, 250)\n\n  const status = res.status()\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(status).toBe(200)\n  expect(body).toEqual({ mocked: true })\n})\n\ntest('uses realistic server response delay when no delay value is provided', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(DELAY_EXAMPLE)\n\n  const res = await fetch('/delay')\n  const timing = res.request().timing()\n\n  expect(timing.responseStart).toRoughlyEqual(250, 300)\n\n  const status = res.status()\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n\ntest('uses realistic server response delay when \"real\" delay mode is provided', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(DELAY_EXAMPLE)\n  const res = await fetch('/delay?mode=real')\n  const timing = res.request().timing()\n\n  expect(timing.responseStart).toRoughlyEqual(250, 300)\n\n  const status = res.status()\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/distribution/iife.mocks.js",
    "content": "const { setupWorker, http, HttpResponse } = MockServiceWorker\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/distribution/iife.test.ts",
    "content": "import fs from 'node:fs'\nimport { test, expect } from '../../playwright.extend'\n\ntest('supports the usage of the iife bundle in a <script> tag', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./iife.mocks.js', import.meta.url), {\n    markup: `<script src=\"./iife/index.js\"></script>`,\n    beforeNavigation(compilation) {\n      compilation.use((router) => {\n        router.get('/iife/index.js', (_, res) => {\n          fs.createReadStream(\n            new URL('../../../../lib/iife/index.js', import.meta.url),\n          ).pipe(res)\n\n          return res\n        })\n      })\n    },\n  })\n\n  expect(consoleSpy.get('error')).toBeUndefined()\n\n  const response = await fetch('/user')\n\n  expect(response.status()).toBe(200)\n  expect(await response.json()).toEqual({\n    firstName: 'John',\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/exception-handling.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://api.github.com/users/:username', () => {\n    // @ts-expect-error nonExisting should not be defined\n    nonExisting()\n    return\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/exception-handling.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('activates the worker without errors', async ({\n  loadExample,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./exception-handling.mocks.ts', import.meta.url))\n\n  expect(consoleSpy.get('error')).toBeUndefined()\n})\n\ntest('transforms uncaught exceptions into a 500 response', async ({\n  loadExample,\n  fetch,\n  spyOnConsole,\n}) => {\n  await loadExample(new URL('./exception-handling.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  const res = await fetch('https://api.github.com/users/octocat')\n\n  expect(res.status()).toBe(500)\n  expect(res.statusText()).toBe('Request Handler Error')\n  expect(res.fromServiceWorker()).toBe(true)\n\n  expect(await res.json()).toEqual({\n    name: 'ReferenceError',\n    message: 'nonExisting is not defined',\n    stack: expect.stringContaining(\n      'ReferenceError: nonExisting is not defined',\n    ),\n  })\n\n  const errors = consoleSpy.get('error')\n\n  expect(errors).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining('ReferenceError: nonExisting is not defined'),\n      expect.stringContaining('  at '),\n    ]),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/hard-reload.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://example.com/resource', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/hard-reload.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('keeps the mocking enabled after hard-reload of the page', async ({\n  loadExample,\n  page,\n  fetch,\n  waitForMswActivation,\n}) => {\n  await loadExample(new URL('./hard-reload.mocks.ts', import.meta.url))\n\n  page.evaluate(() => {\n    /**\n     * Emulate a forced reload.\n     * Since `location.reload(true)` is deprecated, use a workaround.\n     * @see https://stackoverflow.com/a/65544086/2754939\n     */\n    location.replace(location.href)\n  })\n\n  await waitForMswActivation()\n\n  const res = await fetch('https://example.com/resource')\n  const body = await res.json()\n\n  // Still intercepts and mocks responses after a hard-reload.\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({ mocked: true })\n})\n"
  },
  {
    "path": "test/browser/msw-api/integrity-check-invalid.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://example.com/users/:username', () => {\n    return HttpResponse.json({\n      mocked: true,\n    })\n  }),\n)\n\nworker.start({\n  serviceWorker: {\n    // Use custom Service Worker URL for the purpose of intentionally\n    // registering an outdated worker. Please do not use this as an example.\n    url: './mockServiceWorker-outdated.js',\n    options: {\n      scope: '/',\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/integrity-check-valid.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://example.com/users/octocat', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/integrity-check.test.ts",
    "content": "import fs from 'node:fs'\nimport { test, expect } from '../playwright.extend'\nimport copyServiceWorker from '../../../config/copyServiceWorker'\nimport packageJson from '../../../package.json' assert { type: 'json' }\n// @ts-expect-error Importing a Javascript module.\nimport { SERVICE_WORKER_SOURCE_PATH } from '../../../config/constants.js'\n\ntest('activates the worker without errors given the latest integrity', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(\n    new URL('./integrity-check-valid.mocks.ts', import.meta.url),\n  )\n\n  expect(consoleSpy.get('error')).toBeUndefined()\n\n  const res = await fetch('https://example.com/users/octocat')\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n\ntest('errors when activating the worker with an outdated integrity', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  const TEMP_SERVICE_WORKER_PATH = new URL(\n    '../../tmp/mockServiceWorker-outdated.js',\n    import.meta.url,\n  ).pathname\n\n  // Manually create a Service Worker file with invalid integrity\n  await copyServiceWorker(\n    SERVICE_WORKER_SOURCE_PATH,\n    TEMP_SERVICE_WORKER_PATH,\n    'intentionally-invalid-checksum',\n  )\n\n  const consoleSpy = spyOnConsole()\n  await loadExample(\n    new URL('./integrity-check-invalid.mocks.ts', import.meta.url),\n    {\n      skipActivation: true,\n      beforeNavigation(compilation) {\n        compilation.use((router) => {\n          router.use('/', (_, res, next) => {\n            // Appended router are relative to the compilation path.\n            // Allow the nested worker script to control the root scope.\n            res.setHeader('Service-Worker-Allowed', '/')\n            next()\n          })\n\n          router.get('/mockServiceWorker-outdated.js', (_, res) => {\n            return res\n              .set('content-type', 'application/javascript')\n              .send(fs.readFileSync(TEMP_SERVICE_WORKER_PATH, 'utf8'))\n          })\n        })\n      },\n    },\n  )\n\n  await waitFor(() => {\n    // Produces a meaningful error in the browser's console.\n    expect(consoleSpy.get('warning')).toEqual(\n      expect.arrayContaining([\n        `[MSW] The currently registered Service Worker has been generated by a different version of MSW (${packageJson.version}) and may not be fully compatible with the installed version.\n\nIt's recommended you update your worker script by running this command:\n\n  \\u2022 npx msw init <PUBLIC_DIR>\n\nYou can also automate this process and make the worker script update automatically upon the library installations. Read more: https://mswjs.io/docs/cli/init.`,\n      ]),\n    )\n  })\n\n  // Still keeps the mocking enabled.\n  const res = await fetch('https://example.com/users/octocat')\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    mocked: true,\n  })\n\n  fs.unlinkSync(TEMP_SERVICE_WORKER_PATH)\n})\n"
  },
  {
    "path": "test/browser/msw-api/regression/2129-worker-use.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start()\n\nworker.use(\n  http.get('/v1/issues', () => {\n    return HttpResponse.text('get-body')\n  }),\n)\n\nworker.use(\n  http.post('/v1/issues', () => {\n    return HttpResponse.text('post-body')\n  }),\n)\n"
  },
  {
    "path": "test/browser/msw-api/regression/2129-worker-use.test.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/issues/2129\n */\nimport { test, expect } from '../../playwright.extend'\n\ntest('handles a stream response without throwing a timeout error', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./2129-worker-use.mocks.ts', import.meta.url))\n\n  const getResponse = await fetch('/v1/issues')\n  expect(await getResponse.text()).toBe('get-body')\n\n  const postResponse = await fetch('/v1/issues', { method: 'POST' })\n  expect(await postResponse.text()).toBe('post-body')\n})\n"
  },
  {
    "path": "test/browser/msw-api/regression/handle-stream.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.events.on('response:bypass', async ({ response }) => {\n  const responseText = await response.clone().text()\n  console.warn(`[response:bypass] ${responseText}`)\n})\n\nworker.start({ onUnhandledRequest: 'bypass' })\n"
  },
  {
    "path": "test/browser/msw-api/regression/handle-stream.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('handles a stream response without throwing a timeout error', async ({\n  createServer,\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n  waitFor,\n}) => {\n  const server = await createServer((app) => {\n    app.get('/stream', (_, res) => {\n      res.write('first-chunk')\n\n      setTimeout(() => {\n        res.write(' last-chunk')\n        res.end()\n      }, 250 * 6)\n    })\n  })\n\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./handle-stream.mocks.ts', import.meta.url))\n\n  const getStreamResponse = () => {\n    return page.evaluate(\n      ([endpointUrl]) => {\n        const abortController = new AbortController()\n        const abortTimeout = setTimeout(() => abortController.abort(), 250 * 5)\n\n        return new Promise<string>((resolve, reject) => {\n          let textResponse = ''\n          const decoder = new TextDecoder()\n\n          return fetch(endpointUrl, {\n            signal: abortController.signal,\n          })\n            .then((response) => {\n              // @ts-expect-error Response is a runtime object.\n              const reader = response.body.getReader()\n              clearTimeout(abortTimeout)\n              reader.read().then(function processStream({ done, value }) {\n                if (done) {\n                  resolve(textResponse)\n                  return\n                }\n\n                textResponse += decoder.decode(value, { stream: true })\n                return reader.read().then(processStream)\n              })\n            })\n            .catch(reject)\n        })\n      },\n      [server.http.url('/stream')],\n    )\n  }\n\n  const response = await getStreamResponse()\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toEqual([\n      `[response:bypass] first-chunk last-chunk`,\n    ])\n  })\n\n  expect(response).toEqual('first-chunk last-chunk')\n})\n"
  },
  {
    "path": "test/browser/msw-api/regression/null-body.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get<{ code: string }>('/api/:code', ({ params }) => {\n    return new HttpResponse(null, { status: parseInt(params.code) })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/regression/null-body.test.ts",
    "content": "import { expect, test } from '../../playwright.extend'\n\nfor (const code of [204, 205, 304]) {\n  test(`gracefully handles a ${code} response null body during life-cycle events`, async ({\n    loadExample,\n    fetch,\n    page,\n  }) => {\n    await loadExample(new URL('./null-body.mocks.ts', import.meta.url))\n\n    const errors: Array<Error> = []\n    page.on('pageerror', (pageError) => {\n      errors.push(pageError)\n    })\n\n    await fetch(`/api/${code}`)\n    expect(errors).toEqual([])\n  })\n}\n"
  },
  {
    "path": "test/browser/msw-api/req/passthrough.mocks.ts",
    "content": "import { http, passthrough, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('/', () => {\n    return passthrough()\n  }),\n)\n\nworker.start()\n\nObject.assign(window, {\n  msw: {\n    worker,\n    http,\n    passthrough,\n    HttpResponse,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/req/passthrough.test.ts",
    "content": "import { HttpResponse, http, passthrough } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { expect, test } from '../../playwright.extend'\n\nconst PASSTHROUGH_EXAMPLE = new URL('./passthrough.mocks.ts', import.meta.url)\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n    passthrough: typeof passthrough\n    HttpResponse: typeof HttpResponse\n  }\n}\n\ninterface ResponseBody {\n  name: string\n}\n\ntest('performs request as-is when returning \"req.passthrough\" call in the resolver', async ({\n  createServer,\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n}) => {\n  const server = await createServer((app) => {\n    app.post('/user', (_, res) => {\n      res.json({ name: 'John' })\n    })\n  })\n\n  const consoleSpy = spyOnConsole()\n  await loadExample(PASSTHROUGH_EXAMPLE)\n  const endpointUrl = server.http.url('/user')\n\n  await page.evaluate((endpointUrl) => {\n    const { worker, http, passthrough } = window.msw\n    worker.use(\n      http.post<never, ResponseBody>(endpointUrl, () => {\n        return passthrough()\n      }),\n    )\n  }, endpointUrl)\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const headers = await res.allHeaders()\n  const json = await res.json()\n\n  expect(headers).toHaveProperty('x-powered-by', 'Express')\n  expect(json).toEqual({\n    name: 'John',\n  })\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n\ntest('does not allow fall-through when returning \"req.passthrough\" call in the resolver', async ({\n  createServer,\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n}) => {\n  const server = await createServer((app) => {\n    app.post('/user', (_, res) => {\n      res.json({ name: 'John' })\n    })\n  })\n\n  const consoleSpy = spyOnConsole()\n  await loadExample(PASSTHROUGH_EXAMPLE)\n  const endpointUrl = server.http.url('/user')\n\n  await page.evaluate((endpointUrl) => {\n    const { worker, http, passthrough, HttpResponse } = window.msw\n\n    worker.use(\n      http.post<never, ResponseBody>(endpointUrl, () => {\n        return passthrough()\n      }),\n      http.post<never, ResponseBody>(endpointUrl, () => {\n        return HttpResponse.json({ name: 'Kate' })\n      }),\n    )\n  }, endpointUrl)\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const headers = await res.allHeaders()\n  const json = await res.json()\n\n  expect(headers).toHaveProperty('x-powered-by', 'Express')\n  expect(json).toEqual({\n    name: 'John',\n  })\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n\ntest('performs a request as-is if nothing was returned from the resolver', async ({\n  createServer,\n  loadExample,\n  fetch,\n  page,\n}) => {\n  const server = await createServer((app) => {\n    app.post('/user', (_, res) => {\n      res.json({ name: 'John' })\n    })\n  })\n\n  await loadExample(PASSTHROUGH_EXAMPLE)\n  const endpointUrl = server.http.url('/user')\n\n  await page.evaluate((endpointUrl) => {\n    const { worker, http } = window.msw\n    worker.use(\n      http.post<never, ResponseBody>(endpointUrl, () => {\n        return\n      }),\n    )\n  }, endpointUrl)\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const headers = await res.allHeaders()\n  const json = await res.json()\n\n  expect(headers).toHaveProperty('x-powered-by', 'Express')\n  expect(json).toEqual({\n    name: 'John',\n  })\n})\n\nfor (const code of [204, 205, 304]) {\n  test(`performs a ${code} request as-is if passthrough was returned from the resolver`, async ({\n    createServer,\n    loadExample,\n    fetch,\n    page,\n  }) => {\n    const server = await createServer((app) => {\n      app.post('/user', (_, res) => {\n        res.status(code).send()\n      })\n    })\n\n    await loadExample(PASSTHROUGH_EXAMPLE)\n    const endpointUrl = server.http.url('/user')\n\n    const errors: Array<Error> = []\n    page.on('pageerror', (pageError) => {\n      errors.push(pageError)\n    })\n\n    await page.evaluate((endpointUrl) => {\n      const { worker, http, passthrough } = window.msw\n      worker.use(\n        http.post<never, ResponseBody>(endpointUrl, () => {\n          return passthrough()\n        }),\n      )\n    }, endpointUrl)\n\n    const res = await fetch(endpointUrl, { method: 'POST' })\n    expect(res.status()).toBe(code)\n    expect(errors).toEqual([])\n  })\n\n  test(`performs a ${code} request as-is if nothing was returned from the resolver`, async ({\n    createServer,\n    loadExample,\n    fetch,\n    page,\n  }) => {\n    const server = await createServer((app) => {\n      app.post('/user', (_, res) => {\n        res.status(code).send()\n      })\n    })\n\n    await loadExample(PASSTHROUGH_EXAMPLE)\n    const endpointUrl = server.http.url('/user')\n\n    const errors: Array<Error> = []\n    page.on('pageerror', (pageError) => {\n      errors.push(pageError)\n    })\n\n    await page.evaluate((endpointUrl) => {\n      const { worker, http } = window.msw\n      worker.use(\n        http.post<never, ResponseBody>(endpointUrl, () => {\n          return\n        }),\n      )\n    }, endpointUrl)\n\n    const res = await fetch(endpointUrl, { method: 'POST' })\n    expect(res.status()).toBe(code)\n    expect(errors).toEqual([])\n  })\n}\n"
  },
  {
    "path": "test/browser/msw-api/res/network-error.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.error()\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/res/network-error.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('throws a network error', async ({ spyOnConsole, loadExample, page }) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./network-error.mocks.ts', import.meta.url))\n\n  // Do not use `runtime.request()`, because it always awaits a response.\n  // In this case we await a network error, performing a request manually.\n  const requestPromise = page.evaluate(() => {\n    return fetch('/user')\n  })\n\n  await expect(requestPromise).rejects.toThrow(\n    // The `fetch` call itself rejects with the \"Failed to fetch\" error,\n    // the same error that happens on a regular network error.\n    'TypeError: Failed to fetch',\n  )\n\n  // Assert a network error message printed into the console\n  // before `fetch` rejects.\n  expect(consoleSpy.get('error')).toEqual([\n    'Failed to load resource: net::ERR_FAILED',\n  ])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/user', () => {\n    return HttpResponse.json({ name: 'John Maverick' })\n  }),\n)\n\nworker.start()\n\nObject.assign(window, { worker })\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/fallback-mode/fallback-mode.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { createTeardown } from 'fs-teardown'\nimport { Page } from '@playwright/test'\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { fromTemp } from '../../../../support/utils'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const worker: SetupWorkerApi\n}\n\nconst fsMock = createTeardown({\n  rootDir: fromTemp('fallback-mode'),\n})\n\nlet server: HttpServer\n\nasync function gotoStaticPage(page: Page, workerIndex: number): Promise<void> {\n  await page.goto(\n    `file://${fsMock.resolve(`worker-${workerIndex}/index.html`)}`,\n    { waitUntil: 'networkidle' },\n  )\n}\n\ninterface DirectFetchResponse {\n  status: number\n  statusText: string\n  headers: Record<string, string>\n  body: Record<string, unknown>\n}\n\nfunction createFetchWithoutNetwork(page: Page) {\n  return (\n    input: RequestInfo,\n    init?: RequestInit,\n  ): Promise<DirectFetchResponse> => {\n    return page.evaluate(\n      ([input, init]) => {\n        return fetch(input, init)\n          .then((res) => {\n            const headers: Record<string, string> = {}\n            res.headers.forEach((value, key) => {\n              headers[key] = value\n            })\n\n            return res.json().then((body) => ({\n              status: res.status,\n              statusText: res.statusText,\n              headers,\n              body,\n            }))\n          })\n          .catch(() => null as any)\n      },\n      [input, init] as [RequestInfo, RequestInit],\n    )\n  }\n}\n\ntest.beforeAll(async () => {\n  await fsMock.prepare()\n})\n\ntest.beforeEach(async ({ webpackServer }, testInfo) => {\n  const compilation = await webpackServer.compile([\n    new URL('./fallback-mode.mocks.ts', import.meta.url).pathname,\n  ])\n  const bundleUrl = new URL('./main.js', compilation.previewUrl)\n  await fsMock.create({\n    // Scope static files per worker to prevent shared state.\n    // The tests below are run in parallel.\n    [`worker-${testInfo.workerIndex}`]: {\n      'index.html': `<script src=\"${bundleUrl.href}\"></script>`,\n    },\n  })\n})\n\ntest.beforeEach(async ({ createServer }) => {\n  server = await createServer((app) => {\n    app.get('/user', (_, res) => {\n      res.json({ name: 'Actual User' })\n    })\n  })\n})\n\ntest.afterAll(async () => {\n  await fsMock.cleanup()\n})\n\ntest('prints a fallback start message in the console', async ({\n  spyOnConsole,\n  page,\n  waitFor,\n}, testInfo) => {\n  const consoleSpy = spyOnConsole()\n  await gotoStaticPage(page, testInfo.workerIndex)\n  const consoleGroups = consoleSpy.get('startGroupCollapsed')\n\n  await waitFor(() => {\n    expect(consoleGroups).toContain('[MSW] Mocking enabled (fallback mode).')\n  })\n})\n\ntest('responds with a mocked response to a handled request', async ({\n  spyOnConsole,\n  waitFor,\n  page,\n}, testInfo) => {\n  const fetch = createFetchWithoutNetwork(page)\n  const consoleSpy = spyOnConsole()\n  await gotoStaticPage(page, testInfo.workerIndex)\n\n  const response = await fetch(server.https.url('/user'))\n\n  // Prints the request message group in the console.\n  await waitFor(() => {\n    expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /\\[MSW\\] \\d{2}:\\d{2}:\\d{2} GET https:\\/\\/127\\.0\\.0\\.1:\\d+\\/user 200 OK/,\n        ),\n      ]),\n    )\n  })\n\n  // Responds with a mocked response.\n  expect(response.status).toEqual(200)\n  expect(response.statusText).toEqual('OK')\n  expect(response.body).toEqual({\n    name: 'John Maverick',\n  })\n})\n\ntest('warns on the unhandled request by default', async ({\n  spyOnConsole,\n  page,\n}, testInfo) => {\n  const fetch = createFetchWithoutNetwork(page)\n  const consoleSpy = spyOnConsole()\n  await gotoStaticPage(page, testInfo.workerIndex)\n\n  await fetch(server.http.url('/unknown-resource'))\n\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET ${server.http.url('/unknown-resource')}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`),\n    ]),\n  )\n})\n\ntest('stops the fallback interceptor when called \"worker.stop()\"', async ({\n  spyOnConsole,\n  page,\n}, testInfo) => {\n  const fetch = createFetchWithoutNetwork(page)\n  const consoleSpy = spyOnConsole()\n  await gotoStaticPage(page, testInfo.workerIndex)\n\n  await page.evaluate(() => {\n    window.worker.stop()\n  })\n\n  expect(consoleSpy.get('log')).toContain('[MSW] Mocking disabled.')\n\n  const response = await fetch(server.http.url('/user'))\n\n  expect(response.status).toBe(200)\n  expect(response.body).toEqual({ name: 'Actual User' })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/input-validation.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\n//@ts-expect-error invalid parameter provided to setupWorker so we can validate it throws\nconst worker = setupWorker([\n  http.get('/book/:bookId', function originalResolver() {\n    return HttpResponse.json({ title: 'Original title' })\n  }),\n])\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/input-validation.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('throws an error given an Array of request handlers to \"setupWorker\"', async ({\n  loadExample,\n  page,\n  waitFor,\n}) => {\n  await loadExample(new URL('./input-validation.mocks.ts', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const exceptions: Array<string> = []\n  page.on('pageerror', (error) => {\n    exceptions.push(error.message)\n  })\n\n  await page.reload({ waitUntil: 'networkidle' })\n\n  await waitFor(() => {\n    expect(exceptions).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining(\n          '[MSW] Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?',\n        ),\n      ]),\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/life-cycle-events/on.mocks.ts",
    "content": "import {\n  HttpResponse,\n  http,\n  LifeCycleEventsMap,\n  passthrough,\n  bypass,\n} from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/user', () => {\n    return HttpResponse.text('response-body', { status: 400 })\n  }),\n  http.post('*/no-response', () => {\n    return\n  }),\n  http.get('*/passthrough', () => {\n    return passthrough()\n  }),\n  http.get('*/bypass', async ({ request }) => {\n    return fetch(bypass(request, { method: 'POST' }))\n  }),\n  http.get('*/unhandled-exception', () => {\n    throw new Error('Unhandled resolver error')\n  }),\n)\n\nworker.events.on('request:start', ({ request, requestId }) => {\n  console.warn(`[request:start] ${request.method} ${request.url} ${requestId}`)\n})\n\nworker.events.on('request:match', ({ request, requestId }) => {\n  console.warn(`[request:match] ${request.method} ${request.url} ${requestId}`)\n})\n\nworker.events.on('request:unhandled', ({ request, requestId }) => {\n  console.warn(\n    `[request:unhandled] ${request.method} ${request.url} ${requestId}`,\n  )\n})\n\nconst requestEndListener: (\n  ...args: LifeCycleEventsMap['request:end']\n) => void = ({ request, requestId }) => {\n  console.warn(`[request:end] ${request.method} ${request.url} ${requestId}`)\n}\n\nworker.events.on('request:end', requestEndListener)\n\nworker.events.on(\n  'response:mocked',\n  async ({ response, request, requestId }) => {\n    const body = await response.clone().text()\n    console.warn(\n      `[response:mocked] ${response.status} ${response.url} ${body} ${request.method} ${request.url} ${requestId}`,\n    )\n  },\n)\n\nworker.events.on(\n  'response:bypass',\n  async ({ response, request, requestId }) => {\n    const body = await response.clone().text()\n    console.warn(\n      `[response:bypass] ${response.status} ${response.url} ${body} ${request.method} ${request.url} ${requestId}`,\n    )\n  },\n)\n\nworker.events.on('unhandledException', ({ error, request, requestId }) => {\n  console.warn(\n    `[unhandledException] ${request.method} ${request.url} ${requestId} ${error.message}`,\n  )\n})\n\nworker.start({\n  onUnhandledRequest: 'bypass',\n})\n\nObject.assign(window, {\n  msw: {\n    worker,\n    requestEndListener,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/life-cycle-events/on.test.ts",
    "content": "import type { SetupWorker } from 'msw/browser'\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport type { ConsoleMessages } from 'page-with'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorker\n  }\n}\n\nconst ON_EXAMPLE = new URL('./on.mocks.ts', import.meta.url)\n\nconst server = new HttpServer((app) => {\n  app.post('/no-response', (_req, res) => {\n    res.send('original-response')\n  })\n  app.get('/unknown-route', (_req, res) => {\n    res.status(404)\n    res.send('majestic-unknown')\n  })\n  app.get('/passthrough', (_req, res) => {\n    res.send('passthrough-response')\n  })\n  app.post('/bypass', (_req, res) => {\n    res.send('bypassed-response')\n  })\n})\n\nexport function getRequestId(messages: ConsoleMessages) {\n  const requestStartMessage = messages.get('warning')?.find((message) => {\n    return message.startsWith('[request:start]')\n  })\n  return requestStartMessage?.split(' ')?.[3]\n}\n\ntest.beforeAll(async () => {\n  await server.listen()\n})\n\ntest.afterAll(async () => {\n  await server.close()\n})\n\ntest('emits events for a handled request and mocked response', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = server.http.url('/user')\n  await fetch(url)\n  const requestId = getRequestId(consoleSpy)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  expect(consoleSpy.get('warning')).toEqual([\n    `[request:start] GET ${url} ${requestId}`,\n    `[request:match] GET ${url} ${requestId}`,\n    `[request:end] GET ${url} ${requestId}`,\n    `[response:mocked] 400 ${url} response-body GET ${url} ${requestId}`,\n  ])\n})\n\ntest('emits events for a handled request with no response', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = server.http.url('/no-response')\n  await fetch(url, { method: 'POST' })\n  const requestId = getRequestId(consoleSpy)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:bypass]'),\n    )\n  })\n\n  expect(consoleSpy.get('warning')).toEqual([\n    `[request:start] POST ${url} ${requestId}`,\n    `[request:end] POST ${url} ${requestId}`,\n    `[response:bypass] 200 ${url} original-response POST ${url} ${requestId}`,\n  ])\n})\n\ntest('emits events for an unhandled request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = server.http.url('/unknown-route')\n  await fetch(url)\n  const requestId = getRequestId(consoleSpy)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:bypass]'),\n    )\n  })\n\n  expect(consoleSpy.get('warning')).toEqual([\n    `[request:start] GET ${url} ${requestId}`,\n    `[request:unhandled] GET ${url} ${requestId}`,\n    `[request:end] GET ${url} ${requestId}`,\n    `[response:bypass] 404 ${url} majestic-unknown GET ${url} ${requestId}`,\n  ])\n})\n\ntest('emits events for a passthrough request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  // Explicit \"passthrough()\" request must go through the\n  // same request processing pipeline to contain both\n  // \"request\" and \"response\" in the life-cycle event listener.\n  const url = server.http.url('/passthrough')\n  await fetch(url)\n  const requestId = getRequestId(consoleSpy)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toEqual([\n      `[request:start] GET ${url} ${requestId}`,\n      `[request:end] GET ${url} ${requestId}`,\n      `[response:bypass] 200 ${url} passthrough-response GET ${url} ${requestId}`,\n    ])\n  })\n})\n\ntest('emits events for a bypassed request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const pageErrors: Array<Error> = []\n  page.on('pageerror', (error) => pageErrors.push(error))\n\n  const url = server.http.url('/bypass')\n  await fetch(url)\n\n  await waitFor(() => {\n    // First, must print the events for the original (mocked) request.\n    expect(consoleSpy.get('warning')).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining(`[request:start] GET ${url}`),\n        expect.stringContaining(`[request:end] GET ${url}`),\n        expect.stringContaining(\n          `[response:mocked] 200 ${url} bypassed-response GET ${url}`,\n        ),\n      ]),\n    )\n\n    // Then, must also print events for the bypassed request.\n    expect(consoleSpy.get('warning')).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining(`[request:start] POST ${url}`),\n        expect.stringContaining(`[request:end] POST ${url}`),\n        expect.stringContaining(\n          `[response:bypass] 200 ${url} bypassed-response POST ${url}`,\n        ),\n      ]),\n    )\n\n    expect(pageErrors).toEqual([])\n  })\n})\n\ntest('emits unhandled exceptions in the request handler', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = server.http.url('/unhandled-exception')\n  await fetch(url)\n  const requestId = getRequestId(consoleSpy)\n\n  expect(consoleSpy.get('warning')).toContain(\n    `[unhandledException] GET ${url} ${requestId} Unhandled resolver error`,\n  )\n})\n\ntest('stops emitting events once the worker is stopped', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  await page.evaluate(() => {\n    return window.msw.worker.stop()\n  })\n  await fetch('/unknown-route')\n\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/life-cycle-events/removeAllListeners.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\nconst ON_EXAMPLE = new URL('./on.mocks.ts', import.meta.url)\n\ntest('removes all listeners attached to the worker instance', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = 'http://localhost/user'\n  await fetch(url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  // Remove all life-cycle events listeners.\n  await page.evaluate(() => {\n    const { msw } = window\n    msw.worker.events.removeAllListeners()\n  })\n\n  // Request the same endpoint again.\n  consoleSpy.clear()\n  await fetch(url)\n\n  // Negative assertion. We don't want this to pass.\n  const promise = waitFor(() => {\n    const warnings = consoleSpy.get('warning')\n    expect(warnings).toBeDefined()\n    expect(warnings).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  await expect(promise).rejects.toThrow()\n})\n\ntest('removes all the listeners by the event name', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(ON_EXAMPLE)\n\n  const url = 'http://localhost/user'\n  await fetch(url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  // Request the same endpoint again.\n  await page.evaluate(() => {\n    const { msw } = window\n    msw.worker.events.removeAllListeners('request:end')\n  })\n\n  // Request the same endpoint again.\n  consoleSpy.clear()\n  await fetch(url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  expect(consoleSpy.get('warning')).not.toContainEqual(\n    expect.stringContaining('[request:end]'),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/life-cycle-events/removeListener.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    requestEndListener: any\n  }\n}\n\ntest('removes a listener by the event name', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n  waitFor,\n  makeUrl,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./on.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { msw } = window\n    msw.worker.events.removeListener('request:end', msw.requestEndListener)\n  })\n\n  const url = makeUrl('/user')\n  await fetch(url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toContainEqual(\n      expect.stringContaining('[response:mocked]'),\n    )\n  })\n\n  expect(consoleSpy.get('warning')).not.toContainEqual(\n    expect.stringContaining('[request:end]'),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/listHandlers.mocks.ts",
    "content": "import { http, graphql } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst resolver = () => void 0\n\nconst github = graphql.link('https://api.github.com')\n\nconst worker = setupWorker(\n  http.get('https://test.mswjs.io/book/:bookId', resolver),\n  graphql.query('GetUser', resolver),\n  graphql.mutation('UpdatePost', resolver),\n  graphql.operation(resolver),\n  github.query('GetRepo', resolver),\n  github.operation(resolver),\n)\n\nworker.start()\n\nObject.assign(window, {\n  msw: {\n    worker,\n    http,\n    graphql,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/listHandlers.test.ts",
    "content": "import { http, graphql } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n    graphql: typeof graphql\n  }\n}\n\nconst LIST_HANDLER_EXAMPLE = new URL('./listHandlers.mocks.ts', import.meta.url)\n\ntest('lists all current request handlers', async ({ loadExample, page }) => {\n  await loadExample(LIST_HANDLER_EXAMPLE)\n\n  const handlerHeaders = await page.evaluate(() => {\n    const handlers = window.msw.worker.listHandlers()\n    return handlers.map((handler) => handler.info.header)\n  })\n\n  expect(handlerHeaders).toEqual([\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetUser (origin: *)',\n    'mutation UpdatePost (origin: *)',\n    'all (origin: *)',\n    'query GetRepo (origin: https://api.github.com)',\n    'all (origin: https://api.github.com)',\n  ])\n})\n\ntest('forbids from modifying the list of handlers', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(LIST_HANDLER_EXAMPLE)\n\n  /**\n   * @note For some reason, property assignment on frozen object\n   * does not throw an error: handlers[0] = 1\n   */\n  await expect(\n    page.evaluate(() => {\n      const handlers = window.msw.worker.listHandlers()\n      // @ts-expect-error Intentional runtime misusage.\n      handlers.push(1)\n    }),\n  ).rejects.toThrow(/Cannot add property \\d+, object is not extensible/)\n})\n\ntest('includes runtime request handlers when listing handlers', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(LIST_HANDLER_EXAMPLE)\n\n  const handlerHeaders = await page.evaluate(() => {\n    const { worker, http, graphql } = window.msw\n    worker.use(\n      http.get('https://test.mswjs.io/book/:bookId', () => void 0),\n      graphql.query('GetRandomNumber', () => void 0),\n    )\n    const handlers = worker.listHandlers()\n    return handlers.map((handler) => handler.info.header)\n  })\n\n  expect(handlerHeaders).toEqual([\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetRandomNumber (origin: *)',\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetUser (origin: *)',\n    'mutation UpdatePost (origin: *)',\n    'all (origin: *)',\n    'query GetRepo (origin: https://api.github.com)',\n    'all (origin: https://api.github.com)',\n  ])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/resetHandlers.test.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../playwright.extend'\n\ndeclare namespace window {\n  // Annotate global references to the worker and rest request handlers.\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n    HttpResponse: typeof HttpResponse\n  }\n}\n\nconst USE_EXAMPLE = new URL('./use.mocks.ts', import.meta.url)\n\ntest('removes all runtime request handlers when resetting without explicit next handlers', async ({\n  loadExample,\n  page,\n  fetch,\n}) => {\n  await loadExample(USE_EXAMPLE)\n\n  await page.evaluate(() => {\n    const { msw } = window\n\n    // Add a request handler on runtime\n    msw.worker.use(\n      msw.http.post('/login', () => {\n        return msw.HttpResponse.json({ accepted: true })\n      }),\n    )\n  })\n\n  // Request handlers added on runtime affect the network communication.\n  const loginResponse = await fetch('/login', {\n    method: 'POST',\n  })\n  const loginStatus = loginResponse.status()\n  const loginBody = await loginResponse.json()\n  expect(loginStatus).toBe(200)\n  expect(loginBody).toEqual({ accepted: true })\n\n  // Reset request handlers to initial handlers.\n  await page.evaluate(() => {\n    const { msw } = window\n\n    msw.worker.resetHandlers()\n  })\n\n  // Any runtime request handlers are removed upon reset.\n  const secondLoginResponse = await fetch('/login', {\n    method: 'POST',\n  })\n  const secondLoginStatus = secondLoginResponse.status()\n  expect(secondLoginStatus).toBe(404)\n\n  // Initial request handlers (given to `setupWorker`) are not affected.\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'Original title' })\n})\n\ntest('replaces all handlers with the explicit next runtime handlers upon reset', async ({\n  loadExample,\n  page,\n  fetch,\n}) => {\n  await loadExample(USE_EXAMPLE)\n\n  // Add a runtime request handler.\n  await page.evaluate(() => {\n    const { msw } = window\n\n    msw.worker.use(\n      msw.http.post('/login', () => {\n        return msw.HttpResponse.json({ accepted: true })\n      }),\n    )\n  })\n\n  // Reset request handlers with explicit next handlers.\n  await page.evaluate(() => {\n    const { msw } = window\n\n    msw.worker.resetHandlers(\n      msw.http.get('/products', () => {\n        return msw.HttpResponse.json([1, 2, 3])\n      }),\n    )\n  })\n\n  // Any runtime request handlers must be removed.\n  const loginResponse = await fetch('/login', {\n    method: 'POST',\n  })\n  const secondLoginStatus = loginResponse.status()\n  expect(secondLoginStatus).toBe(404)\n\n  // Any initial request handler must be removed.\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  expect(bookStatus).toEqual(404)\n\n  // Should leave only explicit reset request handlers.\n  const productsResponse = await fetch('/products')\n  const productsStatus = productsResponse.status()\n  const productsBody = await productsResponse.json()\n  expect(productsStatus).toBe(200)\n  expect(productsBody).toEqual([1, 2, 3])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/response-logging.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\nfunction createResponseLogRegexp(username: string): RegExp {\n  return new RegExp(\n    `^\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} GET https://example\\\\.com/users/${username} 200 OK$`,\n  )\n}\n\ntest('prints the response info to the console', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n}) => {\n  await loadExample(new URL('../../rest-api/basic.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  const waitForResponseLog = async (exp: RegExp) => {\n    await waitFor(() => {\n      expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n        expect.arrayContaining([expect.stringMatching(exp)]),\n      )\n    })\n  }\n\n  const getResponseLogs = (exp: RegExp) => {\n    return consoleSpy.get('startGroupCollapsed')?.filter((log) => {\n      return exp.test(log)\n    })\n  }\n\n  const firstResponseLogRegexp = createResponseLogRegexp('octocat')\n  await fetch('https://example.com/users/octocat')\n  await waitForResponseLog(firstResponseLogRegexp)\n\n  // Must print the response summary to the console.\n  expect(getResponseLogs(firstResponseLogRegexp)).toHaveLength(1)\n\n  const secondResponseLogRegExp = createResponseLogRegexp('john.doe')\n  await fetch('https://example.com/users/john.doe')\n  await waitForResponseLog(secondResponseLogRegExp)\n\n  /**\n   * Must not duplicate response logs for the current and previous requests.\n   * @see https://github.com/mswjs/msw/issues/1411\n   */\n  expect(getResponseLogs(secondResponseLogRegExp)).toHaveLength(1)\n  expect(getResponseLogs(firstResponseLogRegexp)).toHaveLength(1)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/restoreHandlers.test.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n    HttpResponse: typeof HttpResponse\n  }\n}\n\ntest('returns a mocked response from the used one-time request handler when restored', async ({\n  loadExample,\n  page,\n  fetch,\n}) => {\n  await loadExample(new URL('./use.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { worker, http, HttpResponse } = window.msw\n\n    worker.use(\n      http.get<{ bookId: string }>(\n        '/book/:bookId',\n        () => {\n          return HttpResponse.json({ title: 'One-time override' })\n        },\n        { once: true },\n      ),\n    )\n  })\n\n  // One-time request handler hasn't been used yet,\n  // so expect its response upon first request hit.\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'One-time override' })\n\n  // One-time request handler has been used, so expect\n  // the original response.\n  const secondBookResponse = await fetch('/book/abc-123')\n  const secondBookStatus = secondBookResponse.status()\n  const secondBookBody = await secondBookResponse.json()\n  expect(secondBookStatus).toBe(200)\n  expect(secondBookBody).toEqual({ title: 'Original title' })\n\n  // Restore the one-time request handlers, marking them as unused.\n  await page.evaluate(() => {\n    const { worker } = window.msw\n    worker.restoreHandlers()\n  })\n\n  // Once restored, one-time request handler affect network again.\n  const thirdBookResponse = await fetch('/book/abc-123')\n  const thirdBookStatus = thirdBookResponse.status()\n  const thirdBookBody = await thirdBookResponse.json()\n  expect(thirdBookStatus).toBe(200)\n  expect(thirdBookBody).toEqual({ title: 'One-time override' })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/custom-transformers.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport * as JSONbig from 'json-bigint'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new HttpResponse(\n      JSONbig.stringify({\n        username: 'john.maverick',\n        balance: BigInt(1597928668063727616),\n      }),\n      {\n        headers: {\n          'Content-Type': 'application/json',\n        },\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/custom-transformers.test.ts",
    "content": "import * as JSONBig from 'json-bigint'\nimport { test, expect } from '../../../playwright.extend'\n\ntest('uses a custom transformer to parse BigInt in response body', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./custom-transformers.mocks.ts', import.meta.url))\n\n  const res = await fetch('/user')\n  const body = await res.text()\n\n  expect(body).toEqual(\n    JSONBig.stringify({\n      username: 'john.maverick',\n      balance: BigInt(1597928668063727616),\n    }),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/errors/internal-error.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    throw new Error('Custom error message')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/errors/internal-error.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('propagates the exception originating from a handled request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  waitFor,\n  makeUrl,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./internal-error.mocks.ts', import.meta.url))\n\n  const endpointUrl = makeUrl('/user')\n  const res = await fetch(endpointUrl)\n\n  // Expect the exception to be handled as a 500 error response.\n  expect(res.status()).toBe(500)\n  expect(res.statusText()).toBe('Request Handler Error')\n  expect(await res.json()).toEqual({\n    name: 'Error',\n    message: 'Custom error message',\n    stack: expect.stringContaining('Error: Custom error message'),\n  })\n\n  // Expect standard request failure message from the browser.\n  await waitFor(() => {\n    expect(consoleSpy.get('error')).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining(\n          'Failed to load resource: the server responded with a status of 500',\n        ),\n      ]),\n    )\n  })\n\n  expect(consoleSpy.get('error')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Uncaught exception in the request handler for \"GET ${endpointUrl}\":\n\nError: Custom error message\n`),\n    ]),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/errors/network-error.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.error()\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/errors/network-error.test.ts",
    "content": "import { until } from 'until-async'\nimport { test, expect } from '../../../../playwright.extend'\n\ntest('propagates a mocked network error', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  page,\n  makeUrl,\n}) => {\n  const consoleSpy = spyOnConsole()\n  const { workerConsole } = await loadExample(\n    new URL('./network-error.mocks.ts', import.meta.url),\n  )\n\n  const endpointUrl = makeUrl('/user')\n  await until(() => page.evaluate((url) => fetch(url), endpointUrl))\n\n  // Expect the fetch error message.\n  expect(consoleSpy.get('error')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining('Failed to load resource: net::ERR_FAILED'),\n    ]),\n  )\n\n  // The worker must not produce any errors.\n  expect(workerConsole.messages.get('error')).toBeUndefined()\n})\n\ntest('propagates a CORS violation error from a non-matching request', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./network-error.mocks.ts', import.meta.url))\n\n  await until(() => page.evaluate(() => fetch('/user')))\n\n  // Must print the failed fetch error to the console.\n  await waitFor(() => {\n    expect(consoleSpy.get('error')).toEqual(\n      expect.arrayContaining([\n        expect.stringContaining('Failed to load resource: net::ERR_FAILED'),\n      ]),\n    )\n  })\n\n  /**\n   * @todo Ideally, assert the Chromium warning about\n   * the Service Worker responding to the fetch event\n   * with a network error response. For some reason,\n   * it never appears in the console/worker console messages.\n   */\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/fall-through.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*', () => console.log('[get] first')),\n  http.get('/us*', () => console.log('[get] second')),\n  http.get('/user', () => HttpResponse.json({ firstName: 'John' })),\n  http.get('/user', () => console.log('[get] third')),\n\n  http.post('/blog/*', () => console.log('[post] first')),\n  http.post('/blog/article', () => console.log('[post] second')),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/fall-through.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('falls through all relevant request handlers until response is returned', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./fall-through.mocks.ts', import.meta.url))\n\n  const res = await fetch('/user')\n  const body = await res.json()\n\n  // One of the handlers returns a mocked response.\n  expect(body).toEqual({ firstName: 'John' })\n\n  // These two handlers execute before the one that returned the response.\n  expect(consoleSpy.get('log')).toContain('[get] first')\n  expect(consoleSpy.get('log')).toContain('[get] second')\n\n  // The third handler is listed after the one that returns the response,\n  // so it must never execute (response is sent).\n  expect(consoleSpy.get('log')).not.toContain('[get] third')\n})\n\ntest('falls through all relevant handler even if none returns response', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./fall-through.mocks.ts', import.meta.url))\n\n  const res = await fetch('/blog/article', {\n    method: 'POST',\n  })\n  const status = res.status()\n\n  // Neither of request handlers returned a mocked response.\n  expect(status).toBe(404)\n  expect(consoleSpy.get('log')).toContain('[post] first')\n  expect(consoleSpy.get('log')).toContain('[post] second')\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/app.html",
    "content": "<script>\n  window.request = () => {\n    fetch('./user')\n      .then((res) => res.json())\n      .then((data) => {\n        const node = document.createElement('p')\n        node.setAttribute('id', 'first-name')\n        node.innerText = data.firstName\n        document.body.appendChild(node)\n      })\n  }\n\n  document.addEventListener('click', window.request)\n</script>\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/iframe.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts",
    "content": "import { Frame } from '@playwright/test'\nimport * as express from 'express'\nimport { test, expect } from '../../../../playwright.extend'\n\ndeclare global {\n  interface Window {\n    request(): Promise<void>\n  }\n}\n\nfunction findFrame(frame: Frame) {\n  return frame.name() === ''\n}\n\nconst staticMiddleware = (router: express.Router) => {\n  router.use(express.static(new URL('./', import.meta.url).pathname))\n}\n\ntest('intercepts a request from an iframe (nested client)', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {\n    markup: new URL('page-in-iframe.html', import.meta.url).pathname,\n    beforeNavigation(compilation) {\n      compilation.use(staticMiddleware)\n    },\n  })\n\n  const frame = page.mainFrame().childFrames().find(findFrame)!\n  await frame.evaluate(() => window.request())\n\n  const firstNameElement = await frame.waitForSelector('#first-name')\n  const firstName = await firstNameElement.evaluate((node) => node.textContent)\n\n  expect(firstName).toBe('John')\n})\n\ntest('intercepts a request from a deeply nested iframe', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {\n    markup: new URL('page-in-nested-iframe.html', import.meta.url).pathname,\n    beforeNavigation(compilation) {\n      compilation.use(staticMiddleware)\n    },\n  })\n\n  const deepFrame = page\n    .mainFrame()\n    .childFrames()\n    .find(findFrame)!\n    .childFrames()\n    .find(findFrame)!\n\n  await deepFrame.evaluate(() => window.request())\n  const firstNameElement = await deepFrame.waitForSelector('#first-name')\n  const firstName = await firstNameElement.evaluate((node) => node.textContent)\n\n  expect(firstName).toBe('John')\n})\n\ntest('intercepts a request from a deeply nested iframe given MSW is registered in a parent nested iframe', async ({\n  webpackServer,\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./iframe.mocks.ts', import.meta.url), {\n    markup: new URL('page-in-iframe.html', import.meta.url).pathname,\n    beforeNavigation(compilation) {\n      compilation.use(staticMiddleware)\n    },\n  })\n\n  // Intentionally empty compilation just to serve\n  // a custom page with an embedded iframe.\n  await webpackServer.compile([], {\n    markup: `<iframe src=\"${page.url()}\"></iframe>`,\n  })\n\n  const deepFrame = page.mainFrame().childFrames().find(findFrame)!\n  await deepFrame.evaluate(() => window.request())\n  const firstNameElement = await deepFrame.waitForSelector('#first-name')\n  const firstName = await firstNameElement.evaluate((node) => node.textContent)\n\n  expect(firstName).toBe('John')\n})\n\ntest('intercepts a request from an iframe given MSW is registered in a sibling iframe', async ({\n  webpackServer,\n  loadExample,\n  page,\n  context,\n}) => {\n  // A frame that registers MSW, but does no requests.\n  await loadExample(new URL('./iframe.mocks.ts', import.meta.url))\n\n  // A request-issuing frame. Here lives the `window.fetch` call.\n  const requestPage = await context.newPage()\n  const requestCompilation = await webpackServer.compile([], {\n    markup: new URL('page-in-iframe.html', import.meta.url).pathname,\n  })\n  requestCompilation.use(staticMiddleware)\n  await requestPage.goto(requestCompilation.previewUrl)\n\n  // A parent frame that hosts two frames above.\n  const parentPage = await context.newPage()\n  const parentCompilation = await webpackServer.compile([], {\n    markup: `\n<iframe src=\"${requestPage.url()}\"></iframe>\n<iframe src=\"${page.url()}\"></iframe>\n      `,\n  })\n  await parentPage.goto(parentCompilation.previewUrl)\n  await parentPage.bringToFront()\n\n  const frame = parentPage\n    .mainFrame()\n    .childFrames()\n    .find(findFrame)!\n    .childFrames()\n    .find(findFrame)!\n\n  await frame.evaluate(() => window.request())\n  const firstNameElement = await frame.waitForSelector('#first-name')\n  const firstName = await firstNameElement.evaluate((node) => node.textContent)\n\n  expect(firstName).toBe('John')\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/child.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/resource', () => {\n    return new Response('hello world')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/iframe-multiple-workers.test.ts",
    "content": "import { test, expect } from '../../../../../playwright.extend'\n\ntest('intercepts a request issued by child frame when both child and parent have MSW', async ({\n  webpackServer,\n  page,\n}) => {\n  const parentCompilation = await webpackServer.compile([\n    new URL('./parent.mocks.ts', import.meta.url).pathname,\n  ])\n  const childCompilation = await webpackServer.compile([\n    new URL('./child.mocks.ts', import.meta.url).pathname,\n  ])\n\n  await page.goto(parentCompilation.previewUrl, { waitUntil: 'networkidle' })\n\n  await page.evaluate((childFrameUrl) => {\n    const iframe = document.createElement('iframe')\n    iframe.setAttribute('id', 'child-frame')\n    iframe.setAttribute('src', childFrameUrl)\n    document.body.appendChild(iframe)\n  }, childCompilation.previewUrl)\n\n  const childFrameElement = await page.locator('#child-frame').elementHandle()\n  const childFrame = await childFrameElement!.contentFrame()\n  await childFrame!.waitForLoadState('networkidle')\n\n  const responseText = await childFrame!.evaluate(async () => {\n    const response = await fetch('/resource')\n    return response.text()\n  })\n\n  expect(responseText).toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/multiple-workers/parent.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\n// The parent frame has a worker without any handlers.\nconst worker = setupWorker()\n\n// This registration is awaited by the `loadExample` command in the test.\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/page-in-iframe.html",
    "content": "<iframe src=\"./app.html\"></iframe>\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe/page-in-nested-iframe.html",
    "content": "<iframe src=\"./page-in-iframe.html\"></iframe>\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/app.html",
    "content": "\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start()\n\nwindow.msw = {\n  // @ts-expect-error\n  worker,\n  http,\n}\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/iframe-isolated-response.test.ts",
    "content": "import * as express from 'express'\nimport type { Frame, Page } from '@playwright/test'\nimport { test, expect } from '../../../../playwright.extend'\n\nconst staticMiddleware = (router: express.Router) => {\n  router.use(express.static(new URL('./', import.meta.url).pathname))\n}\n\nexport function getFrameById(id: string, page: Page): Frame {\n  const frame = page\n    .mainFrame()\n    .childFrames()\n    .find((frame) => frame.name() === id)\n\n  if (!frame) {\n    throw new Error(`Unable to find frame with id \"${id}\" on the page`)\n  }\n\n  return frame\n}\n\ntest('responds with different responses for the same request based on request referrer (frame url)', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(\n    new URL('./iframe-isolated-response.mocks.ts', import.meta.url),\n    {\n      markup: new URL('app.html', import.meta.url).pathname,\n      beforeNavigation(compilation) {\n        compilation.use(staticMiddleware)\n      },\n    },\n  )\n\n  // Add iframes dynamically after `window.msw` is set on the parent\n  // to prevent the iframe scripts from racing with the mocks setup.\n  await page.evaluate(() => {\n    for (const [id, src] of [\n      ['frame-one', './one.html'],\n      ['frame-two', './two.html'],\n    ]) {\n      const iframe = document.createElement('iframe')\n      iframe.id = id\n      iframe.name = id\n      iframe.src = src\n      document.body.appendChild(iframe)\n    }\n  })\n\n  // Wait for child frames to be attached and navigated.\n  await page.waitForFunction(() => {\n    return document.querySelectorAll('iframe').length === 2\n  })\n  const frameOne = getFrameById('frame-one', page)\n  const frameTwo = getFrameById('frame-two', page)\n\n  // Wait for the iframe scripts to load and define `window.request`.\n  await Promise.all([\n    frameOne.waitForFunction(() => typeof window.request === 'function'),\n    frameTwo.waitForFunction(() => typeof window.request === 'function'),\n  ])\n\n  await Promise.all([\n    frameOne.evaluate(() => window.request()),\n    frameTwo.evaluate(() => window.request()),\n  ])\n\n  /**\n   * @note Each frame is able to receive a unique response\n   * because it uses the `isolatedResolver` utility.\n   * It's IMPORTANT it runs in the frame's context. We cannot\n   * ship that logic in MSW because MSW always runs in the\n   * main thread (the top-level client, which is the parent).\n   */\n  await expect(frameOne.getByText('one')).toBeVisible()\n  await expect(frameTwo.getByText('two')).toBeVisible()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/one.html",
    "content": "<script>\n  const { worker, http } = window.parent.msw\n\n  function isolatedResolver(resolver) {\n    return (info) => {\n      if (info.request.referrer !== location.href) {\n        return\n      }\n      return resolver(info)\n    }\n  }\n\n  worker.use(\n    http.get(\n      './resource',\n      isolatedResolver(({ request }) => {\n        return new Response('one')\n      }),\n    ),\n  )\n\n  window.request = () => {\n    return fetch('./resource')\n      .then((response) => response.text())\n      .then((data) => {\n        const node = document.createElement('p')\n        node.innerText = data\n        document.body.appendChild(node)\n      })\n      .catch((error) => console.error(error))\n  }\n\n  document.addEventListener('click', window.request)\n</script>\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/iframe-isolated-response/two.html",
    "content": "<script>\n  const { worker, http } = window.parent.msw\n\n  function isolatedResolver(resolver) {\n    return (info) => {\n      if (info.request.referrer !== location.href) {\n        return\n      }\n      return resolver(info)\n    }\n  }\n\n  worker.use(\n    http.get(\n      './resource',\n      isolatedResolver(({ request }) => {\n        return new Response('two')\n      }),\n    ),\n  )\n\n  window.request = () => {\n    return fetch('./resource')\n      .then((response) => response.text())\n      .then((data) => {\n        const node = document.createElement('p')\n        node.innerText = data\n        document.body.appendChild(node)\n      })\n      .catch((error) => console.error(error))\n  }\n\n  document.addEventListener('click', window.request)\n</script>\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/scope/scope-nested-quiet.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.start({\n  quiet: true,\n  serviceWorker: {\n    url: './public/mockServiceWorker.js',\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/scope/scope-nested.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.start({\n  serviceWorker: {\n    url: './public/mockServiceWorker.js',\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/scope/scope-root.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.start({\n  serviceWorker: {\n    url: '/mockServiceWorker.js',\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/scope/scope-validation.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n// @ts-expect-error Importing a JavaScript module.\nimport { SERVICE_WORKER_BUILD_PATH } from '../../../../../../config/constants.js'\n\ntest('warns when visiting the page outside of the worker scope', async ({\n  loadExample,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  const { compilation } = await loadExample(\n    new URL('./scope-nested.mocks.ts', import.meta.url),\n    {\n      beforeNavigation(compilation) {\n        // Create a proxy to the worker script located under a nested (\"/public\") path.\n        compilation.use((router) => {\n          router.get('/public/mockServiceWorker.js', (_, res) => {\n            res.sendFile(SERVICE_WORKER_BUILD_PATH)\n          })\n        })\n      },\n    },\n  )\n\n  // Must display the out-of-scope warning.\n  const workerScope = new URL('./public', compilation.previewUrl)\n\n  expect(consoleSpy.get('warning')).toContain(\n    `[MSW] Cannot intercept requests on this page because it's outside of the worker's scope (\"${workerScope}/\"). If you wish to mock API requests on this page, you must resolve this scope issue.\n\n- (Recommended) Register the worker at the root level (\"/\") of your application.\n- Set the \"Service-Worker-Allowed\" response header to allow out-of-scope workers.`,\n  )\n  expect(consoleSpy.get('error')).toEqual(undefined)\n})\n\ntest('does not print the scope warning when the page is within the worker scope', async ({\n  loadExample,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./scope-root.mocks.ts', import.meta.url))\n\n  expect(consoleSpy.get('warning')).toEqual(undefined)\n  expect(consoleSpy.get('error')).toEqual(undefined)\n})\n\ntest('does not print the scope warning when the \"quiet\" option is enabled', async ({\n  loadExample,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./scope-nested-quiet.mocks.ts', import.meta.url), {\n    skipActivation: true,\n    beforeNavigation(compilation) {\n      // Create a proxy to the worker script located under a nested (\"/public\") path.\n      compilation.use((router) => {\n        router.get('/public/mockServiceWorker.js', (_, res) => {\n          res.sendFile(SERVICE_WORKER_BUILD_PATH)\n        })\n      })\n    },\n  })\n\n  // Although the page is out of the worker's scope,\n  // the \"quiet\" option is set to true.\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/shared-worker/shared-worker.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport express from 'express'\nimport { test, expect } from '../../../../playwright.extend'\n\ntest('does not interfere with a shared worker', async ({\n  loadExample,\n  spyOnConsole,\n  waitFor,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./shared-worker.mocks.ts', import.meta.url), {\n    beforeNavigation(compilation) {\n      compilation.use((router) => {\n        router.use(express.static(new URL('./', import.meta.url).pathname))\n      })\n    },\n  })\n\n  await page.evaluate(() => {\n    const worker = new SharedWorker('./worker.js')\n\n    worker.addEventListener('error', () =>\n      console.error('There is an error with worker'),\n    )\n\n    worker.port.onmessage = (event) => {\n      console.log(event.data)\n    }\n\n    worker.port.postMessage('john')\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('error')).toBeUndefined()\n    expect(consoleSpy.get('log')).toContain('hello, john')\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/shared-worker/worker.js",
    "content": "onconnect = (event) => {\n  const port = event.ports[0]\n\n  port.onmessage = (event) => {\n    port.postMessage(`hello, ${event.data}`)\n  }\n}\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/text-event-stream.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new HttpResponse()\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/scenarios/text-event-stream.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\nimport { sleep } from '../../../../support/utils'\n\ntest('bypasses the unhandled request with the \"Accept\" header containing \"text/event-stream\"', async ({\n  loadExample,\n  spyOnConsole,\n  createServer,\n  page,\n  waitFor,\n}) => {\n  const server = await createServer((app) => {\n    app.get('/user', async (req, res) => {\n      res.set({\n        'Content-Type': 'text/event-stream',\n        Connection: 'keep-alive',\n      })\n      res.flushHeaders()\n\n      const chunks = ['hello', 'beautiful', 'world']\n\n      for (const chunk of chunks) {\n        res.write(`data: ${chunk}\\n\\n`)\n        await sleep(150)\n      }\n    })\n  })\n\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./text-event-stream.mocks.ts', import.meta.url))\n\n  await page.evaluate((endpointUrl) => {\n    const source = new EventSource(endpointUrl)\n    source.addEventListener('message', (message) => {\n      console.log(message.data)\n    })\n  }, server.http.url('/user'))\n\n  await waitFor(() => {\n    expect(consoleSpy.get('error')).toBeUndefined()\n    expect(consoleSpy.get('log')).toEqual(\n      expect.arrayContaining(['hello', 'beautiful', 'world']),\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/error.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new Response()\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    worker,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/error.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\ntest('rejects with a custom error message when given a non-existing worker script', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./error.mocks.ts', import.meta.url), {\n    skipActivation: true,\n  })\n\n  // Playwright is so fast we need to await the runtime module\n  // exposing MSW on the global scope.\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await expect(\n    page.evaluate(() => {\n      return window.msw.worker.start({\n        serviceWorker: {\n          url: 'invalidServiceWorker',\n        },\n      })\n    }),\n  ).rejects.toThrowError(/\\[MSW\\] Failed/)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/find-worker.error.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new Response()\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    registration: worker\n      .start({\n        findWorker: (scriptURL, _mockServiceWorkerUrl) => {\n          return scriptURL.includes('some-bad-filename-that-does-not-exist.js')\n        },\n      })\n      .then((registration) => {\n        console.log('Registration Promise resolved')\n        // This will throw as as there is no instance returned with a non-matching worker name.\n        return registration?.constructor.name\n      })\n      .catch((error) => {\n        console.error('Error - no worker instance after starting', error)\n        throw error\n      }),\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/find-worker.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new Response()\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    registration: worker\n      .start({\n        // This is the default matching behavior if left unspecified.\n        findWorker(scriptURL, mockServiceWorkerUrl) {\n          return scriptURL === mockServiceWorkerUrl\n        },\n      })\n      .then((registration) => {\n        console.log('Registration Promise resolved', registration)\n        return registration?.constructor.name\n      }),\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/find-worker.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    registration: ReturnType<SetupWorkerApi['start']>\n  }\n}\n\ntest('resolves the \"start\" Promise and returns a ServiceWorkerRegistration when using a findWorker that returns true', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./find-worker.mocks.ts', import.meta.url))\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  const resolvedPayload = await page.evaluate(() => {\n    return window.msw.registration\n  })\n\n  expect(resolvedPayload).toBe('ServiceWorkerRegistration')\n\n  const activationMessageIndex =\n    consoleSpy.get('startGroupCollapsed')?.findIndex((text) => {\n      return text.includes('[MSW] Mocking enabled')\n    }) ?? -1\n\n  const customMessageIndex =\n    consoleSpy.get('log')?.findIndex((text) => {\n      return text.includes('Registration Promise resolved')\n    }) ?? -1\n\n  expect(activationMessageIndex).toBeGreaterThan(-1)\n  expect(customMessageIndex).toBeGreaterThan(-1)\n  expect(customMessageIndex).toBeGreaterThan(activationMessageIndex)\n})\n\ntest('fails to return a ServiceWorkerRegistration when using a findWorker that returns false', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./find-worker.error.mocks.ts', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  const workerStartError = await page.evaluate(() => {\n    return window.msw.registration.catch((error) => error.message)\n  })\n\n  const activationMessage = consoleSpy\n    .get('startGroupCollapsed')\n    ?.findIndex((text) => {\n      return text.includes('[MSW] Mocking enabled')\n    })\n\n  const errorMessageIndex = consoleSpy.get('error')?.findIndex((text) => {\n    return text.includes('Error - no worker instance after starting')\n  })\n\n  expect(workerStartError).toMatch(`\\\n[MSW] Failed to locate the Service Worker registration using a custom \"findWorker\" predicate.\n\nPlease ensure that the custom predicate properly locates the Service Worker registration at \"/mockServiceWorker.js\".\nMore details: https://mswjs.io/docs/api/setup-worker/start#findworker\\\n`)\n\n  expect(activationMessage).toBeUndefined()\n  expect(errorMessageIndex).toBeGreaterThan(-1)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/bypass.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start({\n  onUnhandledRequest: 'bypass',\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/bypass.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('bypasses an unhandled request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./bypass.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://mswjs.io/non-existing-page')\n  const status = res.status()\n\n  expect(consoleSpy.get('error')).toBeUndefined()\n  expect(consoleSpy.get('warning')).toBeUndefined()\n\n  // Performs the request as-is.\n  expect(status).toBe(404)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/callback-print.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start({\n  onUnhandledRequest(request, print) {\n    console.log(`Oops, unhandled ${request.method} ${request.url}`)\n    const url = new URL(request.url)\n\n    if (url.pathname.includes('/use-warn')) {\n      // Using \"print\" allows you to execute the default strategy.\n      print.warning()\n    } else {\n      print.error()\n    }\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/callback-print.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('executes a default \"warn\" strategy in a custom callback', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./callback-print.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://mswjs.io/use-warn')\n  const status = res.status()\n\n  // Request is performed as-is.\n  expect(status).toBe(404)\n\n  // Custom callback executed.\n  expect(consoleSpy.get('log')).toContain(\n    'Oops, unhandled GET https://mswjs.io/use-warn',\n  )\n  expect(consoleSpy.get('error')).toBeUndefined()\n\n  // Prints the unhandled request warning upon `print.warning()`.\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET https://mswjs.io/use-warn\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`),\n    ]),\n  )\n})\n\ntest('executes a default \"error\" strategy in a custom callback', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./callback-print.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://mswjs.io/use-error')\n  const status = res.status()\n\n  // Request is performed as-is.\n  expect(status).toBe(500)\n\n  // Custom callback executed.\n  expect(consoleSpy.get('log')).toContain(\n    'Oops, unhandled GET https://mswjs.io/use-error',\n  )\n  expect(consoleSpy.get('warning')).toBeUndefined()\n\n  // Prints the unhandled request error upon `print.error()`.\n  expect(consoleSpy.get('error')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Error: intercepted a request without a matching request handler:\n\n  • GET https://mswjs.io/use-error\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`),\n    ]),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/callback-throws.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start({\n  onUnhandledRequest(request) {\n    throw new Error(`Forbid unhandled ${request.method} ${request.url}`)\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/callback.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start({\n  onUnhandledRequest(request) {\n    console.log(`Oops, unhandled ${request.method} ${request.url}`)\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/callback.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('executes a given callback on an unhandled request', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./callback.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://mswjs.io/non-existing-page')\n  const status = res.status()\n\n  // Request is performed as-is.\n  expect(status).toBe(404)\n\n  // Custom callback executed.\n  expect(consoleSpy.get('log')).toContain(\n    'Oops, unhandled GET https://mswjs.io/non-existing-page',\n  )\n\n  // No warnings/errors produced by MSW.\n  expect(consoleSpy.get('error')).toBeUndefined()\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/default.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\n// By default any unhandled requests are performed as-is\n// but produce warnings.\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/default.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('warns on unhandled requests by default', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./default.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://mswjs.io/non-existing-page')\n  const status = res.status()\n\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringMatching(\n        /\\[MSW\\] Warning: intercepted a request without a matching request handler/,\n      ),\n    ]),\n  )\n\n  expect(consoleSpy.get('error')).toBeUndefined()\n\n  // Performs the request as-is.\n  expect(status).toBe(404)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n  http.post('/explicit-return', () => {\n    // Short-circuiting in a handler makes it perform the request as-is,\n    // but still treats this request as handled.\n    return\n  }),\n  http.post('/implicit-return', () => {\n    // The handler that has no return also performs the request as-is,\n    // still treating this request as handled.\n  }),\n)\n\nworker.start({\n  // Warn on the requests that are not handled in the request handlers above.\n  // Does not cancel the request.\n  onUnhandledRequest: 'warn',\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/on-unhandled-request/warn.test.ts",
    "content": "import { test, expect } from '../../../../playwright.extend'\n\ntest('warns on an unhandled REST API request with an absolute URL', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n  createServer,\n}) => {\n  const server = await createServer((app) => {\n    app.get('/resource', (req, res) => res.status(404).end())\n  })\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./warn.mocks.ts', import.meta.url))\n\n  const res = await fetch(server.http.url('/resource'))\n  const status = res.status()\n\n  expect(status).toBe(404)\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET ${server.http.url('/resource')}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`),\n    ]),\n  )\n})\n\ntest('warns on an unhandled REST API request with a relative URL', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./warn.mocks.ts', import.meta.url))\n\n  const res = await fetch('/user-details')\n  const status = res.status()\n\n  expect(status).toBe(404)\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.arrayContaining([\n      expect.stringContaining(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET /user-details\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`),\n    ]),\n  )\n})\n\ntest('does not warn on request which handler explicitly returns no mocked response', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./warn.mocks.ts', import.meta.url))\n\n  const res = await fetch('/explicit-return', { method: 'POST' })\n  const status = res.status()\n\n  expect(status).toBe(404)\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.not.arrayContaining([\n      expect.stringContaining(\n        '[MSW] Warning: intercepted a request without a matching request handler',\n      ),\n    ]),\n  )\n})\n\ntest('does not warn on request which handler implicitly returns no mocked response', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./warn.mocks.ts', import.meta.url))\n\n  const res = await fetch('/implicit-return', { method: 'POST' })\n  const status = res.status()\n\n  expect(status).toBe(404)\n  expect(consoleSpy.get('warning')).toEqual(\n    expect.not.arrayContaining([\n      expect.stringContaining(\n        '[MSW] Warning: intercepted a request without a matching request handler',\n      ),\n    ]),\n  )\n})\n\ntest('ignores common static assets when using the \"warn\" strategy', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./warn.mocks.ts', import.meta.url))\n\n  // This request will error so perform it accordingly.\n  await page.evaluate(() => {\n    return fetch('http://localhost/styles/main.css').catch(() => null)\n  })\n\n  expect(consoleSpy.get('warning')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/options-sw-scope.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nworker.start({\n  serviceWorker: {\n    options: {\n      // Service Worker would control the network traffic\n      // outgoing only from the \"/profile/*\" pages.\n      scope: '/profile',\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/options-sw-scope.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('respects a custom \"scope\" Service Worker option', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('options-sw-scope.mocks.ts', import.meta.url))\n\n  expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n    expect.arrayContaining([expect.stringContaining('[MSW] Mocking enabled.')]),\n  )\n\n  const res = await fetch('/user')\n  const status = res.status()\n\n  // Since the root \"/\" page lies outside of the custom worker scope,\n  // it won't be able to intercept an otherwise matching request.\n  expect(status).toBe(404)\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/quiet.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.json({\n      firstName: 'John',\n      age: 32,\n    })\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    registration: worker.start({\n      // Disable logging of matched requests into browser's console\n      quiet: true,\n    }),\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/quiet.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    registration: ReturnType<SetupWorkerApi['start']>\n  }\n}\n\ntest('does not log the intercepted request when the \"quiet\" option is set to \"true\"', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./quiet.mocks.ts', import.meta.url), {\n    // Using the \"quiet\" option to suppress the activation message.\n    skipActivation: true,\n  })\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(() => {\n    return window.msw.registration\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toBeUndefined()\n\n  const res = await fetch('/user')\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    firstName: 'John',\n    age: 32,\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/start.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return new Response()\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    async startWorker() {\n      await worker.start({\n        serviceWorker: {\n          // Use a custom Service Worker for this test that intentionally\n          // delays the worker installation time. This allows us to test\n          // that the \"worker.start()\" Promise indeed resolves only after\n          // the worker has been activated and not just registered.\n          url: './worker.js',\n        },\n      })\n    },\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/start.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { TestFixtures, test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    startWorker(): ReturnType<SetupWorkerApi['start']>\n  }\n}\n\nconst exampleOptions: Parameters<TestFixtures['loadExample']> = [\n  new URL('./start.mocks.ts', import.meta.url),\n  {\n    skipActivation: true,\n    beforeNavigation(compilation) {\n      compilation.use((router) => {\n        router.get('/worker.js', (_, res) => {\n          res.sendFile(new URL('worker.delayed.js', import.meta.url).pathname)\n        })\n      })\n    },\n  },\n]\n\ntest('resolves the \"start\" Promise when the worker has been activated', async ({\n  loadExample,\n  spyOnConsole,\n  waitFor,\n  page,\n}) => {\n  await loadExample(...exampleOptions)\n  const consoleSpy = spyOnConsole()\n  const events: Array<string> = []\n\n  const untilWorkerActivated = page\n    .evaluate(() => {\n      return new Promise((resolve) => {\n        navigator.serviceWorker.addEventListener('controllerchange', resolve)\n      })\n    })\n    .then(() => events.push('worker activated'))\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  const untilStartResolved = page\n    .evaluate(() => window.msw.startWorker())\n    .then(() => events.push('start resolved'))\n\n  const untilActivationMessage = waitFor(() => {\n    expect(consoleSpy.get('startGroupCollapsed')).toContain(\n      '[MSW] Mocking enabled.',\n    )\n    events.push('enabled message')\n  })\n\n  await Promise.all([\n    untilActivationMessage,\n    untilWorkerActivated,\n    untilStartResolved,\n  ])\n\n  expect(events[0]).toEqual('worker activated')\n  expect(events[1]).toEqual('start resolved')\n  expect(events[2]).toEqual('enabled message')\n  expect(events).toHaveLength(3)\n})\n\ntest('prints the start message when the worker has been registered', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const { compilation } = await loadExample(...exampleOptions)\n  const consoleSpy = spyOnConsole()\n\n  const expectedWorkerScope = new URL('.', compilation.previewUrl).href\n  const expectedWorkerUrl = new URL('./worker.js', compilation.previewUrl).href\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(() => {\n    return window.msw.startWorker()\n  })\n\n  expect(consoleSpy.get('log')).toContain(\n    `Worker scope: ${expectedWorkerScope}`,\n  )\n  expect(consoleSpy.get('log')).toContain(\n    `Worker script URL: ${expectedWorkerUrl}`,\n  )\n})\n\ntest('prints a warning if \"worker.start()\" is called multiple times', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  await loadExample(...exampleOptions)\n  const consoleSpy = spyOnConsole()\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(async () => {\n    await window.msw.startWorker()\n    await window.msw.startWorker()\n  })\n\n  // The activation message ise printed only once.\n  expect(consoleSpy.get('startGroupCollapsed')).toEqual([\n    '[MSW] Mocking enabled.',\n  ])\n\n  // The warning is printed about multiple calls of \"worker.start()\".\n  expect(consoleSpy.get('warning')).toEqual([\n    `[MSW] Found a redundant \"worker.start()\" call. Note that starting the worker while mocking is already enabled will have no effect. Consider removing this \"worker.start()\" call.`,\n  ])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/warn-on-wait-until-ready.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start({\n  /**\n   * @note This option is being deprecated.\n   */\n  waitUntilReady: true,\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/warn-on-wait-until-ready.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\nimport { waitFor } from '../../../../support/waitFor'\n\ntest('warns on the \"waitUntilReady\" option in \"worker.start()\"', async ({\n  loadExample,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(\n    new URL('./warn-on-wait-until-ready.mocks.ts', import.meta.url),\n  )\n\n  await waitFor(() => {\n    expect(consoleSpy.get('warning')).toEqual([\n      `[MSW] The \"waitUntilReady\" option has been deprecated. Please remove it from this \"worker.start()\" call. Follow the recommended Browser integration (https://mswjs.io/docs/integrations/browser) to eliminate any race conditions between the Service Worker registration and any requests made by your application on initial render.`,\n    ])\n  })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/start/worker.delayed.js",
    "content": "importScripts('/mockServiceWorker.js')\n\nself.addEventListener('install', (event) => {\n  event.waitUntil(\n    new Promise((resolve) => {\n      // Emulate long worker installation.\n      setTimeout(resolve, 500)\n    }),\n  )\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/in-flight-request.mocks.ts",
    "content": "import { http, HttpResponse, delay } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/resource', async () => {\n    await delay(500)\n    return HttpResponse.text('hello world')\n  }),\n)\n\nworker.start()\n\nwindow.msw = {\n  // @ts-expect-error\n  worker,\n}\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/in-flight-request.test.ts",
    "content": "import type { SetupWorkerApi } from '../../../../../src/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\ntest.beforeEach(() => {\n  test.setTimeout(5000)\n})\n\ntest('resolves in-flight requests before the worker was stopped', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./in-flight-request.mocks.ts', import.meta.url))\n\n  const dataPromise: Promise<string> = page.evaluate(() => {\n    return fetch('/resource').then((response) => response.text())\n  })\n\n  await page.evaluate(() => {\n    window.msw.worker.stop()\n  })\n\n  await expect(dataPromise).resolves.toBe('hello world')\n})\n\ntest('bypasses requests made after the worker was stopped', async ({\n  loadExample,\n  page,\n  fetch,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./in-flight-request.mocks.ts', import.meta.url),\n    {\n      beforeNavigation(compilation) {\n        compilation.use((router) => {\n          router.get('/resource', (_req, res) => {\n            res.send('original response')\n          })\n        })\n      },\n    },\n  )\n\n  const resourceUrl = new URL('./resource', compilation.previewUrl)\n\n  await page.evaluate(() => {\n    window.msw.worker.stop()\n  })\n\n  const data = await page.evaluate((url) => {\n    return fetch(url).then((response) => response.text())\n  }, resourceUrl.href)\n\n  expect(data).toBe('original response')\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/quiet.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nObject.assign(window, {\n  msw: {\n    worker,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/quiet.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\nconst QUIET_EXAMPLE = new URL('./quiet.mocks.ts', import.meta.url)\n\ntest('prints out the console stop message', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(QUIET_EXAMPLE, {\n    // Because the worker is started within the test.\n    skipActivation: true,\n  })\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(() => {\n    return window.msw.worker.start()\n  })\n\n  await page.evaluate(() => {\n    return window.msw.worker.stop()\n  })\n\n  expect(consoleSpy.get('log')).toContain('[MSW] Mocking disabled.')\n})\n\ntest('does not print out any console stop message when in \"quite\" mode', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(QUIET_EXAMPLE, {\n    skipActivation: true,\n  })\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(() => {\n    return window.msw.worker.start({ quiet: true })\n  })\n\n  await page.evaluate(() => {\n    return window.msw.worker.stop()\n  })\n\n  expect(consoleSpy.get('log')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/removes-all-listeners.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst createWorker = () => {\n  return setupWorker(\n    http.get('/user', () => {\n      return new HttpResponse()\n    }),\n  )\n}\n\nObject.assign(window, {\n  msw: {\n    createWorker,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop/removes-all-listeners.test.ts",
    "content": "import type { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    createWorker(): SetupWorkerApi\n  }\n}\n\ntest('removes all listeners when the worker is stopped', async ({\n  loadExample,\n  spyOnConsole,\n  browser,\n  page,\n  fetch,\n}) => {\n  const firstPageConsoleSpy = spyOnConsole()\n  await loadExample(\n    new URL('./removes-all-listeners.mocks.ts', import.meta.url),\n    {\n      skipActivation: true,\n    },\n  )\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(async () => {\n    await window.msw.createWorker().start()\n  })\n\n  const secondPage = await browser.newPage()\n  const secondPageConsoleSpy = spyOnConsole(secondPage)\n  await secondPage.goto(page.url())\n  await secondPage.evaluate(async () => {\n    const worker = window.msw.createWorker()\n    await worker.start()\n    worker.stop()\n  })\n\n  expect(firstPageConsoleSpy.get('startGroupCollapsed')).toEqual([\n    '[MSW] Mocking enabled.',\n  ])\n\n  expect(secondPageConsoleSpy.get('startGroupCollapsed')).toEqual([\n    '[MSW] Mocking enabled.',\n  ])\n  expect(secondPageConsoleSpy.get('log')).toContain('[MSW] Mocking disabled.')\n\n  await page.evaluate(() => fetch('/user'))\n  await page.waitForLoadState('networkidle')\n  expect(firstPageConsoleSpy.get('startGroupCollapsed')).toEqual([\n    '[MSW] Mocking enabled.',\n    expect.stringContaining('GET /user'),\n  ])\n\n  await secondPage.evaluate(() => fetch('/user'))\n  expect(secondPageConsoleSpy.get('startGroupCollapsed')).toEqual([\n    '[MSW] Mocking enabled.',\n  ])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://api.github.com', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n\nObject.assign(window, {\n  msw: {\n    worker,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/stop.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { Page } from '@playwright/test'\nimport { test, expect } from '../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\nconst stopWorkerOn = async (page: Page) => {\n  page.evaluate(() => {\n    return window.msw.worker.stop()\n  })\n\n  await new Promise<void>((resolve, reject) => {\n    const timeout = setTimeout(() => {\n      reject(new Error('Failed to await the worker stop console message!'))\n    }, 5000)\n\n    page.on('console', (message) => {\n      const text = message.text()\n\n      if (\n        // Successful stop console message.\n        text.includes('[MSW] Mocking disabled.') ||\n        // Warning when calling \"stop()\" multiple times.\n        text.includes('worker.stop()')\n      ) {\n        clearTimeout(timeout)\n        resolve()\n      }\n    })\n  })\n}\n\ntest('disables the mocking when the worker is stopped', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./stop.mocks.ts', import.meta.url))\n  await stopWorkerOn(page)\n\n  const res = await fetch('https://api.github.com')\n  const body = await res.json()\n\n  expect.soft(res.fromServiceWorker()).toBe(true)\n  expect.soft(body).not.toEqual({\n    mocked: true,\n  })\n})\n\ntest('keeps the mocking enabled in one tab when stopping the worker in another tab', async ({\n  loadExample,\n  context,\n  fetch,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./stop.mocks.ts', import.meta.url),\n  )\n\n  const firstPage = await context.newPage()\n  await firstPage.goto(compilation.previewUrl, {\n    waitUntil: 'networkidle',\n  })\n\n  const secondPage = await context.newPage()\n  await secondPage.goto(compilation.previewUrl, {\n    waitUntil: 'networkidle',\n  })\n\n  await stopWorkerOn(firstPage)\n\n  // Switch to another page.\n  await secondPage.bringToFront()\n\n  const res = await fetch('https://api.github.com', undefined, {\n    page: secondPage,\n  })\n  const body = await res.json()\n\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n\ntest('prints a warning on multiple \"worker.stop()\" calls', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./stop.mocks.ts', import.meta.url))\n\n  function byStopMessage(text: string): boolean {\n    return text === '[MSW] Mocking disabled.'\n  }\n\n  await stopWorkerOn(page)\n\n  // Prints the stop message and no warnings.\n  expect(consoleSpy.get('log')!.filter(byStopMessage)).toHaveLength(1)\n  expect(consoleSpy.get('warning')).toBeUndefined()\n\n  await stopWorkerOn(page)\n\n  // Does not print a duplicate stop message.\n  expect(consoleSpy.get('log')!.filter(byStopMessage)).toHaveLength(1)\n\n  // Prints a warning so the user knows something is not right.\n  expect(consoleSpy.get('warning')).toEqual([\n    `[MSW] Found a redundant \"worker.stop()\" call. Notice that stopping the worker after it has already been stopped has no effect. Consider removing this \"worker.stop()\" call.`,\n  ])\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/use.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/book/:bookId', function originalResolver() {\n    return HttpResponse.json({\n      title: 'Original title',\n    })\n  }),\n)\n\nworker.start()\n\nObject.assign(window, {\n  msw: {\n    worker,\n    http,\n    HttpResponse,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/use.test.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n    HttpResponse: typeof HttpResponse\n  }\n}\n\ntest('returns a mocked response from a runtime request handler upon match', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./use.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { worker, http, HttpResponse } = window.msw\n\n    worker.use(\n      http.post('/login', function postLoginResolver() {\n        return HttpResponse.json({ accepted: true })\n      }),\n    )\n  })\n\n  const loginResponse = await fetch('/login', {\n    method: 'POST',\n  })\n  const loginStatus = loginResponse.status()\n  const loginBody = await loginResponse.json()\n  expect(loginStatus).toBe(200)\n  expect(loginBody).toEqual({ accepted: true })\n\n  // Other request handlers are preserved, if there are no overlaps.\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'Original title' })\n})\n\ntest('returns a mocked response from a persistent request handler override', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./use.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { worker, http, HttpResponse } = window.msw\n\n    worker.use(\n      http.get('/book/:bookId', function permanentOverride() {\n        return HttpResponse.json({ title: 'Permanent override' })\n      }),\n    )\n  })\n\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'Permanent override' })\n\n  const anotherBookResponse = await fetch('/book/abc-123')\n  const anotherBookStatus = anotherBookResponse.status()\n  const anotherBookBody = await anotherBookResponse.json()\n  expect(anotherBookStatus).toBe(200)\n  expect(anotherBookBody).toEqual({ title: 'Permanent override' })\n})\n\ntest('returns a mocked response from a one-time request handler override only upon first request match', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./use.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { worker, http, HttpResponse } = window.msw\n\n    worker.use(\n      http.get(\n        '/book/:bookId',\n        function oneTimeOverride() {\n          return HttpResponse.json({ title: 'One-time override' })\n        },\n        { once: true },\n      ),\n    )\n  })\n\n  const bookResponse = await fetch('/book/abc-123')\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'One-time override' })\n\n  const anotherBookResponse = await fetch('/book/abc-123')\n  const anotherBookStatus = anotherBookResponse.status()\n  const anotherBookBody = await anotherBookResponse.json()\n  expect(anotherBookStatus).toBe(200)\n  expect(anotherBookBody).toEqual({ title: 'Original title' })\n})\n\ntest('returns a mocked response from a one-time request handler override only upon first request match with parallel requests', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./use.mocks.ts', import.meta.url))\n\n  await page.evaluate(() => {\n    const { worker, http, HttpResponse } = window.msw\n\n    worker.use(\n      http.get<{ bookId: string }>(\n        '/book/:bookId',\n        function oneTimeOverride({ params }) {\n          const { bookId } = params\n\n          return HttpResponse.json({ title: 'One-time override', bookId })\n        },\n        { once: true },\n      ),\n    )\n  })\n\n  const bookPromise = fetch('/book/abc-123')\n\n  const anotherBookPromise = fetch('/book/abc-123')\n\n  const bookResponse = await bookPromise\n  const bookStatus = bookResponse.status()\n  const bookBody = await bookResponse.json()\n  expect(bookStatus).toBe(200)\n  expect(bookBody).toEqual({ title: 'One-time override', bookId: 'abc-123' })\n\n  const anotherBookResponse = await anotherBookPromise\n  const anotherBookStatus = anotherBookResponse.status()\n  const anotherBookBody = await anotherBookResponse.json()\n  expect(anotherBookStatus).toBe(200)\n  expect(anotherBookBody).toEqual({ title: 'Original title' })\n})\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/worker-passthrough-header.mocks.ts",
    "content": "import { http, passthrough } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/resource', function originalResolver() {\n    return passthrough()\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/msw-api/setup-worker/worker-passthrough-header.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../../playwright.extend'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/resource', (req, res) => {\n    res.set(req.headers)\n    res.send('hello world')\n  })\n})\n\ntest.beforeAll(async () => {\n  await httpServer.listen()\n})\n\ntest.afterAll(async () => {\n  await httpServer.close()\n})\n\ntest('removes the internal passthrough request header', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(\n    new URL('./worker-passthrough-header.mocks.ts', import.meta.url),\n  )\n\n  const response = await fetch(httpServer.http.url('/resource'), {\n    headers: { 'x-custom-header': 'yes' },\n  })\n  const headers = await response.allHeaders()\n\n  expect(headers).toMatchObject({\n    // The default header value.\n    accept: '*/*',\n    'x-custom-header': 'yes',\n  })\n  await expect(response.text()).resolves.toBe('hello world')\n})\n\ntest('preserves existing \"accept\" header values when removing the internal passthrough request header', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(\n    new URL('./worker-passthrough-header.mocks.ts', import.meta.url),\n  )\n\n  const response = await fetch(httpServer.http.url('/resource'), {\n    headers: {\n      accept: 'text/plain, application/json',\n      'x-custom-header': 'yes',\n    },\n  })\n  const headers = await response.allHeaders()\n\n  expect(headers).toMatchObject({\n    accept: 'text/plain, application/json',\n    'x-custom-header': 'yes',\n  })\n  await expect(response.text()).resolves.toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/msw-api/unregister.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/resource', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nObject.assign(window, {\n  msw: {\n    worker,\n  },\n})\n"
  },
  {
    "path": "test/browser/msw-api/unregister.test.ts",
    "content": "import { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n  }\n}\n\ntest('unregisters itself when not prompted to be activated again', async ({\n  loadExample,\n  page,\n  fetch,\n  waitForMswActivation,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./unregister.mocks.ts', import.meta.url),\n    {\n      skipActivation: true,\n      beforeNavigation(compilation) {\n        compilation.use((router) => {\n          router.get('/resource', (_, res) => {\n            res.json({ original: true })\n          })\n        })\n      },\n    },\n  )\n\n  const resourceUrl = new URL('./resource', compilation.previewUrl).href\n\n  await page.waitForFunction(() => {\n    return typeof window.msw !== 'undefined'\n  })\n\n  await page.evaluate(() => {\n    return window.msw.worker.start()\n  })\n  await waitForMswActivation()\n\n  // Should have the mocking enabled.\n  const firstResponse = await fetch(resourceUrl)\n  const body = await firstResponse.json()\n\n  expect(firstResponse.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({ mocked: true })\n\n  // Reload the page, not starting the worker manually this time.\n  await page.reload({ waitUntil: 'networkidle' })\n\n  const secondResponse = await fetch(resourceUrl)\n  const secondBody = await secondResponse.json()\n\n  expect(secondResponse.fromServiceWorker()).toBe(false)\n  expect(secondBody).toEqual({ original: true })\n\n  // Refresh the page the second time.\n  await page.reload()\n  const thirdResponse = await fetch(resourceUrl)\n  const thirdBody = await thirdResponse.json()\n\n  expect(secondResponse.fromServiceWorker()).toBe(false)\n  expect(thirdBody).toEqual({ original: true })\n})\n"
  },
  {
    "path": "test/browser/playwright.config.ts",
    "content": "import { type PlaywrightTestConfig, devices } from '@playwright/test'\n\nexport default {\n  projects: [\n    {\n      name: 'chromium',\n      use: { ...devices['Desktop Chrome'] },\n    },\n  ],\n  timeout: 10_000,\n  retries: process.env.CI ? 1 : undefined,\n  workers: process.env.CI ? 3 : undefined,\n  use: {\n    trace: 'on-first-retry',\n    launchOptions: {\n      devtools: !process.env.CI,\n    },\n    screenshot: 'only-on-failure',\n    video: 'retain-on-failure',\n  },\n  outputDir: './test-results',\n  snapshotDir: './test-snapshots',\n  forbidOnly: !!process.env.CI,\n  reporter: 'list',\n  // Run every test in parallel to ensure that tests are isolated\n  // and there's no shared state leaking from the shared compilation\n  // server or the preview server.\n  fullyParallel: true,\n} satisfies PlaywrightTestConfig\n"
  },
  {
    "path": "test/browser/playwright.extend.ts",
    "content": "import url from 'node:url'\nimport crypto from 'node:crypto'\nimport { test as base, expect, type Response, Page } from '@playwright/test'\nimport {\n  Headers,\n  headersToObject,\n  flattenHeadersObject,\n  type FlatHeadersObject,\n} from 'headers-polyfill'\nimport { spyOnConsole, ConsoleMessages } from 'page-with'\nimport {\n  HttpServer,\n  HttpServerMiddleware,\n} from '@open-draft/test-server/lib/http.js'\nimport {\n  Compilation,\n  CompilationOptions,\n  WebpackHttpServer,\n} from 'webpack-http-server'\nimport { waitFor } from '../support/waitFor'\nimport { WorkerConsole } from './setup/workerConsole'\nimport { getWebpackServer } from './setup/webpackHttpServer'\nimport { WebSocketServer } from '../support/WebSocketServer'\n\nexport interface TestFixtures {\n  /**\n   * Create a test server instance.\n   */\n  createServer(...middleware: Array<HttpServerMiddleware>): Promise<HttpServer>\n  webpackServer: WebpackHttpServer\n  loadExample(\n    entry: string | Array<string> | URL,\n    options?: CompilationOptions & {\n      /**\n       * Do not await the \"Mocking enabled\" message in the console.\n       */\n      skipActivation?: boolean\n      beforeNavigation?(compilation: Compilation): void\n    },\n  ): Promise<{\n    compilation: Compilation\n    workerConsole: WorkerConsole\n  }>\n  fetch(\n    url: string,\n    init?: RequestInit,\n    options?: FetchOptions,\n  ): Promise<Response>\n  query(uri: string, options: GraphQLQueryOptions): Promise<Response>\n  makeUrl(path: string): string\n  spyOnConsole(page?: Page): ConsoleMessages\n  waitFor(predicate: () => unknown): Promise<void>\n  waitForMswActivation(): Promise<void>\n  defineWebSocketServer(): Promise<WebSocketServer>\n}\n\ninterface FetchOptions {\n  page?: Page\n  waitForResponse?(res: Response): Promise<boolean> | boolean\n}\n\ninterface GraphQLQueryOptions {\n  method?: 'GET' | 'POST'\n  query: string\n  variables?: Record<string, any>\n  multipartOptions?: GraphQLMultipartDataOptions\n}\n\ninterface GraphQLMultipartDataOptions {\n  map: Record<string, Array<string>>\n  fileContents: Array<string>\n}\n\nexport const test = base.extend<TestFixtures>({\n  async createServer({}, use) {\n    let server: HttpServer | undefined\n\n    await use(async (...middleware) => {\n      server = new HttpServer(...middleware)\n      await server.listen()\n      return server\n    })\n\n    await server?.close()\n  },\n  async webpackServer({}, use) {\n    use(await getWebpackServer())\n  },\n  async loadExample({ page, webpackServer, waitForMswActivation }, use) {\n    const pageExceptions: Array<Error> = []\n    page.on('pageerror', (error) => pageExceptions.push(error))\n\n    const workerConsole = new WorkerConsole()\n    let compilation: Compilation | undefined\n\n    await use(async (entry, options = {}) => {\n      const resolvedEntry =\n        entry instanceof URL ? url.fileURLToPath(entry) : entry\n\n      compilation = await webpackServer.compile(\n        Array.prototype.concat([], resolvedEntry),\n        options,\n      )\n\n      // Allow arbitrary setup code before navigating to the compilation preview.\n      // This is useful to set up console watchers and other side-effects.\n      options.beforeNavigation?.(compilation)\n\n      // Forward browser runtime errors/warnings to the test runner.\n      page.on('pageerror', console.error)\n\n      const oncePageReady = [\n        page.waitForLoadState('domcontentloaded', { timeout: 15_000 }),\n        page.waitForEvent('load', { timeout: 30_000 }),\n        page.waitForLoadState('networkidle', { timeout: 5_000 }),\n      ]\n      page.goto(compilation.previewUrl)\n      await Promise.all(oncePageReady)\n\n      // All examples await the MSW activation message by default.\n      // Support opting-out from this behavior for tests where activation\n      // is not expected (e.g. when testing activation errors).\n      if (!options.skipActivation) {\n        await waitForMswActivation()\n      }\n\n      await workerConsole.init(page)\n\n      return {\n        compilation,\n        workerConsole,\n      }\n    })\n\n    workerConsole.removeAllListeners()\n    await compilation?.dispose()\n  },\n  async waitFor({}, use) {\n    await use(waitFor)\n  },\n  async waitForMswActivation({ spyOnConsole }, use) {\n    const consoleSpy = spyOnConsole()\n\n    await use(() => {\n      return waitFor(() => {\n        const groupMessages = consoleSpy.get('startGroupCollapsed')\n\n        if (groupMessages?.includes('[MSW] Mocking enabled.')) {\n          consoleSpy.clear()\n          return Promise.resolve()\n        }\n\n        return Promise.reject()\n      })\n    })\n\n    consoleSpy.clear()\n  },\n  async fetch({ page }, use) {\n    await use(async (url, init, options = {}) => {\n      const target = options.page || page\n\n      const requestId = crypto.randomBytes(16).toString('hex')\n\n      const fetchOptions = init || {}\n      const initialHeaders = fetchOptions.headers || {}\n      const requestHeaders = new Headers(initialHeaders)\n\n      const identityHeaderName = 'accept-language'\n      requestHeaders.set(identityHeaderName, requestId)\n\n      const resolvedInit = {\n        ...fetchOptions,\n        headers: flattenHeadersObject(headersToObject(requestHeaders)),\n      }\n\n      // Don't await the request here so that we can await the response\n      // later on based on the request identity headers. This way we can\n      // perform multiple requests in parallel.\n      target.evaluate<unknown, [string, RequestInit]>(\n        ([url, init]) => fetch(url, init as RequestInit),\n        [url, resolvedInit],\n      )\n\n      return target.waitForResponse(async (res) => {\n        if (typeof options.waitForResponse !== 'undefined') {\n          return options.waitForResponse(res)\n        }\n\n        const {\n          [identityHeaderName]: actualRequestId,\n          ['x-msw-bypass']: isBypassRequest,\n        } = res.request().headers()\n\n        return isBypassRequest !== 'true' && actualRequestId === requestId\n      })\n    })\n  },\n  async query({ page }, use) {\n    await use(async (uri, options) => {\n      const requestId = crypto.randomUUID()\n      const method = options.method || 'POST'\n      const requestUrl = new URL(uri, 'http://localhost:8080')\n      const headers: FlatHeadersObject = {\n        'x-request-id': requestId,\n      }\n\n      if (method === 'GET') {\n        requestUrl.searchParams.set('query', options.query)\n\n        if (options.variables) {\n          requestUrl.searchParams.set(\n            'variables',\n            JSON.stringify(options.variables),\n          )\n        }\n      }\n\n      const responsePromise = page.evaluate<\n        globalThis.Response,\n        {\n          url: string\n          method: string\n          headers: FlatHeadersObject\n          options: GraphQLQueryOptions\n        }\n      >(\n        ({ url, method, headers, options }) => {\n          const init: RequestInit = {\n            method,\n            headers,\n          }\n\n          const operations = JSON.stringify({\n            query: options.query,\n            variables: options.variables,\n          })\n\n          function getMultipartGraphQLBody() {\n            if (!options.multipartOptions) {\n              throw new Error(\n                'Failed to construct a multi-part data GraphQL request: no options provided',\n              )\n            }\n\n            if (method !== 'POST') {\n              throw new Error(\n                'Cannot perform a multi-part data GraphQL request: must use \"POST\" method',\n              )\n            }\n\n            const body = new FormData()\n            body.set('operations', operations)\n            body.set('map', JSON.stringify(options.multipartOptions.map))\n\n            options.multipartOptions.fileContents.forEach(\n              (fileContent, index) => {\n                const file = new File([fileContent], `file${index}.txt`)\n                body.append(index.toString(), file)\n              },\n            )\n\n            return body\n          }\n\n          if (method === 'POST') {\n            if (!options.multipartOptions) {\n              headers['Content-Type'] = 'application/json'\n            }\n\n            init.body = options.multipartOptions\n              ? getMultipartGraphQLBody()\n              : operations\n          }\n\n          return fetch(url, init).catch(() => {\n            /**\n             * @note Silence request rejections so that request errors\n             * could be asserted in tests.\n             */\n            return new Response(null, { status: 508 })\n          })\n        },\n        {\n          url: requestUrl.href,\n          method,\n          headers,\n          options,\n        },\n      )\n\n      return new Promise<Response>((resolve, reject) => {\n        responsePromise.catch(reject)\n\n        return page\n          .waitForResponse(async (res) => {\n            const {\n              ['x-request-id']: actualRequestId,\n              ['x-msw-bypass']: isBypassRequest,\n            } = res.request().headers()\n\n            return isBypassRequest !== 'true' && actualRequestId === requestId\n          })\n          .then(resolve)\n          .catch(resolve)\n      })\n    })\n  },\n  async makeUrl({ webpackServer }, use) {\n    await use((pathname) => {\n      return new URL(pathname, webpackServer.serverUrl).href\n    })\n  },\n  async spyOnConsole({ page }, use) {\n    let messages: ConsoleMessages | undefined\n\n    await use((customPage) => {\n      messages = spyOnConsole(customPage || (page as any))\n      return messages\n    })\n\n    messages?.clear()\n  },\n  async defineWebSocketServer({}, use) {\n    const server = new WebSocketServer()\n    await use(async () => {\n      await server.listen()\n      return server\n    })\n    await server.close()\n  },\n})\n\nexport { expect }\n"
  },
  {
    "path": "test/browser/rest-api/204-response.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\n\nconst httpServer = new HttpServer((app) => {\n  /**\n   * @todo Test setup already spawns a single API server.\n   * Reuse it instead of creating a new one in tests.\n   */\n  app.get('/posts', (req, res) => {\n    return res.status(204).end()\n  })\n})\n\ntest.beforeAll(async () => {\n  await httpServer.listen()\n})\n\ntest.afterEach(async () => {\n  await httpServer.close()\n})\n\ntest('handles a 204 status response without Response instance exceptions', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./basic.mocks.ts', import.meta.url))\n\n  let pageError: Error\n\n  page.on('pageerror', (error) => {\n    pageError = error\n  })\n\n  const res = await fetch(httpServer.http.url('/posts'))\n\n  // There must be no such exception:\n  // Failed to construct 'Response': Response with null body status cannot have body\n  expect(pageError).toBeUndefined()\n  expect(res.status()).toBe(204)\n})\n"
  },
  {
    "path": "test/browser/rest-api/206-response.mocks.ts",
    "content": "import { HttpResponse, http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst data = 'hello world'\nconst buffer = new TextEncoder().encode(data)\nconst totalSize = buffer.byteLength\n\nconst worker = setupWorker(\n  http.get('/mocked-range', ({ request }) => {\n    const range = request.headers.get('Range')\n\n    if (!range) {\n      throw HttpResponse.text('Missing Range', { status: 400 })\n    }\n\n    const ranges = range.replace(/bytes=/, '').split('-')\n    const start = +ranges[0]\n    const end = ranges[1] ? +ranges[1] : totalSize - 1\n    const content = buffer.slice(start, end)\n\n    return HttpResponse.arrayBuffer(content, {\n      status: 206,\n      headers: {\n        'Accept-Range': 'bytes',\n        'Content-Range': `bytes=${start}-${end}/${totalSize}`,\n        'Content-Length': content.byteLength.toString(),\n        'Content-Type': 'text/plain',\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/206-response.test.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/issues/1972\n */\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { expect, test } from '../playwright.extend'\n\nconst encoder = new TextEncoder()\n\nconst server = new HttpServer((app) => {\n  const data = 'hello world'\n  const buffer = encoder.encode(data)\n  const totalSize = buffer.byteLength\n\n  app.get('/range', (req, res) => {\n    const { range } = req.headers\n\n    if (range) {\n      const ranges = range.replace(/bytes=/, '').split('-')\n      const start = +ranges[0]\n      const end = ranges[1] ? +ranges[1] : totalSize - 1\n      const content = buffer.slice(start, end)\n\n      res.writeHead(206, {\n        'Accept-Range': 'bytes',\n        'Content-Range': `bytes=${start}-${end}/${totalSize}`,\n        'Content-Length': content.byteLength,\n        'Content-Type': 'text/plain',\n      })\n      return res.end(content)\n    }\n\n    res.writeHead(400)\n    res.end('range missing')\n  })\n})\n\ntest.beforeAll(async () => {\n  await server.listen()\n})\n\ntest.afterAll(async () => {\n  await server.close()\n})\n\ntest('forwards the 206 response to a bypassed \"Range\" request', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./206-response.mocks.ts', import.meta.url))\n\n  const response = await fetch(server.http.url('/range'), {\n    headers: {\n      Range: 'bytes=2-8',\n    },\n  })\n\n  expect(response.status()).toBe(206)\n  expect(response.headers()).toMatchObject({\n    'accept-range': 'bytes',\n    'content-range': 'bytes=2-8/11',\n    'content-length': '6',\n    'content-type': 'text/plain',\n  })\n  expect(await response.text()).toBe('llo wo')\n})\n\ntest('responds with a 206 response to a mocked \"Range\" request', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./206-response.mocks.ts', import.meta.url))\n\n  const response = await fetch('/mocked-range', {\n    headers: {\n      Range: 'bytes=2-8',\n    },\n  })\n\n  expect(response.status()).toBe(206)\n  expect(response.headers()).toMatchObject({\n    'accept-range': 'bytes',\n    'content-range': 'bytes=2-8/11',\n    'content-length': '6',\n    'content-type': 'text/plain',\n  })\n  expect(await response.text()).toBe('llo wo')\n})\n"
  },
  {
    "path": "test/browser/rest-api/basic.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://example.com/users/:username', ({ params }) => {\n    const { username } = params\n\n    return HttpResponse.json({\n      name: 'John Maverick',\n      originalUsername: username,\n    })\n  }),\n)\n\nworker.start()\n\nObject.assign(window, { worker })\n"
  },
  {
    "path": "test/browser/rest-api/basic.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('mocks response to a GET request', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./basic.mocks.ts', import.meta.url))\n\n  const response = await fetch('https://example.com/users/octocat')\n  const status = response.status()\n  const body = await response.json()\n\n  expect(status).toBe(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    name: 'John Maverick',\n    originalUsername: 'octocat',\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/body.mocks.ts",
    "content": "import { http, HttpResponse, ResponseResolver } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst forwardRequestBody: ResponseResolver<any> = async ({ request }) => {\n  const requestText =\n    request.headers.get('Content-Type') === 'application/json' && request.body\n      ? await request.json()\n      : await request.text()\n\n  return HttpResponse.json({ value: requestText })\n}\n\nconst forwardMultipartRequestBody: ResponseResolver<any> = async ({\n  request,\n}) => {\n  const formData = await request.formData()\n  const responseBody: Record<string, string | Array<string>> = {}\n\n  for (const [name, value] of formData.entries()) {\n    const nextValue = value instanceof File ? await value.text() : value\n\n    if (responseBody[name]) {\n      responseBody[name] = Array.prototype.concat(\n        [],\n        responseBody[name],\n        nextValue,\n      )\n    } else {\n      responseBody[name] = nextValue\n    }\n  }\n\n  return HttpResponse.json(responseBody)\n}\n\nconst worker = setupWorker(\n  http.get('/resource', forwardRequestBody),\n  http.post('/resource', forwardRequestBody),\n  http.post('/upload', forwardMultipartRequestBody),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/body.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\nconst EXAMPLE_PATH = new URL('./body.mocks.ts', import.meta.url)\n\ntest('handles a GET request without a body', async ({ loadExample, fetch }) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/resource')\n  const body = await res.json()\n\n  expect(body).toEqual({ value: '' })\n})\n\ntest('handles a POST request with an explicit empty body', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/resource', {\n    method: 'POST',\n    body: '',\n  })\n  const json = await res.json()\n\n  expect(json).toEqual({ value: '' })\n})\n\ntest('handles a POST request with a textual body', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/resource', {\n    method: 'POST',\n    body: 'text-body',\n  })\n  const json = await res.json()\n\n  expect(json).toEqual({ value: 'text-body' })\n})\n\ntest('handles a POST request with a JSON body and \"Content-Type: application/json\" header', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/resource', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({\n      firstName: 'John',\n    }),\n  })\n  const json = await res.json()\n\n  expect(json).toEqual({\n    value: {\n      firstName: 'John',\n    },\n  })\n})\n\ntest('handles a POST request with a multipart body and \"Content-Type: multipart/form-data\" header', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  await page.evaluate(() => {\n    const data = new FormData()\n    data.set('file', new File(['file content'], 'file1.txt'))\n    data.set('text', 'text content')\n    data.set('text2', 'another text content')\n    data.append('text2', 'another text content 2')\n\n    fetch('/upload', {\n      method: 'POST',\n      body: data,\n    })\n  })\n\n  const res = await page.waitForResponse(/\\/upload/)\n  const body = await res.json()\n\n  expect(body).toEqual({\n    file: 'file content',\n    text: 'text content',\n    text2: ['another text content', 'another text content 2'],\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/context.mocks.ts",
    "content": "import { http, HttpResponse, delay } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://test.mswjs.io/', async () => {\n    await delay(2000)\n    return HttpResponse.json(\n      { mocked: true },\n      {\n        status: 201,\n        statusText: 'Yahoo!',\n        headers: {\n          Accept: 'foo/bar',\n          'Custom-Header': 'arbitrary-value',\n        },\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/context.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('composes various context utilities into a valid mocked response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./context.mocks.ts', import.meta.url))\n\n  const res = await fetch('https://test.mswjs.io/')\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(res.status()).toEqual(201)\n  expect(res.statusText()).toEqual('Yahoo!')\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(headers).toHaveProperty('accept', 'foo/bar')\n  expect(headers).toHaveProperty('custom-header', 'arbitrary-value')\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/cors.mocks.ts",
    "content": "import { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/cors.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\n\nconst server = new HttpServer((app) => {\n  // Enable a strict CORS policy on this test server.\n  // Requests from the test must use `mode: \"no-cors\"` to obtain the response.\n  app.use('*', (req, res, next) => {\n    res.set('Access-Control-Allow-Origin', server.http.url())\n    next()\n  })\n\n  app.get('/', (req, res) => {\n    res.status(200).send('hello')\n  })\n})\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('handles a CORS request with an \"opaque\" response', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./cors.mocks.ts', import.meta.url))\n\n  const errors = []\n  page.on('pageerror', (error) => errors.push(error))\n\n  const res = await fetch(server.http.url(), {\n    mode: 'no-cors',\n  })\n\n  expect(res.status()).toBe(200)\n  expect(await res.text()).toBe('hello')\n\n  expect(errors).toEqual([])\n})\n"
  },
  {
    "path": "test/browser/rest-api/generator.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get<{ maxCount: string }>('/polling/:maxCount', function* ({ params }) {\n    const { maxCount } = params\n    let count = 0\n\n    while (count < Number(maxCount)) {\n      count += 1\n\n      yield HttpResponse.json({\n        status: 'pending',\n        count,\n      })\n    }\n\n    return HttpResponse.json({\n      status: 'complete',\n      count,\n    })\n  }),\n\n  http.get<{ maxCount: string }>(\n    '/polling/once/:maxCount',\n    function* ({ params }) {\n      const { maxCount } = params\n      let count = 0\n\n      while (count < Number(maxCount)) {\n        count += 1\n\n        yield HttpResponse.json({\n          status: 'pending',\n          count,\n        })\n      }\n\n      return HttpResponse.json({\n        status: 'complete',\n        count,\n      })\n    },\n    { once: true },\n  ),\n  http.get('/polling/once/:maxCount', () => {\n    return HttpResponse.json({ status: 'done' })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/generator.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntype ExpectedResponseBody =\n  | {\n      status: 'pending' | 'complete'\n      count: number\n    }\n  | {\n      status: 'done'\n    }\n\ntest('supports a generator function as the response resolver', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./generator.mocks.ts', import.meta.url))\n\n  const assertRequest = async (expectedBody: ExpectedResponseBody) => {\n    const res = await fetch('/polling/3')\n    const body = await res.json()\n    expect(res.fromServiceWorker()).toBe(true)\n    expect(res.status()).toBe(200)\n    expect(body).toEqual(expectedBody)\n  }\n\n  await assertRequest({ status: 'pending', count: 1 })\n  await assertRequest({ status: 'pending', count: 2 })\n  await assertRequest({ status: 'pending', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n})\n\ntest('supports one-time handlers with the generator as the response resolver', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./generator.mocks.ts', import.meta.url))\n\n  const assertRequest = async (expectedBody: ExpectedResponseBody) => {\n    const res = await fetch('/polling/once/3')\n    const body = await res.json()\n    expect(res.fromServiceWorker()).toBe(true)\n    expect(res.status()).toBe(200)\n    expect(body).toEqual(expectedBody)\n  }\n\n  await assertRequest({ status: 'pending', count: 1 })\n  await assertRequest({ status: 'pending', count: 2 })\n  await assertRequest({ status: 'pending', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n  await assertRequest({ status: 'done' })\n  await assertRequest({ status: 'done' })\n})\n"
  },
  {
    "path": "test/browser/rest-api/headers-multiple.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('https://test.mswjs.io', ({ request }) => {\n    return HttpResponse.json({\n      'x-header': request.headers.get('x-header'),\n    })\n  }),\n\n  http.get('https://test.mswjs.io', () => {\n    return HttpResponse.json(\n      {\n        mocked: true,\n      },\n      {\n        headers: {\n          // List header values separated by comma\n          // to set multie-value header on the mocked response.\n          Accept: 'application/json, image/png',\n        },\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/headers-multiple.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\nconst EXAMPLE_PATH = new URL('./headers-multiple.mocks.ts', import.meta.url)\n\ntest('receives all headers from the request header with multiple values', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const headers = new Headers({ 'x-header': 'application/json' })\n  headers.append('x-header', 'application/hal+json')\n\n  const res = await fetch('https://test.mswjs.io', {\n    method: 'POST',\n    headers: Object.fromEntries(headers.entries()),\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual({\n    /**\n     * @fixme Multiple headers value becomes incompatible\n     * with the latest testing setup changes.\n     */\n    'x-header': 'application/json, application/hal+json',\n  })\n})\n\ntest('supports setting a header with multiple values on the mocked response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('https://test.mswjs.io')\n  const status = res.status()\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(headers).toHaveProperty('accept', 'application/json, image/png')\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/logging.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\nimport { StatusCodeColor } from '../../../src/core/utils/logging/getStatusCodeColor'\nimport { waitFor } from '../../support/waitFor'\n\ntest('prints the intercepted request info into browser console', async ({\n  loadExample,\n  spyOnConsole,\n  fetch,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./basic.mocks.ts', import.meta.url))\n\n  await fetch('https://example.com/users/octocat')\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          new RegExp(\n            `^\\\\[MSW\\\\] \\\\d{2}:\\\\d{2}:\\\\d{2} GET https://example.com/users/octocat \\\\(%c200 OK%c\\\\) color:${StatusCodeColor.Success} color:inherit$`,\n          ),\n        ),\n      ]),\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/params.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\ntype RequestParams = {\n  username: string\n  messageId: string\n}\n\nconst worker = setupWorker(\n  http.get<RequestParams>(\n    'https://api.github.com/users/:username/messages/:messageId',\n    ({ params }) => {\n      const { username, messageId } = params\n\n      return HttpResponse.json({\n        username,\n        messageId,\n      })\n    },\n  ),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/params.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('parses request URL parameters', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./params.mocks.ts', import.meta.url))\n\n  const res = await fetch(\n    'https://api.github.com/users/octocat/messages/abc-123',\n  )\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    username: 'octocat',\n    messageId: 'abc-123',\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/plain-response.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/greeting', () => {\n    return new Response('Hello, world!')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/plain-response.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('returns a plain Response as a mocked response', async ({\n  loadExample,\n  fetch,\n  spyOnConsole,\n}) => {\n  await loadExample(new URL('./plain-response.mocks.ts', import.meta.url))\n  const consoleSpy = spyOnConsole()\n\n  const response = await fetch('/greeting')\n  const status = response.status()\n  const body = await response.text()\n\n  // Must return the correct response.\n  expect(status).toBe(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  expect(body).toEqual('Hello, world!')\n\n  // Must print the correct log message in the console.\n  expect(consoleSpy.get('startGroupCollapsed')).toEqual(\n    expect.arrayContaining([\n      expect.stringMatching(/\\[MSW\\] \\d{2}:\\d{2}:\\d{2} GET \\/greeting 200 OK/),\n    ]),\n  )\n})\n"
  },
  {
    "path": "test/browser/rest-api/query-params-warning.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  // WARNING: Intentionally invalid example of including a query parameter\n  // in the request handler URL. Don't do that, consider matching against a path\n  // and accessing query parameters in the response resolver instead.\n  http.get('/user?name=admin', () => {\n    return HttpResponse.text('user-response')\n  }),\n  http.post('/login?id=123&type=auth', () => {\n    return HttpResponse.text('login-response')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/query-params-warning.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('warns when a request handler URL contains query parameters', async ({\n  loadExample,\n  fetch,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./query-params-warning.mocks.ts', import.meta.url))\n\n  expect(consoleSpy.get('warning')).toEqual([\n    `[MSW] Found a redundant usage of query parameters in the request handler URL for \"GET /user?name=admin\". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`,\n    `[MSW] Found a redundant usage of query parameters in the request handler URL for \"POST /login?id=123&type=auth\". Please match against a path instead and access query parameters using \"new URL(request.url).searchParams\" instead. Learn more: https://mswjs.io/docs/http/intercepting-requests#querysearch-parameters`,\n  ])\n\n  await fetch('/user?name=admin').then(async (res) => {\n    expect(res.status()).toBe(200)\n    expect(await res.text()).toBe('user-response')\n  })\n\n  await fetch('/user').then(async (res) => {\n    expect(res.status()).toBe(200)\n    expect(await res.text()).toBe('user-response')\n  })\n\n  await fetch('/login?id=123&type=auth', {\n    method: 'POST',\n  }).then(async (res) => {\n    expect(res.status()).toBe(200)\n    expect(await res.text()).toBe('login-response')\n  })\n\n  await fetch('/login', {\n    method: 'POST',\n  }).then(async (res) => {\n    expect(res.status()).toBe(200)\n    expect(await res.text()).toBe('login-response')\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/query.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://test.mswjs.io/api/books', ({ request }) => {\n    const url = new URL(request.url)\n    const bookId = url.searchParams.get('id')\n\n    return HttpResponse.json({ bookId })\n  }),\n\n  http.post('https://test.mswjs.io/products', ({ request }) => {\n    const url = new URL(request.url)\n    const productIds = url.searchParams.getAll('id')\n\n    return HttpResponse.json({ productIds })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/query.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\nconst EXAMPLE_PATH = new URL('./query.mocks.ts', import.meta.url)\n\ntest('retrieves a single request URL query parameter', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('https://test.mswjs.io/api/books?id=abc-123')\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    bookId: 'abc-123',\n  })\n})\n\ntest('retrieves multiple request URL query parameters', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('https://test.mswjs.io/products?id=1&id=2&id=3', {\n    method: 'POST',\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    productIds: ['1', '2', '3'],\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/redirect.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/login', () => {\n    return HttpResponse.text(null, {\n      status: 307,\n      headers: {\n        Location: '/user',\n      },\n    })\n  }),\n  http.get('/user', () => {\n    return HttpResponse.json({\n      firstName: 'John',\n      lastName: 'Maverick',\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/redirect.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('supports redirect in a mocked response', async ({\n  loadExample,\n  fetch,\n  makeUrl,\n  page,\n}) => {\n  await loadExample(new URL('./redirect.mocks.ts', import.meta.url))\n\n  const [res, redirectRes] = await Promise.all([\n    await fetch('/login'),\n    await page.waitForResponse(makeUrl('/user')),\n  ])\n  const headers = await res.allHeaders()\n\n  // Assert the original response returns redirect.\n  expect(headers).toHaveProperty('location', '/user')\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(res.status()).toBe(307)\n\n  const redirectStatus = redirectRes.status()\n  const redirectBody = await redirectRes.json()\n\n  // Assert redirect gets requested and mocked.\n  expect(redirectStatus).toBe(200)\n  expect(redirectRes.fromServiceWorker()).toBe(true)\n  expect(redirectBody).toEqual({\n    firstName: 'John',\n    lastName: 'Maverick',\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-arraybuffer-range.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst buffer = new TextEncoder().encode('hello world')\n\nconst worker = setupWorker(\n  http.get('/resource', async ({ request }) => {\n    const range = request.headers.get('range')\n\n    if (!range) {\n      throw new Response('Missing range', { status: 400 })\n    }\n\n    const ranges = range.replace(/bytes=/, '').split('-')\n    const start = +ranges[0]\n    const end = ranges[1] ? +ranges[1] : buffer.byteLength - 1\n    const content = buffer.slice(start, end)\n\n    return HttpResponse.arrayBuffer(content, {\n      status: 206,\n      headers: {\n        'accept-range': 'bytes',\n        'content-range': `bytes=${start}-${end}/${buffer.byteLength}`,\n        'content-length': content.byteLength.toString(),\n        'content-type': 'text/plain',\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-arraybuffer-range.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with a range of a mocked buffer response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(\n    new URL('./body-arraybuffer-range.mocks.ts', import.meta.url),\n  )\n\n  const response = await fetch('/resource', {\n    headers: {\n      range: 'bytes=4-8',\n    },\n  })\n\n  expect.soft(response.status()).toBe(206)\n  await expect.soft(response.text()).resolves.toBe('o wo')\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-arraybuffer.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('reads request body as array buffer', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/json', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n  const body = await res.body()\n\n  expect(res.status()).toBe(200)\n  expect(body).toEqual(Buffer.from(JSON.stringify({ firstName: 'John' })))\n})\n\ntest('reads buffer request body as array buffer', async ({\n  loadExample,\n  fetch,\n  page,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  page.evaluate(() => {\n    return fetch('/json', {\n      method: 'POST',\n      body: new TextEncoder().encode(JSON.stringify({ firstName: 'John' })),\n    })\n  })\n  const res = await page.waitForResponse(makeUrl('/json'))\n  const body = await res.body()\n\n  expect(res.status()).toBe(200)\n  expect(body).toEqual(Buffer.from(JSON.stringify({ firstName: 'John' })))\n})\n\ntest('reads null request body as empty array buffer', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const [body, status] = await page.evaluate(() => {\n    return fetch('/arrayBuffer', {\n      method: 'POST',\n      body: null,\n    }).then((res) =>\n      res\n        .arrayBuffer()\n        .then((body) => [new TextDecoder().decode(body), res.status]),\n    )\n  })\n\n  expect(status).toBe(200)\n  expect(body).toBe('')\n})\n\ntest('reads undefined request body as empty array buffer', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n  const [body, status] = await page.evaluate(() => {\n    return fetch('/arrayBuffer', {\n      method: 'POST',\n      body: undefined,\n    }).then((res) =>\n      res\n        .arrayBuffer()\n        .then((body) => [new TextDecoder().decode(body), res.status]),\n    )\n  })\n\n  expect(status).toBe(200)\n  expect(body).toBe('')\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-form-data.page.html",
    "content": "<!DOCTYPE html>\n<html>\n  <body>\n    <script>\n      window.makeRequest = () => {\n        const data = new FormData()\n        data.set('name', 'Alice')\n        data.set('file', new File(['hello world'], 'file.txt'))\n        data.set(\n          'ids',\n          new Blob([JSON.stringify([1, 2, 3])], {\n            type: 'application/json',\n          }),\n        )\n\n        fetch('/formData', {\n          method: 'POST',\n          body: data,\n        })\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-form-data.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ndeclare global {\n  interface Window {\n    makeRequest(): void\n  }\n}\n\ntest('handles FormData as a request body', async ({\n  loadExample,\n  page,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url), {\n    markup: new URL('./body-form-data.page.html', import.meta.url),\n  })\n\n  await page.evaluate(() => window.makeRequest())\n\n  const res = await page.waitForResponse(makeUrl('/formData'))\n  const status = res.status()\n  const json = await res.json()\n\n  expect(status).toBe(200)\n  expect(json).toEqual({\n    name: 'Alice',\n    file: 'hello world',\n    ids: [1, 2, 3],\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-json.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('reads request body as json', async ({ loadExample, fetch, page }) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/json', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n\n  const json = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(json).toEqual({ firstName: 'John' })\n})\n\ntest('reads a single number as json request body', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/json', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify(123),\n  })\n  const json = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(json).toEqual(123)\n})\n\ntest('reads request body using json() method', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/json', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n  const json = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(json).toEqual({ firstName: 'John' })\n})\n\ntest('reads array buffer request body using json() method', async ({\n  loadExample,\n  fetch,\n  page,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  page.evaluate(() => {\n    return fetch('/json', {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: new TextEncoder().encode(\n        JSON.stringify({\n          firstName: 'John',\n        }),\n      ),\n    })\n  })\n  const res = await page.waitForResponse(makeUrl('/json'))\n  const json = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(json).toEqual({ firstName: 'John' })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body-text.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('reads plain text request body as text', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/text', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'text/plain',\n    },\n    body: 'hello-world',\n  })\n  const body = await res.text()\n\n  expect(res.status()).toBe(200)\n  expect(body).toBe('hello-world')\n})\n\ntest('reads json request body as text', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const res = await fetch('/text', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n  const body = await res.text()\n\n  expect(res.status()).toBe(200)\n  expect(body).toBe(`{\"firstName\":\"John\"}`)\n})\n\ntest('reads buffer request body as text', async ({\n  loadExample,\n  page,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  page.evaluate(() => {\n    return fetch('/text', {\n      method: 'POST',\n      body: new TextEncoder().encode('hello-world'),\n    })\n  })\n  const res = await page.waitForResponse(makeUrl('/text'))\n  const body = await res.text()\n\n  expect(res.status()).toBe(200)\n  expect(body).toBe('hello-world')\n})\n\ntest('reads null request body as empty text', async ({ loadExample, page }) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const [body, status] = await page.evaluate(() => {\n    return fetch('/text', {\n      method: 'POST',\n      body: null,\n    }).then((res) => res.text().then((text) => [text, res.status]))\n  })\n\n  expect(status).toBe(200)\n  expect(body).toBe('')\n})\n\ntest('reads undefined request body as empty text', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./body.mocks.ts', import.meta.url))\n\n  const [body, status] = await page.evaluate(() => {\n    return fetch('/text', {\n      method: 'POST',\n      body: undefined,\n    }).then((res) => res.text().then((text) => [text, res.status]))\n  })\n\n  expect(status).toBe(200)\n  expect(body).toBe('')\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/body/body.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('/text', async ({ request }) => {\n    return HttpResponse.text(await request.text())\n  }),\n  http.post('/json', async ({ request }) => {\n    return HttpResponse.json(await request.json())\n  }),\n  http.post('/arrayBuffer', async ({ request }) => {\n    return HttpResponse.arrayBuffer(await request.arrayBuffer())\n  }),\n  http.post('/formData', async ({ request }) => {\n    const data = await request.formData()\n    const name = data.get('name')\n    const file = data.get('file') as File\n    const fileText = await file.text()\n    const ids = data.get('ids') as File\n    const idsJson = JSON.parse(await ids.text())\n\n    return HttpResponse.json({\n      name,\n      file: fileText,\n      ids: idsJson,\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/all.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.all('*/api/*', () => {\n    return HttpResponse.text('hello world')\n  }),\n  http.all('*', () => {\n    return HttpResponse.text('welcome to the jungle')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/all.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { Response } from '@playwright/test'\nimport { test, expect } from '../../../playwright.extend'\n\nfunction forEachMethod(\n  callback: (method: string) => Promise<Response>,\n): Promise<Response[]> {\n  return Promise.all(\n    ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'].map((method) =>\n      callback(method),\n    ),\n  )\n}\n\ntest('respects custom path when matching requests', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./all.mocks.ts', import.meta.url))\n\n  // Root request.\n  const rootResponses = await forEachMethod((method) => {\n    return fetch('http://localhost/api/', { method })\n  })\n\n  for (const response of rootResponses) {\n    expect(response.status()).toEqual(200)\n    expect(await response.text()).toEqual('hello world')\n  }\n\n  // Nested request.\n  const nestedResponses = await forEachMethod((method) => {\n    return fetch('http://localhost/api/user', { method })\n  })\n\n  for (const response of nestedResponses) {\n    expect(response.status()).toBe(200)\n    expect(await response.text()).toBe('hello world')\n  }\n\n  // Mismatched request.\n  // There's a fallback \"http.all()\" in this test that acts\n  // as a fallback request handler for all otherwise mismatched requests.\n  const mismatchedResponses = await forEachMethod((method) => {\n    return fetch('http://localhost/foo', { method })\n  })\n\n  for (const response of mismatchedResponses) {\n    expect(response.status()).toEqual(200)\n    expect(await response.text()).toEqual('welcome to the jungle')\n  }\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/custom-predicate.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker()\nworker.start()\n\nwindow.msw = {\n  // @ts-expect-error\n  worker,\n  http,\n}\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/custom-predicate.test.ts",
    "content": "import { http } from 'msw'\nimport { SetupWorkerApi } from 'msw/browser'\nimport { test, expect } from '../../../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    worker: SetupWorkerApi\n    http: typeof http\n  }\n}\n\nconst PREDICATE_EXAMPLE = new URL(\n  './custom-predicate.mocks.ts',\n  import.meta.url,\n)\n\ntest('matches the request when the predicate function returns true', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(PREDICATE_EXAMPLE)\n\n  await page.evaluate(() => {\n    const { worker, http } = window.msw\n\n    worker.use(\n      http.post(\n        async ({ request }) => {\n          const requestBody = await request.clone().text()\n          return requestBody === 'hello world'\n        },\n        ({ request }) => {\n          return new Response(request.clone().body, request)\n        },\n      ),\n    )\n  })\n\n  const response = await fetch('/irrelevant', {\n    method: 'POST',\n    body: 'hello world',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.text()).resolves.toBe('hello world')\n})\n\ntest('does not match the request when the predicate function returns false', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(PREDICATE_EXAMPLE)\n\n  await page.evaluate(() => {\n    const { worker, http } = window.msw\n\n    worker.use(\n      http.post(\n        async ({ request }) => {\n          const requestBody = await request.clone().text()\n          return requestBody === 'hello world'\n        },\n        ({ request }) => {\n          return new Response(request.clone().body, request)\n        },\n      ),\n    )\n  })\n\n  const response = await fetch('/irrelevant', {\n    method: 'POST',\n    body: 'non-matching-request',\n  })\n\n  expect(response.status()).toBe(404)\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/method.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('*/user', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/method.test.ts",
    "content": "import { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../../../playwright.extend'\n\nconst server = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.json({ uses: 'original' })\n  })\n\n  app.post('/user', (req, res) => {\n    res.status(500).json({ mocked: false })\n  })\n})\n\ntest.beforeEach(async () => {\n  await server.listen()\n})\n\ntest.afterEach(async () => {\n  await server.close()\n})\n\ntest('sends a mocked response to a matching method and url', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./method.mocks.ts', import.meta.url))\n\n  const res = await fetch(server.http.url('/user'), {\n    method: 'POST',\n  })\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n\ntest('sends original response to a non-matching request', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./method.mocks.ts', import.meta.url))\n\n  const res = await fetch(server.http.url('/user'))\n  const status = res.status()\n  const headers = await res.allHeaders()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(headers).toHaveProperty('x-powered-by', 'Express')\n  expect(body).toEqual({ uses: 'original' })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/path-params-decode.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://test.mswjs.io/reflect-url/:url', ({ params }) => {\n    const { url } = params\n    return HttpResponse.json({ url })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/path-params-decode.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('decodes url componets', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./path-params-decode.mocks.ts', import.meta.url))\n\n  const url = 'http://example.com:5001/example'\n  const res = await fetch(\n    `https://test.mswjs.io/reflect-url/${encodeURIComponent(url)}`,\n  )\n\n  expect(res.status()).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(await res.json()).toEqual({\n    url,\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/uri.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://api.github.com/made-up', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n\n  http.get('https://test.mswjs.io/messages/:messageId', ({ params }) => {\n    const { messageId } = params\n    return HttpResponse.json({ messageId })\n  }),\n\n  http.get('https://test.mswjs.io/messages/:messageId/items', ({ params }) => {\n    const { messageId } = params\n    return HttpResponse.json({ messageId })\n  }),\n\n  http.get(/(.+?)\\.google\\.com\\/path/, () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n\n  http.get(`/resource\\\\('id'\\\\)`, () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n\n  http.get('./', ({ request }) => {\n    const url = new URL(request.url)\n\n    if (url.searchParams.has('resourceId')) {\n      return HttpResponse.json({ mocked: true })\n    }\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/matching/uri.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('matches an exact string with the same request URL with a trailing slash', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch('https://api.github.com/made-up/')\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    mocked: true,\n  })\n})\n\ntest('does not match an exact string with a different request URL with a trailing slash', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await page.evaluate(() =>\n    fetch('https://api.github.com/other/'),\n  )\n\n  expect(response.status).not.toBe(200)\n})\n\ntest('matches an exact string with the same request URL without a trailing slash', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch('https://api.github.com/made-up')\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    mocked: true,\n  })\n})\n\ntest('does not match an exact string with a different request URL without a trailing slash', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await page.evaluate(() =>\n    fetch('https://api.github.com/other'),\n  )\n\n  expect(response.status).not.toBe(200)\n})\n\ntest('matches a mask against a matching request URL', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch('https://test.mswjs.io/messages/abc-123')\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    messageId: 'abc-123',\n  })\n})\n\ntest('ignores query parameters when matching a mask against a matching request URL', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch(\n    'https://test.mswjs.io/messages/abc-123/items?hello=true',\n  )\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    messageId: 'abc-123',\n  })\n})\n\ntest('does not match a mask against a non-matching request URL', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await page.evaluate(() =>\n    fetch('https://test.mswjs.io/users/def-456').catch(() => null),\n  )\n\n  expect(response).toBeNull()\n})\n\ntest('matches a RegExp against a matching request URL', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch('https://mswjs.google.com/path')\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    mocked: true,\n  })\n})\n\ntest('does not match a RegExp against a non-matching request URL', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await page.evaluate(() =>\n    fetch('https://mswjs.google.com/other').catch(() => null),\n  )\n\n  expect(response).toBeNull()\n})\n\ntest('supports escaped parentheses in the request URL', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch(`/resource('id')`)\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    mocked: true,\n  })\n})\n\ntest('matches a relative URL starting with search parameters', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./uri.mocks.ts', import.meta.url))\n\n  const response = await fetch('?resourceId=abc-123')\n\n  expect(response.status()).toEqual(200)\n  expect(response.fromServiceWorker()).toBe(true)\n  await expect(response.json()).resolves.toEqual({\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/request/request-cookies.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/cookies', ({ cookies }) => {\n    return HttpResponse.json(cookies)\n  }),\n  http.post('/set-cookies', async ({ request }) => {\n    return new HttpResponse(null, {\n      headers: {\n        'Set-Cookie': await request.clone().text(),\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/request/request-cookies.test.ts",
    "content": "import type { Page } from '@playwright/test'\nimport { test, expect } from '../../playwright.extend'\n\nasync function bakeCookies(page: Page, cookies: Array<string>) {\n  await page.evaluate((cookies) => {\n    cookies.forEach((cookie) => {\n      document.cookie = cookie\n    })\n  }, cookies)\n}\n\ntest('returns empty object if document has no cookies', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  const response = await fetch('/cookies')\n  const documentCookies = await page.evaluate(() => document.cookie)\n\n  expect(response.status()).toBe(200)\n  await expect(response.json()).resolves.toEqual({})\n  expect(documentCookies).toBe('')\n})\n\ntest('returns empty object for request with \"credentials: omit\"', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n  const response = await fetch('/cookies', { credentials: 'omit' })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({})\n})\n\ntest('returns empty object for cross-origin request with \"credentials: same-origin\"', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n  const response = await fetch('https://example.com/cookies', {\n    credentials: 'same-origin',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({})\n})\n\ntest('returns cookies for same-origin request with \"credentials: same-origin\"', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n  const response = await fetch('/cookies', {\n    credentials: 'same-origin',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    documentCookie: 'value',\n  })\n})\n\ntest('returns cookies for same-origin request with \"credentials: include\"', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['firstCookie=value', 'secondCookie=anotherValue'])\n  const response = await fetch('/cookies', {\n    credentials: 'include',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    firstCookie: 'value',\n    secondCookie: 'anotherValue',\n  })\n})\n\ntest('returns cookies for cross-origin request with \"credentials: include\"', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n  const response = await fetch('https://example.com/cookies', {\n    credentials: 'include',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    documentCookie: 'value',\n  })\n})\n\ntest('inherits mocked cookies', async ({ loadExample, fetch, page }) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n\n  // Make a request that sends mocked cookies.\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: 'mockedCookie=mockedValue',\n  })\n  const response = await fetch('/cookies', {\n    credentials: 'include',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    documentCookie: 'value',\n    mockedCookie: 'mockedValue',\n  })\n})\n\ntest('inherits mocked cookies after page reload', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: 'mockedCookie=mockedValue',\n  })\n  // Reload the page to ensure that the mocked cookies persist.\n  await page.reload({ waitUntil: 'networkidle' })\n\n  const response = await fetch('/cookies', {\n    credentials: 'include',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    documentCookie: 'value',\n    mockedCookie: 'mockedValue',\n  })\n})\n\ntest('inherits mocked \"HttpOnly\" cookies', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n  await bakeCookies(page, ['documentCookie=value'])\n\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: 'mockedCookie=mockedValue; HttpOnly',\n  })\n  await page.reload({ waitUntil: 'networkidle' })\n\n  const response = await fetch('/cookies', {\n    credentials: 'include',\n  })\n\n  expect.soft(response.status()).toBe(200)\n  await expect.soft(response.json()).resolves.toEqual({\n    documentCookie: 'value',\n    mockedCookie: 'mockedValue',\n  })\n})\n\ntest('respects cookie \"Path\" when exposing cookies', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n\n  /**\n   * @note I tried including the `document.cookie` with\n   * a specific `Path` but it behaves differently. It doesn't\n   * even expose the cookie unless the PAGE path matches the\n   * cookie path (reproducible in the browser).\n   */\n\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: `mockedCookie=mockedValue; Path=/dashboard`,\n  })\n\n  const nonMatchingResponse = await fetch('/cookies')\n  // Must not return cookies for the request under a different path.\n  await expect(nonMatchingResponse.json()).resolves.toEqual({})\n\n  // Must return the mocked cookie for a request with a matching path.\n  const matchingResponse = await fetch('/dashboard/cookies')\n  await expect(matchingResponse.json()).resolves.toEqual({\n    mockedCookie: 'mockedValue',\n  })\n})\n\ntest('deletes a cookie when sending \"max-age=0\" in a mocked response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./request-cookies.mocks.ts', import.meta.url))\n\n  // First, set the cookie.\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: `mockedCookie=mockedValue`,\n  })\n\n  // Must forward the mocked cookied to the matching request.\n  await expect(fetch('/cookies').then((res) => res.json())).resolves.toEqual({\n    mockedCookie: 'mockedValue',\n  })\n\n  // Next, delete the cookie by setting \"max-age=0\".\n  await fetch('/set-cookies', {\n    method: 'POST',\n    body: `mockedCookie=mockedValue; max-age=0`,\n  })\n\n  // Must NOT have any cookies on the matching request.\n  await expect(\n    fetch('/cookies').then((response) => response.json()),\n  ).resolves.toEqual({})\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-binary.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport base64Image from 'url-loader!../../../../fixtures/image.jpg'\n\nconst worker = setupWorker(\n  http.get('/images/:imageId', async () => {\n    const imageBuffer = await fetch(base64Image).then((res) =>\n      res.arrayBuffer(),\n    )\n\n    return HttpResponse.arrayBuffer(imageBuffer, {\n      headers: {\n        'Content-Type': 'image/jpeg',\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-binary.test.ts",
    "content": "import fs from 'node:fs'\nimport { test, expect } from '../../../playwright.extend'\n\ntest('responds with a given binary body', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-binary.mocks.ts', import.meta.url))\n\n  const res = await fetch('/images/abc-123')\n  const status = res.status()\n  const body = await res.body()\n\n  const expectedBuffer = fs.readFileSync(\n    new URL('../../../../fixtures/image.jpg', import.meta.url),\n  )\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(new Uint8Array(body)).toEqual(new Uint8Array(expectedBuffer))\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-blob.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/greeting', async () => {\n    const blob = new Blob(['hello world'], {\n      type: 'text/plain',\n    })\n\n    return new HttpResponse(blob)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-blob.test.ts",
    "content": "import { test, expect } from '../.././../playwright.extend'\n\ntest('responds to a request with a Blob', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-blob.mocks.ts', import.meta.url))\n  const res = await fetch('/greeting')\n\n  const headers = await res.allHeaders()\n  expect(headers).toHaveProperty('content-type', 'text/plain')\n  expect(res.fromServiceWorker()).toBe(true)\n\n  const text = await res.text()\n  expect(text).toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-formdata.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', async () => {\n    const data = new FormData()\n    data.append('name', 'Alice')\n    data.append('age', '32')\n\n    return HttpResponse.formData(data)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-formdata.test.ts",
    "content": "import { test, expect } from '../.././../playwright.extend'\n\ntest('responds to a request with FormData', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-formdata.mocks.ts', import.meta.url))\n  const res = await fetch('/user')\n\n  const headers = await res.allHeaders()\n  expect(headers).toHaveProperty(\n    'content-type',\n    expect.stringContaining('multipart/form-data'),\n  )\n  expect(res.fromServiceWorker()).toBe(true)\n\n  const text = await res.text()\n  expect(text).toMatch(\n    /------WebKitFormBoundary.+?\\r\\nContent-Disposition: form-data; name=\"name\"\\r\\n\\r\\nAlice\\r\\n------WebKitFormBoundary.+?\\r\\nContent-Disposition: form-data; name=\"age\"\\r\\n\\r\\n32\\r\\n------WebKitFormBoundary.+?--/gm,\n  )\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-html.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.html(`\n<p class=\"user\" id=\"abc-123\">\n  Jane Doe\n</p>`)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-html.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with an HTML response body', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-html.mocks.ts', import.meta.url))\n\n  const res = await fetch('/user')\n  const status = res.status()\n  const headers = await res.allHeaders()\n  const text = await res.text()\n\n  expect(status).toBe(200)\n  expect(headers['content-type']).toBe('text/html')\n  expect(text).toEqual(`\n<p class=\"user\" id=\"abc-123\">\n  Jane Doe\n</p>`)\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-json.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/json', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n  http.get('/number', () => {\n    return HttpResponse.json(123)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-json.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with a JSON response body', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-json.mocks.ts', import.meta.url))\n\n  const res = await fetch('/json')\n  const headers = await res.allHeaders()\n  const json = await res.json()\n\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(json).toEqual({ firstName: 'John' })\n})\n\ntest('responds with a single number JSON response body', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./body-json.mocks.ts', import.meta.url))\n\n  const res = await fetch('/number')\n  const headers = await res.allHeaders()\n  const json = await res.json()\n\n  expect(headers).toHaveProperty('content-type', 'application/json')\n  expect(json).toEqual(123)\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-stream.mocks.ts",
    "content": "import { http, HttpResponse, delay } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst encoder = new TextEncoder()\nconst chunks = ['hello', 'streaming', 'world']\n\nconst worker = setupWorker(\n  http.get('/stream', () => {\n    const stream = new ReadableStream({\n      async start(controller) {\n        for (const chunk of chunks) {\n          controller.enqueue(encoder.encode(chunk))\n          await delay(250)\n        }\n\n        controller.close()\n      },\n    })\n\n    return new HttpResponse(stream, {\n      headers: {\n        'Content-Type': 'application/octet-stream',\n        'Content-Length': chunks.join('').length.toString(),\n      },\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-stream.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with a mocked ReadableStream response', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./body-stream.mocks.ts', import.meta.url))\n\n  const chunks = await page.evaluate(() => {\n    return fetch('/stream').then(async (res) => {\n      if (res.body === null) {\n        return []\n      }\n\n      const decoder = new TextDecoder()\n      const chunks: Array<{ text: string; timestamp: number }> = []\n      const reader = res.body.getReader()\n\n      while (true) {\n        const { value, done } = await reader.read()\n\n        if (done) {\n          return chunks\n        }\n\n        chunks.push({\n          text: decoder.decode(value),\n          timestamp: performance.now(),\n        })\n      }\n    })\n  })\n\n  // Must stream the mocked response in three chunks.\n  const chunksText = chunks.map((chunk) => chunk.text)\n  expect(chunksText).toEqual(['hello', 'streaming', 'world'])\n\n  const chunkDeltas = chunks.map((chunk, index) => {\n    const prevChunk = chunks[index - 1]\n    return prevChunk ? chunk.timestamp - prevChunk.timestamp : 0\n  })\n\n  expect(chunkDeltas[0]).toBe(0)\n  expect(chunkDeltas[1]).toBeGreaterThanOrEqual(200)\n  expect(chunkDeltas[2]).toBeGreaterThanOrEqual(200)\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-text.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/text', () => {\n    return HttpResponse.text('hello world')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-text.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with a text response body', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-text.mocks.ts', import.meta.url))\n\n  const res = await fetch('/text')\n  const headers = await res.allHeaders()\n  const text = await res.text()\n\n  expect(headers).toHaveProperty('content-type', 'text/plain')\n  expect(text).toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-xml.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/user', () => {\n    return HttpResponse.xml(`\n<user>\n  <id>abc-123</id>\n  <firstName>John</firstName>\n  <lastName>Maverick</lastName>\n</user>`)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/body/body-xml.test.ts",
    "content": "import { test, expect } from '../../../playwright.extend'\n\ntest('responds with an XML response body', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./body-xml.mocks.ts', import.meta.url))\n\n  const res = await fetch('/user')\n  const status = res.status()\n  const headers = await res.allHeaders()\n  const text = await res.text()\n\n  expect(status).toBe(200)\n  expect(headers['content-type']).toBe('text/xml')\n  expect(text).toEqual(`\n<user>\n  <id>abc-123</id>\n  <firstName>John</firstName>\n  <lastName>Maverick</lastName>\n</user>`)\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/response-cookies.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/single-cookie', () => {\n    return new HttpResponse(null, {\n      headers: {\n        'Set-Cookie': 'myCookie=value',\n      },\n    })\n  }),\n  http.get('/multiple-cookies', () => {\n    return new HttpResponse(null, {\n      headers: [\n        ['Set-Cookie', 'firstCookie=yes'],\n        ['Set-Cookie', 'secondCookie=no; Max-Age=1000'],\n        ['Set-Cookie', 'thirdCookie=1,2,3'],\n      ],\n    })\n  }),\n  http.get('/cookies-via-headers', () => {\n    const headers = new Headers({\n      'Set-Cookie': 'myCookie=value',\n    })\n\n    return new HttpResponse(null, { headers })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/response-cookies.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('supports mocking a single response cookie', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./response-cookies.mocks.ts', import.meta.url))\n  const response = await fetch('/single-cookie')\n  const documentCookies = await page.evaluate(() => document.cookie)\n\n  expect(response.status()).toBe(200)\n  // Must not expose the forbidden \"Set-Cookie\" header.\n  expect(await response.allHeaders()).not.toHaveProperty('set-cookie')\n  // Must set the mocked cookie onto the document.\n  expect(documentCookies).toBe('myCookie=value')\n})\n\ntest('supports mocking multiple response cookies', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./response-cookies.mocks.ts', import.meta.url))\n  const response = await fetch('/multiple-cookies')\n  const documentCookies = await page.evaluate(() => document.cookie)\n\n  expect(response.status()).toBe(200)\n  expect(await response.allHeaders()).not.toHaveProperty('set-cookie')\n  /**\n   * @note The `Max-Age` attribute is not propagated onto the document.\n   * If that's unexpected, raise an issue.\n   */\n  expect(documentCookies).toBe(\n    'firstCookie=yes; secondCookie=no; thirdCookie=1,2,3',\n  )\n})\n\ntest('supports mocking cookies via a standalone Headers instance', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./response-cookies.mocks.ts', import.meta.url))\n  const response = await fetch('/cookies-via-headers')\n  const documentCookies = await page.evaluate(() => document.cookie)\n\n  expect(response.status()).toBe(200)\n  expect(await response.allHeaders()).not.toHaveProperty('set-cookie')\n  expect(documentCookies).toBe('myCookie=value')\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/response-error.mocks.ts",
    "content": "import { http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/resource', () => {\n    return Response.error()\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/response-error.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('responds with a network error using \"Response.error\" shorthand', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./response-error.mocks.ts', import.meta.url))\n\n  const networkError = await page.evaluate(() => {\n    return fetch('/resource')\n      .then(() => null)\n      .catch((error) => ({\n        name: error.name,\n        message: error.message,\n        stack: error.stack,\n        cause: error.cause,\n      }))\n  })\n\n  // Responding with a \"Response.error()\" produced a \"Failed to fetch\" error,\n  // breaking the request. This is analogous to a network error.\n  expect(networkError?.name).toBe('TypeError')\n  expect(networkError?.message).toBe('Failed to fetch')\n  // Guard against false positives due to exceptions arising from the library.\n  expect(networkError?.cause).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/rest-api/response/throw-response.mocks.ts",
    "content": "import { HttpResponse, http } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/throw/plain', () => {\n    throw new Response('hello world')\n  }),\n  http.get('/throw/http-response', () => {\n    throw HttpResponse.text('hello world')\n  }),\n  http.get('/throw/error', () => {\n    throw HttpResponse.text('invalid input', { status: 400 })\n  }),\n  http.get('/throw/network-error', () => {\n    throw HttpResponse.error()\n  }),\n  http.get('/middleware', ({ request }) => {\n    const url = new URL(request.url)\n\n    if (!url.searchParams.has('id')) {\n      throw HttpResponse.text('must have id', { status: 400 })\n    }\n\n    return HttpResponse.text('ok')\n  }),\n  http.get('/throw/non-response-error', () => {\n    throw new Error('Oops!')\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response/throw-response.test.ts",
    "content": "import { test, expect } from '../../playwright.extend'\n\ntest('supports throwing a plain Response in a response resolver', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  const response = await fetch('/throw/plain')\n  expect(response.status()).toBe(200)\n  expect(await response.text()).toBe('hello world')\n})\n\ntest('supports throwing an HttpResponse in a response resolver', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  const response = await fetch('/throw/http-response')\n  expect(response.status()).toBe(200)\n  expect(await response.headerValue('Content-Type')).toBe('text/plain')\n  expect(await response.text()).toBe('hello world')\n})\n\ntest('supports throwing an error response in a response resolver', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  const errorResponse = await fetch('/throw/error')\n  expect(errorResponse.status()).toBe(400)\n  expect(await errorResponse.headerValue('Content-Type')).toBe('text/plain')\n  expect(await errorResponse.text()).toBe('invalid input')\n})\n\ntest('supports throwing a network error in a response resolver', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  const networkError = await page.evaluate(() => {\n    return fetch('/throw/network-error')\n      .then(() => null)\n      .catch((error) => ({\n        name: error.name,\n        message: error.message,\n        stack: error.stack,\n        cause: error.cause,\n      }))\n  })\n\n  expect(networkError?.name).toBe('TypeError')\n  expect(networkError?.message).toBe('Failed to fetch')\n  expect(networkError?.cause).toBeUndefined()\n})\n\ntest('supports middleware-style responses', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  const response = await fetch('/middleware?id=1')\n  expect(response.status()).toBe(200)\n  expect(await response.text()).toBe('ok')\n\n  const errorResponse = await fetch('/middleware')\n  expect(errorResponse.status()).toBe(400)\n  expect(await errorResponse.text()).toBe('must have id')\n})\n\ntest('throws a non-Response error as-is', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./throw-response.mocks.ts', import.meta.url))\n\n  // Unhandled exceptions in the response resolver in the browser\n  // are coerces to 500 Internal Server Error responses by MSW.\n  const networkError = await fetch('/throw/non-response-error')\n\n  expect(networkError.status()).toBe(500)\n  expect(await networkError.json()).toEqual({\n    name: 'Error',\n    message: 'Oops!',\n    stack: expect.any(String),\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/response-patching.mocks.ts",
    "content": "import { http, HttpResponse, bypass } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('*/user', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request.url))\n    const body = await originalResponse.json()\n\n    return HttpResponse.json(\n      {\n        name: body.name,\n        location: body.location,\n        mocked: true,\n      },\n      {\n        headers: {\n          'X-Source': 'msw',\n        },\n      },\n    )\n  }),\n\n  http.get('*/repos/:owner/:repoName', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n    const body = await originalResponse.json()\n\n    return HttpResponse.json(\n      {\n        name: body.name,\n        stargazers_count: 9999,\n      },\n      {\n        headers: {\n          'X-Source': 'msw',\n        },\n      },\n    )\n  }),\n\n  http.get('*/headers', async ({ request }) => {\n    const proxyUrl = new URL('/headers-proxy', request.url)\n    const originalResponse = await fetch(\n      bypass(proxyUrl, {\n        method: 'POST',\n        headers: request.headers,\n      }),\n    )\n    const body = await originalResponse.json()\n\n    return HttpResponse.json(body, {\n      headers: {\n        'X-Source': 'msw',\n      },\n    })\n  }),\n\n  http.post('*/posts', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n    const body = await originalResponse.json()\n\n    return HttpResponse.json(\n      {\n        ...body,\n        mocked: true,\n      },\n      {\n        headers: {\n          'X-Source': 'msw',\n          'X-Custom': originalResponse.headers.get('x-custom') || '',\n        },\n      },\n    )\n  }),\n\n  http.get('*/posts', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n    const body = await originalResponse.json()\n\n    return HttpResponse.json(\n      {\n        ...body,\n        mocked: true,\n      },\n      {\n        headers: {\n          'X-Source': 'msw',\n        },\n      },\n    )\n  }),\n\n  http.head('*/posts', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n\n    return HttpResponse.json(\n      {\n        mocked: true,\n      },\n      {\n        headers: {\n          'X-Source': 'msw',\n          'X-Custom': originalResponse.headers.get('x-custom') || '',\n        },\n      },\n    )\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/response-patching.test.ts",
    "content": "import { matchRequestUrl } from 'msw'\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '../playwright.extend'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.status(200).json({\n      name: 'The Octocat',\n      location: 'San Francisco',\n    })\n  })\n\n  app.get('/repos/:owner/:name', (req, res) => {\n    res.status(200).json({ name: req.params.name })\n  })\n\n  app.post('/headers-proxy', (req, res) => {\n    if (!req.headers.authorization) {\n      return res.status(403).json({ message: 'error' })\n    }\n\n    return res.status(200).json({ message: 'success' })\n  })\n\n  app.head('/posts', (req, res) => {\n    res\n      .status(200)\n      .set({\n        'Access-Control-Expose-Headers': 'X-Custom',\n        'X-Custom': 'HEAD REQUEST PATCHED',\n      })\n      .end()\n  })\n\n  app.get('/posts', (req, res) => {\n    res.status(200).json({ id: 101 })\n  })\n\n  app.post('/posts', (req, res) => {\n    res\n      .status(200)\n      .set({\n        'Access-Control-Expose-Headers': 'X-Custom',\n        'X-Custom': 'POST REQUEST PATCHED',\n      })\n      .json({ id: 101 })\n  })\n})\n\ntest.beforeEach(async () => {\n  await httpServer.listen()\n})\n\ntest.afterEach(async () => {\n  await httpServer.close()\n})\n\ntest('responds with a combination of the mocked and original responses', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const res = await fetch(httpServer.http.url('/user'))\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    name: 'The Octocat',\n    location: 'San Francisco',\n    mocked: true,\n  })\n})\n\ntest('bypasses the original request when it equals the mocked request', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const res = await fetch(\n    httpServer.http.url('/repos/mswjs/msw?mocked=true'),\n    undefined,\n    {\n      waitForResponse(res) {\n        return (\n          // Await the response from MSW so that the original response\n          // from the same URL would not interfere.\n          matchRequestUrl(new URL(res.request().url()), res.url()).matches &&\n          res.headers()['x-source'] === 'msw'\n        )\n      },\n    },\n  )\n\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({\n    name: 'msw',\n    stargazers_count: 9999,\n  })\n})\n\ntest('forwards custom request headers to the original request', async ({\n  loadExample,\n  fetch,\n  page,\n}) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const requestPromise = fetch(httpServer.http.url('/headers'), {\n    headers: {\n      Authorization: 'token',\n    },\n  })\n  const req = await page.waitForRequest(httpServer.http.url('/headers'))\n  const res = await requestPromise\n\n  expect(req.headers()).toHaveProperty('authorization', 'token')\n  expect(req.headers()).not.toHaveProperty('_headers')\n  expect(req.headers()).not.toHaveProperty('_names')\n\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toEqual(200)\n  expect(body).toEqual({ message: 'success' })\n})\n\ntest('supports patching a HEAD request', async ({ loadExample, fetch }) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const res = await fetch(\n    httpServer.http.url('/posts'),\n    {\n      method: 'HEAD',\n    },\n    {\n      waitForResponse(res) {\n        const headers = res.headers()\n\n        return (\n          headers['x-source'] === 'msw' && headers['x-msw-bypass'] !== 'true'\n        )\n      },\n    },\n  )\n\n  const status = res.status()\n  const headers = res.headers()\n\n  expect(status).toBe(200)\n  expect(headers).toEqual(\n    expect.objectContaining({\n      'x-source': 'msw',\n      'x-custom': 'HEAD REQUEST PATCHED',\n    }),\n  )\n})\n\ntest('supports patching a GET request', async ({\n  loadExample,\n  fetch,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const res = await fetch(\n    httpServer.http.url('/posts'),\n    {\n      method: 'GET',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n    },\n    {\n      waitForResponse(res) {\n        return (\n          matchRequestUrl(new URL(makeUrl(res.request().url())), res.url())\n            .matches && res.headers()['x-source'] === 'msw'\n        )\n      },\n    },\n  )\n  const status = res.status()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(body).toEqual({ id: 101, mocked: true })\n})\n\ntest('supports patching a POST request', async ({\n  loadExample,\n  fetch,\n  makeUrl,\n}) => {\n  await loadExample(new URL('./response-patching.mocks.ts', import.meta.url))\n\n  const res = await fetch(\n    httpServer.http.url('/posts'),\n    {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        title: 'foo',\n        body: 'bar',\n        userId: 1,\n      }),\n    },\n    {\n      waitForResponse(res) {\n        return (\n          matchRequestUrl(new URL(makeUrl(res.request().url())), res.url())\n            .matches && res.headers()['x-source'] === 'msw'\n        )\n      },\n    },\n  )\n  const status = res.status()\n  const headers = res.headers()\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(res.fromServiceWorker()).toBe(true)\n  expect(headers).toHaveProperty('x-custom', 'POST REQUEST PATCHED')\n  expect(body).toEqual({\n    id: 101,\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/rest-api/send-beacon.mocks.ts",
    "content": "import { http, bypass } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('/analytics', ({ request }) => {\n    return new Response(request.body)\n  }),\n  http.post('*/analytics-bypass', ({ request }) => {\n    const nextRequest = bypass(request)\n    return fetch(nextRequest)\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/send-beacon.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('supports mocking a response to a \"sendBeacon\" request', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./send-beacon.mocks.ts', import.meta.url))\n\n  const isQueuedPromise = page.evaluate(() => {\n    return navigator.sendBeacon(\n      '/analytics',\n      JSON.stringify({ event: 'pageview' }),\n    )\n  })\n\n  const response = await page.waitForResponse((response) => {\n    return response.url().endsWith('/analytics')\n  })\n\n  expect(response.status()).toBe(200)\n  // Technically, \"sendBeacon\" responses don't send any body back.\n  // We use this body only to verify that the request body was accessible\n  // in the request handlers.\n  await expect(response.text()).resolves.toBe('{\"event\":\"pageview\"}')\n\n  // Must return true, indicating that the server has queued the sent data.\n  await expect(isQueuedPromise).resolves.toBe(true)\n})\n\ntest('supports bypassing \"sendBeacon\" requests', async ({\n  loadExample,\n  page,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./send-beacon.mocks.ts', import.meta.url),\n    {\n      beforeNavigation(compilation) {\n        compilation.use((router) => {\n          router.post('/analytics-bypass', (_req, res) => {\n            res.status(200).end()\n          })\n        })\n      },\n    },\n  )\n\n  const url = new URL('./analytics-bypass', compilation.previewUrl).href\n  const isQueuedPromise = page.evaluate((url) => {\n    return navigator.sendBeacon(url, JSON.stringify({ event: 'pageview' }))\n  }, url)\n\n  const response = await page.waitForResponse(url)\n  expect(response.status()).toBe(200)\n\n  await expect(isQueuedPromise).resolves.toBe(true)\n})\n"
  },
  {
    "path": "test/browser/rest-api/status.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('/posts', () => {\n    // Setting response status code without status text\n    // implicitly sets the correct status text.\n    return HttpResponse.text(null, { status: 403 })\n  }),\n  http.get('/user', () => {\n    // Response status text can be overridden\n    // to an arbitrary string value.\n    return HttpResponse.text(null, {\n      status: 401,\n      statusText: 'Custom text',\n    })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/status.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\nconst EXAMPLE_PATH = new URL('./status.mocks.ts', import.meta.url)\n\ntest('sets given status code on the mocked response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/posts')\n  const status = res.status()\n  const statusText = res.statusText()\n\n  expect(status).toBe(403)\n  expect(statusText).toBe('Forbidden')\n})\n\ntest('supports custom status text on the mocked response', async ({\n  loadExample,\n  fetch,\n}) => {\n  await loadExample(EXAMPLE_PATH)\n\n  const res = await fetch('/user')\n  const status = res.status()\n  const statusText = res.statusText()\n\n  expect(status).toBe(401)\n  expect(statusText).toBe('Custom text')\n})\n"
  },
  {
    "path": "test/browser/rest-api/xhr.mocks.ts",
    "content": "import { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.get('https://api.github.com/users/octocat', () => {\n    return HttpResponse.json({ mocked: true })\n  }),\n)\n\nworker.start()\n"
  },
  {
    "path": "test/browser/rest-api/xhr.test.ts",
    "content": "import { test, expect } from '../playwright.extend'\n\ntest('mocks a response to an XMLHttpRequest', async ({ loadExample, page }) => {\n  await loadExample(new URL('./xhr.mocks.ts', import.meta.url))\n\n  const REQUEST_URL = 'https://api.github.com/users/octocat'\n\n  page.evaluate((url) => {\n    const req = new XMLHttpRequest()\n    req.open('GET', url)\n    req.send()\n  }, REQUEST_URL)\n\n  const res = await page.waitForResponse(REQUEST_URL)\n  const body = await res.json()\n\n  expect(res.status()).toBe(200)\n  expect(body).toEqual({\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/browser/setup/webpackHttpServer.ts",
    "content": "import fs from 'node:fs'\nimport { WebpackHttpServer } from 'webpack-http-server'\n// @ts-expect-error Importing a JavaScript module.\nimport { SERVICE_WORKER_BUILD_PATH } from '../../../config/constants.js'\n\ndeclare global {\n  var webpackServerPromise: Promise<WebpackHttpServer> | null\n}\n\nglobalThis.webpackServerPromise = null\n\nexport async function getWebpackServer(): Promise<WebpackHttpServer> {\n  if (globalThis.webpackServerPromise) {\n    return globalThis.webpackServerPromise\n  }\n\n  globalThis.webpackServerPromise = startWebpackServer()\n\n  return globalThis.webpackServerPromise\n}\n\nasync function startWebpackServer(): Promise<WebpackHttpServer> {\n  const server = new WebpackHttpServer({\n    before(app) {\n      // Prevent Express from responding with cached 304 responses.\n      app.set('etag', false)\n\n      app.get('/mockServiceWorker.js', (req, res) => {\n        res.set('Content-Type', 'application/javascript; charset=utf8')\n        res.set('Content-Encoding', 'chunked')\n\n        const readable = fs.createReadStream(SERVICE_WORKER_BUILD_PATH)\n        // Apply the worker script patch to forward console messages\n        // from the worker to all its clients.\n        // readable.push(workerScriptPatch, 'utf8')\n        readable.pipe(res)\n      })\n    },\n    webpackConfig: {\n      module: {\n        rules: [\n          {\n            test: /\\.ts$/,\n            use: [\n              {\n                loader: 'esbuild-loader',\n                options: {\n                  loader: 'ts',\n                  tsconfigRaw: fs.readFileSync(\n                    new URL('../../tsconfig.json', import.meta.url),\n                  ),\n                },\n              },\n            ],\n          },\n        ],\n      },\n      resolve: {\n        alias: {\n          'msw/browser': new URL(\n            '../../../lib/browser/index.mjs',\n            import.meta.url,\n          ).pathname,\n          msw: new URL('../../../lib/core/index.mjs', import.meta.url).pathname,\n        },\n        extensions: ['.ts', '.js', '.mjs', '.cjs'],\n      },\n    },\n  })\n\n  await server.listen()\n\n  return server\n}\n"
  },
  {
    "path": "test/browser/setup/workerConsole.ts",
    "content": "import { format } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport { type Page } from '@playwright/test'\n\ntype WorkerConsoleMessageType =\n  | 'log'\n  | 'info'\n  | 'warn'\n  | 'error'\n  | 'debug'\n  | 'trace'\n  | 'dir'\n  | 'dirxml'\n  | 'table'\n  | 'clear'\n  | 'startGroup'\n  | 'startGroupCollapsed'\n  | 'endGroup'\n  | 'assert'\n  | 'count'\n  | 'countReset'\n  | 'time'\n  | 'timeLog'\n  | 'timeEnd'\n  | 'group'\n  | 'groupCollapsed'\n  | 'groupEnd'\n  | 'profile'\n  | 'profileEnd'\n  | 'timeline'\n  | 'timelineEnd'\n  | 'timeStamp'\n  | 'context'\n  | 'memory'\n\ntype WorkerConsoleEventMap = {\n  [MessageType in WorkerConsoleMessageType]: [message: string]\n}\n\ntype InternalWorkerConsoleMessageData = {\n  type: 'internal/console'\n  payload: {\n    messageType: WorkerConsoleMessageType\n    args: Array<string>\n  }\n}\n\ndeclare global {\n  interface Window {\n    handleIncomingWorkerConsoleMessage: (\n      messageType: WorkerConsoleMessageType,\n      args: Array<string>,\n    ) => void\n  }\n}\n\nexport class WorkerConsole extends Emitter<WorkerConsoleEventMap> {\n  public messages: Map<WorkerConsoleMessageType, Array<string>> = new Map()\n\n  private addMessage(\n    messageType: WorkerConsoleMessageType,\n    message: string,\n  ): void {\n    const messages = this.messages.get(messageType) || []\n    this.messages.set(messageType, messages.concat(message))\n  }\n\n  public async init(page: Page): Promise<void> {\n    // Ensure the worker is activated before establishing the listener.\n    await page.evaluate(() => {\n      if (navigator.serviceWorker.controller) {\n        // Only await the worker if it actually exists.\n        // This prevents the WorkerConsole from throwing\n        // when initialized in the scenarios where MSW is\n        // expected to fail/skip registration. Respectively,\n        // no console message forwarding will be established.\n        return navigator.serviceWorker.ready\n      }\n    })\n\n    await page.exposeFunction(\n      'handleIncomingWorkerConsoleMessage',\n      (messageType: WorkerConsoleMessageType, args: Array<string>) => {\n        const [template, ...positionals] = args\n        const formattedMessage = format(template, ...positionals)\n\n        this.addMessage(messageType, formattedMessage)\n        this.emit(messageType, formattedMessage)\n      },\n    )\n\n    await page.evaluate(() => {\n      navigator.serviceWorker.addEventListener(\n        'message',\n        (event: MessageEvent<InternalWorkerConsoleMessageData>) => {\n          const { data } = event\n\n          if (data.type === 'internal/console') {\n            const { messageType, args } = data.payload\n            window.handleIncomingWorkerConsoleMessage(messageType, args)\n          }\n        },\n      )\n    })\n  }\n\n  public removeAllListeners(...args: Array<any>) {\n    this.messages.clear()\n    return super.removeAllListeners(...args)\n  }\n}\n\n/**\n * @why Service Worker lives in a separate thread and doesn't\n * trigger the Playwright's page console events. No way to access\n * the console events issued in the worker.\n * @see https://github.com/microsoft/playwright/issues/6559\n * @see https://stackoverflow.com/questions/54339039/puppeteer-can-not-listen-service-workers-console\n */\nexport function getWorkerScriptPatch(): string {\n  return `\n// EVERYTHING BELOW THIS LINE HAS BEEN APPENDED\n// TO FORWARD WORKER CONSOLE MESSAGES TO THE CLIENTS.\n\nasync function sendToAll(payload) {\n  const clients = await self.clients.matchAll()\n  for (const client of clients) {\n    client.postMessage(payload)\n  }\n}\n\nfunction interceptConsoleCalls(listener) {\n  globalThis.console = new Proxy(globalThis.console, {\n    get(target, property) {\n      if (property in target) {\n        return (...args) => {\n          listener(property, args)\n          return Reflect.get(target, property)\n        }\n      }\n    },\n  })\n}\n\ninterceptConsoleCalls((messageType, args) => {\n  sendToAll({\n    type: 'internal/console',\n    payload: { messageType, args }\n  })\n})\n  `\n}\n"
  },
  {
    "path": "test/browser/sse-api/sse.client.send.extraneous.test.ts",
    "content": "import { http, sse, type ServerSentEventMessage } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    http: typeof http\n    sse: typeof sse\n  }\n}\n\ntest('supports triggerring events from another handlers', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./sse.mocks.ts', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, http, sse } = window.msw\n    const target = new EventTarget()\n\n    const worker = setupWorker(\n      sse('/stream', ({ client }) => {\n        // Listen to the event target dispatching message events\n        // to trigger server-sent events to the client.\n        target.addEventListener('message', (event) => {\n          if (event instanceof MessageEvent) {\n            client.send(event.data)\n          }\n        })\n      }),\n      http.get('/trigger', () => {\n        // Dispatch a message event onto the event target\n        // to trigger a server-sent event to the client.\n        target.dispatchEvent(\n          new MessageEvent('message', {\n            data: {\n              data: 'hello world',\n            } satisfies ServerSentEventMessage,\n          }),\n        )\n\n        return new Response()\n      }),\n    )\n\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>(async (resolve, reject) => {\n      const source = new EventSource('/stream')\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n      source.addEventListener('error', () => {\n        reject(new Error('EventSource errored'))\n      })\n\n      source.addEventListener('open', async () => {\n        await fetch('/trigger').catch((error) => reject(error))\n      })\n    })\n  })\n\n  expect(message).toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.client.send.multiline.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('sends data with LF newline', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: 'line1\\nline2' })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message).toBe('line1\\nline2')\n})\n\ntest('sends data with double LF (blank line in middle)', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: 'before\\n\\nafter' })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message).toBe('before\\n\\nafter')\n})\n\ntest('sends data with CR newline', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: 'line1\\rline2' })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message, 'Normalizes CR to LF (via EventSource parser)').toBe(\n    'line1\\nline2',\n  )\n})\n\ntest('sends data with CRLF newline', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: 'line1\\r\\nline2' })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message, 'Normalizes CRLF to LF (via EventSource parser)').toBe(\n    'line1\\nline2',\n  )\n})\n\ntest('sends data with mixed line endings', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({\n          // Mix of LF, CR, and CRLF\n          data: 'a\\nb\\rc\\r\\nd',\n        })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message, 'Normalizes line endings to LF').toBe('a\\nb\\nc\\nd')\n})\n\ntest('sends data with multiple consecutive newlines', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({\n          data: 'a\\n\\n\\nb',\n        })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message).toBe('a\\n\\n\\nb')\n})\n\ntest('sends an empty string data', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: '' })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject(new Error('EventSource error'))\n\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  })\n\n  expect(message).toBe('')\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.client.send.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('sends a mock message event', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({\n          data: { username: 'john' },\n        })\n      }),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject()\n\n      source.addEventListener('message', (event) => {\n        resolve(`${event.type}:${event.data}`)\n      })\n    })\n  })\n\n  expect(message).toBe('message:{\"username\":\"john\"}')\n})\n\ntest('sends a mock custom event', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse<{ userconnect: { username: string } }>(\n        'http://localhost/stream',\n        ({ client }) => {\n          client.send({\n            event: 'userconnect',\n            data: { username: 'john' },\n          })\n        },\n      ),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.addEventListener('userconnect', (event) => {\n        resolve(`${event.type}:${event.data}`)\n      })\n      source.onerror = () => reject()\n    })\n  })\n\n  expect(message).toEqual('userconnect:{\"username\":\"john\"}')\n})\n\ntest('sends a mock message event with custom id', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse<{ userconnect: { username: string } }>(\n        'http://localhost/stream',\n        ({ client }) => {\n          client.send({\n            id: 'abc-123',\n            event: 'userconnect',\n            data: { username: 'john' },\n          })\n        },\n      ),\n    )\n    await worker.start()\n  })\n\n  const message = await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.addEventListener('userconnect', (event) => {\n        resolve(`${event.type}:${event.lastEventId}:${event.data}`)\n      })\n      source.onerror = () => reject()\n    })\n  })\n\n  expect(message).toBe('userconnect:abc-123:{\"username\":\"john\"}')\n})\n\ntest('errors the connected source', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream-error', ({ client }) => {\n        queueMicrotask(() => client.error())\n      }),\n    )\n    await worker.start()\n  })\n\n  const readyState = await page.evaluate(() => {\n    return new Promise<number>((resolve) => {\n      const source = new EventSource('http://localhost/stream-error')\n      source.onerror = () => resolve(source.readyState)\n      source.onopen = () => console.log('OPEN?')\n    })\n  })\n\n  // EventSource must be closed.\n  expect(readyState).toBe(2)\n\n  /**\n   * @note That erroring the stream does not throw any errors.\n   */\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.mocks.ts",
    "content": "import { http, sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nwindow.msw = {\n  setupWorker,\n  // @ts-ignore\n  http,\n  sse,\n}\n"
  },
  {
    "path": "test/browser/sse-api/sse.quiet.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('does not log anything if the \"quiet\" option is set to true', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({\n          data: { username: 'john' },\n        })\n      }),\n    )\n    await worker.start({ quiet: true })\n  })\n\n  await page.evaluate(() => {\n    return new Promise<string>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.onerror = () => reject()\n\n      source.addEventListener('message', (event) => {\n        resolve(`${event.type}:${event.data}`)\n      })\n    })\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.retry.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('supports mocking the retry time', async ({ loadExample, page }) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({\n          retry: 2000,\n        })\n\n        // Simulate the connection closure.\n        // This will trigger the client to reconnect.\n        queueMicrotask(() => client.close())\n      }),\n    )\n    await worker.start()\n  })\n\n  const reconnectionTime = await page.evaluate(() => {\n    return new Promise<number>((resolve) => {\n      const source = new EventSource('http://localhost/stream')\n\n      source.onerror = () => {\n        const errorAt = Date.now()\n\n        console.assert(\n          source.readyState === EventSource.CONNECTING,\n          'Expected the connection to be in CONNECTING state but got %d',\n          source.readyState,\n        )\n\n        source.addEventListener('open', () => {\n          const reconnectAt = Date.now()\n          resolve(reconnectAt - errorAt)\n        })\n      }\n    })\n  })\n\n  expect(reconnectionTime).toBeGreaterThanOrEqual(2000)\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.server.connect.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { createTestHttpServer } from '@epic-web/test-server/http'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\nglobalThis.console = new Proxy(globalThis.console, {\n  apply(target, thisArg, argArray) {\n    process.stdout.write('console called!')\n    process.stdout.write(new Error().stack!)\n    return Reflect.apply(target as any, thisArg, argArray)\n  },\n})\n\ntest('makes the actual request when called \"server.connect()\"', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await using server = await createTestHttpServer({\n    defineRoutes(routes) {\n      routes.get('/stream', () => {\n        const stream = new ReadableStream({\n          start(controller) {\n            controller.enqueue(\n              new TextEncoder().encode('data: {\"message\": \"hello\"}\\n\\n'),\n            )\n            controller.close()\n          },\n        })\n\n        return new Response(stream, {\n          headers: {\n            'access-control-allow-origin': '*',\n            'content-type': 'text/event-stream',\n            'cache-control': 'no-cache',\n            connection: 'keep-alive',\n          },\n        })\n      })\n    },\n  })\n  const url = server.http.url('/stream').href\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse(url, ({ server }) => {\n        // Calling \"server.connect()\" establishes the actual connection.\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, url)\n\n  const openPromise = page.evaluate((url) => {\n    return new Promise<void>((resolve, reject) => {\n      const source = new EventSource(url)\n      source.onopen = () => resolve()\n      source.onerror = () => reject(new Error('EventSource connection failed'))\n    })\n  }, url)\n\n  await expect(openPromise).resolves.toBeUndefined()\n})\n\ntest('forwards message event from the server to the client automatically', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await using server = await createTestHttpServer({\n    defineRoutes(routes) {\n      routes.get('/stream', () => {\n        const stream = new ReadableStream({\n          start(controller) {\n            controller.enqueue(\n              new TextEncoder().encode('data: {\"message\": \"hello\"}\\n\\n'),\n            )\n          },\n        })\n\n        return new Response(stream, {\n          headers: {\n            'access-control-allow-origin': '*',\n            'content-type': 'text/event-stream',\n            'cache-control': 'no-cache',\n            connection: 'keep-alive',\n          },\n        })\n      })\n    },\n  })\n  const url = server.http.url('/stream').href\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse(url, ({ server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, url)\n\n  const message = await page.evaluate((url) => {\n    return new Promise<{ message: string }>((resolve, reject) => {\n      const source = new EventSource(url)\n      source.addEventListener('message', (event) => {\n        resolve(JSON.parse(event.data))\n      })\n      source.onerror = () => reject(new Error('EventSource connection failed'))\n    })\n  }, url)\n\n  expect(message).toEqual({ message: 'hello' })\n})\n\ntest('forwards custom event from the server to the client automatically', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await using server = await createTestHttpServer({\n    defineRoutes(routes) {\n      routes.get('/stream', () => {\n        const stream = new ReadableStream({\n          start(controller) {\n            controller.enqueue(\n              new TextEncoder().encode(\n                'event: custom\\ndata: {\"message\": \"hello\"}\\n\\n',\n              ),\n            )\n          },\n        })\n\n        return new Response(stream, {\n          headers: {\n            'access-control-allow-origin': '*',\n            'content-type': 'text/event-stream',\n            'cache-control': 'no-cache',\n            connection: 'keep-alive',\n          },\n        })\n      })\n    },\n  })\n  const url = server.http.url('/stream').href\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse(url, ({ server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, url)\n\n  const message = await page.evaluate((url) => {\n    return new Promise<{ message: string }>((resolve, reject) => {\n      const source = new EventSource(url)\n      source.addEventListener('custom', (event) => {\n        resolve(JSON.parse(event.data))\n      })\n      source.onerror = () => reject(new Error('EventSource connection failed'))\n    })\n  }, url)\n\n  expect(message).toEqual({ message: 'hello' })\n})\n\ntest('forwards error event from the server to the client automatically', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await using server = await createTestHttpServer({\n    defineRoutes(routes) {\n      routes.get('/stream', () => {\n        const stream = new ReadableStream({\n          start(controller) {\n            controller.error()\n          },\n        })\n\n        return new Response(stream, {\n          headers: {\n            'access-control-allow-origin': '*',\n            'content-type': 'text/event-stream',\n            'cache-control': 'no-cache',\n            connection: 'keep-alive',\n          },\n        })\n      })\n    },\n  })\n  const url = server.http.url('/stream').href\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse(url, ({ server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, url)\n\n  const errorPromise = page.evaluate((url) => {\n    return new Promise<void>((resolve, reject) => {\n      const source = new EventSource(url)\n      source.onerror = () => resolve()\n      source.onmessage = () => reject(new Error('Must not receive a message'))\n    })\n  }, url)\n\n  await expect(errorPromise).resolves.toBeUndefined()\n})\n\ntest('forward custom stream errors from the original server to the client automatically', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await using server = await createTestHttpServer({\n    defineRoutes(routes) {\n      routes.get('/stream', () => {\n        const stream = new ReadableStream({\n          start(controller) {\n            controller.error(new Error('Custom stream error'))\n          },\n        })\n\n        return new Response(stream, {\n          headers: {\n            'access-control-allow-origin': '*',\n            'content-type': 'text/event-stream',\n            'cache-control': 'no-cache',\n            connection: 'keep-alive',\n          },\n        })\n      })\n    },\n  })\n  const url = server.http.url('/stream').href\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse(url, ({ server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, url)\n\n  const errorPromise = page.evaluate((url) => {\n    return new Promise<void>((resolve, reject) => {\n      const source = new EventSource(url)\n      source.onerror = () => resolve()\n      source.onmessage = () => {\n        reject(new Error('Must not receive a message'))\n      }\n    })\n  }, url)\n\n  await expect(errorPromise).resolves.toBeUndefined()\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.use.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('supports server-sent event handler overrides', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  const workerRef = await page.evaluateHandle(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ client }) => {\n        client.send({ data: 'happy-path' })\n      }),\n    )\n    await worker.start()\n    return worker\n  })\n\n  await page.evaluate((worker) => {\n    const { sse } = window.msw\n\n    worker.use(\n      // Adding this runtime request handler will make it\n      // take precedence over the happy path handler above.\n      sse('http://localhost/stream', ({ client }) => {\n        // Queue the data for the next tick to rule out\n        // the happy path handler from executing.\n        queueMicrotask(() => {\n          client.send({ data: 'override' })\n        })\n      }),\n    )\n  }, workerRef)\n\n  const message = await page.evaluate(() => {\n    return new Promise((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream')\n      source.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n      source.onerror = reject\n    })\n  })\n\n  expect(message).toBe('override')\n})\n"
  },
  {
    "path": "test/browser/sse-api/sse.with-credentials.test.ts",
    "content": "import { sse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export const msw: {\n    setupWorker: typeof setupWorker\n    sse: typeof sse\n  }\n}\n\nconst EXAMPLE_URL = new URL('./sse.mocks.ts', import.meta.url)\n\ntest('forwards document cookies on the request when \"withCredentials\" is set to true', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(EXAMPLE_URL, {\n    skipActivation: true,\n  })\n\n  await page.evaluate(() => {\n    document.cookie = 'foo=bar'\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, sse } = window.msw\n\n    const worker = setupWorker(\n      sse('http://localhost/stream', ({ cookies }) => {\n        console.log(JSON.stringify({ cookies }))\n      }),\n    )\n    await worker.start()\n  })\n\n  await page.evaluate((url) => {\n    return new Promise<void>((resolve, reject) => {\n      const source = new EventSource('http://localhost/stream', {\n        withCredentials: true,\n      })\n      source.onopen = () => resolve()\n      source.onerror = () => reject(new Error('EventSource connection failed'))\n    })\n  })\n\n  expect(consoleSpy.get('log')).toContain(\n    JSON.stringify({\n      cookies: {\n        foo: 'bar',\n      },\n    }),\n  )\n})\n"
  },
  {
    "path": "test/browser/third-party/axios-upload.browser.test.ts",
    "content": "import type { AxiosResponse } from 'axios'\nimport { test, expect } from '../playwright.extend'\n\ndeclare namespace window {\n  export let upload: () => Promise<\n    AxiosResponse<{ message: string; content: string }>\n  >\n  export let progressEvents: Array<ProgressEvent>\n}\n\ntest('responds with a mocked response to an upload request', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./axios-upload.runtime.js', import.meta.url))\n\n  const uploadResult = await page.evaluate(() => {\n    return window.upload().then((response) => response.data)\n  })\n\n  expect(uploadResult).toEqual({\n    message: 'Successfully uploaded \"doc.txt\"!',\n    content: 'Helloworld',\n  })\n\n  const progressEvents = await page.evaluate(() => {\n    return window.progressEvents\n  })\n\n  expect(progressEvents.length).toBeGreaterThan(0)\n  expect(progressEvents[0]).toMatchObject({\n    bytes: expect.any(Number),\n    loaded: expect.any(Number),\n  })\n})\n"
  },
  {
    "path": "test/browser/third-party/axios-upload.runtime.js",
    "content": "import axios from 'axios'\nimport { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nconst worker = setupWorker(\n  http.post('/upload', async ({ request }) => {\n    const data = await request.formData()\n    const file = data.get('file')\n\n    if (!file) {\n      return new HttpResponse('Missing document upload', { status: 400 })\n    }\n\n    if (!(file instanceof File)) {\n      return new HttpResponse('Uploaded document is not a File', {\n        status: 400,\n      })\n    }\n\n    return HttpResponse.json({\n      message: `Successfully uploaded \"${file.name}\"!`,\n      content: await file.text(),\n    })\n  }),\n)\nworker.start()\n\nconst progressEvents = []\nconst request = axios.create({\n  baseURL: '/',\n  onDownloadProgress(event) {\n    progressEvents.push(event)\n  },\n})\n\nwindow.progressEvents = progressEvents\nwindow.upload = async function () {\n  const formData = new FormData()\n  const file = new Blob(['Hello', 'world'], { type: 'text/plain' })\n  formData.set('file', file, 'doc.txt')\n\n  return request.post('/upload', formData)\n}\n"
  },
  {
    "path": "test/browser/ws-api/ws.apply.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { SetupWorker, setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    worker: SetupWorker\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('does not apply the interceptor until \"worker.start()\" is called', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(() => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://example.com')\n    window.worker = setupWorker(api.addEventListener('connection', () => {}))\n  })\n\n  await expect(\n    page.evaluate(() => {\n      return new WebSocket('wss://example.com').constructor.name\n    }),\n  ).resolves.toBe('WebSocket')\n\n  await page.evaluate(async () => {\n    await window.worker.start()\n  })\n\n  await expect(\n    page.evaluate(() => {\n      return new WebSocket('wss://example.com').constructor.name\n    }),\n  ).resolves.not.toBe('WebSocket')\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.client.send.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport type { Page } from '@playwright/test'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('sends data to a single client on connection', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('wss://example.com')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        // Send a message to the client as soon as it connects.\n        client.send('hello world')\n      }),\n    )\n    await worker.start()\n  })\n\n  const clientMessage = await page.evaluate(async () => {\n    const socket = new WebSocket('wss://example.com')\n    return new Promise<string>((resolve, reject) => {\n      socket.onmessage = (event) => resolve(event.data)\n      socket.onerror = () => reject(new Error('WebSocket error'))\n    }).finally(() => socket.close())\n  })\n\n  expect(clientMessage).toBe('hello world')\n})\n\ntest('sends data to multiple clients on connection', async ({\n  loadExample,\n  browser,\n  page,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./ws.runtime.js', import.meta.url),\n    {\n      skipActivation: true,\n    },\n  )\n\n  async function createSocketAndGetFirstMessage(page: Page) {\n    await page.evaluate(async () => {\n      const { setupWorker, ws } = window.msw\n      const service = ws.link('wss://example.com')\n\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ client }) => {\n          // Send a message to the client as soon as it connects.\n          client.send('hello world')\n        }),\n      )\n      await worker.start()\n    })\n\n    return page.evaluate(async () => {\n      const socket = new WebSocket('wss://example.com')\n      return new Promise<string>((resolve, reject) => {\n        socket.onmessage = (event) => resolve(event.data)\n        socket.onerror = () => reject(new Error('WebSocket error'))\n      }).finally(() => socket.close())\n    })\n  }\n\n  const secondPage = await browser.newPage()\n  await secondPage.goto(compilation.previewUrl)\n\n  const [firstClientMessage, secondClientMessage] = await Promise.all([\n    createSocketAndGetFirstMessage(page),\n    createSocketAndGetFirstMessage(secondPage),\n  ])\n\n  expect(firstClientMessage).toBe('hello world')\n  expect(secondClientMessage).toBe('hello world')\n})\n\ntest('sends data in response to a client message', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('wss://example.com')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (typeof event.data === 'string' && event.data === 'hello') {\n            client.send('hello world')\n          }\n        })\n      }),\n    )\n    await worker.start()\n  })\n\n  const clientMessage = await page.evaluate(async () => {\n    const socket = new WebSocket('wss://example.com')\n    socket.onopen = () => {\n      socket.send('ignore this')\n      socket.send('hello')\n    }\n\n    return new Promise<string>((resolve, reject) => {\n      socket.onmessage = (event) => resolve(event.data)\n      socket.onerror = () => reject(new Error('WebSocket error'))\n    }).finally(() => socket.close())\n  })\n\n  expect(clientMessage).toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.clients.browser.test.ts",
    "content": "import type { WebSocketLink, ws } from 'msw'\nimport type { SetupWorker, setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n    worker: SetupWorker\n    link: WebSocketLink\n    ws: WebSocket\n    messages: string[]\n  }\n}\n\ntest('returns the number of active clients in the same runtime', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://example.com')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    window.link = api\n    await worker.start()\n  })\n\n  // Must return 0 when no clients are present.\n  expect(\n    await page.evaluate(() => {\n      return window.link.clients.size\n    }),\n  ).toBe(0)\n\n  await page.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  // Must return 1 after a single client joined.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 1),\n  ).resolves.toBeTruthy()\n\n  await page.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  // Must return 2 now that another client has joined.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 2),\n  ).resolves.toBeTruthy()\n})\n\ntest('returns the number of active clients across different runtimes', async ({\n  loadExample,\n  context,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./ws.runtime.js', import.meta.url),\n    {\n      skipActivation: true,\n    },\n  )\n\n  const pageOne = await context.newPage()\n  const pageTwo = await context.newPage()\n\n  for (const page of [pageOne, pageTwo]) {\n    await page.goto(compilation.previewUrl)\n    await page.evaluate(async () => {\n      const { setupWorker, ws } = window.msw\n      const api = ws.link('wss://example.com')\n      const worker = setupWorker(api.addEventListener('connection', () => {}))\n      window.link = api\n      await worker.start()\n    })\n  }\n\n  await pageOne.bringToFront()\n  await pageOne.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  await expect(\n    pageOne.waitForFunction(() => window.link.clients.size === 1),\n  ).resolves.toBeTruthy()\n  await expect(\n    pageTwo.waitForFunction(() => window.link.clients.size === 1),\n  ).resolves.toBeTruthy()\n\n  await pageTwo.bringToFront()\n  await pageTwo.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  await expect(\n    pageTwo.waitForFunction(() => window.link.clients.size === 2),\n  ).resolves.toBeTruthy()\n  await expect(\n    pageOne.waitForFunction(() => window.link.clients.size === 2),\n  ).resolves.toBeTruthy()\n})\n\ntest('broadcasts messages across runtimes', async ({\n  loadExample,\n  context,\n  page,\n}) => {\n  const { compilation } = await loadExample(\n    new URL('./ws.runtime.js', import.meta.url),\n    {\n      skipActivation: true,\n    },\n  )\n\n  const pageOne = await context.newPage()\n  const pageTwo = await context.newPage()\n\n  for (const page of [pageOne, pageTwo]) {\n    await page.goto(compilation.previewUrl)\n    await page.evaluate(async () => {\n      const { setupWorker, ws } = window.msw\n      const api = ws.link('wss://example.com')\n\n      // @ts-expect-error\n      window.api = api\n\n      const worker = setupWorker(\n        api.addEventListener('connection', ({ client }) => {\n          client.addEventListener('message', (event) => {\n            api.broadcast(event.data)\n          })\n        }),\n      )\n      await worker.start()\n\n      window.worker = worker\n    })\n\n    await page.evaluate(() => {\n      window.messages = []\n      const ws = new WebSocket('wss://example.com')\n      window.ws = ws\n      ws.onmessage = (event) => {\n        window.messages.push(event.data)\n      }\n    })\n  }\n\n  await pageOne.evaluate(() => {\n    window.ws.send('hi from one')\n  })\n\n  {\n    await pageOne.waitForFunction(() => window.messages.length === 1)\n    await expect(pageOne.evaluate(() => window.messages)).resolves.toEqual([\n      'hi from one',\n    ])\n\n    await pageTwo.waitForFunction(() => window.messages.length === 1)\n    await expect(pageTwo.evaluate(() => window.messages)).resolves.toEqual([\n      'hi from one',\n    ])\n  }\n\n  await pageTwo.evaluate(() => {\n    window.ws.send('hi from two')\n  })\n\n  {\n    await pageTwo.waitForFunction(() => window.messages.length === 2)\n    await expect(pageTwo.evaluate(() => window.messages)).resolves.toEqual([\n      'hi from one',\n      'hi from two',\n    ])\n\n    await pageOne.waitForFunction(() => window.messages.length === 2)\n    await expect(pageOne.evaluate(() => window.messages)).resolves.toEqual([\n      'hi from one',\n      'hi from two',\n    ])\n  }\n})\n\ntest('clears the list of clients when the worker is stopped', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://example.com')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    window.link = api\n    window.worker = worker\n    await worker.start()\n  })\n\n  await expect(page.evaluate(() => window.link.clients.size)).resolves.toBe(0)\n\n  await page.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  // Must return the number of joined clients.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 1),\n  ).resolves.toBeTruthy()\n\n  await page.evaluate(() => {\n    window.worker.stop()\n  })\n\n  // Must purge the local storage on reload.\n  // The worker has been started as a part of the test, not runtime,\n  // so it will start with empty clients.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 0),\n  ).resolves.toBeTruthy()\n})\n\ntest('clears the list of clients when the page is reloaded', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const enableMocking = async () => {\n    await page.evaluate(async () => {\n      const { setupWorker, ws } = window.msw\n      const api = ws.link('wss://example.com')\n      const worker = setupWorker(api.addEventListener('connection', () => {}))\n      window.link = api\n      window.worker = worker\n      await worker.start()\n    })\n  }\n\n  await enableMocking()\n\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 0),\n  ).resolves.toBeTruthy()\n\n  await page.evaluate(async () => {\n    const ws = new WebSocket('wss://example.com')\n    await new Promise((done) => (ws.onopen = done))\n  })\n\n  // Must return the number of joined clients.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 1),\n  ).resolves.toBeTruthy()\n\n  await page.reload()\n  await enableMocking()\n\n  // Must purge the local storage on reload.\n  // The worker has been started as a part of the test, not runtime,\n  // so it will start with empty clients.\n  await expect(\n    page.waitForFunction(() => window.link.clients.size === 0),\n  ).resolves.toBeTruthy()\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.intercept.client.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('does not throw on connecting to a non-existing host', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        queueMicrotask(() => client.close())\n      }),\n    )\n    await worker.start()\n  })\n\n  const clientClosePromise = page.evaluate(() => {\n    const socket = new WebSocket('ws://non-existing-host.com')\n\n    return new Promise<void>((resolve, reject) => {\n      socket.onclose = () => resolve()\n      socket.onerror = () => reject('WebSocket connection errored')\n    })\n  })\n\n  await expect(clientClosePromise).resolves.toBeUndefined()\n})\n\ntest('intercepts outgoing client text message', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const clientMessagePromise = page.evaluate(() => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('wss://example.com')\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ client }) => {\n          client.addEventListener('message', (event) => {\n            if (typeof event.data === 'string') {\n              resolve(event.data)\n            }\n          })\n        }),\n      )\n      await worker.start()\n    })\n  })\n\n  await page.evaluate(() => {\n    const socket = new WebSocket('wss://example.com')\n    socket.onopen = () => socket.send('hello world')\n  })\n\n  await expect(clientMessagePromise).resolves.toBe('hello world')\n})\n\ntest('intercepts outgoing client Blob message', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const clientMessagePromise = page.evaluate(() => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('wss://example.com')\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ client }) => {\n          client.addEventListener('message', (event) => {\n            if (event.data instanceof Blob) {\n              resolve(event.data.text())\n            }\n          })\n        }),\n      )\n      await worker.start()\n    })\n  })\n\n  await page.evaluate(() => {\n    const socket = new WebSocket('wss://example.com')\n    socket.onopen = () => socket.send(new Blob(['hello world']))\n  })\n\n  await expect(clientMessagePromise).resolves.toBe('hello world')\n})\n\ntest('intercepts outgoing client ArrayBuffer message', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const clientMessagePromise = page.evaluate(() => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('wss://example.com')\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ client }) => {\n          client.addEventListener('message', (event) => {\n            if (event.data instanceof Uint8Array) {\n              resolve(new TextDecoder().decode(event.data))\n            }\n          })\n        }),\n      )\n      await worker.start()\n    })\n  })\n\n  await page.evaluate(() => {\n    const socket = new WebSocket('wss://example.com')\n    socket.onopen = () => socket.send(new TextEncoder().encode('hello world'))\n  })\n\n  await expect(clientMessagePromise).resolves.toBe('hello world')\n})\n\ntest('resolves relative link URL against the page origin', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('/api')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        console.log('HANDLER!')\n\n        client.send('hello world')\n      }),\n    )\n    await worker.start()\n  })\n\n  const messagePromise = page.evaluate(() => {\n    const pendingMessage = Promise.withResolvers<string>()\n    const socket = new WebSocket('/api')\n    socket.onmessage = (event) => pendingMessage.resolve(event.data)\n    socket.onerror = () =>\n      pendingMessage.reject('Did not match the WebSocket connection')\n\n    return pendingMessage.promise\n  })\n\n  await expect(messagePromise).resolves.toBe('hello world')\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.intercept.server.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('intercepts incoming server text message', async ({\n  loadExample,\n  page,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.on('connection', (client) => {\n    client.send('hello')\n  })\n\n  const serverMessagePromise = page.evaluate((serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ server }) => {\n          server.connect()\n          server.addEventListener('message', (event) => {\n            if (typeof event.data === 'string') {\n              resolve(event.data)\n            }\n          })\n        }),\n      )\n      await worker.start()\n    })\n  }, server.url)\n\n  const clientMessage = await page.evaluate((serverUrl) => {\n    const socket = new WebSocket(serverUrl)\n\n    return new Promise<string>((resolve, reject) => {\n      socket.onerror = () => reject(new Error('Socket error'))\n      socket.addEventListener('message', (event) => {\n        resolve(event.data)\n      })\n    })\n  }, server.url)\n\n  expect(clientMessage).toBe('hello')\n  expect(await serverMessagePromise).toBe('hello')\n})\n\ntest('intercepts incoming server Blob message', async ({\n  loadExample,\n  page,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.on('connection', async (client) => {\n    /**\n     * `ws` doesn't support sending Blobs.\n     * @see https://github.com/websockets/ws/issues/2206\n     */\n    client.send(await new Blob(['hello']).arrayBuffer())\n  })\n\n  const serverMessagePromise = page.evaluate((serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ server }) => {\n          server.connect()\n          server.addEventListener('message', (event) => {\n            if (event.data instanceof Blob) {\n              resolve(event.data.text())\n            }\n          })\n        }),\n      )\n      await worker.start()\n    })\n  }, server.url)\n\n  const clientMessage = await page.evaluate((serverUrl) => {\n    const socket = new WebSocket(serverUrl)\n\n    return new Promise<string>((resolve, reject) => {\n      socket.onerror = () => reject(new Error('Socket error'))\n      socket.addEventListener('message', (event) => {\n        resolve(event.data.text())\n      })\n    })\n  }, server.url)\n\n  expect(clientMessage).toBe('hello')\n  expect(await serverMessagePromise).toBe('hello')\n})\n\ntest('intercepts outgoing server ArrayBuffer message', async ({\n  loadExample,\n  page,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const encoder = new TextEncoder()\n  server.on('connection', async (client) => {\n    client.binaryType = 'arraybuffer'\n    client.send(encoder.encode('hello'))\n  })\n\n  const serverMessagePromise = page.evaluate((serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    return new Promise<string>(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ server }) => {\n          server.connect()\n          server.addEventListener('message', (event) => {\n            resolve(new TextDecoder().decode(event.data as Uint8Array))\n          })\n        }),\n      )\n      await worker.start()\n    })\n  }, server.url)\n\n  const clientMessage = await page.evaluate((serverUrl) => {\n    const socket = new WebSocket(serverUrl)\n    socket.binaryType = 'arraybuffer'\n\n    return new Promise<string>((resolve, reject) => {\n      socket.onerror = () => reject(new Error('Socket error'))\n      socket.addEventListener('message', (event) => {\n        resolve(new TextDecoder().decode(event.data))\n      })\n    })\n  }, server.url)\n\n  expect(clientMessage).toBe('hello')\n  expect(await serverMessagePromise).toBe('hello')\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.logging.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('does not log anything if \"quiet\" was set to \"true\"', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start({ quiet: true })\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => {\n      ws.send('hello')\n      ws.send('world')\n      ws.close()\n    }\n\n    return new Promise<void>((resolve, reject) => {\n      ws.onclose = () => resolve()\n      ws.onerror = () => reject(new Error('Client connection closed'))\n    })\n  })\n\n  expect(consoleSpy.get('startGroupCollapsed')).toBeUndefined()\n})\n\ntest('logs the open event', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    new WebSocket('wss://localhost/path')\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2} %c▶%c wss:\\/\\/localhost\\/path color:#3b82f6 color:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs the close event initiated by the client', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => ws.close()\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c■%c wss:\\/\\/localhost\\/path color:#3b82f6 color:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs the close event initiated by the original server', async ({\n  loadExample,\n  spyOnConsole,\n  page,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.on('connection', (ws) => {\n    ws.close(1003)\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    new WebSocket(url)\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c■%c ws:\\/\\/(.+):\\d{4,}\\/ color:#3b82f6 color:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs the close event initiated by the event handler', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ client }) => {\n        client.close()\n      }),\n    )\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    new WebSocket('wss://localhost/path')\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c■%c wss:\\/\\/localhost\\/path color:#3b82f6 color:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending text', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => ws.send('hello world')\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c hello world %c11%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending long text', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => ws.send('this is an extremely long sentence to log out')\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c this is an extremely lon… %c45%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending Blob', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => ws.send(new Blob(['hello world']))\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c Blob\\(hello world\\) %c11%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending long Blob', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () =>\n      ws.send(new Blob(['this is an extremely long sentence to log out']))\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c Blob\\(this is an extremely lon…\\) %c45%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending ArrayBuffer data', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () => ws.send(new TextEncoder().encode('hello world'))\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c ArrayBuffer\\(hello world\\) %c11%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs outgoing client message sending long ArrayBuffer', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n}) => {\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link('wss://localhost/*')\n    const worker = setupWorker(api.addEventListener('connection', () => {}))\n    await worker.start()\n  })\n\n  await page.evaluate(() => {\n    const ws = new WebSocket('wss://localhost/path')\n    ws.onopen = () =>\n      ws.send(\n        new TextEncoder().encode(\n          'this is an extremely long sentence to log out',\n        ),\n      )\n  })\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c ArrayBuffer\\(this is an extremely lon…\\) %c45%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs incoming server messages', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.addListener('connection', (ws) => {\n    ws.send('hello from server')\n\n    ws.addEventListener('message', (event) => {\n      if (event.data === 'how are you, server?') {\n        ws.send('thanks, not bad')\n      }\n    })\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ client, server }) => {\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    const ws = new WebSocket(url)\n    ws.addEventListener('message', (event) => {\n      if (event.data === 'hello from server') {\n        ws.send('how are you, server?')\n      }\n    })\n  }, server.url)\n\n  // Initial message sent to every connected client.\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬇%c hello from server %c17%c color:#ef4444 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n\n  // Message sent in response to a client message.\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬇%c thanks, not bad %c15%c color:#ef4444 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs raw incoming server events', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.addListener('connection', (ws) => {\n    ws.send('hello from server')\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ client, server }) => {\n        server.connect()\n\n        server.addEventListener('message', (event) => {\n          event.preventDefault()\n          // This is the only data the client will receive\n          // but we should still print the raw server message.\n          client.send('intercepted server event')\n        })\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    new WebSocket(url)\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        // The actual (raw) message received from the server.\n        // The arrow is dotted because the message's default has been prevented.\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⇣%c hello from server %c17%c color:#ef4444 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n\n        // The mocked message sent from the event handler (client.send()).\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬇%c intercepted server event %c24%c color:#ff6a33 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs mocked outgoing client message (server.send)', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ server }) => {\n        server.connect()\n        server.send('hello from handler')\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    new WebSocket(url)\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬆%c hello from handler %c18%c color:#ff6a33 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('logs mocked incoming server message (client.send)', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ client }) => {\n        client.send('hello from handler')\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    new WebSocket(url)\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⬇%c hello from handler %c18%c color:#ff6a33 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('marks the prevented outgoing client event as dashed', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          event.preventDefault()\n        })\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    const socket = new WebSocket(url)\n    socket.onopen = () => socket.send('hello world')\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⇡%c hello world %c11%c color:#22c55e color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n\ntest('marks the prevented incoming server event as dashed', async ({\n  loadExample,\n  page,\n  spyOnConsole,\n  waitFor,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  const consoleSpy = spyOnConsole()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.addListener('connection', (ws) => {\n    ws.send('hello from server')\n  })\n\n  await page.evaluate(async (url) => {\n    const { setupWorker, ws } = window.msw\n    const api = ws.link(url)\n    const worker = setupWorker(\n      api.addEventListener('connection', ({ server }) => {\n        server.connect()\n        server.addEventListener('message', (event) => {\n          event.preventDefault()\n        })\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  await page.evaluate((url) => {\n    new WebSocket(url)\n  }, server.url)\n\n  await waitFor(() => {\n    expect(consoleSpy.get('raw')!.get('startGroupCollapsed')).toEqual(\n      expect.arrayContaining([\n        expect.stringMatching(\n          /^\\[MSW\\] \\d{2}:\\d{2}:\\d{2}\\.\\d{3} %c⇣%c hello from server %c17%c color:#ef4444 color:inherit color:gray;font-weight:normal color:inherit;font-weight:inherit$/,\n        ),\n      ]),\n    )\n  })\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.runtime.js",
    "content": "import { ws } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nwindow.msw = {\n  ws,\n  setupWorker,\n}\n"
  },
  {
    "path": "test/browser/ws-api/ws.server.connect.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('does not connect to the actual server by default', async ({\n  loadExample,\n  page,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.once('connection', (client) => {\n    client.send('must not receive this')\n  })\n\n  await page.evaluate(async (serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        queueMicrotask(() => client.send('mock'))\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  const clientMessage = await page.evaluate((serverUrl) => {\n    const socket = new WebSocket(serverUrl)\n\n    return new Promise((resolve, reject) => {\n      socket.onmessage = (event) => resolve(event.data)\n      socket.onerror = () => reject(new Error('WebSocket error'))\n    }).finally(() => socket.close())\n  }, server.url)\n\n  expect(clientMessage).toBe('mock')\n})\n\ntest('forwards incoming server events to the client once connected', async ({\n  loadExample,\n  page,\n  defineWebSocketServer,\n}) => {\n  const server = await defineWebSocketServer()\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  server.once('connection', (client) => {\n    client.send('hello from server')\n  })\n\n  await page.evaluate(async (serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ server }) => {\n        // Calling \"connect()\" establishes the connection\n        // to the actual WebSocket server.\n        server.connect()\n      }),\n    )\n    await worker.start()\n  }, server.url)\n\n  const clientMessage = await page.evaluate((serverUrl) => {\n    const socket = new WebSocket(serverUrl)\n\n    return new Promise((resolve, reject) => {\n      socket.onmessage = (event) => {\n        resolve(event.data)\n        socket.close()\n      }\n      socket.onerror = reject\n    })\n  }, server.url)\n\n  expect(clientMessage).toBe('hello from server')\n})\n\ntest('throws an error when connecting to a non-existing server', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  const error = await page.evaluate((serverUrl) => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link(serverUrl)\n\n    return new Promise(async (resolve) => {\n      const worker = setupWorker(\n        service.addEventListener('connection', ({ server }) => {\n          server.connect()\n        }),\n      )\n      await worker.start()\n\n      const socket = new WebSocket(serverUrl)\n      socket.onerror = () => resolve('Connection failed')\n    })\n  }, 'ws://non-existing-websocket-address.com')\n\n  expect(error).toMatch('Connection failed')\n})\n"
  },
  {
    "path": "test/browser/ws-api/ws.use.browser.test.ts",
    "content": "import type { ws } from 'msw'\nimport type { setupWorker } from 'msw/browser'\nimport { test, expect } from '../playwright.extend'\n\ndeclare global {\n  interface Window {\n    msw: {\n      ws: typeof ws\n      setupWorker: typeof setupWorker\n    }\n  }\n}\n\ntest('resolves outgoing events using initial handlers', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            client.send('hello from mock')\n          }\n        })\n      }),\n    )\n    await worker.start()\n  })\n\n  const clientMessage = await page.evaluate(() => {\n    const socket = new WebSocket('wss://example.com')\n    return new Promise((resolve, reject) => {\n      socket.onopen = () => socket.send('hello')\n      socket.onmessage = (event) => resolve(event.data)\n      socket.onerror = reject\n    })\n  })\n\n  expect(clientMessage).toBe('hello from mock')\n})\n\ntest('overrides an outgoing event listener', async ({ loadExample, page }) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            client.send('must not be sent')\n          }\n        })\n      }),\n    )\n    await worker.start()\n\n    worker.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            event.stopImmediatePropagation()\n            client.send('howdy, client!')\n          }\n        })\n      }),\n    )\n  })\n\n  const clientMessage = await page.evaluate(() => {\n    const socket = new WebSocket('wss://example.com')\n    return new Promise((resolve, reject) => {\n      socket.onopen = () => socket.send('hello')\n      socket.onmessage = (event) => resolve(event.data)\n      socket.onerror = reject\n    })\n  })\n\n  expect(clientMessage).toBe('howdy, client!')\n})\n\ntest('combines initial and override listeners', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // This will be sent the last since the initial\n            // event listener is attached the first.\n            client.send('hello from mock')\n            queueMicrotask(() => client.close())\n          }\n        })\n      }),\n    )\n    await worker.start()\n\n    worker.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // This will be sent first since the override listener\n            // is attached the last.\n            client.send('override data')\n          }\n        })\n      }),\n    )\n  })\n\n  const clientMessages = await page.evaluate(() => {\n    const messages: Array<string> = []\n    const socket = new WebSocket('wss://example.com')\n\n    return new Promise<Array<string>>((resolve, reject) => {\n      socket.onopen = () => socket.send('hello')\n      socket.onmessage = (event) => messages.push(event.data)\n      socket.onclose = () => resolve(messages)\n      socket.onerror = reject\n    })\n  })\n\n  expect(clientMessages).toEqual(['override data', 'hello from mock'])\n})\n\ntest('combines initial and override listeners in the opposite order', async ({\n  loadExample,\n  page,\n}) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            client.send('hello from mock')\n          }\n        })\n      }),\n    )\n    await worker.start()\n\n    worker.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // Queue this send to the next tick so it\n            // happens after the initial listener's send.\n            queueMicrotask(() => {\n              client.send('override data')\n              queueMicrotask(() => client.close())\n            })\n          }\n        })\n      }),\n    )\n  })\n\n  const clientMessages = await page.evaluate(() => {\n    const messages: Array<string> = []\n    const socket = new WebSocket('wss://example.com')\n\n    return new Promise<Array<string>>((resolve, reject) => {\n      socket.onopen = () => socket.send('hello')\n      socket.onmessage = (event) => messages.push(event.data)\n      socket.onclose = () => resolve(messages)\n      socket.onerror = reject\n    })\n  })\n\n  expect(clientMessages).toEqual(['hello from mock', 'override data'])\n})\n\ntest('does not affect unrelated events', async ({ loadExample, page }) => {\n  await loadExample(new URL('./ws.runtime.js', import.meta.url), {\n    skipActivation: true,\n  })\n\n  await page.evaluate(async () => {\n    const { setupWorker, ws } = window.msw\n    const service = ws.link('*')\n\n    const worker = setupWorker(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            client.send('must not be sent')\n          }\n\n          if (event.data === 'fallthrough') {\n            client.send('ok')\n            queueMicrotask(() => client.close())\n          }\n        })\n      }),\n    )\n    await worker.start()\n\n    worker.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            event.stopImmediatePropagation()\n            client.send('howdy, client!')\n          }\n        })\n      }),\n    )\n  })\n\n  const clientMessages = await page.evaluate(() => {\n    const messages: Array<string> = []\n    const socket = new WebSocket('wss://example.com')\n\n    return new Promise<Array<string>>((resolve, reject) => {\n      socket.onopen = () => socket.send('hello')\n      socket.onmessage = (event) => {\n        messages.push(event.data)\n        if (event.data === 'howdy, client!') {\n          socket.send('fallthrough')\n        }\n      }\n      socket.onclose = () => resolve(messages)\n      socket.onerror = reject\n    })\n  })\n\n  expect(clientMessages).toEqual(['howdy, client!', 'ok'])\n})\n"
  },
  {
    "path": "test/e2e/auto-update-worker.node.test.ts",
    "content": "import fs from 'node:fs'\nimport { inject } from 'vitest'\nimport { createTeardown } from 'fs-teardown'\nimport { fromTemp } from '../support/utils.js'\n\nconst TARBALL_PATH = inject('tarballPath')\n\nconst fsMock = createTeardown({\n  rootDir: fromTemp('worker-script-auto-update'),\n})\n\ndescribe(\n  'worker script auto-update',\n  {\n    sequential: true,\n  },\n  () => {\n    beforeAll(async () => {\n      await fsMock.prepare()\n    })\n\n    afterEach(async () => {\n      await fsMock.reset()\n    })\n\n    afterAll(async () => {\n      await fsMock.cleanup()\n    })\n\n    it('updates the worker script on the \"postinstall\" hook', async () => {\n      await fsMock.create({\n        'package.json': JSON.stringify({\n          name: 'example',\n          msw: {\n            workerDirectory: 'public',\n          },\n        }),\n      })\n\n      // Install \"msw\" from the tarball into the dummy project.\n      const installCommand = await fsMock.exec(`npm install ${TARBALL_PATH}`)\n      expect(installCommand.stderr).toBe('')\n\n      // Asset the worker script has been created/updated.\n      expect(\n        fs.existsSync(fsMock.resolve('public/mockServiceWorker.js')),\n      ).toEqual(true)\n    })\n\n    it('updates multiple directories on the \"postinstall\" hook', async () => {\n      await fsMock.create({\n        'package.json': JSON.stringify({\n          name: 'example-multiple-dirs',\n          msw: {\n            workerDirectory: ['./packages/one', './packages/two'],\n          },\n        }),\n      })\n\n      const installCommand = await fsMock.exec(`npm install ${TARBALL_PATH}`)\n      /**\n       * @note Cannot assert on the empty stderr because npm\n       * writes to stderr if there's a new version of npm available.\n       */\n      // expect(installCommand.stderr).toBe('')\n\n      expect(\n        fs.existsSync(fsMock.resolve('packages/one/mockServiceWorker.js')),\n      ).toEqual(true)\n      expect(\n        fs.existsSync(fsMock.resolve('packages/two/mockServiceWorker.js')),\n      ).toEqual(true)\n    })\n  },\n)\n"
  },
  {
    "path": "test/e2e/cli-init.node.test.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport url from 'node:url'\nimport { spawnSync } from 'node:child_process'\nimport { createTeardown } from 'fs-teardown'\nimport { fromTemp } from '../support/utils'\n\nconst fsMock = createTeardown({\n  rootDir: fromTemp('cli/init'),\n})\n\nconst CLI_PATH = url.fileURLToPath(\n  new URL('../../cli/index.js', import.meta.url),\n)\n\nfunction readJson(filePath: string) {\n  const rawContent = fs.readFileSync(filePath, 'utf8')\n  try {\n    const content = JSON.parse(rawContent)\n    return content\n  } catch (error) {\n    return rawContent\n  }\n}\n\nbeforeAll(async () => {\n  spawnSync('pnpm', ['build'])\n  await fsMock.prepare()\n})\n\nbeforeEach(async () => {\n  await fsMock.reset()\n})\n\nafterEach(() => {\n  vi.restoreAllMocks()\n})\n\nafterAll(async () => {\n  await fsMock.cleanup()\n})\n\nasync function init(inlineArgs: Array<string>): ReturnType<typeof fsMock.exec> {\n  const result = await fsMock.exec(\n    `node ${CLI_PATH} init ${inlineArgs.join(' ')}`,\n  )\n\n  return {\n    ...result,\n    // Strip stdout from color unicode characters:\n    stdout: result.stdout.replace(/\\x1b\\[\\d+m/gi, ''),\n    stderr: result.stderr.replace(/\\x1b\\[\\d+m/gi, ''),\n  }\n}\n\ntest('copies the script to a given path without saving', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n    }),\n  })\n\n  const initCommand = await init([\n    fsMock.resolve('./public'),\n    /**\n     * @note Pass the \"--no-save\" flag to prevent the \"init\" command\n     * from spawning a \"Would you like to save the path\" prompt.\n     */\n    '--no-save',\n  ])\n\n  expect(initCommand.stderr).toBe('')\n  expect(initCommand.stdout).toContain(\n    `Worker script successfully copied!\\n  - ${fsMock.resolve('public')}`,\n  )\n  expect(fs.existsSync(fsMock.resolve('public/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  // Must not write anything to package.json\n  expect(readJson(fsMock.resolve('package.json'))).toEqual({\n    name: 'test',\n  })\n})\n\ntest('saves the path in \"msw.workerDirectory\" if the \"--save\" flag was provided', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n    }),\n  })\n\n  const initCommand = await init([fsMock.resolve('./public'), '--save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(initCommand.stdout).toContain(\n    `Worker script successfully copied!\\n  - ${fsMock.resolve('public')}`,\n  )\n  expect(fs.existsSync(fsMock.resolve('public/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['public'],\n    },\n  })\n})\n\ntest('deduplicates saved paths in \"msw.workerDirectory\" (using plain string)', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n      msw: {\n        /**\n         * @note Use the plain string value that most users have.\n         */\n        workerDirectory: 'public',\n      },\n    }),\n  })\n\n  const initCommand = await init(['./public', '--save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(fs.existsSync(fsMock.resolve('public/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      // The plain string value will be left as-is because no\n      // updates are necessary to package.json\n      workerDirectory: 'public',\n    },\n  })\n})\n\ntest('deduplicates saved paths in \"msw.workerDirectory\" (using array)', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n      msw: {\n        workerDirectory: ['public', 'another'],\n      },\n    }),\n  })\n\n  const initCommand = await init(['./public', '--save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(fs.existsSync(fsMock.resolve('public/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['public', 'another'],\n    },\n  })\n})\n\ntest('does not save the path if the \"--no-save\" flag was provided', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n      msw: {\n        workerDirectory: ['public'],\n      },\n    }),\n  })\n\n  const initCommand = await init(['./static', '--no-save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(fs.existsSync(fsMock.resolve('static/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['public'],\n    },\n  })\n})\n\ntest('adds multiple paths to \"msw.workerDirectory\"', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n    }),\n  })\n\n  await init(['one', '--save'])\n\n  expect(fs.existsSync(fsMock.resolve('one/mockServiceWorker.js'))).toBe(true)\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['one'],\n    },\n  })\n\n  await init(['two', '--save'])\n  expect(fs.existsSync(fsMock.resolve('two/mockServiceWorker.js'))).toBe(true)\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['one', 'two'],\n    },\n  })\n})\n\ntest('throws if creating a directory under path failed', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n    }),\n  })\n\n  /**\n   * @note Require the \"init\" command source\n   * so that the \"fs\" mocks could apply.\n   */\n  // @ts-expect-error\n  const { init } = await import('../../cli/init.js')\n\n  // Mock the \"mkdir\" method throwing an error.\n  const error = new Error('Failed to create directory')\n  vi.spyOn(fs.promises, 'mkdir').mockRejectedValue(error)\n\n  const exitSpy = vi.spyOn(process, 'exit').mockImplementationOnce(() => {\n    throw error\n  })\n  const consoleErrorSpy = vi\n    .spyOn(console, 'error')\n    .mockImplementationOnce(() => void 0)\n\n  const initCommandPromise = init({\n    _: [null, './does/not/exist'],\n    save: false,\n  })\n\n  await expect(initCommandPromise).rejects.toThrowError(error)\n  expect(consoleErrorSpy).toHaveBeenCalledWith(\n    expect.stringContaining(`Failed to copy the worker script at`),\n    // The absolute public directory path will be resolved\n    // against CWD, and not \"fsMock\". No need to assert it.\n    expect.any(String),\n    error,\n  )\n  expect(exitSpy).toHaveBeenCalledWith(1)\n})\n\ntest('does not copy the script to saved paths if public directory was provided', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n      msw: {\n        workerDirectory: ['one', 'two'],\n      },\n    }),\n  })\n\n  const initCommand = await init(['three', '--save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(initCommand.stdout).toContain('- three')\n  expect(initCommand.stdout).not.toContain('- one')\n  expect(initCommand.stdout).not.toContain('- two')\n\n  // Must not copy the worker script to stored paths\n  // when the \"init\" command is called with a new path.\n  expect(fs.existsSync(fsMock.resolve('one/mockServiceWorker.js'))).toBe(false)\n  expect(fs.existsSync(fsMock.resolve('two/mockServiceWorker.js'))).toBe(false)\n\n  // Must copy the worker script only to the provided path.\n  expect(fs.existsSync(fsMock.resolve('three/mockServiceWorker.js'))).toBe(true)\n})\n\ntest('copies the script to all saved paths if the public directory was not provided', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n      msw: {\n        workerDirectory: ['packages/one/public', 'packages/two/static'],\n      },\n    }),\n  })\n\n  const initCommand = await init([])\n\n  expect(initCommand.stderr).toBe('')\n  expect(\n    fs.existsSync(fsMock.resolve('packages/one/public/mockServiceWorker.js')),\n  ).toBe(true)\n  expect(\n    fs.existsSync(fsMock.resolve('packages/two/static/mockServiceWorker.js')),\n  ).toBe(true)\n  expect(readJson(fsMock.resolve('package.json'))).toMatchObject({\n    msw: {\n      workerDirectory: ['packages/one/public', 'packages/two/static'],\n    },\n  })\n})\n\ntest('throws when called with \"--save\" flag and without the public directory', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'test',\n      msw: {\n        workerDirectory: ['public'],\n      },\n    }),\n  })\n\n  const initCommandPromise = init(['--save'])\n\n  // Must throw a meaningful arrow about a no-op \"--save\" flag.\n  await expect(initCommandPromise).rejects.toThrowError(\n    `Failed to copy the worker script: cannot call the \"init\" command without a public directory but with the \"--save\" flag. Either drop the \"--save\" flag to copy the worker script to all paths listed in \"msw.workerDirectory\", or add an explicit public directory to the command, like \"npx msw init ./public\".`,\n  )\n\n  // Must not modify the package.json.\n  expect(readJson(fsMock.resolve('package.json'))).toEqual({\n    name: 'test',\n    msw: {\n      workerDirectory: ['public'],\n    },\n  })\n\n  // Must not copy the worker script.\n  expect(\n    expect(fs.existsSync(fsMock.resolve('public/mockServiceWorker.js'))).toBe(\n      false,\n    ),\n  )\n})\n\ntest('prints the list of failed paths to copy', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n      msw: {\n        workerDirectory: ['one', 'problematic'],\n      },\n    }),\n  })\n\n  vi.spyOn(fs, 'copyFileSync').mockImplementation((_, dest) => {\n    // Only fail one of the stored paths.\n    if (dest.toString().includes('/problematic/')) {\n      throw copyFileError\n    }\n  })\n\n  // @ts-expect-error\n  const { init } = await import('../../cli/init.js')\n  const copyFileError = new Error('Failed to copy file')\n\n  const consoleLogSpy = vi\n    .spyOn(console, 'log')\n    .mockImplementation(() => void 0)\n  const consoleErrorSpy = vi\n    .spyOn(console, 'error')\n    .mockImplementationOnce(() => void 0)\n\n  await init({\n    // Calling \"init\" without the public directory\n    // to trigger it to copy the worker script to all\n    // stored paths at \"msw.workerDirectory\".\n    _: [null],\n    // Use a custom CWD so that the direct call to \"init\"\n    // resolves the \"package.json\" from the \"fsMock\".\n    cwd: fsMock.resolve('.'),\n  })\n\n  // Must still print the successful message if any paths succeeded.\n  expect(consoleLogSpy).toHaveBeenCalledWith(\n    expect.stringContaining('Worker script successfully copied!'),\n  )\n  expect(consoleLogSpy).toHaveBeenCalledWith(\n    expect.stringContaining(\n      `  - ${fsMock.resolve('one/mockServiceWorker.js')}`,\n    ),\n  )\n\n  // Must print the failed paths.\n  expect(consoleErrorSpy).toHaveBeenCalledWith(\n    expect.stringContaining(\n      `Copying the worker script failed at following paths:`,\n    ),\n  )\n  expect(consoleErrorSpy).toHaveBeenCalledWith(\n    expect.stringContaining(`  - ${fsMock.resolve('problematic')}`),\n  )\n  expect(consoleErrorSpy).toHaveBeenCalledWith(\n    expect.stringContaining(copyFileError.message),\n  )\n})\n\ntest('supports a mix of unix/windows paths in \"workerDirectory\"', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n      msw: {\n        // Use a mix of different path styles to emulate multiple developers\n        // working from different operating systems.\n        workerDirectory: [\n          path.win32.join('public', 'windows-style'),\n          'unix/style',\n        ],\n      },\n    }),\n  })\n\n  const initCommand = await init([''])\n\n  expect(initCommand.stderr).toBe('')\n  expect(\n    fs.existsSync(fsMock.resolve('public/windows-style/mockServiceWorker.js')),\n  ).toBe(true)\n  expect(fs.existsSync(fsMock.resolve('unix/style/mockServiceWorker.js'))).toBe(\n    true,\n  )\n\n  const normalizedPaths = readJson(fsMock.resolve('package.json')).msw\n    .workerDirectory\n\n  // Expect normalized paths\n  expect(normalizedPaths).toContain('public\\\\windows-style')\n  expect(normalizedPaths).toContain('unix/style')\n})\n\ntest('copies the script only to provided windows path in args', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n      msw: {\n        workerDirectory: ['unix/style'],\n      },\n    }),\n  })\n\n  const initCommand = await init([\n    `\"${path.win32.join('.', 'windows-style', 'new-folder')}\"`,\n    '--save',\n  ])\n\n  expect(initCommand.stderr).toBe('')\n  expect(\n    fs.existsSync(\n      fsMock.resolve('windows-style/new-folder/mockServiceWorker.js'),\n    ),\n  ).toBe(true)\n  expect(fs.existsSync(fsMock.resolve('unix/style/mockServiceWorker.js'))).toBe(\n    false,\n  )\n})\n\ntest('copies the script only to provided unix path in args', async () => {\n  await fsMock.create({\n    'package.json': JSON.stringify({\n      name: 'example',\n      msw: {\n        workerDirectory: [path.win32.join('windows-style', 'new-folder')],\n      },\n    }),\n  })\n\n  const initCommand = await init(['./unix/style', '--save'])\n\n  expect(initCommand.stderr).toBe('')\n  expect(fs.existsSync(fsMock.resolve('unix/style/mockServiceWorker.js'))).toBe(\n    true,\n  )\n  expect(\n    fs.existsSync(\n      fsMock.resolve('windows-style/new-folder/mockServiceWorker.js'),\n    ),\n  ).toBe(false)\n})\n"
  },
  {
    "path": "test/e2e/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"./**/*.test.ts\", \"./vitest.d.ts\", \"./vitest.global.setup.ts\"]\n}\n"
  },
  {
    "path": "test/e2e/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    dir: './test/e2e',\n    globals: true,\n    environment: 'node',\n    globalSetup: './test/e2e/vitest.global.setup.ts',\n    testTimeout: 60_000,\n    hookTimeout: 60_000,\n  },\n})\n"
  },
  {
    "path": "test/e2e/vitest.d.ts",
    "content": "declare module 'vitest' {\n  export interface ProvidedContext {\n    tarballPath: string\n  }\n}\n\nexport {}\n"
  },
  {
    "path": "test/e2e/vitest.global.setup.ts",
    "content": "import fs from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { spawnSync } from 'node:child_process'\nimport { invariant } from 'outvariant'\nimport type { GlobalSetupContext } from 'vitest/node'\nimport * as packageJson from '../../package.json'\n\nexport default function setup({ provide }: GlobalSetupContext) {\n  const tarballPath = fileURLToPath(\n    new URL(`../../msw-${packageJson.version}.tgz`, import.meta.url),\n  )\n\n  if (fs.existsSync(tarballPath)) {\n    return\n  }\n\n  // Pack the library before all E2E tests.\n  spawnSync('pnpm', ['pack'], {\n    stdio: 'inherit',\n  })\n\n  invariant(\n    fs.existsSync(tarballPath),\n    'Failed to set up e2e tests: library tarball not found at \"%s\"',\n    tarballPath,\n  )\n\n  console.log('Library built at \"%s\"!', tarballPath)\n\n  provide('tarballPath', tarballPath)\n}\n"
  },
  {
    "path": "test/global.d.ts",
    "content": "declare module 'url-loader!*' {\n  const content: string\n  export default content\n}\n"
  },
  {
    "path": "test/modules/browser/esm-browser.test.ts",
    "content": "import url from 'node:url'\nimport { invariant } from 'outvariant'\nimport { createTeardown } from 'fs-teardown'\nimport * as express from 'express'\nimport { HttpServer } from '@open-draft/test-server/lib/http.js'\nimport { test, expect } from '@playwright/test'\nimport { spyOnConsole } from 'page-with'\nimport { startDevServer } from '@web/dev-server'\nimport { installLibrary } from '../module-utils'\n\ntype DevServer = Awaited<ReturnType<typeof startDevServer>>\n\nconst fsMock = createTeardown({\n  rootDir: url.fileURLToPath(new URL('esm-browser-tests', import.meta.url)),\n  paths: {\n    'package.json': JSON.stringify({ type: 'module' }),\n  },\n})\n\nlet devServer: DevServer\n\nfunction getDevServerUrl(): string {\n  const address = devServer.server?.address()\n\n  invariant(address, 'Failed to retrieve dev server url: null')\n\n  if (typeof address === 'string') {\n    return new URL(address).href\n  }\n\n  return new URL(`http://localhost:${address.port}`).href\n}\n\nconst httpServer = new HttpServer((app) => {\n  app.use(express.static(fsMock.resolve('.')))\n})\n\ntest.beforeAll(async () => {\n  devServer = await startDevServer({\n    config: {\n      rootDir: fsMock.resolve('.'),\n      port: 0,\n      nodeResolve: {\n        exportConditions: ['browser'],\n      },\n    },\n    logStartMessage: false,\n  })\n\n  await httpServer.listen()\n  await fsMock.prepare()\n  await installLibrary(fsMock.resolve('.'))\n})\n\ntest.afterAll(async () => {\n  await devServer?.stop()\n  await httpServer.close()\n  await fsMock.cleanup()\n})\n\ntest('runs in an ESM browser project', async ({ page }) => {\n  await fsMock.create({\n    'entry.mjs': `\nimport { http,HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\nconst worker = setupWorker(\n  http.get('/resource', () => new Response()),\n  http.post('/login', () => HttpResponse.json([1, 2, 3]))\n)\nconsole.log(typeof worker.start)\n    `,\n    'index.html': `\n<script type=\"module\" src=\"./entry.mjs\"></script>\n    `,\n  })\n  const consoleSpy = spyOnConsole(page)\n  const pageErrors: Array<string> = []\n  page.on('pageerror', (error) =>\n    pageErrors.push(`${error.message}\\n${error.stack}`),\n  )\n\n  await page.goto(getDevServerUrl(), { waitUntil: 'networkidle' })\n\n  expect(pageErrors).toEqual([])\n  expect(consoleSpy.get('error')).toBeUndefined()\n  expect(consoleSpy.get('log')).toEqual(expect.arrayContaining(['function']))\n})\n"
  },
  {
    "path": "test/modules/browser/playwright.config.ts",
    "content": "import url from 'node:url'\nimport { type Config } from '@playwright/test'\n\nconst TEST_DIR = url.fileURLToPath(new URL('./', import.meta.url))\n\nexport default {\n  testDir: TEST_DIR,\n  use: {\n    launchOptions: {\n      devtools: !process.env.CI,\n    },\n  },\n  fullyParallel: true,\n} satisfies Config\n"
  },
  {
    "path": "test/modules/module-utils.ts",
    "content": "import fs from 'node:fs'\nimport url from 'node:url'\nimport { spawnSync } from 'node:child_process'\nimport { invariant } from 'outvariant'\nimport packageJson from '../../package.json' assert { type: 'json' }\n\nasync function getLibraryTarball(): Promise<string> {\n  const ROOT_PATH = new URL('../..', import.meta.url)\n  const packFilename = `msw-${packageJson.version}.tgz`\n  const packPath = url.fileURLToPath(new URL(packFilename, ROOT_PATH))\n\n  /**\n   * @note Beware that you need to remove the tarball after\n   * the test run is done. Don't want to use a stale tgarball, do you?\n   */\n  if (fs.existsSync(packPath)) {\n    return packPath\n  }\n\n  const out = spawnSync('pnpm', ['pack'], { cwd: ROOT_PATH })\n\n  if (out.error) {\n    console.error(out.error)\n  }\n\n  invariant(\n    fs.existsSync(packPath),\n    'Failed to pack the library at \"%s\"',\n    packPath,\n  )\n\n  return packPath\n}\n\nexport async function installLibrary(projectPath: string) {\n  const TARBALL_PATH = await getLibraryTarball()\n\n  const output = spawnSync('pnpm', ['install', TARBALL_PATH], {\n    cwd: projectPath,\n  })\n\n  if (output.error) {\n    console.error(output.error)\n    return Promise.reject(\n      'Failed to install the library. See the stderr output above.',\n    )\n  }\n\n  /**\n   * @todo Assert that pnpm printed success:\n   * + msw 0.0.0-fetch.rc-11\n   */\n}\n"
  },
  {
    "path": "test/modules/node/esm-node.test.ts",
    "content": "import url from 'node:url'\nimport { createTeardown } from 'fs-teardown'\nimport { installLibrary } from '../module-utils'\n\nconst fsMock = createTeardown({\n  rootDir: url.fileURLToPath(new URL('node-esm-tests', import.meta.url)),\n  paths: {\n    'package.json': JSON.stringify({ type: 'module' }),\n  },\n})\n\nbeforeAll(async () => {\n  await fsMock.prepare()\n  await installLibrary(fsMock.resolve('.'))\n})\n\nafterAll(async ({ result }) => {\n  if (result?.state === 'fail') {\n    return\n  }\n\n  await fsMock.cleanup()\n})\n\nit('runs in a ESM Node.js project', async () => {\n  await fsMock.create({\n    'resolve.mjs': `\nconsole.log('msw:', await import.meta.resolve('msw'))\nconsole.log('msw/node:', await import.meta.resolve('msw/node'))\nconsole.log('msw/native:', await import.meta.resolve('msw/native'))\n`,\n    'runtime.mjs': `\nimport { http } from 'msw'\nimport { setupServer } from 'msw/node'\nconst server = setupServer(\n  http.get('/resource', () => new Response())\n)\nconsole.log(typeof server.listen)\n`,\n  })\n\n  const resolveStdio = await fsMock.exec(\n    /**\n     * @note Using the import meta resolve flag\n     * to enable the \"import.meta.resolve\" API to see\n     * what library imports resolve to in Node.js ESM.\n     */\n    'node --experimental-import-meta-resolve ./resolve.mjs',\n  )\n  expect(resolveStdio.stderr).toBe('')\n  /**\n   * @todo Take these expected export paths from package.json.\n   * That should be the source of truth.\n   */\n  expect(resolveStdio.stdout).toMatch(\n    /^msw: (.+?)\\/node_modules\\/msw\\/lib\\/core\\/index\\.mjs/m,\n  )\n  expect(resolveStdio.stdout).toMatch(\n    /^msw\\/node: (.+?)\\/node_modules\\/msw\\/lib\\/node\\/index\\.mjs/m,\n  )\n  expect(resolveStdio.stdout).toMatch(\n    /^msw\\/native: (.+?)\\/node_modules\\/msw\\/lib\\/native\\/index\\.mjs/m,\n  )\n\n  /**\n   * @todo Also test the \"msw/browser\" import that throws,\n   * saying that the \"./browser\" export is not defined.\n   * That's correct, it's explicitly set as \"browser: null\" for Node.js.\n   */\n\n  const runtimeStdio = await fsMock.exec('node ./runtime.mjs')\n  expect(runtimeStdio.stderr).toBe('')\n  expect(runtimeStdio.stdout).toMatch(/function/m)\n})\n\nit('runs in a CJS Node.js project', async () => {\n  await fsMock.create({\n    'resolve.cjs': `\nconsole.log('msw:', require.resolve('msw'))\nconsole.log('msw/node:', require.resolve('msw/node'))\nconsole.log('msw/native:', require.resolve('msw/native'))\n`,\n    'runtime.cjs': `\nconst { http } = require('msw')\nconst { setupServer } = require('msw/node')\nconst server = setupServer(\n  http.get('/resource', () => new Response())\n)\nconsole.log(typeof server.listen)\n`,\n  })\n\n  const resolveStdio = await fsMock.exec('node ./resolve.cjs')\n  expect(resolveStdio.stderr).toBe('')\n\n  /**\n   * @todo Take these expected export paths from package.json.\n   * That should be the source of truth.\n   */\n\n  /**\n   * @note Although the test requires the package in CJS,\n   * the \"module-sync\" condition allows loading the ESM build.\n   * This is supported in Node.js v20+.\n   */\n  expect(resolveStdio.stdout).toMatch(\n    /^msw: (.+?)\\/node_modules\\/msw\\/lib\\/core\\/index\\.mjs/m,\n  )\n  expect(resolveStdio.stdout).toMatch(\n    /^msw\\/node: (.+?)\\/node_modules\\/msw\\/lib\\/node\\/index\\.mjs/m,\n  )\n\n  // Must load regular CJS build for React Native.\n  expect(resolveStdio.stdout).toMatch(\n    /^msw\\/native: (.+?)\\/node_modules\\/msw\\/lib\\/native\\/index\\.js/m,\n  )\n\n  const runtimeStdio = await fsMock.exec('node ./runtime.mjs')\n  expect(runtimeStdio.stderr).toBe('')\n  expect(runtimeStdio.stdout).toMatch(/function/m)\n})\n"
  },
  {
    "path": "test/modules/node/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"include\": [\"./**/*.test.ts\"]\n}\n"
  },
  {
    "path": "test/modules/node/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    dir: __dirname,\n    environment: 'node',\n    testTimeout: 60_000,\n    hookTimeout: 60_000,\n  },\n})\n"
  },
  {
    "path": "test/native/node-events.native.test.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/pull/1858\n * @see https://github.com/mswjs/msw/issues/1868\n */\nimport { setupServer } from 'msw/native'\n\ntest('calls \"setupServer\" without errors in React Native', async () => {\n  /**\n   * @note Asserting that mocking works is not possible with\n   * the current testing setup. We force Vitest to alias \"msw\"\n   * imports to their ESM build, which is a hack.\n   *\n   * We need Vitest to load the ESM build here in order to\n   * use \"vi.mock()\" to mock the \"node:events\" imports to throw.\n   * Vitest doesn't support module mocking in CommonJS.\n   *\n   * But aliasing the build isn't enough for it to function.\n   * The root-level package.json is still CJS, which, I suspects,\n   * resolves any subsequent in-build imports to their CJS counterparts.\n   */\n  expect(() => setupServer()).not.toThrow()\n})\n"
  },
  {
    "path": "test/native/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"resolveJsonModule\": true,\n    // Support default imports for modules that have no default exports.\n    // This way \"http\" imports stay \"import http from 'http'\".\n    // Using wildcard there breaks request interception since it\n    // encapsulates the values under the \".default\" key.\n    \"allowSyntheticDefaultImports\": true,\n    \"types\": [\"node\", \"vitest/globals\"]\n  },\n  \"include\": [\"../../global.d.ts\", \"./**/*.test.ts\"]\n}\n"
  },
  {
    "path": "test/native/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { mswExports } from '../support/alias.js'\n\nexport default defineConfig({\n  test: {\n    root: './test/native',\n    include: ['**/*.native.test.ts'],\n    globals: true,\n    setupFiles: ['./vitest.setup.ts'],\n    alias: {\n      /**\n       * @note Force Vitest load ESM targets of MSW.\n       * If we run ESM in tests, we can use \"vi.mock()\" to\n       * emulate certain standard Node.js modules missing\n       * (like \"node:events\") in React Native.\n       *\n       * Vitest won't pick up the ESM targets because\n       * the root-level \"package.json\" is not \"module\".\n       */\n      ...mswExports,\n    },\n  },\n})\n"
  },
  {
    "path": "test/native/vitest.setup.ts",
    "content": "import { vi } from 'vitest'\n\n/**\n * @note The list of standard Node.js modules missing\n * in the React Native runtime.\n */\nconst reactNativeMissingModules = ['events', 'node:events']\n\nreactNativeMissingModules.forEach((moduleName) => {\n  vi.doMock(moduleName, () => {\n    throw new Error(\n      `Failed to import module \"${moduleName}\": it does not exist in React Native. This likely means MSW tries to import something too optimistically in that environment.`,\n    )\n  })\n})\n"
  },
  {
    "path": "test/node/graphql-api/anonymous-operations.test.ts",
    "content": "// @vitest-environment node\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { HttpResponse, graphql } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient } from '../../support/graphql'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (req, res) => {\n    res.json({\n      data: {\n        user: { id: 'abc-123' },\n      },\n    })\n  })\n})\n\nconst server = setupServer(graphql.query('GetUser', () => {}))\n\nbeforeAll(async () => {\n  server.listen()\n  await httpServer.listen()\n  vi.spyOn(console, 'warn').mockImplementation(() => {})\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.clearAllMocks()\n})\n\nafterAll(async () => {\n  vi.restoreAllMocks()\n  server.close()\n  await httpServer.close()\n})\n\nit('warns on unhandled anonymous GraphQL operations', async () => {\n  const endpointUrl = httpServer.http.url('/graphql')\n  const client = createGraphQLClient({ uri: endpointUrl })\n\n  const result = await client({\n    query: `\n      query {\n        user {\n          id\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    user: { id: 'abc-123' },\n  })\n\n  expect(console.warn, 'Warns about an anonymous operation')\n    .toHaveBeenCalledWith(`\\\n[MSW] Failed to intercept a GraphQL request at \"POST ${endpointUrl}\": anonymous GraphQL operations are not supported.\n\nConsider naming this operation or using \"graphql.operation()\" request handler to intercept GraphQL requests regardless of their operation name/type. Read more: https://mswjs.io/docs/api/graphql/#graphqloperationresolver`)\n})\n\nit('does not print a warning when using anonymous operation with \"graphql.operation()\"', async () => {\n  server.use(\n    graphql.operation(async () => {\n      return HttpResponse.json({\n        data: {\n          pets: [{ name: 'Tom' }, { name: 'Jerry' }],\n        },\n      })\n    }),\n  )\n\n  const endpointUrl = httpServer.http.url('/graphql')\n  const client = createGraphQLClient({ uri: endpointUrl })\n\n  const result = await client({\n    query: `\n      query {\n        pets {\n          name\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    pets: [{ name: 'Tom' }, { name: 'Jerry' }],\n  })\n  expect(console.warn, 'Must not print any warnings').not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/node/graphql-api/batched-queries.apollo.test.ts",
    "content": "/**\n * @vitest-environment node\n * Example of mocking batched GraphQL queries via Apollo.\n * @see https://github.com/mswjs/msw/issues/510\n * @see https://www.apollographql.com/docs/router/executing-operations/query-batching\n */\nimport {\n  http,\n  graphql,\n  bypass,\n  HttpResponse,\n  getResponse,\n  RequestHandler,\n} from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (req, res) => {\n    res.json({\n      data: {\n        server: { url: httpServer.http.address.href },\n      },\n    })\n  })\n})\n\n/**\n * A higher-order request handler function that resolves any\n * batched GraphQL queries to the given URL against the list\n * of request handlers.\n */\nfunction batchedGraphQLQuery(url: string, handlers: Array<RequestHandler>) {\n  return http.post(url, async ({ request }) => {\n    const data = await request.json()\n\n    // Ignore GraphQL queries that are not batched queries.\n    if (!Array.isArray(data)) {\n      return\n    }\n\n    const responses = await Promise.all(\n      // Resolve each individual query against the existing\n      // array of GraphQL request handlers.\n      data.map(async (operation) => {\n        const scopedRequest = new Request(request, {\n          body: JSON.stringify(operation),\n        })\n        const response = await getResponse(handlers, scopedRequest)\n        return response || fetch(bypass(scopedRequest))\n      }),\n    )\n\n    // Read the mocked response JSON bodies to use\n    // in the response to the entire batched query.\n    const queryData = await Promise.all(\n      responses.map((response) => response?.json()),\n    )\n\n    return HttpResponse.json(queryData)\n  })\n}\n\nconst graphqlHandlers = [\n  graphql.query('GetUser', () => {\n    return HttpResponse.json({\n      data: {\n        user: { id: 1 },\n      },\n    })\n  }),\n  graphql.query('GetProduct', () => {\n    return HttpResponse.json({\n      data: {\n        product: { name: 'Hoover 2000' },\n      },\n    })\n  }),\n]\n\nconst server = setupServer(...graphqlHandlers)\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n\n  /**\n   * @note This handler doesn't have to be a runtime handler.\n   * This is a prerequisite of how MSW spawns a test server\n   * for this particular test. Move it to the top of the rest\n   * of your request handlers.\n   */\n  server.use(\n    batchedGraphQLQuery(httpServer.http.url('/graphql'), graphqlHandlers),\n  )\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('sends a mocked response to a batched GraphQL query', async () => {\n  const response = await fetch(httpServer.http.url('/graphql'), {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify([\n      {\n        query: `\n          query GetUser {\n            user {\n              id\n            }\n          }\n        `,\n      },\n      {\n        query: `\n          query GetProduct {\n            product {\n              name\n            }\n          }\n        `,\n      },\n    ]),\n  })\n\n  expect(await response.json()).toEqual([\n    {\n      data: { user: { id: 1 } },\n    },\n    {\n      data: { product: { name: 'Hoover 2000' } },\n    },\n  ])\n})\n\nit('combines mocked and original responses in a single batched query', async () => {\n  const response = await fetch(httpServer.http.url('/graphql'), {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify([\n      {\n        query: `\n          query GetUser {\n            user {\n              id\n            }\n          }\n        `,\n      },\n      {\n        query: `\n          query UnmockedQuery {\n            server {\n              url\n            }\n          }\n        `,\n      },\n    ]),\n  })\n\n  expect(await response.json()).toEqual([\n    {\n      data: { user: { id: 1 } },\n    },\n    {\n      data: { server: { url: httpServer.http.address.href } },\n    },\n  ])\n})\n"
  },
  {
    "path": "test/node/graphql-api/batched-queries.batched-execute.test.ts",
    "content": "/**\n * @vitest-environment node\n * Example of mocking batched GraphQL queries via \"batched-execute\".\n * @see https://github.com/mswjs/msw/issues/510\n * @see https://the-guild.dev/graphql/stitching/handbook/appendices/batching-arrays-and-queries\n */\nimport {\n  buildSchema,\n  graphql as executeGraphQL,\n  print,\n  defaultFieldResolver,\n} from 'graphql'\nimport { http, HttpResponse, GraphQLVariables, bypass } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { createGraphQLClient } from '../../support/graphql'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (req, res) => {\n    res.json({\n      data: {\n        server: { url: httpServer.http.address.href },\n      },\n    })\n  })\n})\n\nconst schema = buildSchema(`\n  type User {\n    id: ID!\n  }\n\n  type Product {\n    name: String!\n  }\n\n  type Server {\n    url: String!\n  }\n\n  type Query {\n    user: User\n    product: Product\n    server: Server\n  }\n`)\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.listen()\n  server.use(\n    http.post<never, { query: string; variables?: GraphQLVariables }>(\n      httpServer.http.url('/graphql'),\n      async ({ request }) => {\n        const data = await request.json()\n\n        // \"batched-execute\" produces a standard-compliant GraphQL query\n        // so you can resolve it against the mocked schema as-is!\n        const result = await executeGraphQL({\n          source: data.query,\n          variableValues: data.variables,\n          schema,\n          rootValue: {\n            // Since \"batched-execute\" produces a single query\n            // with individual queries as fields, you have to\n            // go with a field-based mocking.\n            user: () => ({ id: 'abc-123' }),\n            product: () => ({ name: 'Hoover 2000' }),\n          },\n          async fieldResolver(source, args, context, info) {\n            // Resolve known fields in \"rootValue\" as usual.\n            if (source[info.fieldName]) {\n              return defaultFieldResolver(source, args, context, info)\n            }\n\n            // Proxy the unknown fields to the actual GraphQL server.\n            const compiledQuery = info.fieldNodes\n              .map((node) => print(node))\n              .join('\\n')\n\n            const query = `${info.operation.operation} { ${compiledQuery} }`\n            const queryRequest = new Request(request, {\n              body: JSON.stringify({ query }),\n            })\n            const response = await fetch(bypass(queryRequest))\n            const { error, data } = await response.json()\n\n            if (error) {\n              throw error\n            }\n\n            return data[info.fieldName]\n          },\n        })\n\n        return HttpResponse.json(result)\n      },\n    ),\n  )\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('sends a mocked response to a batched GraphQL query', async () => {\n  const client = createGraphQLClient({\n    uri: httpServer.http.url('/graphql'),\n  })\n\n  const result = await client({\n    query: `\n      query {\n        user_0: user {\n          id\n        }\n        product_0: product {\n          name\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    user_0: { id: 'abc-123' },\n    product_0: { name: 'Hoover 2000' },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('combines mocked and original responses in a single batched query', async () => {\n  const client = createGraphQLClient({\n    uri: httpServer.http.url('/graphql'),\n  })\n\n  const result = await client({\n    query: `\n      query {\n        user_0: user {\n          id\n        }\n        server_0: server {\n          url\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    user_0: { id: 'abc-123' },\n    server_0: { url: httpServer.http.address.href },\n  })\n  expect.soft(result.errors).toEqual(undefined)\n})\n"
  },
  {
    "path": "test/node/graphql-api/compatibility.node.test.ts",
    "content": "// @vitest-environment node\nimport { graphql as executeGraphql, buildSchema } from 'graphql'\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\nconst schema = gql`\n  type User {\n    firstName: String!\n  }\n\n  type Query {\n    user: User!\n  }\n`\n\nconst server = setupServer(\n  graphql.query('GetUser', async ({ query }) => {\n    const executionResult = await executeGraphql({\n      schema: buildSchema(schema),\n      source: query,\n      rootValue: {\n        user: {\n          firstName: 'John',\n        },\n      },\n    })\n\n    return HttpResponse.json({\n      data: executionResult.data,\n      errors: executionResult.errors,\n    })\n  }),\n)\n\nconst client = createGraphQLClient({\n  uri: 'http://localhost:3000/graphql',\n})\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('fetches the data from a GraphQL schema', async () => {\n  const result = await client({\n    query: gql`\n      query GetUser {\n        user {\n          firstName\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    user: {\n      firstName: 'John',\n    },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('propagates execution errors', async () => {\n  const result = await client({\n    query: gql`\n      query GetUser {\n        user {\n          firstName\n          # Intentionally querying a non-existing field\n          # to cause a GraphQL error upon execution.\n          lastName\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toBeUndefined()\n  expect.soft(result.errors).toEqual([\n    expect.objectContaining({\n      message:\n        'Cannot query field \"lastName\" on type \"User\". Did you mean \"firstName\"?',\n    }),\n  ])\n})\n"
  },
  {
    "path": "test/node/graphql-api/content-type.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient } from '../../support/graphql'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with the \"application/json\" content type by default', async () => {\n  server.use(\n    graphql.query('GetUser', () => {\n      return HttpResponse.json({\n        data: { user: { name: 'John Maverick' } },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://any.host.here/irrelevant',\n  })\n\n  const result = await client({\n    query: `\n      query GetUser {\n        user {\n          name\n        }\n      }\n    `,\n  })\n\n  expect\n    .soft(result.response.headers.get('content-type'))\n    .toBe('application/json')\n  expect.soft(result.data).toEqual({ user: { name: 'John Maverick' } })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('responds with the \"application/graphql-response+json\" content type if the client accepts it', async () => {\n  server.use(\n    graphql.mutation('CreatePost', () => {\n      return HttpResponse.json({\n        data: { post: { id: 'abc-123' } },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://any.host.here/irrelevant',\n  })\n\n  {\n    const result = await client({\n      query: `\n        mutation CreatePost {\n          post {\n            id\n          }\n        }\n    `,\n      headers: {\n        accept: 'application/graphql-response+json',\n      },\n    })\n\n    expect\n      .soft(\n        result.response.headers.get('content-type'),\n        'Supports the new accept type exclusively',\n      )\n      .toBe('application/graphql-response+json')\n    expect.soft(result.data).toEqual({ post: { id: 'abc-123' } })\n    expect.soft(result.errors).toBeUndefined()\n  }\n\n  {\n    const result = await client({\n      query: `\n        mutation CreatePost {\n          post {\n            id\n          }\n        }\n    `,\n      headers: {\n        accept: 'application/graphql-response+json, application/json;q=0.9',\n      },\n    })\n\n    expect\n      .soft(\n        result.response.headers.get('content-type'),\n        'Supports a mix of the new and old accept types',\n      )\n      .toBe('application/graphql-response+json')\n    expect.soft(result.data).toEqual({ post: { id: 'abc-123' } })\n    expect.soft(result.errors).toBeUndefined()\n  }\n})\n\nit('respects the \"Accept\" request header quality', async () => {\n  server.use(\n    graphql.mutation('CreatePost', () => {\n      return HttpResponse.json({\n        data: { post: { id: 'abc-123' } },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://any.host.here/irrelevant',\n  })\n\n  {\n    const result = await client({\n      query: `\n        mutation CreatePost {\n          post {\n            id\n          }\n        }\n    `,\n      headers: {\n        accept: ' application/graphql-response+json;q=0.5, application/json',\n      },\n    })\n\n    expect\n      .soft(result.response.headers.get('content-type'))\n      .toBe('application/json')\n    expect.soft(result.data).toEqual({ post: { id: 'abc-123' } })\n    expect.soft(result.errors).toBeUndefined()\n  }\n})\n\nit('responds with the \"application/graphql-response+json\" in generator responses', async () => {\n  server.use(\n    graphql.query('GetForecast', function* () {\n      yield HttpResponse.json({\n        data: { forecast: { degrees: 25 } },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://any.host.here/irrelevant',\n  })\n\n  const result = await client({\n    query: `\n      query GetForecast {\n        forecast {\n          degrees\n        }\n      }\n    `,\n    headers: {\n      accept: 'application/graphql-response+json',\n    },\n  })\n\n  expect\n    .soft(result.response.headers.get('content-type'))\n    .toBe('application/graphql-response+json')\n  expect.soft(result.data).toEqual({ forecast: { degrees: 25 } })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('ignores request \"Accept\" preferences if an explicit \"content-type\" is set on the mocked response', async () => {\n  server.use(\n    graphql.query('GetUser', () => {\n      return HttpResponse.json(\n        {\n          data: { user: { name: 'John Maverick' } },\n        },\n        {\n          headers: {\n            // Simulating an old server that doesn't support the modern mime type.\n            'content-type': 'application/json',\n          },\n        },\n      )\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://any.host.here/irrelevant',\n  })\n\n  const result = await client({\n    query: `\n      query GetUser {\n        user {\n          name\n        }\n      }\n    `,\n    headers: {\n      accept: 'application/graphql-response+json',\n    },\n  })\n\n  expect\n    .soft(result.response.headers.get('content-type'))\n    .toBe('application/json')\n  expect.soft(result.data).toEqual({ user: { name: 'John Maverick' } })\n  expect.soft(result.errors).toBeUndefined()\n})\n"
  },
  {
    "path": "test/node/graphql-api/cookies.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('intercepts request cookies', async () => {\n  server.use(\n    graphql.query('GetSession', ({ cookies }) => {\n      return HttpResponse.json({\n        data: {\n          session: {\n            id: cookies.sessionId,\n          },\n        },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: gql`\n      query GetSession {\n        session {\n          id\n        }\n      }\n    `,\n    headers: {\n      cookie: 'sessionId=abc123',\n    },\n  })\n\n  expect.soft(result.data).toEqual({\n    session: { id: 'abc123' },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('mocks a single response cookie', async () => {\n  server.use(\n    graphql.mutation<{ user: { email: string } }, { email: string }>(\n      'SignIn',\n      ({ variables }) => {\n        return HttpResponse.json(\n          {\n            data: {\n              user: {\n                email: variables.email,\n              },\n            },\n          },\n          {\n            headers: {\n              'set-cookie': 'sessionId=abc-123',\n            },\n          },\n        )\n      },\n    ),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: gql`\n      mutation SignIn($email: String!) {\n        user {\n          email\n        }\n      }\n    `,\n    variables: {\n      email: 'test@example.com',\n    },\n  })\n\n  expect\n    .soft(result.response.headers.get('set-cookie'))\n    .toBe('sessionId=abc-123')\n  expect.soft(result.data).toEqual({\n    user: { email: 'test@example.com' },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('mocks a multi-value response cookie', async () => {\n  server.use(\n    graphql.mutation<{ user: { email: string } }, { email: string }>(\n      'SignIn',\n      ({ variables }) => {\n        return HttpResponse.json(\n          {\n            data: {\n              user: {\n                email: variables.email,\n              },\n            },\n          },\n          {\n            headers: [\n              ['set-cookie', 'sessionId=abc-123'],\n              ['set-cookie', 'userId=123'],\n            ],\n          },\n        )\n      },\n    ),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: gql`\n      mutation SignIn($email: String!) {\n        user {\n          email\n        }\n      }\n    `,\n    variables: {\n      email: 'test@example.com',\n    },\n  })\n\n  expect\n    .soft(result.response.headers.get('set-cookie'))\n    .toBe('sessionId=abc-123, userId=123')\n  expect.soft(result.data).toEqual({\n    user: { email: 'test@example.com' },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n"
  },
  {
    "path": "test/node/graphql-api/custom-predicate.node.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen({\n    onUnhandledRequest: 'bypass',\n  })\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('matches requests when the predicate function returns true', async () => {\n  server.use(\n    graphql.query(\n      ({ operationName }) => {\n        return operationName.toLowerCase().includes('user')\n      },\n      () => {\n        return HttpResponse.json({ data: { user: 1 } })\n      },\n    ),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: gql`\n      query GetUser {\n        user {\n          firstName\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({ user: 1 })\n  expect.soft(result.errors).toBeUndefined()\n})\n\nit('does not match requests when the predicate function returns false', async () => {\n  server.use(\n    graphql.query(\n      ({ operationName }) => {\n        return operationName.toLowerCase().includes('user')\n      },\n      () => {\n        return HttpResponse.json({ data: { user: 1 } })\n      },\n    ),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const requestError = await client({\n    query: gql`\n      query GetCart {\n        cart {\n          id\n        }\n      }\n    `,\n  }).catch((error) => error)\n\n  expect.soft(requestError).toBeInstanceOf(Error)\n  expect.soft(requestError.message).toEqual('fetch failed')\n})\n"
  },
  {
    "path": "test/node/graphql-api/extensions.node.test.ts",
    "content": "// @vitest-environment node\nimport { buildSchema, graphql as executeGraphql } from 'graphql'\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\nconst schema = gql`\n  type User {\n    firstName: String!\n  }\n\n  type Query {\n    user: User!\n  }\n`\n\nconst server = setupServer(\n  graphql.query('GetUser', async ({ query }) => {\n    const { data, errors } = await executeGraphql({\n      schema: buildSchema(schema),\n      source: query,\n      rootValue: {\n        user: {\n          firstName: 'John',\n        },\n      },\n    })\n\n    return HttpResponse.json({\n      data,\n      errors,\n      extensions: {\n        tracking: {\n          version: 1,\n          page: '/test',\n        },\n      },\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('adds extensions to the original response data', async () => {\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: gql`\n      query GetUser {\n        user {\n          firstName\n        }\n      }\n    `,\n  })\n\n  expect.soft(result.data).toEqual({\n    user: {\n      firstName: 'John',\n    },\n  })\n  expect.soft(result.errors).toBeUndefined()\n  expect.soft(result.extensions).toEqual({\n    tracking: {\n      version: 1,\n      page: '/test',\n    },\n  })\n})\n"
  },
  {
    "path": "test/node/graphql-api/response-patching.node.test.ts",
    "content": "// @vitest-environment node\nimport { bypass, graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { graphql as executeGraphql, buildSchema } from 'graphql'\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { createGraphQLClient, gql } from '../../support/graphql'\n\nconst server = setupServer(\n  graphql.query('GetUser', async ({ request }) => {\n    const originalResponse = await fetch(bypass(request))\n    const { requestHeaders, queryResult } = await originalResponse.json()\n\n    return HttpResponse.json({\n      data: {\n        user: {\n          firstName: 'Christian',\n          lastName: queryResult.data?.user?.lastName,\n        },\n        // Setting the request headers on the response data on purpose\n        // to access them in the response of the Apollo client.\n        requestHeaders,\n      },\n      errors: queryResult.errors,\n    })\n  }),\n)\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', async (req, res) => {\n    const result = await executeGraphql({\n      schema: buildSchema(gql`\n        type User {\n          firstName: String!\n          lastName: String!\n        }\n\n        # Describing an additional type to return\n        # the request headers back to the request handler.\n        # Apollo will strip off any extra data that\n        # doesn't match the query.\n        type RequestHeader {\n          name: String!\n          value: String!\n        }\n\n        type Query {\n          user: User!\n          requestHeaders: [RequestHeader!]\n        }\n      `),\n      operationName: 'GetUser',\n      source: req.body.query,\n      rootValue: {\n        user: {\n          firstName: 'John',\n          lastName: 'Maverick',\n        },\n      },\n    })\n\n    return res.status(200).json({\n      requestHeaders: req.headers,\n      queryResult: result,\n    })\n  })\n})\n\nbeforeAll(async () => {\n  server.listen()\n\n  // This test server acts as a production server MSW will be hitting\n  // when performing a request patching with `ctx.fetch()`.\n  await httpServer.listen()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('patches a GraphQL response', async () => {\n  const client = createGraphQLClient({\n    uri: httpServer.http.url('/graphql'),\n  })\n\n  const res = await client<{\n    user: {\n      firstName: string\n      lastName: string\n    }\n    requestHeaders: Record<string, string>\n  }>({\n    query: gql`\n      query GetUser {\n        user {\n          firstName\n          lastName\n        }\n        requestHeaders {\n          name\n          value\n        }\n      }\n    `,\n  })\n\n  expect(res.errors).toBeUndefined()\n  expect(res.data).toHaveProperty('user', {\n    firstName: 'Christian',\n    lastName: 'Maverick',\n  })\n  expect(res.data?.requestHeaders).toHaveProperty('accept', '*/*')\n  expect(res.data?.requestHeaders).not.toHaveProperty('_headers')\n  expect(res.data?.requestHeaders).not.toHaveProperty('_names')\n})\n"
  },
  {
    "path": "test/node/graphql-api/typed-document-node.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport {\n  gql,\n  createTypedDocumentNode,\n  createGraphQLClient,\n} from '../../support/graphql'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports TypedDocumentNode as request predicate', async () => {\n  const GET_USER = gql`\n    query GetUser($id: ID!) {\n      user(id: $id) {\n        id\n        name\n      }\n    }\n  `\n\n  const documentNode = createTypedDocumentNode<\n    { user: { id: string; name: string } },\n    { id: string }\n  >(GET_USER)\n\n  server.use(\n    graphql.query(documentNode, ({ variables }) => {\n      return HttpResponse.json({\n        data: {\n          user: {\n            id: variables.id,\n            name: 'John Doe',\n          },\n        },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: GET_USER,\n    variables: {\n      id: 'abc-123',\n    },\n  })\n\n  expect\n    .soft(result.data)\n    .toEqual({ user: { id: 'abc-123', name: 'John Doe' } })\n  expect.soft(result.errors).toBeUndefined()\n})\n"
  },
  {
    "path": "test/node/graphql-api/typed-document-string.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport {\n  gql,\n  createGraphQLClient,\n  createTypedDocumentString,\n} from '../../support/graphql'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports TypedDocumentString as request predicate', async () => {\n  const GET_USER = gql`\n    query GetUser($id: ID!) {\n      user(id: $id) {\n        id\n        name\n      }\n    }\n  `\n\n  const documentString = createTypedDocumentString<\n    { user: { id: string; name: string } },\n    { id: string }\n  >(GET_USER)\n\n  server.use(\n    graphql.query(documentString, ({ variables }) => {\n      return HttpResponse.json({\n        data: {\n          user: {\n            id: variables.id,\n            name: 'John Doe',\n          },\n        },\n      })\n    }),\n  )\n\n  const client = createGraphQLClient({\n    uri: 'http://localhost:3000/graphql',\n  })\n\n  const result = await client({\n    query: GET_USER,\n    variables: { id: 'abc-123' },\n  })\n\n  expect.soft(result.data).toEqual({\n    user: {\n      id: 'abc-123',\n      name: 'John Doe',\n    },\n  })\n  expect.soft(result.errors).toBeUndefined()\n})\n"
  },
  {
    "path": "test/node/msw-api/context/delay-infinite.fixture.js",
    "content": "import { delay, HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://any.host.here/irrelevant', async () => {\n    await delay('infinite')\n  }),\n)\n\nserver.listen()\n\nfetch('http://any.host.here/irrelevant')\n\nsetTimeout(() => {\n  server.close()\n}, 20)\n"
  },
  {
    "path": "test/node/msw-api/context/delay.node.test.ts",
    "content": "// @vitest-environment node\nimport { spawnSync } from 'node:child_process'\nimport { delay, HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { performance } from 'perf_hooks'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nasync function makeRequest(url: string) {\n  const requestStart = performance.now()\n  const res = await fetch(url)\n  const requestEnd = performance.now()\n  const responseTime = requestEnd - requestStart\n\n  return { res, responseTime }\n}\n\ntest('uses explicit server response time', async () => {\n  server.use(\n    http.get('http://localhost/user', async () => {\n      await delay(500)\n      return HttpResponse.text('john')\n    }),\n  )\n\n  const { res, responseTime } = await makeRequest('http://localhost/user')\n\n  expect(responseTime).toBeGreaterThanOrEqual(500)\n  await expect(res.text()).resolves.toBe('john')\n})\n\ntest('uses realistic server response time when no duration is provided', async () => {\n  server.use(\n    http.get('http://localhost/user', async () => {\n      await delay()\n      return HttpResponse.text('john')\n    }),\n  )\n\n  const { res, responseTime } = await makeRequest('http://localhost/user')\n\n  // Realistic server response time in Node.js is set to 5ms.\n  expect(responseTime).toBeGreaterThan(5)\n  await expect(res.text()).resolves.toBe('john')\n})\n\ntest('uses realistic server response time when \"real\" mode is provided', async () => {\n  server.use(\n    http.get('http://localhost/user', async () => {\n      await delay('real')\n      return HttpResponse.text('john')\n    }),\n  )\n\n  const { res, responseTime } = await makeRequest('http://localhost/user')\n\n  // Realistic server response time in Node.js is set to 5ms.\n  expect(responseTime).toBeGreaterThan(5)\n  await expect(res.text()).resolves.toBe('john')\n})\n\ntest('does not keep the process alive when using \"infinite\" delay', () => {\n  const result = spawnSync(\n    process.execPath,\n    [new URL('./delay-infinite.fixture.js', import.meta.url).pathname],\n    {\n      stdio: 'inherit',\n      timeout: 1000,\n    },\n  )\n\n  expect.soft(result.status).toBe(0)\n  expect.soft(result.error).toBeUndefined()\n})\n"
  },
  {
    "path": "test/node/msw-api/req/passthrough.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, passthrough, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.post<never, ResponseBody>('/user', (req, res) => {\n    res.json({ name: 'John' })\n  })\n  app.post('/code/:code', (req, res) => {\n    res.status(parseInt(req.params.code)).send()\n  })\n})\n\nconst server = setupServer()\n\ninterface ResponseBody {\n  name: string\n}\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nbeforeEach(() => {\n  vi.spyOn(console, 'warn').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.restoreAllMocks()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('performs request as-is when returning \"req.passthrough\" call in the resolver', async () => {\n  const endpointUrl = httpServer.http.url('/user')\n  server.use(\n    http.post<ResponseBody>(endpointUrl, () => {\n      return passthrough()\n    }),\n  )\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const json = await res.json()\n\n  expect(json).toEqual<ResponseBody>({\n    name: 'John',\n  })\n  expect(console.warn).not.toHaveBeenCalled()\n})\n\nit('does not allow fall-through when returning \"req.passthrough\" call in the resolver', async () => {\n  const endpointUrl = httpServer.http.url('/user')\n  server.use(\n    http.post<ResponseBody>(endpointUrl, () => {\n      return passthrough()\n    }),\n    http.post<ResponseBody>(endpointUrl, () => {\n      return HttpResponse.json({ name: 'Kate' })\n    }),\n  )\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const json = await res.json()\n\n  expect(json).toEqual<ResponseBody>({\n    name: 'John',\n  })\n  expect(console.warn).not.toHaveBeenCalled()\n})\n\nit('performs a request as-is if nothing was returned from the resolver', async () => {\n  const endpointUrl = httpServer.http.url('/user')\n  server.use(\n    http.post<ResponseBody>(endpointUrl, () => {\n      return\n    }),\n  )\n\n  const res = await fetch(endpointUrl, { method: 'POST' })\n  const json = await res.json()\n\n  expect(json).toEqual<ResponseBody>({\n    name: 'John',\n  })\n})\n\nfor (const code of [204, 205, 304]) {\n  it(`performs a ${code} request as-is if nothing was returned from the resolver`, async () => {\n    const endpointUrl = httpServer.http.url(`/code/${code}`)\n    server.use(\n      http.post<ResponseBody>(endpointUrl, () => {\n        return\n      }),\n    )\n\n    const res = await fetch(endpointUrl, { method: 'POST' })\n\n    expect(res.status).toEqual(code)\n  })\n\n  it(`performs a ${code} request as-is if passthrough was returned from the resolver`, async () => {\n    const endpointUrl = httpServer.http.url(`/code/${code}`)\n    server.use(\n      http.post<ResponseBody>(endpointUrl, () => {\n        return passthrough()\n      }),\n    )\n\n    const res = await fetch(endpointUrl, { method: 'POST' })\n\n    expect(res.status).toEqual(code)\n  })\n}\n"
  },
  {
    "path": "test/node/msw-api/res/network-error.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://example.com/user', () => {\n    return HttpResponse.error()\n  }),\n)\n\nbeforeAll(() => server.listen())\nafterAll(() => server.close())\n\ntest('throws a network error when used with fetch', async () => {\n  await expect(fetch('http://example.com/user')).rejects.toThrow(\n    'Failed to fetch',\n  )\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/boundary/boundary.args.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit.concurrent('forwards arguments to the callback function', async () => {\n  server.boundary((...args) => {\n    expect(args).toEqual([1, { 2: true }, [3]])\n  })(1, { 2: true }, [3])\n})\n\nit.concurrent('returns the result of the callback function', async () => {\n  const result = server.boundary((number: number) => {\n    return number * 10\n  })(2)\n\n  expect(result).toBe(20)\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/boundary/boundary.concurrency.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('/initial', () => {\n    return HttpResponse.text('initial')\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ndescribe.concurrent('concurrent tests', () => {\n  it(\n    'resolves request against the initial handlers',\n    server.boundary(async () => {\n      const response = await fetch('/initial')\n      expect(response.status).toBe(200)\n      expect(await response.text()).toBe('initial')\n    }),\n  )\n\n  it(\n    'resolves request against the in-test handler override',\n    server.boundary(async () => {\n      server.use(\n        http.get('/initial', () => {\n          return HttpResponse.text('override')\n        }),\n      )\n\n      const response = await fetch('/initial')\n      expect(response.status).toBe(200)\n      expect(await response.text()).toBe('override')\n    }),\n  )\n\n  it(\n    'resolves requests against the initial handlers again',\n    server.boundary(async () => {\n      const response = await fetch('/initial')\n      expect(response.status).toBe(200)\n      expect(await response.text()).toBe('initial')\n    }),\n  )\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/boundary/boundary.handlers.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('https://example.com', () => {\n    return HttpResponse.json({ name: 'John' })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit.concurrent(\n  'treats higher scope handlers as initial handlers',\n  server.boundary(async () => {\n    expect(\n      await await fetch('https://example.com').then((response) =>\n        response.json(),\n      ),\n    ).toEqual({ name: 'John' })\n\n    server.use(\n      http.get('https://example.com', () => {\n        return HttpResponse.json({ override: true })\n      }),\n    )\n    expect(\n      await await fetch('https://example.com').then((response) =>\n        response.json(),\n      ),\n    ).toEqual({ override: true })\n  }),\n)\n\nit.concurrent(\n  'resets the runtime handlers to the initial handlers',\n  server.boundary(async () => {\n    server.use(\n      http.get('https://example.com', () => {\n        return HttpResponse.json({ override: true })\n      }),\n    )\n    expect(\n      await await fetch('https://example.com').then((response) =>\n        response.json(),\n      ),\n    ).toEqual({ override: true })\n\n    server.resetHandlers()\n\n    expect(\n      await await fetch('https://example.com').then((response) =>\n        response.json(),\n      ),\n    ).toEqual({ name: 'John' })\n  }),\n)\n\nit.concurrent(\n  'treats the higher boundary handlers as initial handlers for nested boundary',\n  server.boundary(async () => {\n    server.use(\n      http.get('https://example.com', () => {\n        return HttpResponse.json({ override: true })\n      }),\n    )\n\n    await server.boundary(async () => {\n      expect(\n        await await fetch('https://example.com').then((response) =>\n          response.json(),\n        ),\n      ).toEqual({ override: true })\n\n      server.resetHandlers()\n\n      // Reset does nothing at this point because no runtime\n      // request handlers were added within this boundary.\n      expect(\n        await await fetch('https://example.com').then((response) =>\n          response.json(),\n        ),\n      ).toEqual({ override: true })\n\n      server.use(\n        http.get('https://example.com', () => {\n          return HttpResponse.json({ nested: true })\n        }),\n      )\n\n      expect(\n        await await fetch('https://example.com').then((response) =>\n          response.json(),\n        ),\n      ).toEqual({ nested: true })\n    })\n  }),\n)\n"
  },
  {
    "path": "test/node/msw-api/setup-server/input-validation.node.test.ts",
    "content": "import { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\ntest('throws an error given an Array of request handlers to \"setupServer\"', () => {\n  const createServer = () => {\n    // @ts-expect-error intentionally invalid parameters for setupServer to force it to throw\n    return setupServer([\n      http.get('https://test.mswjs.io/book/:bookId', () => {\n        return HttpResponse.json({ title: 'Original title' })\n      }),\n    ])\n  }\n\n  expect(createServer).toThrow(\n    `[MSW] Failed to apply given request handlers: invalid input. Did you forget to spread the request handlers Array?`,\n  )\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/life-cycle-events/on.node.test.ts",
    "content": "// @vitest-environment node\nimport { HttpResponse, http } from 'msw'\nimport { SetupServerApi, setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => res.status(500).end())\n  app.post('/no-response', (req, res) => res.send('original-response'))\n  app.get('/unknown-route', (req, res) => res.send('majestic-unknown'))\n})\n\nconst server = setupServer()\n\nfunction spyOnEvents(server: SetupServerApi) {\n  const listener = vi.fn()\n  const wrapListener = (eventName: string, listener: any) => {\n    return (...args) => listener(eventName, ...args)\n  }\n\n  server.events.on('request:start', wrapListener('request:start', listener))\n  server.events.on('request:match', wrapListener('request:match', listener))\n  server.events.on(\n    'request:unhandled',\n    wrapListener('request:unhandled', listener),\n  )\n  server.events.on('request:end', wrapListener('request:end', listener))\n  server.events.on('response:mocked', wrapListener('response:mocked', listener))\n  server.events.on('response:bypass', wrapListener('response:bypass', listener))\n  server.events.on(\n    'unhandledException',\n    wrapListener('unhandledException', listener),\n  )\n\n  return listener\n}\n\nbeforeAll(async () => {\n  // Supress \"Expected a mocking resolver function to return a mocked response\"\n  // warnings when hitting intentionally empty resolver.\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n\n  await httpServer.listen()\n\n  server.use(\n    http.get(httpServer.http.url('/user'), () => {\n      return HttpResponse.text('response-body')\n    }),\n    http.post(httpServer.http.url('/no-response'), () => {\n      return\n    }),\n    http.get(httpServer.http.url('/unhandled-exception'), () => {\n      throw new Error('Unhandled resolver error')\n    }),\n  )\n  server.listen()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('emits events for a handled request and mocked response', async () => {\n  const listener = spyOnEvents(server)\n  const url = httpServer.http.url('/user')\n  await fetch(url)\n\n  expect(listener).toHaveBeenNthCalledWith(\n    1,\n    'request:start',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId: expect.any(String),\n    }),\n  )\n\n  const { requestId } = listener.mock.calls[0][1]\n\n  expect(listener).toHaveBeenNthCalledWith(\n    2,\n    'request:match',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n    }),\n  )\n  expect(listener).toHaveBeenNthCalledWith(\n    3,\n    'request:end',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n    }),\n  )\n  expect(listener).toHaveBeenNthCalledWith(\n    4,\n    'response:mocked',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n      response: expect.any(Response),\n    }),\n  )\n\n  const { response } = listener.mock.calls[3][1]\n  expect(response.status).toBe(200)\n  expect(response.statusText).toBe('OK')\n  expect(await response.text()).toBe('response-body')\n\n  expect(listener).toHaveBeenCalledTimes(4)\n})\n\ntest('emits events for a handled request with no response', async () => {\n  const listener = spyOnEvents(server)\n  const url = httpServer.http.url('/no-response')\n  await fetch(url, { method: 'POST' })\n\n  expect(listener).toHaveBeenNthCalledWith(\n    1,\n    'request:start',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'POST',\n        url,\n      }),\n      requestId: expect.any(String),\n    }),\n  )\n\n  const { requestId } = listener.mock.calls[0][1]\n\n  expect(listener).toHaveBeenNthCalledWith(\n    2,\n    'request:end',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'POST',\n        url,\n      }),\n      requestId,\n    }),\n  )\n  expect(listener).toHaveBeenNthCalledWith(\n    3,\n    'response:bypass',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'POST',\n        url,\n      }),\n      requestId,\n      response: expect.any(Response),\n    }),\n  )\n\n  const { response } = listener.mock.calls[2][1]\n  expect(response.status).toBe(200)\n  expect(response.statusText).toBe('OK')\n  expect(await response.text()).toBe('original-response')\n\n  expect(listener).toHaveBeenCalledTimes(3)\n})\n\ntest('emits events for an unhandled request', async () => {\n  const listener = spyOnEvents(server)\n  const url = httpServer.http.url('/unknown-route')\n  await fetch(url)\n\n  expect(listener).toHaveBeenNthCalledWith(\n    1,\n    'request:start',\n    expect.objectContaining({\n      request: expect.any(Request),\n      requestId: expect.any(String),\n    }),\n  )\n\n  const { requestId } = listener.mock.calls[0][1]\n\n  expect(listener).toHaveBeenNthCalledWith(\n    2,\n    'request:unhandled',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n    }),\n  )\n  expect(listener).toHaveBeenNthCalledWith(\n    3,\n    'request:end',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n    }),\n  )\n\n  expect(listener).toHaveBeenNthCalledWith(\n    4,\n    'response:bypass',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n      response: expect.any(Response),\n    }),\n  )\n\n  const { response } = listener.mock.calls[3][1]\n  expect(response.status).toBe(200)\n  expect(response.statusText).toBe('OK')\n  expect(await response.text()).toBe('majestic-unknown')\n\n  expect(listener).toHaveBeenCalledTimes(4)\n})\n\ntest('emits unhandled exceptions in the request handler', async () => {\n  const listener = spyOnEvents(server)\n  const url = httpServer.http.url('/unhandled-exception')\n  await fetch(url).catch(() => undefined)\n\n  expect(listener).toHaveBeenNthCalledWith(\n    1,\n    'request:start',\n    expect.objectContaining({\n      request: expect.any(Request),\n      requestId: expect.any(String),\n    }),\n  )\n\n  const { requestId } = listener.mock.calls[0][1]\n\n  expect(listener).toHaveBeenNthCalledWith(\n    2,\n    'unhandledException',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n      error: new Error('Unhandled resolver error'),\n    }),\n  )\n\n  /**\n   * @note The fallback 500 response still counts as a mocked response.\n   * I'm torn on this but I believe we should indicate that the request\n   * (a) received a response; (b) that response was mocked.\n   */\n  expect(listener).toHaveBeenNthCalledWith(\n    3,\n    'response:mocked',\n    expect.objectContaining({\n      request: expect.objectContaining({\n        method: 'GET',\n        url,\n      }),\n      requestId,\n      response: expect.any(Response),\n    }),\n  )\n\n  const { response } = listener.mock.calls[2][1]\n  expect(response.status).toBe(500)\n  expect(response.statusText).toBe('Unhandled Exception')\n\n  expect(listener).toHaveBeenCalledTimes(3)\n})\n\ntest('stops emitting events once the server is stopped', async () => {\n  const listener = spyOnEvents(server)\n  server.close()\n\n  await fetch(httpServer.http.url('/user'))\n\n  expect(listener).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/life-cycle-events/removeAllListeners.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.status(500).end()\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.use(\n    http.get(httpServer.http.url('/user'), () => {\n      return HttpResponse.json({ firstName: 'John' })\n    }),\n  )\n  server.listen()\n})\n\nafterEach(() => {\n  vi.restoreAllMocks()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('removes all listeners attached to the server instance', async () => {\n  const listeners = {\n    requestStart: vi.fn(),\n    requestEnd: vi.fn(),\n  }\n  server.events.on('request:start', listeners.requestStart)\n  server.events.on('request:end', listeners.requestEnd)\n\n  await fetch(httpServer.http.url('/user'))\n  expect(listeners.requestStart).toHaveBeenCalledTimes(1)\n  expect(listeners.requestEnd).toHaveBeenCalledTimes(1)\n  listeners.requestStart.mockReset()\n  listeners.requestEnd.mockReset()\n\n  server.events.removeAllListeners()\n\n  await fetch(httpServer.http.url('/user'))\n  expect(listeners.requestStart).not.toHaveBeenCalled()\n  expect(listeners.requestEnd).not.toHaveBeenCalled()\n})\n\ntest('removes all the listeners by the event name', async () => {\n  const listeners = {\n    requestStart: vi.fn(),\n    requestEnd: vi.fn(),\n  }\n  server.events.on('request:start', listeners.requestStart)\n  server.events.on('request:start', listeners.requestStart)\n  server.events.on('request:start', listeners.requestStart)\n  server.events.on('request:end', listeners.requestEnd)\n  server.events.removeAllListeners('request:start')\n\n  await fetch(httpServer.http.url('/user'))\n  expect(listeners.requestStart).not.toHaveBeenCalled()\n  expect(listeners.requestEnd).toHaveBeenCalledTimes(1)\n})\n\ntest('does not remove the internal listeners', async () => {\n  const listeners = {\n    requestStart: vi.fn(),\n    responseMocked: vi.fn(),\n  }\n\n  server.events.on('request:start', listeners.requestStart)\n  server.events.removeAllListeners()\n  // The \"response:*\" events in Node.js are propagated from the interceptors library.\n  // MSW adds an internal listener to react to those events from the interceptors.\n  server.events.on('response:mocked', listeners.responseMocked)\n\n  await fetch(httpServer.http.url('/user'))\n  expect(listeners.requestStart).not.toHaveBeenCalled()\n  expect(listeners.responseMocked).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/life-cycle-events/removeListener.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.status(500).end()\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.use(\n    http.get(httpServer.http.url('/user'), () => {\n      return HttpResponse.json({ firstName: 'John' })\n    }),\n  )\n  server.listen()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('removes a listener by the event name', async () => {\n  const listeners = {\n    requestStart: vi.fn(),\n    requestEnd: vi.fn(),\n  }\n  server.events.on('request:start', listeners.requestStart)\n  server.events.on('request:end', listeners.requestEnd)\n\n  server.events.removeListener('request:start', listeners.requestStart)\n\n  await fetch(httpServer.http.url('/user'))\n  expect(listeners.requestStart).not.toHaveBeenCalled()\n  expect(listeners.requestEnd).toHaveBeenCalledTimes(1)\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/listHandlers.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http, graphql } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst resolver = () => null\nconst github = graphql.link('https://api.github.com')\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/book/:bookId', resolver),\n  graphql.query('GetUser', resolver),\n  graphql.mutation('UpdatePost', resolver),\n  graphql.operation(resolver),\n  github.query('GetRepo', resolver),\n  github.operation(resolver),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('lists all current request handlers', () => {\n  const handlers = server.listHandlers()\n  const handlerHeaders = handlers.map((handler) => handler.info.header)\n\n  expect(handlerHeaders).toEqual([\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetUser (origin: *)',\n    'mutation UpdatePost (origin: *)',\n    'all (origin: *)',\n    'query GetRepo (origin: https://api.github.com)',\n    'all (origin: https://api.github.com)',\n  ])\n})\n\ntest('forbids from modifying the list of handlers', () => {\n  const handlers = server.listHandlers()\n\n  expect(() => {\n    // @ts-expect-error Intentional runtime misusage.\n    handlers[0] = 1\n  }).toThrow(/Cannot assign to read only property '\\d+' of object/)\n\n  expect(() => {\n    // @ts-expect-error Intentional runtime misusage.\n    handlers.push(1)\n  }).toThrow(/Cannot add property \\d+, object is not extensible/)\n})\n\ntest('includes runtime request handlers when listing handlers', () => {\n  server.use(\n    http.get('https://test.mswjs.io/book/:bookId', resolver),\n    graphql.query('GetRandomNumber', resolver),\n  )\n\n  const handlers = server.listHandlers()\n  const handlerHeaders = handlers.map((handler) => handler.info.header)\n\n  expect(handlerHeaders).toEqual([\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetRandomNumber (origin: *)',\n    'GET https://test.mswjs.io/book/:bookId',\n    'query GetUser (origin: *)',\n    'mutation UpdatePost (origin: *)',\n    'all (origin: *)',\n    'query GetRepo (origin: https://api.github.com)',\n    'all (origin: https://api.github.com)',\n  ])\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/resetHandlers.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/books', () => {\n    return HttpResponse.json({ title: 'Original title' })\n  }),\n)\n\nbeforeAll(() => {\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n  server.listen()\n})\n\nafterAll(() => {\n  vi.restoreAllMocks()\n  server.close()\n})\n\ntest('removes all runtime request handlers when resetting without explicit next handlers', async () => {\n  server.use(\n    http.post('https://test.mswjs.io/login', () => {\n      return HttpResponse.json({ accepted: true })\n    }),\n  )\n\n  // Request handlers added on runtime affect the network communication.\n  const loginResponse = await fetch('https://test.mswjs.io/login', {\n    method: 'POST',\n  })\n  const loginBody = await loginResponse.json()\n  expect(loginResponse.status).toBe(200)\n  expect(loginBody).toEqual({ accepted: true })\n\n  // Once reset, all the runtime request handlers are removed.\n  server.resetHandlers()\n\n  const secondLoginResponse = await fetch('https://test.mswjs.io/login', {\n    method: 'POST',\n  })\n  expect(secondLoginResponse.status).toBe(404)\n\n  // Initial request handlers (given to `setupServer`) are not affected.\n  const booksResponse = await fetch('https://test.mswjs.io/books')\n  const booksBody = await booksResponse.json()\n  expect(booksResponse.status).toBe(200)\n  expect(booksBody).toEqual({ title: 'Original title' })\n})\n\ntest('replaces all handlers with the explicit next runtime handlers upon reset', async () => {\n  server.use(\n    http.post('https://test.mswjs.io/login', () => {\n      return HttpResponse.json({ accepted: true })\n    }),\n  )\n\n  // Once reset with explicit next request handlers,\n  // replaces all present request handlers with those.\n  server.resetHandlers(\n    http.get('https://test.mswjs.io/products', () => {\n      return HttpResponse.json([1, 2, 3])\n    }),\n  )\n\n  const loginResponse = await fetch('https://test.mswjs.io/login')\n  expect(loginResponse.status).toBe(404)\n\n  const booksResponse = await fetch('https://test.mswjs.io/books')\n  expect(booksResponse.status).toBe(404)\n\n  const productsResponse = await fetch('https://test.mswjs.io/products')\n  const productsBody = await productsResponse.json()\n  expect(productsResponse.status).toBe(200)\n  expect(productsBody).toEqual([1, 2, 3])\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/restoreHandlers.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/book/:bookId', () => {\n    return HttpResponse.json({ title: 'Original title' })\n  }),\n)\n\nbeforeAll(() => server.listen())\nafterAll(() => server.close())\n\ntest('returns a mocked response from the used one-time request handler when restored', async () => {\n  server.use(\n    http.get(\n      'https://test.mswjs.io/book/:bookId',\n      () => {\n        return HttpResponse.json({ title: 'Overridden title' })\n      },\n      { once: true },\n    ),\n  )\n\n  const firstResponse = await fetch('https://test.mswjs.io/book/abc-123')\n  const firstBody = await firstResponse.json()\n  expect(firstResponse.status).toBe(200)\n  expect(firstBody).toEqual({ title: 'Overridden title' })\n\n  const secondResponse = await fetch('https://test.mswjs.io/book/abc-123')\n  const secondBody = await secondResponse.json()\n  expect(secondResponse.status).toBe(200)\n  expect(secondBody).toEqual({ title: 'Original title' })\n\n  server.restoreHandlers()\n\n  const thirdResponse = await fetch('https://test.mswjs.io/book/abc-123')\n  const thirdBody = await thirdResponse.json()\n  expect(firstResponse.status).toBe(200)\n  expect(thirdBody).toEqual({ title: 'Overridden title' })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/cookies-request.node.test.ts",
    "content": "// @vitest-environment node\nimport https from 'https'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { httpsAgent, HttpServer } from '@open-draft/test-server/http'\nimport { waitForClientRequest } from '../../../../support/utils'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.json({ works: false })\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('exposes request cookies', async () => {\n  const endpointUrl = httpServer.https.url('/user')\n\n  server.use(\n    http.get(endpointUrl, ({ cookies }) => {\n      return HttpResponse.json({ cookies })\n    }),\n  )\n\n  const url = new URL(endpointUrl)\n\n  const request = https.get({\n    protocol: url.protocol,\n    hostname: url.hostname,\n    path: url.pathname,\n    port: url.port,\n    headers: {\n      Cookie: 'auth-token=abc-123',\n    },\n    agent: httpsAgent,\n  })\n  const { responseText } = await waitForClientRequest(request)\n\n  expect(responseText).toBe('{\"cookies\":{\"auth-token\":\"abc-123\"}}')\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/custom-interceptors.node.test.ts",
    "content": "// @vitest-environment node\nimport nodeHttp from 'node:http'\nimport { HttpResponse, http } from 'msw'\nimport { SetupServerApi } from 'msw/node'\nimport { FetchInterceptor } from '@mswjs/interceptors/fetch'\nimport { waitForClientRequest } from '../../../../support/utils'\n\nconst server = new SetupServerApi(\n  [\n    http.get('http://localhost', () => {\n      return HttpResponse.text('hello world')\n    }),\n  ],\n  [new FetchInterceptor()],\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('uses only the provided interceptors', async () => {\n  {\n    const response = await fetch('http://localhost')\n\n    // Must receive a mocked response per the defined interceptor + handler.\n    expect(response.status).toBe(200)\n    await expect(response.text()).resolves.toBe('hello world')\n  }\n\n  {\n    const request = nodeHttp.get('http://localhost')\n    const requestPromise = waitForClientRequest(request)\n\n    // Must receive a connection error since no intereceptor handles this client.\n    await expect(requestPromise).rejects.toThrow('ECONNREFUSED')\n  }\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/custom-transformers.node.test.ts",
    "content": "import * as JSONbig from 'json-bigint'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://test.mswjs.io/me', () => {\n    return new HttpResponse(\n      JSONbig.stringify({\n        username: 'john.maverick',\n        balance: BigInt(1597928668063727616),\n      }),\n      {\n        headers: {\n          'Content-Tpye': 'application/json',\n        },\n      },\n    )\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('uses custom response transformer to stringify response body', async () => {\n  const res = await fetch('http://test.mswjs.io/me')\n  const body = await res.text()\n\n  expect(body).toEqual(\n    JSONbig.stringify({\n      username: 'john.maverick',\n      balance: BigInt(1597928668063727616),\n    }),\n  )\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/fake-timers.node.test.ts",
    "content": "// @vitest-environment node\nimport { setupServer } from 'msw/node'\nimport { HttpResponse, http } from 'msw'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/pull', () => {\n    return HttpResponse.json({ status: 'pulled' })\n  }),\n)\n\nbeforeAll(() => server.listen())\nafterAll(() => server.close())\n\ntest('tolerates fake timers', async () => {\n  vi.useFakeTimers()\n\n  const res = await fetch('https://test.mswjs.io/pull')\n  const body = await res.json()\n\n  vi.useRealTimers()\n\n  expect(body).toEqual({ status: 'pulled' })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/fall-through.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst log = vi.fn()\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/*', () => log('[get] first')),\n  http.get('https://test.mswjs.io/us*', () => log('[get] second')),\n  http.get('https://test.mswjs.io/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n  http.get('https://test.mswjs.io/user', () => log('[get] third')),\n\n  http.post('https://test.mswjs.io/blog/*', () => log('[post] first')),\n  http.post('https://test.mswjs.io/blog/article', () => log('[post] second')),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('falls through all relevant request handlers until response is returned', async () => {\n  const res = await fetch('https://test.mswjs.io/user')\n  const body = await res.json()\n\n  expect(body).toEqual({\n    firstName: 'John',\n  })\n  expect(log).toHaveBeenNthCalledWith(1, '[get] first')\n  expect(log).toHaveBeenNthCalledWith(2, '[get] second')\n  expect(log).not.toBeCalledWith('[get] third')\n})\n\ntest('falls through all relevant handlers even if none return response', async () => {\n  const res = await fetch('https://test.mswjs.io/blog/article', {\n    method: 'POST',\n  })\n  const { status } = res\n\n  expect(status).toBe(404)\n  expect(log).toHaveBeenNthCalledWith(1, '[post] first')\n  expect(log).toHaveBeenNthCalledWith(2, '[post] second')\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/fetch.node.test.ts",
    "content": "import { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://test.mswjs.io', () => {\n    return HttpResponse.json(\n      {\n        firstName: 'John',\n        age: 32,\n      },\n      {\n        status: 401,\n        headers: {\n          'X-Header': 'yes',\n        },\n      },\n    )\n  }),\n  http.post('https://test.mswjs.io', async ({ request }) => {\n    return HttpResponse.json(await request.json(), {\n      status: 403,\n      headers: {\n        'X-Header': 'yes',\n      },\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('returns a mocked response to a GET request using fetch', async () => {\n  const res = await fetch('http://test.mswjs.io')\n\n  expect(res.status).toEqual(401)\n  expect(res.headers.get('content-type')).toEqual('application/json')\n  expect(res.headers.get('x-header')).toEqual('yes')\n\n  expect(await res.json()).toEqual({\n    firstName: 'John',\n    age: 32,\n  })\n})\n\nit('returns a mocked response to a POST request using fetch', async () => {\n  const res = await fetch('https://test.mswjs.io', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({\n      payload: 'info',\n    }),\n  })\n\n  expect(res.status).toEqual(403)\n  expect(res.headers.get('content-type')).toEqual('application/json')\n  expect(res.headers.get('x-header')).toEqual('yes')\n  expect(await res.json()).toEqual({\n    payload: 'info',\n  })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/generator.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get<{ maxCount: string }>(\n    'https://example.com/polling/:maxCount',\n    function* ({ params }) {\n      const maxCount = parseInt(params.maxCount)\n      let count = 0\n\n      while (count < maxCount) {\n        count += 1\n        yield HttpResponse.json({\n          status: 'pending',\n          count,\n        })\n      }\n\n      return HttpResponse.json({\n        status: 'complete',\n        count,\n      })\n    },\n  ),\n\n  http.get<{ maxCount: string }>(\n    'https://example.com/polling/once/:maxCount',\n    function* ({ params }) {\n      const maxCount = parseInt(params.maxCount)\n      let count = 0\n\n      while (count < maxCount) {\n        count += 1\n        yield HttpResponse.json({\n          status: 'pending',\n          count,\n        })\n      }\n\n      return HttpResponse.json({\n        status: 'complete',\n        count,\n      })\n    },\n    { once: true },\n  ),\n  http.get<{ maxCount: string }>(\n    'https://example.com/polling/once/:maxCount',\n    () => {\n      return HttpResponse.json({ status: 'done' })\n    },\n  ),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('supports generator as the response resolver', async () => {\n  type ExpectedResponseBody = {\n    status: 'pending' | 'complete'\n    count: number\n  }\n\n  const assertRequest = async (expectedBody: ExpectedResponseBody) => {\n    const res = await fetch('https://example.com/polling/3')\n    const body = await res.json()\n    expect(res.status).toBe(200)\n    expect(body).toEqual(expectedBody)\n  }\n\n  await assertRequest({ status: 'pending', count: 1 })\n  await assertRequest({ status: 'pending', count: 2 })\n  await assertRequest({ status: 'pending', count: 3 })\n\n  // Once the generator is done, any subsequent requests\n  // return the last mocked response.\n  await assertRequest({ status: 'complete', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n})\n\ntest('supports one-time handlers with the generator as the response resolver', async () => {\n  type ExpectedResponseBody =\n    | {\n        status: 'pending' | 'complete'\n        count: number\n      }\n    | { status: 'done' }\n\n  const assertRequest = async (expectedBody: ExpectedResponseBody) => {\n    const res = await fetch('https://example.com/polling/once/3')\n    const body = await res.json()\n    expect(res.status).toBe(200)\n    expect(body).toEqual(expectedBody)\n  }\n\n  await assertRequest({ status: 'pending', count: 1 })\n  await assertRequest({ status: 'pending', count: 2 })\n  await assertRequest({ status: 'pending', count: 3 })\n  await assertRequest({ status: 'complete', count: 3 })\n\n  // Since the last response from the one-time handler\n  // has been returned, it falls through to the next one.\n  await assertRequest({ status: 'done' })\n  await assertRequest({ status: 'done' })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/graphql.node.test.ts",
    "content": "// @vitest-environment node\nimport { graphql, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { createGraphQLClient, gql } from '../../../../support/graphql'\n\nconst apolloClient = createGraphQLClient({\n  uri: 'http://localhost:3000',\n})\n\nconst GET_USER_DETAIL = gql`\n  query GetUserDetail($userId: String!) {\n    user {\n      id\n      firstName\n      age\n    }\n  }\n`\n\nconst LOGIN = gql`\n  mutation Login($username: String!) {\n    user {\n      id\n    }\n  }\n`\n\nconst server = setupServer(\n  graphql.query('GetUserDetail', ({ variables }) => {\n    const { userId } = variables\n\n    return HttpResponse.json({\n      data: {\n        user: {\n          id: userId,\n          firstName: 'John',\n          age: 32,\n        },\n      },\n    })\n  }),\n  graphql.mutation('Login', ({ variables }) => {\n    const { username } = variables\n\n    return HttpResponse.json({\n      errors: [\n        {\n          message: `User \"${username}\" is not found`,\n          locations: [\n            {\n              line: 12,\n              column: 4,\n            },\n          ],\n        },\n      ],\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('returns the mocked response for a GraphQL query', async () => {\n  const res = await apolloClient({\n    query: GET_USER_DETAIL,\n    variables: {\n      userId: 'abc-123',\n    },\n  })\n\n  expect(res.errors).toBeUndefined()\n  expect(res.data).toEqual({\n    user: {\n      firstName: 'John',\n      age: 32,\n      id: 'abc-123',\n    },\n  })\n})\n\nit('returns the mocked response for a GraphQL mutation', async () => {\n  const res = await apolloClient({\n    query: LOGIN,\n    variables: {\n      username: 'john',\n    },\n  })\n\n  expect(res.data).toBeUndefined()\n  expect(res.errors).toEqual([\n    {\n      message: `User \"john\" is not found`,\n      locations: [\n        {\n          line: 12,\n          column: 4,\n        },\n      ],\n    },\n  ])\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/http.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport nodeHttp from 'http'\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { waitForClientRequest } from '../../../../support/utils'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/resource', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nbeforeEach(() => {\n  server.use(\n    http.get(httpServer.http.url('/resource'), () => {\n      return HttpResponse.json(\n        { firstName: 'John' },\n        {\n          status: 401,\n          headers: {\n            'x-header': 'yes',\n          },\n        },\n      )\n    }),\n  )\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('returns a mocked response to an \"http.get\" request', async () => {\n  const request = nodeHttp.get(httpServer.http.url('/resource'))\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n\nit('returns a mocked response to an \"http.request\" request', async () => {\n  const request = nodeHttp.request(httpServer.http.url('/resource'))\n  request.end()\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/https.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport https from 'https'\nimport { HttpServer, httpsAgent } from '@open-draft/test-server/http'\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { waitForClientRequest } from '../../../../support/utils'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/resource', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nbeforeEach(() => {\n  server.use(\n    http.get(httpServer.https.url('/resource'), () => {\n      return HttpResponse.json(\n        {\n          firstName: 'John',\n        },\n        {\n          status: 401,\n          headers: {\n            'X-Header': 'yes',\n          },\n        },\n      )\n    }),\n  )\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('returns a mocked response to an \"https.get\" request', async () => {\n  const request = https.get(httpServer.https.url('/resource'), {\n    agent: httpsAgent,\n  })\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n\nit('returns a mocked response to an \"https.request\" request', async () => {\n  const request = https.request(httpServer.https.url('/resource'), {\n    agent: httpsAgent,\n  })\n  request.end()\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/bypass.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/', (req, res) => {\n    res.send('root')\n  })\n  app.get('/user', (req, res) => {\n    res.json({ firstName: 'Miranda' })\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.use(\n    http.get(httpServer.http.url('/user'), () => {\n      return HttpResponse.json({ firstName: 'John' })\n    }),\n  )\n  server.listen({ onUnhandledRequest: 'bypass' })\n\n  vi.spyOn(global.console, 'error').mockImplementation(() => void 0)\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n})\n\nafterAll(async () => {\n  vi.restoreAllMocks()\n  server.close()\n  await httpServer.close()\n})\n\ntest('bypasses unhandled requests', async () => {\n  const res = await fetch(httpServer.http.url('/'))\n\n  // Request should be performed as-is\n  expect(res.status).toBe(200)\n  expect(await res.text()).toEqual('root')\n\n  // No warnings/errors should be printed\n  expect(console.error).not.toBeCalled()\n  expect(console.warn).not.toBeCalled()\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/callback-throws.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { setupServer } from 'msw/node'\nimport { HttpResponse, http } from 'msw'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nbeforeAll(() =>\n  server.listen({\n    onUnhandledRequest(request) {\n      /**\n       * @fixme @todo For some reason, the exception from the \"onUnhandledRequest\"\n       * callback doesn't propagate to the intercepted request but instead is thrown\n       * in this test's context.\n       */\n      throw new Error(`Custom error for ${request.method} ${request.url}`)\n    },\n  }),\n)\n\nafterAll(() => {\n  server.close()\n})\n\ntest('handles exceptions in \"onUnhandledRequest\" callback as 500 responses', async () => {\n  const response = await fetch('https://example.com')\n\n  expect(response.status).toBe(500)\n  expect(response.statusText).toBe('Unhandled Exception')\n  expect(await response.json()).toEqual({\n    name: 'Error',\n    message: 'Custom error for GET https://example.com/',\n    stack: expect.any(String),\n  })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/callback.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { setupServer } from 'msw/node'\nimport { HttpResponse, http } from 'msw'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nconst unhandledListener = vi.fn()\n\nbeforeAll(() => {\n  server.listen({\n    onUnhandledRequest: unhandledListener,\n  })\n})\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('calls the given callback function on un unhandled request', async () => {\n  const response = await fetch('https://test.mswjs.io')\n\n  // Request should be performed as-is, since the callback didn't throw.\n  expect(response).toHaveProperty('status', 404)\n  expect(unhandledListener).toHaveBeenCalledTimes(1)\n\n  const [request, print] = unhandledListener.mock.calls[0]\n  expect(request.method).toBe('GET')\n  expect(request.url).toBe('https://test.mswjs.io/')\n  expect(print).toEqual({\n    error: expect.any(Function),\n    warning: expect.any(Function),\n  })\n})\n\nit('calls the given callback on unhandled \"file://\" requests', async () => {\n  await fetch('file:///does/not/exist').catch(() => void 0)\n\n  expect(unhandledListener).toHaveBeenCalledTimes(1)\n\n  const [request, print] = unhandledListener.mock.calls[0]\n  expect(request.method).toBe('GET')\n  expect(request.url).toBe('file:///does/not/exist')\n  expect(print).toEqual({\n    error: expect.any(Function),\n    warning: expect.any(Function),\n  })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/default.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { setupServer } from 'msw/node'\nimport { HttpResponse, http } from 'msw'\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/user', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n  vi.spyOn(global.console, 'error').mockImplementation(() => void 0)\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\nit('warns on unhandled requests by default', async () => {\n  const response = await fetch('https://test.mswjs.io')\n\n  // Request should be performed as-is\n  expect(response).toHaveProperty('status', 404)\n\n  expect(console.error).not.toBeCalled()\n  expect(console.warn).toBeCalledWith(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET https://test.mswjs.io/\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`)\n})\n\nit('does not warn on unhandled \"file://\" requests', async () => {\n  // This request is expected to fail:\n  // Fetching non-existing file URL.\n  await fetch('file:///file/does/not/exist').catch(() => void 0)\n\n  expect(console.error).not.toBeCalled()\n  expect(console.warn).not.toBeCalled()\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/error.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.status(200).json({ original: true })\n  })\n  app.post('/explicit-return', (req, res) => {\n    res.status(500).end()\n  })\n  app.post('/implicit-return', (req, res) => {\n    res.status(500).end()\n  })\n})\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.use(\n    http.get(httpServer.http.url('/user'), () => {\n      return HttpResponse.json({ mocked: true })\n    }),\n    http.post(httpServer.http.url('/explicit-return'), () => {\n      // Short-circuiting in a handler makes it perform the request as-is,\n      // but still treats this request as handled.\n      return\n    }),\n    http.post(httpServer.http.url('/implicit-return'), () => {\n      // The handler that has no return value so it falls through any\n      // other matching handlers (whicbh are none). In the end,\n      // the request is performed as-is and is still considered handled.\n    }),\n  )\n  server.listen({ onUnhandledRequest: 'error' })\n})\n\nbeforeEach(() => {\n  vi.spyOn(global.console, 'error').mockImplementation(() => void 0)\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.clearAllMocks()\n})\n\nafterAll(async () => {\n  vi.restoreAllMocks()\n  server.close()\n  await httpServer.close()\n})\n\ntest('errors on unhandled request when using the \"error\" strategy', async () => {\n  const endpointUrl = httpServer.http.url('/')\n  const makeRequest = () => {\n    return fetch(endpointUrl)\n      .then(() => {\n        throw new Error('Must not resolve')\n      })\n      .catch<Error>((error) => {\n        return error\n      })\n  }\n\n  const requestError = await makeRequest()\n\n  expect.soft(requestError).toBeInstanceOf(Error)\n  expect\n    .soft(requestError.message)\n    .toBe(\n      '[MSW] Cannot bypass a request when using the \"error\" strategy for the \"onUnhandledRequest\" option.',\n    )\n\n  expect(console.error)\n    .toHaveBeenCalledWith(`[MSW] Error: intercepted a request without a matching request handler:\n\n  • GET ${endpointUrl}\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`)\n  expect(console.warn).not.toHaveBeenCalled()\n})\n\ntest('does not error on request which handler explicitly returns no mocked response', async () => {\n  const makeRequest = () => {\n    return fetch(httpServer.http.url('/explicit-return'), {\n      method: 'POST',\n    })\n  }\n  await makeRequest()\n\n  expect(console.error).not.toHaveBeenCalled()\n})\n\ntest('does not error on request which handler implicitly returns no mocked response', async () => {\n  const makeRequest = () => {\n    return fetch(httpServer.http.url('/implicit-return'), {\n      method: 'POST',\n    })\n  }\n  await makeRequest()\n\n  expect(console.error).not.toHaveBeenCalled()\n})\n\ntest(\n  'ignores common static assets when using the \"error\" strategy',\n  { timeout: 8000 },\n  async () => {\n    await fetch('http://localhost:3000/styles/main.css').catch(() => void 0)\n\n    expect(console.error).not.toHaveBeenCalled()\n  },\n)\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/on-unhandled-request/warn.node.test.ts",
    "content": "// @vitest-environment node\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen({ onUnhandledRequest: 'warn' })\n  vi.spyOn(global.console, 'warn').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  vi.clearAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\ntest('warns on unhandled request when using the \"warn\" strategy', async () => {\n  await fetch('http://localhost:3000/user').catch(() => void 0)\n\n  expect(console.warn).toBeCalledWith(`\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET http://localhost:3000/user\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`)\n})\n\ntest(\n  'ignores common static assets when using the \"warn\" strategy',\n  { timeout: 10_000 },\n  async () => {\n    await fetch('http://localhost:3000/styles/main.css').catch(() => void 0)\n\n    expect(console.warn).not.toHaveBeenCalled()\n  },\n)\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/relative-url.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('/books', () => {\n    return HttpResponse.json([1, 2, 3])\n  }),\n  http.get('https://api.backend.com/path', () => {\n    return HttpResponse.json({ success: true })\n  }),\n)\n\nbeforeAll(() => server.listen())\n\nafterAll(() => server.close())\n\ntest('tolerates relative request handlers on the server', async () => {\n  const res = await fetch('https://api.backend.com/path')\n  const body = await res.json()\n\n  expect(res.status).toBe(200)\n  expect(body).toEqual({ success: true })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/response-patching.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { HttpResponse, http, bypass } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/user', (req, res) => {\n    res.status(200).json({ id: 101 }).end()\n  })\n  app.post('/user', (req, res) => {\n    res.status(200).json({ id: 202 }).end()\n  })\n})\n\ninterface ResponseBody {\n  id: number\n  mocked: boolean\n}\n\nconst server = setupServer(\n  http.get('https://test.mswjs.io/user', async () => {\n    const originalResponse = await fetch(bypass(httpServer.http.url('/user')))\n    const body = await originalResponse.json()\n\n    return HttpResponse.json({\n      id: body.id,\n      mocked: true,\n    })\n  }),\n  http.get('https://test.mswjs.io/complex-request', async ({ request }) => {\n    const url = new URL(request.url)\n\n    const shouldBypass = url.searchParams.get('bypass') === 'true'\n    const performRequest = shouldBypass\n      ? () =>\n          fetch(\n            bypass(\n              new Request(httpServer.http.url('/user'), {\n                method: 'POST',\n              }),\n            ),\n          ).then((res) => res.json())\n      : () =>\n          fetch('https://httpbin.org/post', { method: 'POST' }).then((res) =>\n            res.json(),\n          )\n\n    const originalResponse = await performRequest()\n\n    return HttpResponse.json({\n      id: originalResponse.id,\n      mocked: true,\n    })\n  }),\n  http.post('https://httpbin.org/post', () => {\n    return HttpResponse.json({ id: 303 })\n  }),\n)\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('returns a combination of mocked and original responses', async () => {\n  const res = await fetch('https://test.mswjs.io/user')\n  const { status } = res\n  const body = await res.json()\n\n  expect(status).toBe(200)\n  expect(body).toEqual<ResponseBody>({\n    id: 101,\n    mocked: true,\n  })\n})\n\ntest('bypasses a mocked request when using \"bypass()\"', async () => {\n  const res = await fetch('https://test.mswjs.io/complex-request?bypass=true')\n\n  expect(res.status).toBe(200)\n  expect(await res.json()).toEqual<ResponseBody>({\n    id: 202,\n    mocked: true,\n  })\n})\n\ntest('falls into the mocked request when using \"fetch\" directly', async () => {\n  const res = await fetch('https://test.mswjs.io/complex-request')\n\n  expect(res.status).toBe(200)\n  expect(await res.json()).toEqual<ResponseBody>({\n    id: 303,\n    mocked: true,\n  })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/scenarios/xhr.node.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { stringToHeaders } from 'headers-polyfill'\n\nconst server = setupServer(\n  http.get('http://localhost:3001/resource', ({ request }) => {\n    return new Response(\n      JSON.stringify({\n        firstName: 'John',\n        age: 32,\n      }),\n      {\n        status: 401,\n        statusText: 'Unauthorized',\n        headers: {\n          'Content-Type': 'application/json',\n          'X-Header': 'yes',\n        },\n      },\n    )\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ndescribe('given I perform an XMLHttpRequest', () => {\n  let statusCode: number\n  let headers: Headers\n  let body: string\n\n  beforeAll(async () => {\n    const req = new XMLHttpRequest()\n    req.open('GET', 'http://localhost:3001/resource')\n\n    const requestFinishPromise = new Promise<void>((resolve, reject) => {\n      req.onload = function () {\n        statusCode = this.status\n        body = JSON.parse(this.response)\n        headers = stringToHeaders(this.getAllResponseHeaders())\n        resolve()\n      }\n      req.onerror = reject.bind(req)\n    })\n    req.send()\n\n    await requestFinishPromise\n  })\n\n  test('returns mocked status code', () => {\n    expect(statusCode).toEqual(401)\n  })\n\n  test('returns mocked headers', () => {\n    expect(headers.get('content-type')).toEqual('application/json')\n    expect(headers.get('x-header')).toEqual('yes')\n  })\n\n  test('returns mocked body', () => {\n    expect(body).toEqual({\n      firstName: 'John',\n      age: 32,\n    })\n  })\n})\n"
  },
  {
    "path": "test/node/msw-api/setup-server/use.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { SetupServer, setupServer } from 'msw/node'\nimport { RequestHandler as ExpressRequestHandler } from 'express'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  const handler: ExpressRequestHandler = (req, res) => {\n    res.status(500).send('')\n  }\n  app.get('/book/:bookId', handler)\n  app.post('/login', handler)\n})\n\nlet server: SetupServer\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server = setupServer(\n    http.get<{ bookId: string }>(httpServer.http.url('/book/:bookId'), () => {\n      return HttpResponse.json({ title: 'Original title' })\n    }),\n  )\n\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('returns a mocked response from a runtime request handler upon match', async () => {\n  server.use(\n    http.post(httpServer.http.url('/login'), () => {\n      return HttpResponse.json({ accepted: true })\n    }),\n  )\n\n  // Request handlers added on runtime affect network communication as usual.\n  const loginResponse = await fetch(httpServer.http.url('/login'), {\n    method: 'POST',\n  })\n  const loginBody = await loginResponse.json()\n  expect(loginResponse.status).toBe(200)\n  expect(loginBody).toEqual({ accepted: true })\n\n  // Other request handlers are preserved, if there are no overlaps.\n  const bookResponse = await fetch(httpServer.http.url('/book/abc-123'))\n  expect(bookResponse.status).toBe(200)\n  expect(await bookResponse.json()).toEqual({ title: 'Original title' })\n})\n\ntest('returns a mocked response from a persistent request handler override', async () => {\n  server.use(\n    http.get<{ bookId: string }>(httpServer.http.url('/book/:bookId'), () => {\n      return HttpResponse.json({ title: 'Permanent override' })\n    }),\n  )\n\n  const bookResponse = await fetch(httpServer.http.url('/book/abc-123'))\n  const bookBody = await bookResponse.json()\n  expect(bookResponse.status).toBe(200)\n  expect(bookBody).toEqual({ title: 'Permanent override' })\n\n  const anotherBookResponse = await fetch(httpServer.http.url('/book/abc-123'))\n  expect(anotherBookResponse.status).toBe(200)\n  expect(await anotherBookResponse.json()).toEqual({\n    title: 'Permanent override',\n  })\n})\n\ntest('returns a mocked response from a one-time request handler override only upon first request match', async () => {\n  server.use(\n    http.get<{ bookId: string }>(\n      httpServer.http.url('/book/:bookId'),\n      () => {\n        return HttpResponse.json({ title: 'One-time override' })\n      },\n      { once: true },\n    ),\n  )\n\n  const bookResponse = await fetch(httpServer.http.url('/book/abc-123'))\n  const bookBody = await bookResponse.json()\n  expect(bookResponse.status).toBe(200)\n  expect(bookBody).toEqual({ title: 'One-time override' })\n\n  const anotherBookResponse = await fetch(httpServer.http.url('/book/abc-123'))\n  expect(anotherBookResponse.status).toBe(200)\n  expect(await anotherBookResponse.json()).toEqual({ title: 'Original title' })\n})\n\ntest('returns a mocked response from a one-time request handler override only upon first request match with parallel requests', async () => {\n  server.use(\n    http.get<{ bookId: string }>(\n      httpServer.http.url('/book/:bookId'),\n      ({ params }) => {\n        return HttpResponse.json({\n          title: 'One-time override',\n          bookId: params.bookId,\n        })\n      },\n      { once: true },\n    ),\n  )\n\n  const bookRequestPromise = fetch(httpServer.http.url('/book/abc-123'))\n  const anotherBookRequestPromise = fetch(httpServer.http.url('/book/abc-123'))\n\n  const bookResponse = await bookRequestPromise\n  expect(bookResponse.status).toBe(200)\n  expect(await bookResponse.json()).toEqual({\n    title: 'One-time override',\n    bookId: 'abc-123',\n  })\n\n  const anotherBookResponse = await anotherBookRequestPromise\n  expect(anotherBookResponse.status).toBe(200)\n  expect(await anotherBookResponse.json()).toEqual({ title: 'Original title' })\n})\n\ntest('throws if provided the invalid handlers array', async () => {\n  expect(() =>\n    server.use(\n      // @ts-expect-error Intentionally invalid input.\n      [http.get('*', () => new Response())],\n    ),\n  ).toThrow(\n    '[MSW] Failed to call \"use()\" with the given request handlers: invalid input. Did you forget to spread the array of request handlers?',\n  )\n})\n"
  },
  {
    "path": "test/node/regressions/2129-server-use.test.ts",
    "content": "/**\n * @vitest-environment node\n * @see https://github.com/mswjs/msw/issues/2129\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n})\n\nit('does not override existing handlers when adding override for a different method', async () => {\n  server.use(\n    http.get('http://localhost/v1/issues', () => {\n      return HttpResponse.text('get-body')\n    }),\n  )\n  server.use(\n    http.post('http://localhost/v1/issues', () => {\n      return HttpResponse.text('post-body')\n    }),\n  )\n\n  const geetResponse = await fetch('http://localhost/v1/issues')\n  expect(await geetResponse.text()).toBe('get-body')\n\n  const postResponse = await fetch('http://localhost/v1/issues', {\n    method: 'POST',\n  })\n  expect(await postResponse.text()).toBe('post-body')\n})\n"
  },
  {
    "path": "test/node/regressions/2370-listen-after-close.test.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/issues/2370\n */\n// @vitest-environment node\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst server = setupServer()\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/resource', (_req, res) => {\n    res.send('original')\n  })\n})\n\nbeforeAll(async () => {\n  server.listen()\n  await httpServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('intercepts a request once `server.listen()` is called after `server.close()`', async () => {\n  const requestUrl = httpServer.http.url('/resource')\n\n  server.use(\n    http.get(requestUrl, () => {\n      return HttpResponse.text('mocked')\n    }),\n  )\n\n  // Must respond with a mocked response while MSW is active.\n  {\n    const response = await fetch(requestUrl)\n    await expect(response.text()).resolves.toBe('mocked')\n  }\n\n  server.close()\n\n  // Must respond with the original response once MSW is closed.\n  {\n    const response = await fetch(requestUrl)\n    await expect(response.text()).resolves.toBe('original')\n  }\n\n  server.listen()\n\n  // Must respond with the mocked response once MSW is active again.\n  {\n    const response = await fetch(requestUrl)\n    await expect(response.text()).resolves.toBe('mocked')\n  }\n})\n"
  },
  {
    "path": "test/node/regressions/many-request-handlers-jsdom.test.ts",
    "content": "// @vitest-environment jsdom\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { graphql, http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n  app.post('/resource/not-defined', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n})\n\nconst server = setupServer()\n\nconst requestCloneSpy = vi.spyOn(Request.prototype, 'clone')\nconst processErrorSpy = vi.spyOn(process.stderr, 'write')\n\nconst NUMBER_OF_REQUEST_HANDLERS = 100\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.clearAllMocks()\n})\n\nafterAll(async () => {\n  server.close()\n  vi.restoreAllMocks()\n  await httpServer.close()\n})\n\ndescribe('http handlers', () => {\n  beforeEach(() => {\n    server.use(\n      ...new Array(NUMBER_OF_REQUEST_HANDLERS).fill(null).map((_, index) => {\n        return http.post(\n          httpServer.http.url(`/resource/${index}`),\n          async ({ request }) => {\n            const text = await request.text()\n            return HttpResponse.text(text + index.toString())\n          },\n        )\n      }),\n    )\n  })\n\n  it('does not print a memory leak warning for the last handler', async () => {\n    const httpResponse = await fetch(\n      `${httpServer.http.url(`/resource/${NUMBER_OF_REQUEST_HANDLERS - 1}`)}`,\n      {\n        method: 'POST',\n        body: 'request-body-',\n      },\n    ).then((response) => response.text())\n    // Each clone is a new AbortSignal listener which needs to be registered\n    expect(requestCloneSpy).toHaveBeenCalledTimes(1)\n    expect(httpResponse).toBe(`request-body-${NUMBER_OF_REQUEST_HANDLERS - 1}`)\n    expect(processErrorSpy).not.toHaveBeenCalled()\n  })\n\n  it('does not print a memory leak warning for onUnhandledRequest', async () => {\n    const httpResponse = await fetch(\n      `${httpServer.http.url(`/resource/not-defined`)}`,\n      {\n        method: 'POST',\n        body: 'request-body-',\n      },\n    )\n    // Each clone is a new AbortSignal listener which needs to be registered.\n    // One clone is `onUnhandledRequest` reading the request body to print.\n    expect(requestCloneSpy).toHaveBeenCalledTimes(3)\n    expect(httpResponse.status).toBe(500)\n    expect(processErrorSpy).not.toHaveBeenCalled()\n  })\n})\n\ndescribe('graphql handlers', () => {\n  beforeEach(() => {\n    server.use(\n      ...new Array(NUMBER_OF_REQUEST_HANDLERS).fill(null).map((_, index) => {\n        return graphql.query(`Get${index}`, () => {\n          return HttpResponse.json({ data: { index } })\n        })\n      }),\n    )\n  })\n\n  it('does not print a memory leak warning', async () => {\n    const graphqlResponse = await fetch(httpServer.http.url('/graphql'), {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        query: `query Get${NUMBER_OF_REQUEST_HANDLERS - 1} { index }`,\n      }),\n    }).then((response) => response.json())\n\n    expect(requestCloneSpy).toHaveBeenCalledTimes(2)\n    expect(graphqlResponse).toEqual({\n      data: { index: NUMBER_OF_REQUEST_HANDLERS - 1 },\n    })\n    expect(processErrorSpy).not.toHaveBeenCalled()\n  })\n\n  it('does not print a memory leak warning for onUnhandledRequest', async () => {\n    const unhandledResponse = await fetch(httpServer.http.url('/graphql'), {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        query: `query NotDefinedAtAll { index }`,\n      }),\n    })\n\n    expect(unhandledResponse.status).toEqual(500)\n    expect(requestCloneSpy).toHaveBeenCalledTimes(4)\n    // Must not print any memory leak warnings.\n    expect(processErrorSpy).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/node/regressions/many-request-handlers.test.ts",
    "content": "// @vitest-environment node\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { graphql, http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/graphql', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n  app.post('/resource/not-defined', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n})\n\nconst server = setupServer()\n\nconst requestCloneSpy = vi.spyOn(Request.prototype, 'clone')\nconst stdErrSpy = vi.spyOn(process.stderr, 'write')\n\nconst NUMBER_OF_REQUEST_HANDLERS = 100\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.clearAllMocks()\n})\n\nafterAll(async () => {\n  server.close()\n  vi.restoreAllMocks()\n  await httpServer.close()\n})\n\ndescribe('http handlers', () => {\n  beforeEach(() => {\n    server.use(\n      ...new Array(NUMBER_OF_REQUEST_HANDLERS).fill(null).map((_, index) => {\n        return http.post(\n          httpServer.http.url(`/resource/${index}`),\n          async ({ request }) => {\n            const text = await request.text()\n            return HttpResponse.text(text + index.toString())\n          },\n        )\n      }),\n    )\n  })\n\n  it('does not print a memory leak warning for the last handler', async () => {\n    const httpResponse = await fetch(\n      `${httpServer.http.url(`/resource/${NUMBER_OF_REQUEST_HANDLERS - 1}`)}`,\n      {\n        method: 'POST',\n        body: 'request-body-',\n      },\n    ).then((response) => response.text())\n\n    // Each clone is a new AbortSignal listener which needs to be registered\n    expect(requestCloneSpy).toHaveBeenCalledTimes(1)\n    expect(httpResponse).toBe(`request-body-${NUMBER_OF_REQUEST_HANDLERS - 1}`)\n    expect(stdErrSpy).not.toHaveBeenCalled()\n  })\n\n  it('does not print a memory leak warning for onUnhandledRequest', async () => {\n    const httpResponse = await fetch(\n      `${httpServer.http.url(`/resource/not-defined`)}`,\n      {\n        method: 'POST',\n        body: 'request-body-',\n      },\n    )\n    // Each clone is a new AbortSignal listener which needs to be registered.\n    // One clone is `onUnhandledRequest` reading the request body to print.\n    expect(requestCloneSpy).toHaveBeenCalledTimes(3)\n    expect(httpResponse.status).toBe(500)\n    expect(stdErrSpy).not.toHaveBeenCalled()\n  })\n})\n\ndescribe('graphql handlers', () => {\n  beforeEach(() => {\n    server.use(\n      ...new Array(NUMBER_OF_REQUEST_HANDLERS).fill(null).map((_, index) => {\n        return graphql.query(`Get${index}`, () => {\n          return HttpResponse.json({ data: { index } })\n        })\n      }),\n    )\n  })\n\n  it('does not print a memory leak warning', async () => {\n    const graphqlResponse = await fetch(httpServer.http.url('/graphql'), {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        query: `query Get${NUMBER_OF_REQUEST_HANDLERS - 1} { index }`,\n      }),\n    }).then((response) => response.json())\n\n    // Each clone is a new AbortSignal listener which needs to be registered\n    expect(requestCloneSpy).toHaveBeenCalledTimes(2)\n    expect(graphqlResponse).toEqual({\n      data: { index: NUMBER_OF_REQUEST_HANDLERS - 1 },\n    })\n    expect(stdErrSpy).not.toHaveBeenCalled()\n  })\n\n  it('does not print a memory leak warning for onUnhandledRequest', async () => {\n    const unhandledResponse = await fetch(httpServer.http.url('/graphql'), {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        query: `query NotDefinedAtAll { index }`,\n      }),\n    })\n\n    expect(unhandledResponse.status).toEqual(500)\n    expect(requestCloneSpy).toHaveBeenCalledTimes(4)\n    // Must not print any memory leak warnings.\n    expect(stdErrSpy).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/node/regressions/miniflare.node.test.ts",
    "content": "/**\n * @vitest-environment miniflare\n */\nimport nodeHttp from 'http'\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { waitForClientRequest } from '../../support/utils'\n\nconst httpServer = new HttpServer((app) => {\n  app.get('/resource', (_, res) => {\n    return res.status(500).send('original-response')\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n  server.listen()\n})\n\nbeforeEach(() => {\n  server.use(\n    http.get(httpServer.http.url('/resource'), () => {\n      return HttpResponse.json(\n        { firstName: 'John' },\n        {\n          status: 401,\n          headers: {\n            'x-header': 'yes',\n          },\n        },\n      )\n    }),\n  )\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('returns a mocked response to an \"http.get\" request', async () => {\n  const request = nodeHttp.get(httpServer.http.url('/resource'))\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n\nit('returns a mocked response to an \"http.request\" request', async () => {\n  const request = nodeHttp.request(httpServer.http.url('/resource'))\n  request.end()\n  const { response, responseText } = await waitForClientRequest(request)\n\n  expect(response.statusCode).toBe(401)\n  expect(response.headers).toEqual(\n    expect.objectContaining({\n      'content-type': 'application/json',\n      'x-header': 'yes',\n    }),\n  )\n  expect(responseText).toBe('{\"firstName\":\"John\"}')\n})\n"
  },
  {
    "path": "test/node/regressions/mixed-graphql-http-with-query-in-body.node.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { graphql, http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst mswGraphql = graphql.link('https://mswjs.com/graphql')\nconst server = setupServer()\n\nbeforeAll(async () => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n})\n\ntest('no console error occurs when the http handler is first', async () => {\n  server.use(\n    http.post('https://mswjs.com/example', () => {\n      return HttpResponse.text('http route')\n    }),\n    mswGraphql.query('GetData', () => {\n      return HttpResponse.json({\n        data: {\n          data: 'graphql route',\n        },\n      })\n    }),\n    graphql.query('GetOtherUser', () => {\n      return HttpResponse.json({\n        data: {\n          data: 'graphql route',\n        },\n      })\n    }),\n  )\n\n  const consoleError = vi.spyOn(console, 'error')\n  const response = await fetch('https://mswjs.com/example', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'some query',\n    }),\n  })\n  await expect(response.text()).resolves.toEqual('http route')\n\n  const graphqlResponse = await fetch('https://mswjs.com/graphql', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'query GetData { id }',\n    }),\n  })\n  await expect(graphqlResponse.json()).resolves.toEqual({\n    data: { data: 'graphql route' },\n  })\n\n  expect(consoleError).not.toHaveBeenCalled()\n})\n\ntest('no console error occurs when the http handler is first, but we apply a use after it', async () => {\n  server.use(\n    http.post('https://mswjs.com/example', () => {\n      return HttpResponse.text('http route')\n    }),\n    mswGraphql.query('GetData', () => {\n      return HttpResponse.json({\n        data: { data: 'graphql route' },\n      })\n    }),\n  )\n\n  server.use(\n    mswGraphql.query('GetData', () => {\n      return HttpResponse.json({\n        data: {\n          data: 'graphql route',\n        },\n      })\n    }),\n  )\n\n  const consoleError = vi.spyOn(console, 'error')\n  const response = await fetch('https://mswjs.com/example', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'some query',\n    }),\n  })\n  await expect(response.text()).resolves.toEqual('http route')\n\n  const graphqlResponse = await fetch('https://mswjs.com/graphql', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'query GetData { id }',\n    }),\n  })\n  await expect(graphqlResponse.json()).resolves.toEqual({\n    data: { data: 'graphql route' },\n  })\n  expect(consoleError).not.toHaveBeenCalled()\n})\n\ntest('no console error occurs when the http handler is second to the graphql handler', async () => {\n  server.use(\n    mswGraphql.query('GetData', () => {\n      return HttpResponse.json({\n        data: {\n          data: 'graphql route',\n        },\n      })\n    }),\n    http.post('https://mswjs.com/example', () => {\n      return HttpResponse.text('http route')\n    }),\n  )\n\n  const consoleError = vi.spyOn(console, 'error')\n  const response = await fetch('https://mswjs.com/example', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'some query',\n    }),\n  })\n  await expect(response.text()).resolves.toEqual('http route')\n\n  const graphqlResponse = await fetch('https://mswjs.com/graphql', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'query GetData { id }',\n    }),\n  })\n  await expect(graphqlResponse.json()).resolves.toEqual({\n    data: { data: 'graphql route' },\n  })\n  expect(consoleError).not.toHaveBeenCalled()\n})\n\ntest(\"a console error occurs when the http handler is second to the graphql handler, and we don't use link\", async () => {\n  server.use(\n    graphql.query('GetData', () => {\n      return HttpResponse.json({\n        data: {\n          data: 'graphql route',\n        },\n      })\n    }),\n    http.post('https://mswjs.com/example', () => {\n      return HttpResponse.text('http route')\n    }),\n  )\n\n  const consoleError = vi.spyOn(console, 'error')\n  const response = await fetch('https://mswjs.com/example', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'some query',\n    }),\n  })\n  await expect(response.text()).resolves.toEqual('http route')\n  expect(consoleError).not.toHaveBeenNthCalledWith(\n    1,\n    expect.stringContaining('[MSW] Failed to intercept a GraphQL request'),\n  )\n\n  const graphqlResponse = await fetch('https://mswjs.com/graphql', {\n    method: 'POST',\n    body: JSON.stringify({\n      query: 'query GetData { id }',\n    }),\n  })\n  await expect(graphqlResponse.json()).resolves.toEqual({\n    data: { data: 'graphql route' },\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/cookies-inheritance.node.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer, SetupServer } from 'msw/node'\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { RequestHandler as ExpressRequestHandler } from 'express'\n\nlet server: SetupServer\n\nconst httpServer = new HttpServer((app) => {\n  const handler: ExpressRequestHandler = (req, res) => {\n    res.status(500).end()\n  }\n  app.post('/login', handler)\n  app.get('/user', handler)\n})\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server = setupServer(\n    http.post(httpServer.https.url('/login'), () => {\n      return new HttpResponse(null, {\n        headers: {\n          'Set-Cookie': `authToken=${encodeURIComponent('abc-123-甲乙丙')}`,\n        },\n      })\n    }),\n    http.get<\n      never,\n      never,\n      { firstName: string; lastName: string } | { error: string }\n    >(httpServer.https.url('/user'), ({ cookies }) => {\n      if (cookies.authToken == null) {\n        return HttpResponse.json(\n          {\n            error: 'Auth token not found',\n          },\n          { status: 403 },\n        )\n      }\n\n      return HttpResponse.json({\n        firstName: 'John',\n        lastName: 'Maverick',\n      })\n    }),\n  )\n\n  server.listen()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\ntest('inherits cookies set from a preceding request', async () => {\n  const res = await fetch(httpServer.https.url('/login'), {\n    method: 'POST',\n  }).then(() => {\n    // Fetch the user after requesting login to see\n    // if the response cookies set in the login request handler\n    // are automatically forwarded to the \"GET /user\" request.\n    return fetch(httpServer.https.url('/user'))\n  })\n\n  expect(res.status).toBe(200)\n\n  const json = await res.json()\n  expect(json).toEqual({\n    firstName: 'John',\n    lastName: 'Maverick',\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/https.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport https from 'https'\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('intercepts and mocks a request made via \"https\"', async () => {\n  server.use(\n    http.get('https://api.example.com/resource', () => {\n      return HttpResponse.text('Hello, world!')\n    }),\n  )\n  const request = https.get('https://api.example.com/resource')\n\n  await new Promise<void>((resolve, reject) => {\n    request.on('response', (response) => {\n      const chunks: Array<Buffer> = []\n      response.on('data', (chunk) => chunks.push(Buffer.from(chunk)))\n\n      response.on('error', (error) => reject(error))\n      response.once('end', () => {\n        expect(chunks).toHaveLength(1)\n\n        const responseText = Buffer.concat(chunks).toString('utf8')\n        expect(responseText).toBe('Hello, world!')\n\n        resolve()\n      })\n    })\n    request.on('error', (error) => reject(error))\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-arraybuffer.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nfunction encodeBuffer(value: unknown) {\n  return Buffer.from(JSON.stringify(value)).buffer\n}\n\nconst server = setupServer(\n  http.post('http://localhost/arrayBuffer', async ({ request }) => {\n    const requestBodyBuffer = await request.arrayBuffer()\n    return HttpResponse.arrayBuffer(requestBodyBuffer)\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('reads text request body as array buffer', async () => {\n  const res = await fetch('http://localhost/arrayBuffer', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: 'foo bar',\n  })\n  const body = await res.arrayBuffer()\n\n  expect(res.status).toBe(200)\n  expect(body).toEqual(encodeBuffer('foo bar'))\n})\n\ntest('reads array buffer request body as array buffer', async () => {\n  const res = await fetch('http://localhost/arrayBuffer', {\n    method: 'POST',\n    body: encodeBuffer('foo bar'),\n  })\n  const body = await res.arrayBuffer()\n\n  expect(res.status).toBe(200)\n  expect(body).toEqual(encodeBuffer('foo bar'))\n})\n\ntest('reads null request body as empty array buffer', async () => {\n  const res = await fetch('http://localhost/arrayBuffer', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: undefined,\n  })\n  const body = await res.arrayBuffer()\n\n  expect(res.status).toBe(200)\n  expect(body).toEqual(encodeBuffer(''))\n})\n\ntest('reads undefined request body as empty array buffer', async () => {\n  const res = await fetch('http://localhost/arrayBuffer', {\n    method: 'POST',\n    body: undefined,\n  })\n  const body = await res.arrayBuffer()\n\n  expect(res.status).toBe(200)\n  expect(body).toEqual(encodeBuffer(''))\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-form-data.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.post('http://localhost/resource', async ({ request }) => {\n    const formData = await request.formData()\n    return HttpResponse.json(Array.from(formData.entries()))\n  }),\n  http.post('http://localhost/file', async ({ request }) => {\n    const formData = await request.formData()\n    const file = formData.get('file') as File | null\n\n    if (!file) {\n      throw HttpResponse.text('Missing file', { status: 400 })\n    }\n\n    return HttpResponse.json({\n      name: file.name,\n      size: file.size,\n      content: await file.text(),\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports FormData request body', async () => {\n  // Note that creating a `FormData` instance in Node/JSDOM differs\n  // from the same instance in a real browser. Follow the instructions\n  // of your `fetch` polyfill to learn more.\n  const formData = new FormData()\n  formData.append('username', 'john.maverick')\n  formData.append('password', 'secret123')\n\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n    body: formData,\n  })\n  const json = await res.json()\n\n  expect(res.status).toBe(200)\n  expect(json).toEqual([\n    ['username', 'john.maverick'],\n    ['password', 'secret123'],\n  ])\n})\n\nit('respects Blob size in request body', async () => {\n  const blob = new Blob([JSON.stringify({ data: 1 })], {\n    type: 'application/json',\n  })\n  const formData = new FormData()\n  formData.set('file', blob, 'data.json')\n\n  const response = await fetch('http://localhost/file', {\n    method: 'POST',\n    body: formData,\n  })\n\n  expect(response.status).toBe(200)\n  expect(await response.json()).toEqual({\n    name: 'data.json',\n    size: blob.size,\n    content: await blob.text(),\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-json.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { encodeBuffer } from '@mswjs/interceptors'\n\nconst server = setupServer(\n  http.post('http://localhost/json', async ({ request }) => {\n    return HttpResponse.json(await request.json())\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('reads request body using json() method', async () => {\n  const res = await fetch('http://localhost/json', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n  const json = await res.json()\n\n  expect(res.status).toBe(200)\n  expect(json).toEqual({ firstName: 'John' })\n})\n\ntest('reads array buffer request body using json() method', async () => {\n  const res = await fetch('http://localhost/json', {\n    method: 'POST',\n    body: encodeBuffer(JSON.stringify({ firstName: 'John' })),\n  })\n  const json = await res.json()\n\n  expect(res.status).toBe(200)\n  expect(json).toEqual({ firstName: 'John' })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-protobuf.node.test.ts",
    "content": "// @vitest-environment node\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.post('https://example.com/protobuf', async ({ request }) => {\n    const buffer = await request.arrayBuffer()\n\n    return new HttpResponse(new Uint8Array(buffer), {\n      headers: {\n        'Content-Type': 'application/protobuf',\n      },\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with a \"application/protobuf\" mocked response', async () => {\n  const payload = new Uint8Array([138, 1, 6, 10, 4, 10, 2, 32, 1])\n\n  const response = await fetch('https://example.com/protobuf', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/protobuf',\n    },\n    body: payload,\n  })\n  const body = await response.arrayBuffer()\n\n  expect(new Uint8Array(body)).toEqual(payload)\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-text.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { encodeBuffer } from '@mswjs/interceptors'\n\nconst server = setupServer(\n  http.post('http://localhost/resource', async ({ request }) => {\n    return HttpResponse.text(await request.text())\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('reads plain text request body as text', async () => {\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'text/plain',\n    },\n    body: 'hello-world',\n  })\n  const body = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(body).toBe('hello-world')\n})\n\ntest('reads json request body as text', async () => {\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({ firstName: 'John' }),\n  })\n  const body = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(body).toBe(`{\"firstName\":\"John\"}`)\n})\n\ntest('reads array buffer request body as text', async () => {\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n    body: encodeBuffer('hello-world'),\n  })\n  const body = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(body).toBe('hello-world')\n})\n\ntest('reads null request body as empty text', async () => {\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n    body: null as any,\n  })\n  const body = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(body).toBe('')\n})\n\ntest('reads undefined request body as empty text', async () => {\n  const res = await fetch('http://localhost/resource', {\n    method: 'POST',\n  })\n  const body = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(body).toBe('')\n})\n"
  },
  {
    "path": "test/node/rest-api/request/body/body-used.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\nimport * as express from 'express'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.post('/resource', express.json(), (req, res) => {\n    res.json({ response: `received: ${req.body.message}` })\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  server.listen()\n  await httpServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.restoreAllMocks()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('does not read the body while parsing an unhandled request', async () => {\n  // Expecting an unhandled request warning in this test.\n  vi.spyOn(console, 'warn').mockImplementation(() => {})\n\n  const requestUrl = httpServer.http.url('/resource')\n  const response = await fetch(requestUrl, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({\n      message: 'Hello server',\n    }),\n  })\n  expect(await response.json()).toEqual({ response: `received: Hello server` })\n})\n\nit('does not read the body while parsing an unhandled request', async () => {\n  const requestUrl = httpServer.http.url('/resource')\n  server.use(\n    http.post(requestUrl, () => {\n      return HttpResponse.json({ mocked: true })\n    }),\n  )\n  const response = await fetch(requestUrl, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify({\n      message: 'Hello server',\n    }),\n  })\n  expect(await response.json()).toEqual({ mocked: true })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/matching/all.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpServer } from '@open-draft/test-server/http'\nimport { HttpMethods, http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst httpServer = new HttpServer((app) => {\n  // Responding with \"204 No Content\" because the \"OPTIONS\"\n  // request returns 204 without an obvious way to override that.\n  app.all('*', (req, res) => res.status(204).end())\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  await httpServer.listen()\n\n  server.listen({\n    onUnhandledRequest: 'bypass',\n  })\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nasync function forEachMethod(callback: (method: HttpMethods) => unknown) {\n  for (const method of Object.values(HttpMethods)) {\n    await callback(method)\n  }\n}\n\ntest('matches all requests given no custom path', async () => {\n  server.use(\n    http.all('*', () => {\n      return HttpResponse.text('welcome to the jungle')\n    }),\n  )\n\n  const responses = await Promise.all(\n    Object.values(HttpMethods).reduce<Promise<Response>[]>((all, method) => {\n      return all.concat(\n        [\n          httpServer.http.url('/'),\n          httpServer.http.url('/foo'),\n          'https://example.com',\n        ].map((url) => fetch(url, { method })),\n      )\n    }, []),\n  )\n\n  for (const response of responses) {\n    expect(response.status).toBe(200)\n    expect(await response.text()).toEqual('welcome to the jungle')\n  }\n})\n\ntest('respects custom path when matching requests', async () => {\n  server.use(\n    http.all(httpServer.http.url('/api/*'), () => {\n      return HttpResponse.text('hello world')\n    }),\n  )\n\n  // Root requests.\n  await forEachMethod(async (method) => {\n    const response = await fetch(httpServer.http.url('/api/'), { method })\n    expect(response.status).toBe(200)\n    expect(await response.text()).toEqual('hello world')\n  })\n\n  // Nested requests.\n  await forEachMethod(async (method) => {\n    const response = await fetch(httpServer.http.url('/api/foo'), {\n      method,\n    })\n    expect(response.status).toBe(200)\n    expect(await response.text()).toEqual('hello world')\n  })\n\n  // Mismatched requests.\n  await forEachMethod(async (method) => {\n    const response = await fetch(httpServer.http.url('/foo'), { method })\n    expect(response.status).toEqual(204)\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/matching/custom-predicate.node.test.ts",
    "content": "// @vitest-environment node\nimport { http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen({ onUnhandledRequest: 'bypass' })\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('matches requests when the predicate function returns true', async () => {\n  server.use(\n    http.post(\n      async ({ request }) => {\n        const requestBody = await request.clone().text()\n        return requestBody === 'hello world'\n      },\n      async ({ request }) => {\n        return new Response(request.clone().body, request)\n      },\n    ),\n  )\n\n  const response = await fetch('http://localhost/irrelevant', {\n    method: 'POST',\n    body: 'hello world',\n  })\n\n  expect.soft(response.status).toBe(200)\n  await expect.soft(response.text()).resolves.toBe('hello world')\n})\n\nit('does not match requests when the predicate function returns false', async () => {\n  server.use(\n    http.post(\n      async ({ request }) => {\n        const requestBody = await request.clone().text()\n        return requestBody === 'hello world'\n      },\n      async ({ request }) => {\n        return new Response(request.clone().body, request)\n      },\n    ),\n  )\n\n  await expect(\n    fetch('http://localhost/irrelevant', {\n      method: 'POST',\n      body: 'non-matching-request',\n    }),\n  ).rejects.toThrow('fetch failed')\n})\n"
  },
  {
    "path": "test/node/rest-api/request/matching/path-params-decode.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get<{ url: string }>(\n    'https://test.mswjs.io/reflect-url/:url',\n    ({ params }) => {\n      return HttpResponse.json({ url: params.url })\n    },\n  ),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('decodes url componets', async () => {\n  const url = 'http://example.com:5001/example'\n\n  const res = await fetch(\n    `https://test.mswjs.io/reflect-url/${encodeURIComponent(url)}`,\n  )\n\n  expect(res.status).toBe(200)\n  expect(await res.json()).toEqual({\n    url,\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/matching/path-params-optional.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('intercepts the request that fully matches the path', async () => {\n  server.use(\n    http.get('http://localhost/user/:id?', () =>\n      HttpResponse.json({ mocked: true }),\n    ),\n  )\n\n  const response = await fetch('http://localhost/user/123')\n  expect(response.status).toBe(200)\n  expect(await response.json()).toEqual({ mocked: true })\n})\n\nit('intercepts the request that partially matches the path', async () => {\n  server.use(\n    http.get('http://localhost/user/:id?', () =>\n      HttpResponse.json({ mocked: true }),\n    ),\n  )\n\n  const response = await fetch('http://localhost/user')\n  expect(response.status).toBe(200)\n  expect(await response.json()).toEqual({ mocked: true })\n})\n"
  },
  {
    "path": "test/node/rest-api/request/matching/relative-url.node.test.ts",
    "content": "/**\n * @vitest-environment jsdom\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('/api/movies', () => {\n    return HttpResponse.json([\n      { title: 'The Lord of the Rings' },\n      { title: 'The Matrix' },\n    ])\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds to a relative URL in jsdom', async () => {\n  const response = await fetch('/api/movies')\n\n  expect(response.status).toBe(200)\n  expect(await response.json()).toEqual([\n    { title: 'The Lord of the Rings' },\n    { title: 'The Matrix' },\n  ])\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-binary.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport * as path from 'path'\nimport * as fs from 'fs'\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nfunction getImageBuffer() {\n  return fs.readFileSync(path.resolve(__dirname, '../../../fixtures/image.jpg'))\n}\n\nconst server = setupServer(\n  http.get('http://test.mswjs.io/image', () => {\n    const imageBuffer = getImageBuffer()\n\n    return HttpResponse.arrayBuffer(imageBuffer, {\n      headers: {\n        'Content-Type': 'image/jpeg',\n        'Content-Length': imageBuffer.byteLength.toString(),\n      },\n    })\n  }),\n)\n\nbeforeAll(() => server.listen())\nafterAll(() => server.close())\n\ntest('returns given buffer in the mocked response', async () => {\n  const response = await fetch('http://test.mswjs.io/image')\n  const actualImageBuffer = await response.arrayBuffer()\n  const expectedImageBuffer = getImageBuffer()\n\n  expect(response.status).toBe(200)\n  expect(response.headers.get('content-length')).toBe(\n    actualImageBuffer.byteLength.toString(),\n  )\n  expect(\n    Buffer.compare(Buffer.from(actualImageBuffer), expectedImageBuffer),\n  ).toBe(0)\n})\n\ntest('returns given blob in the mocked response', async () => {\n  const response = await fetch('http://test.mswjs.io/image')\n  const blob = await response.blob()\n  const expectedImageBuffer = getImageBuffer()\n\n  expect(response.status).toBe(200)\n  expect(blob.type).toBe('image/jpeg')\n  expect(blob.size).toBe(Number(response.headers.get('content-length')))\n  expect(\n    Buffer.compare(Buffer.from(await blob.arrayBuffer()), expectedImageBuffer),\n  ).toBe(0)\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-html.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://localhost/html', () => {\n    return HttpResponse.html(`\n<p class=\"user\" id=\"abc-123\">\n  Jane Doe\n</p>`)\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('responds with an HTML response body', async () => {\n  const res = await fetch('http://localhost/html')\n  const text = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(res.headers.get('content-type')).toBe('text/html')\n  expect(text).toEqual(`\n<p class=\"user\" id=\"abc-123\">\n  Jane Doe\n</p>`)\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-json.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://localhost/json', () => {\n    return HttpResponse.json({ firstName: 'John' })\n  }),\n  http.get('http://localhost/number', () => {\n    return HttpResponse.json(123)\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with a JSON response body', async () => {\n  const response = await fetch('http://localhost/json')\n\n  expect(response.headers.get('Content-Type')).toBe('application/json')\n  expect(await response.json()).toEqual({ firstName: 'John' })\n})\n\nit('responds with a single number JSON response body', async () => {\n  const response = await fetch('http://localhost/number')\n\n  expect(response.headers.get('Content-Type')).toBe('application/json')\n  expect(await response.json()).toEqual(123)\n})\n\nit('implicitly sets \"Content-Length\" header on the mocked response', async () => {\n  const response = await fetch('http://localhost/json')\n  expect(response.headers.get('Content-Length')).toBe('20')\n})\n\nit('implicitly sets \"Content-Length\" to 0 if the mocked response body is empty', async () => {\n  server.use(\n    http.get('http://localhost/json', () => {\n      return HttpResponse.json()\n    }),\n  )\n\n  const response = await fetch('http://localhost/json')\n  expect(response.headers.get('Content-Length')).toBe('0')\n})\n\nit('respects custom \"Content-Length\" mocked response header', async () => {\n  server.use(\n    http.get('http://localhost/json', () => {\n      return HttpResponse.json(\n        { firstName: 'John' },\n        {\n          headers: {\n            'Content-Length': '32',\n          },\n        },\n      )\n    }),\n  )\n\n  const response = await fetch('http://localhost/json')\n  expect(response.headers.get('Content-Length')).toBe('32')\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-stream.node.test.ts",
    "content": "// @vitest-environment node\nimport https from 'node:https'\nimport { HttpResponse, http, delay } from 'msw'\nimport { setupServer } from 'msw/node'\n\ninterface CustomMatchers<R = unknown> {\n  toRoughlyEqual: (actual: number, deviation: number) => R\n}\n\ndeclare module 'vitest' {\n  interface Matchers<T = any> extends CustomMatchers<T> {}\n}\n\nexpect.extend({\n  /**\n   * Asserts a given actual number to roughly equal to the expected number,\n   * taking the maximum allowed delta `deviation` into account.\n   */\n  toRoughlyEqual(actual, expected, deviation) {\n    const diff = Math.abs(actual - expected)\n    const passes = diff <= deviation\n\n    if (passes) {\n      return {\n        pass: true,\n        message: () =>\n          `expected ${actual} not to be roughly equal to ${expected} (deviation: ${deviation})`,\n      }\n    }\n\n    return {\n      pass: false,\n      message: () =>\n        `expected ${actual} to be roughly equal to ${expected} (deviation: ${deviation})`,\n    }\n  },\n})\n\nconst encoder = new TextEncoder()\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('responds with a ReadableStream', async () => {\n  server.use(\n    http.get('https://api.example.com/stream', () => {\n      const stream = new ReadableStream({\n        start(controller) {\n          controller.enqueue(encoder.encode('hello'))\n          controller.enqueue(encoder.encode('world'))\n          controller.close()\n        },\n      })\n\n      return new HttpResponse(stream, {\n        headers: {\n          'Content-Type': 'text/event-stream',\n        },\n      })\n    }),\n  )\n\n  const response = await fetch('https://api.example.com/stream')\n\n  expect(response.status).toBe(200)\n  expect(response.statusText).toBe('OK')\n  expect(response.body).toBeInstanceOf(ReadableStream)\n  expect(response.body!.locked).toBe(false)\n\n  expect(await response.text()).toBe('helloworld')\n})\n\ntest('supports delays when enqueuing chunks', async () => {\n  server.use(\n    http.get('https://api.example.com/stream', () => {\n      const stream = new ReadableStream({\n        async start(controller) {\n          controller.enqueue(encoder.encode('first'))\n          await delay(250)\n\n          controller.enqueue(encoder.encode('second'))\n          await delay(250)\n\n          controller.enqueue(encoder.encode('third'))\n          await delay(250)\n          controller.close()\n        },\n      })\n\n      return new HttpResponse(stream, {\n        headers: {\n          'Content-Type': 'text/event-stream',\n        },\n      })\n    }),\n  )\n\n  await new Promise<void>((resolve, reject) => {\n    const request = https.get('https://api.example.com/stream', (response) => {\n      const chunks: Array<{ buffer: Buffer; timestamp: number }> = []\n\n      response.on('data', (data) => {\n        chunks.push({\n          buffer: Buffer.from(data),\n          timestamp: performance.now(),\n        })\n      })\n\n      response.once('end', () => {\n        const textChunks = chunks.map((chunk) => chunk.buffer.toString('utf8'))\n        expect(textChunks).toEqual(['first', 'second', 'third'])\n\n        // Ensure that the chunks were sent over time,\n        // respecting the delay set in the mocked stream.\n        const chunkTimings = chunks.map((chunk) => chunk.timestamp)\n        expect(chunkTimings[1] - chunkTimings[0]).toRoughlyEqual(250, 50)\n        expect(chunkTimings[2] - chunkTimings[1]).toRoughlyEqual(250, 50)\n\n        resolve()\n      })\n    })\n\n    request.on('error', (error) => reject(error))\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-text.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://localhost/text', () => {\n    return HttpResponse.text('hello world')\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with a text response body', async () => {\n  const res = await fetch('http://localhost/text')\n  const text = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(res.headers.get('content-type')).toBe('text/plain')\n  expect(text).toBe('hello world')\n})\n\nit('implicitly sets \"Content-Length\" header on a text response', async () => {\n  const response = await fetch('http://localhost/text')\n  expect(response.headers.get('Content-Length')).toBe('11')\n})\n\nit('implicitly sets \"Content-Length\" header to 0 on empty text response', async () => {\n  server.use(\n    http.get('http://localhost/text', () => {\n      return HttpResponse.text('')\n    }),\n  )\n\n  const response = await fetch('http://localhost/text')\n  expect(response.headers.get('Content-Length')).toBe('0')\n})\n\nit('respects custom \"Content-Length\" mocked response header', async () => {\n  server.use(\n    http.get('http://localhost/text', () => {\n      return HttpResponse.text('hello-world', {\n        headers: {\n          'Content-Length': '32',\n        },\n      })\n    }),\n  )\n\n  const response = await fetch('http://localhost/text')\n  expect(response.headers.get('Content-Length')).toBe('32')\n})\n"
  },
  {
    "path": "test/node/rest-api/response/body-xml.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('http://localhost/xml', () => {\n    return HttpResponse.xml(`\n<user>\n  <id>abc-123</id>\n  <firstName>John</firstName>\n  <lastName>Maverick</lastName>\n</user>`)\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\ntest('responds with an XML response body', async () => {\n  const res = await fetch('http://localhost/xml')\n  const text = await res.text()\n\n  expect(res.status).toBe(200)\n  expect(res.headers.get('content-type')).toBe('text/xml')\n  expect(text).toEqual(`\n<user>\n  <id>abc-123</id>\n  <firstName>John</firstName>\n  <lastName>Maverick</lastName>\n</user>`)\n})\n"
  },
  {
    "path": "test/node/rest-api/response/generator.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http, HttpResponse, delay } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nasync function fetchJson(input: string | URL | Request, init?: RequestInit) {\n  return fetch(input, init).then((response) => response.json())\n}\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports generator function as response resolver', async () => {\n  server.use(\n    http.get('https://example.com/weather', function* () {\n      let degree = 10\n\n      while (degree < 13) {\n        degree++\n        yield HttpResponse.json(degree)\n      }\n\n      degree++\n      return HttpResponse.json(degree)\n    }),\n  )\n\n  // Must respond with yielded responses.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13)\n  // Must respond with the final \"done\" response.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14)\n  // Must keep responding with the final \"done\" response.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14)\n})\n\nit('supports async generator function as response resolver', async () => {\n  server.use(\n    http.get('https://example.com/weather', async function* () {\n      await delay(20)\n\n      let degree = 10\n\n      while (degree < 13) {\n        degree++\n        yield HttpResponse.json(degree)\n      }\n\n      degree++\n      return HttpResponse.json(degree)\n    }),\n  )\n\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14)\n})\n\nit('supports generator function as one-time response resolver', async () => {\n  server.use(\n    http.get(\n      'https://example.com/weather',\n      function* () {\n        let degree = 10\n\n        while (degree < 13) {\n          degree++\n          yield HttpResponse.json(degree)\n        }\n\n        degree++\n        return HttpResponse.json(degree)\n      },\n      { once: true },\n    ),\n    http.get('*', () => {\n      return HttpResponse.json('fallback')\n    }),\n  )\n\n  // Must respond with the yielded incrementing responses.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(11)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(12)\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(13)\n  // Must respond with the \"done\" final response from the iterator.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(14)\n  // Must respond with the other handler since the generator one is used.\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(\n    'fallback',\n  )\n  await expect(fetchJson('https://example.com/weather')).resolves.toEqual(\n    'fallback',\n  )\n})\n"
  },
  {
    "path": "test/node/rest-api/response/response-cookies.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports mocking a response cookie', async () => {\n  server.use(\n    http.get('*/resource', () => {\n      return new HttpResponse(null, {\n        headers: {\n          'Set-Cookie': 'a=1',\n        },\n      })\n    }),\n  )\n\n  const response = await fetch('http://localhost/resource')\n  expect(response.headers.get('Set-Cookie')).toBe('a=1')\n})\n\nit('supports mocking multiple response cookies', async () => {\n  server.use(\n    http.get('*/resource', () => {\n      return new HttpResponse(null, {\n        headers: [\n          ['Set-Cookie', 'a=1'],\n          ['Set-Cookie', 'b=2'],\n        ],\n      })\n    }),\n  )\n\n  const response = await fetch('http://localhost/resource')\n  expect(response.headers.get('Set-Cookie')).toBe('a=1, b=2')\n})\n"
  },
  {
    "path": "test/node/rest-api/response/response-error.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with a mocked error response using \"Response.error\" shorthand', async () => {\n  server.use(\n    http.get('https://api.example.com/resource', () => {\n      return Response.error()\n    }),\n  )\n\n  const responseError = await fetch('https://api.example.com/resource')\n    .then(() => null)\n    .catch((error) => error)\n\n  expect(responseError.name).toBe('TypeError')\n  expect(responseError.message).toBe('Failed to fetch')\n\n  // Guard against false positives due to exceptions arising from the library.\n  expect(responseError.cause).toBeInstanceOf(Response)\n  expect(responseError.cause.type).toBe('error')\n  expect(responseError.cause.status).toBe(0)\n})\n"
  },
  {
    "path": "test/node/rest-api/response/throw-response.node.test.ts",
    "content": "/**\n * @vitest-environment node\n */\nimport { HttpResponse, http } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('supports throwing a plain Response in a response resolver', async () => {\n  server.use(\n    http.get('https://example.com/', () => {\n      // You can throw a Response instance in a response resolver\n      // to short-circuit its execution and respond \"early\".\n      throw new Response('hello world')\n    }),\n  )\n\n  const response = await fetch('https://example.com')\n\n  expect(response.status).toBe(200)\n  expect(await response.text()).toBe('hello world')\n})\n\nit('supports throwing an HttpResponse instance in a response resolver', async () => {\n  server.use(\n    http.get('https://example.com/', () => {\n      throw HttpResponse.text('hello world')\n    }),\n  )\n\n  const response = await fetch('https://example.com')\n\n  expect(response.status).toBe(200)\n  expect(response.headers.get('Content-Type')).toBe('text/plain')\n  expect(await response.text()).toBe('hello world')\n})\n\nit('supports throwing an error response in a response resolver', async () => {\n  server.use(\n    http.get('https://example.com/', () => {\n      throw HttpResponse.text('not found', { status: 400 })\n    }),\n  )\n\n  const response = await fetch('https://example.com')\n\n  expect(response.status).toBe(400)\n  expect(response.headers.get('Content-Type')).toBe('text/plain')\n  expect(await response.text()).toBe('not found')\n})\n\nit('supports throwing a network error in a response resolver', async () => {\n  server.use(\n    http.get('https://example.com/', () => {\n      throw HttpResponse.error()\n    }),\n  )\n\n  await expect(fetch('https://example.com')).rejects.toThrow('Failed to fetch')\n})\n\nit('supports middleware-style responses', async () => {\n  server.use(\n    http.get('https://example.com/', ({ request }) => {\n      const url = new URL(request.url)\n\n      if (!url.searchParams.has('id')) {\n        throw HttpResponse.text('must have id', { status: 400 })\n      }\n\n      return HttpResponse.text('ok')\n    }),\n  )\n\n  const response = await fetch('https://example.com/?id=1')\n  expect(response.status).toBe(200)\n  expect(response.headers.get('Content-Type')).toBe('text/plain')\n  expect(await response.text()).toBe('ok')\n\n  const errorResponse = await fetch('https://example.com/')\n  expect(errorResponse.status).toBe(400)\n  expect(errorResponse.headers.get('Content-Type')).toBe('text/plain')\n  expect(await errorResponse.text()).toBe('must have id')\n})\n\nit('handles non-response errors as 500 error responses', async () => {\n  server.use(\n    http.get('https://example.com/', () => {\n      throw new Error('Custom error')\n    }),\n  )\n\n  const response = await fetch('https://example.com')\n\n  expect(response.status).toBe(500)\n  expect(response.statusText).toBe('Unhandled Exception')\n  expect(await response.json()).toEqual({\n    name: 'Error',\n    message: 'Custom error',\n    stack: expect.any(String),\n  })\n})\n"
  },
  {
    "path": "test/node/rest-api/response-patching.node.test.ts",
    "content": "// @vitest-environment node\nimport { http, bypass } from 'msw'\nimport { setupServer } from 'msw/node'\nimport express from 'express'\nimport { HttpServer } from '@open-draft/test-server/http'\n\nconst httpServer = new HttpServer((app) => {\n  app.use('/resource', (_req, res, next) => {\n    res.setHeader('access-control-allow-headers', '*')\n    next()\n  })\n  app.post('/resource', express.text(), (req, res) => {\n    res.json({\n      text: req.body,\n      requestHeaders: req.headers,\n    })\n  })\n})\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  server.listen()\n  await httpServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(async () => {\n  server.close()\n  await httpServer.close()\n})\n\nit('supports patching an original HTTP response', async () => {\n  server.use(\n    http.post(httpServer.http.url('/resource'), async ({ request }) => {\n      const originalResponse = await fetch(bypass(request))\n      const { text, requestHeaders } = await originalResponse.json()\n      return new Response(text.toUpperCase(), { headers: requestHeaders })\n    }),\n  )\n\n  const response = await fetch(httpServer.http.url('/resource'), {\n    method: 'POST',\n    body: 'world',\n  })\n\n  await expect(response.text()).resolves.toBe('WORLD')\n\n  // Must not contain the internal bypass request header.\n  expect(Object.fromEntries(response.headers)).toHaveProperty('accept', '*/*')\n})\n\nit('preserves request \"accept\" header when patching a response', async () => {\n  server.use(\n    http.post(httpServer.http.url('/resource'), async ({ request }) => {\n      const originalResponse = await fetch(bypass(request))\n      const { text, requestHeaders } = await originalResponse.json()\n      return new Response(text.toUpperCase(), { headers: requestHeaders })\n    }),\n  )\n\n  const response = await fetch(httpServer.http.url('/resource'), {\n    method: 'POST',\n    headers: {\n      accept: 'application/json',\n    },\n    body: 'world',\n  })\n\n  await expect(response.text()).resolves.toBe('WORLD')\n\n  // Must not contain the internal bypass request header.\n  expect(Object.fromEntries(response.headers)).toHaveProperty(\n    'accept',\n    'application/json',\n  )\n})\n"
  },
  {
    "path": "test/node/third-party/axios-error-response.test.ts",
    "content": "// @vitest-environment node\nimport axios, { AxiosError } from 'axios'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.get('https://example.com/resource', () => {\n    return HttpResponse.json({ errorMessage: 'Custom error' }, { status: 400 })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with an error response to axios request', async () => {\n  const error = await axios('https://example.com/resource')\n    .then(() => {\n      throw new Error('Must reject the request Promise')\n    })\n    .catch((error) => error as AxiosError)\n\n  expect(error.response?.status).toBe(400)\n  expect(error.response?.data).toEqual({ errorMessage: 'Custom error' })\n})\n"
  },
  {
    "path": "test/node/third-party/axios-timeout.node.test.ts",
    "content": "// @vitest-environment node\nimport axios, { AxiosError } from 'axios'\nimport { http, HttpResponse, delay } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit(\"axios times out when the handler's delay is greater than axios timeout\", async () => {\n  server.use(\n    http.get('http://localhost/slow', async () => {\n      await delay(500)\n      return HttpResponse.json({ ok: true })\n    }),\n  )\n\n  const error = await axios('http://localhost/slow', { timeout: 50 })\n    .then(() => {\n      expect.fail('Request must not succeed')\n    })\n    .catch((error) => error as AxiosError)\n\n  expect(error).toBeInstanceOf(AxiosError)\n  expect(error).toMatchObject<Partial<AxiosError>>({\n    code: 'ECONNABORTED',\n    message: expect.stringMatching(/timeout/i),\n  })\n})\n\nit(\"axios does not time out when the handler's delay is less than axios timeout\", async () => {\n  server.use(\n    http.get('http://localhost/fast', async () => {\n      await delay(50)\n      return HttpResponse.json({ ok: true })\n    }),\n  )\n\n  const response = await axios('http://localhost/fast', { timeout: 200 })\n\n  expect(response.data).toEqual({ ok: true })\n})\n"
  },
  {
    "path": "test/node/third-party/axios-upload.node.test.ts",
    "content": "// @vitest-environment node\nimport { File } from 'node:buffer'\nimport axios from 'axios'\nimport { http, HttpResponse } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer(\n  http.post('https://example.com/upload', async ({ request }) => {\n    const data = await request.formData()\n    const file = data.get('file')\n\n    if (!file) {\n      return new HttpResponse('Missing document upload', { status: 400 })\n    }\n\n    if (!(file instanceof File)) {\n      return new HttpResponse('Uploaded document is not a File', {\n        status: 400,\n      })\n    }\n\n    return HttpResponse.json({\n      message: `Successfully uploaded \"${file.name}\"!`,\n      content: await file.text(),\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit('responds with a mocked response to an upload request', async () => {\n  const onUploadProgress = vi.fn()\n  const request = axios.create({\n    baseURL: 'https://example.com',\n    onUploadProgress,\n  })\n\n  const formData = new FormData()\n  const file = new Blob(['Hello', 'world'], { type: 'text/plain' })\n  formData.set('file', file, 'doc.txt')\n\n  const response = await request.post('/upload', formData).catch((error) => {\n    throw error.response.data\n  })\n\n  expect(response.data).toEqual({\n    message: 'Successfully uploaded \"doc.txt\"!',\n    content: 'Helloworld',\n  })\n\n  expect(onUploadProgress.mock.calls.length).toBeGreaterThan(0)\n  expect(onUploadProgress).toHaveBeenNthCalledWith(\n    1,\n    expect.objectContaining({\n      loaded: expect.any(Number),\n      total: expect.any(Number),\n      bytes: expect.any(Number),\n    }),\n  )\n})\n"
  },
  {
    "path": "test/node/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"../../global.d.ts\", \"./**/*.test.ts\"]\n}\n"
  },
  {
    "path": "test/node/vitest.config.ts",
    "content": "import { defineConfig } from 'vitest/config'\nimport { mswExports, customViteEnvironments } from '../support/alias'\n\nexport default defineConfig({\n  test: {\n    dir: './test/node',\n    globals: true,\n    alias: {\n      ...mswExports,\n      ...customViteEnvironments,\n    },\n    environmentOptions: {\n      jsdom: {\n        url: 'http://localhost/',\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "test/node/ws-api/on-unhandled-request/callback.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst service = ws.link('wss://localhost:4321')\nconst server = setupServer()\n\nconst onUnhandledRequest = vi.fn()\n\nbeforeAll(() => {\n  server.listen({ onUnhandledRequest })\n  vi.spyOn(console, 'error').mockImplementation(() => {})\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\nit('calls a custom callback on an unhandled WebSocket connection', async () => {\n  const socket = new WebSocket('wss://localhost:4321')\n\n  await vi.waitFor(() => {\n    return new Promise((resolve, reject) => {\n      socket.onopen = resolve\n      socket.onerror = reject\n    })\n  })\n\n  expect(onUnhandledRequest).toHaveBeenCalledOnce()\n\n  const [request] = onUnhandledRequest.mock.calls[0]\n  expect(request).toBeInstanceOf(Request)\n  expect(request.method).toBe('GET')\n  expect(request.url).toBe('wss://localhost:4321/')\n  expect(Array.from(request.headers)).toEqual([\n    ['connection', 'upgrade'],\n    ['upgrade', 'websocket'],\n  ])\n})\n\nit('does not call a custom callback for a handled WebSocket connection', async () => {\n  server.use(service.addEventListener('connection', () => {}))\n\n  const socket = new WebSocket('wss://localhost:4321')\n\n  await vi.waitFor(() => {\n    return new Promise((resolve, reject) => {\n      socket.onopen = resolve\n      socket.onerror = reject\n    })\n  })\n\n  expect(onUnhandledRequest).not.toHaveBeenCalled()\n})\n"
  },
  {
    "path": "test/node/ws-api/on-unhandled-request/error.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst service = ws.link('wss://localhost:4321')\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen({ onUnhandledRequest: 'error' })\n  vi.spyOn(console, 'error').mockImplementation(() => {})\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\nit(\n  'errors on unhandled WebSocket connection',\n  server.boundary(async () => {\n    const socket = new WebSocket('wss://localhost:4321')\n    const errorListener = vi.fn()\n\n    await vi.waitUntil(() => {\n      return new Promise((resolve, reject) => {\n        // These are intentionally swapped. The connection MUST error.\n        socket.addEventListener('error', errorListener)\n        socket.addEventListener('error', resolve)\n        socket.onopen = () => {\n          reject(new Error('WebSocket connection opened unexpectedly'))\n        }\n      })\n    })\n\n    expect(console.error).toHaveBeenCalledWith(\n      `\\\n[MSW] Error: intercepted a request without a matching request handler:\n\n  • GET wss://localhost:4321/\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n    )\n\n    expect(errorListener).toHaveBeenCalledOnce()\n\n    // Must forward the original `onUnhandledRequest` error as the\n    // `cause` property of the error event emitted on the connection.\n    const [event] = errorListener.mock.calls[0]\n    expect(event).toBeInstanceOf(Event)\n    expect(event.type).toBe('error')\n    expect(event.cause).toBeInstanceOf(Error)\n    expect(event.cause.message).toBe(\n      '[MSW] Cannot bypass a request when using the \"error\" strategy for the \"onUnhandledRequest\" option.',\n    )\n  }),\n)\n\nit(\n  'does not error on handled WebSocket connection',\n  server.boundary(async () => {\n    server.use(service.addEventListener('connection', () => {}))\n\n    const socket = new WebSocket('wss://localhost:4321')\n\n    await vi.waitFor(() => {\n      return new Promise((resolve, reject) => {\n        socket.onopen = resolve\n        socket.onerror = reject\n      })\n    })\n\n    expect(console.error).not.toHaveBeenCalled()\n  }),\n)\n"
  },
  {
    "path": "test/node/ws-api/on-unhandled-request/warn.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst service = ws.link('wss://localhost:4321')\nconst server = setupServer()\n\nbeforeAll(() => {\n  server.listen({ onUnhandledRequest: 'warn' })\n  vi.spyOn(console, 'warn').mockImplementation(() => {})\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.resetAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\nit(\n  'warns on unhandled WebSocket connection',\n  server.boundary(async () => {\n    const socket = new WebSocket('wss://localhost:4321')\n\n    await vi.waitFor(() => {\n      return new Promise((resolve, reject) => {\n        socket.onopen = resolve\n        socket.onerror = reject\n      })\n    })\n\n    expect(console.warn).toHaveBeenCalledWith(\n      `\\\n[MSW] Warning: intercepted a request without a matching request handler:\n\n  • GET wss://localhost:4321/\n\nIf you still wish to intercept this unhandled request, please create a request handler for it.\nRead more: https://mswjs.io/docs/http/intercepting-requests`,\n    )\n  }),\n)\n\nit(\n  'does not warn on handled WebSocket connection',\n  server.boundary(async () => {\n    server.use(service.addEventListener('connection', () => {}))\n\n    const socket = new WebSocket('wss://localhost:4321')\n\n    await vi.waitFor(() => {\n      return new Promise((resolve, reject) => {\n        socket.onopen = resolve\n        socket.onerror = reject\n      })\n    })\n\n    expect(console.warn).not.toHaveBeenCalled()\n  }),\n)\n"
  },
  {
    "path": "test/node/ws-api/ws.apply.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\n\nafterEach(() => {\n  server.close()\n})\n\nit('patches WebSocket class even if no event handlers were defined', () => {\n  server.listen()\n\n  const raw = new WebSocket('wss://example.com')\n  expect(raw.constructor.name).toBe('WebSocketOverride')\n  expect(raw).toBeInstanceOf(EventTarget)\n})\n\nit('does not patch WebSocket class until server.listen() is called', () => {\n  const api = ws.link('wss://example.com')\n  server.use(api.addEventListener('connection', () => {}))\n\n  const raw = new WebSocket('wss://example.com')\n  expect(raw.constructor.name).toBe('WebSocket')\n  expect(raw).toBeInstanceOf(EventTarget)\n\n  server.listen()\n\n  const mocked = new WebSocket('wss://example.com')\n  expect(mocked.constructor.name).not.toBe('WebSocket')\n  expect(mocked).toBeInstanceOf(EventTarget)\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.event-patching.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { WebSocketServer } from '../../support/WebSocketServer'\n\nconst service = ws.link('ws://*')\nconst originalServer = new WebSocketServer()\n\nconst server = setupServer(\n  service.addEventListener('connection', ({ server }) => {\n    server.connect()\n  }),\n)\n\nbeforeAll(async () => {\n  server.listen()\n  await originalServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  originalServer.resetState()\n})\n\nafterAll(async () => {\n  server.close()\n  await originalServer.close()\n})\n\nit('patches incoming server message', async () => {\n  originalServer.once('connection', (client) => {\n    client.send('hi from John')\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      /**\n       * @note Since the initial handler connects to the server,\n       * there's no need to call `server.connect()` again.\n       */\n      server.addEventListener('message', (event) => {\n        // Preventing the default stops the server-to-client forwarding.\n        // It means that the WebSocket client won't receive the\n        // actual server message.\n        event.preventDefault()\n        client.send(event.data.replace('John', 'Sarah'))\n      })\n    }),\n  )\n\n  const messageListener = vi.fn()\n  const ws = new WebSocket(originalServer.url)\n  ws.onmessage = (event) => messageListener(event.data)\n\n  await vi.waitFor(() => {\n    expect(messageListener).toHaveBeenNthCalledWith(1, 'hi from Sarah')\n    expect(messageListener).toHaveBeenCalledTimes(1)\n  })\n})\n\nit('combines original and mock server messages', async () => {\n  originalServer.once('connection', (client) => {\n    client.send('original message')\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.addEventListener('message', () => {\n        client.send('mocked message')\n      })\n    }),\n  )\n\n  const messageListener = vi.fn()\n  const ws = new WebSocket(originalServer.url)\n  ws.onopen = () => ws.send('hello')\n  ws.onmessage = (event) => messageListener(event.data)\n\n  await vi.waitFor(() => {\n    /**\n     * @note That the server will send the message as soon as the client\n     * connects. This happens before the event handler is called.\n     */\n    expect(messageListener).toHaveBeenNthCalledWith(1, 'original message')\n    expect(messageListener).toHaveBeenNthCalledWith(2, 'mocked message')\n    expect(messageListener).toHaveBeenCalledTimes(2)\n  })\n})\n\nit('combines original and mock server messages in the different order', async () => {\n  originalServer.once('connection', (client) => {\n    client.send('original message')\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.addEventListener('message', (event) => {\n        /**\n         * @note To change the incoming server events order,\n         * prevent the default, send a mocked message, and\n         * then send the original message as-is.\n         */\n        event.preventDefault()\n        client.send('mocked message')\n        client.send(event.data)\n      })\n    }),\n  )\n\n  const messageListener = vi.fn()\n  const ws = new WebSocket(originalServer.url)\n  ws.onmessage = (event) => messageListener(event.data)\n\n  await vi.waitFor(() => {\n    expect(messageListener).toHaveBeenNthCalledWith(1, 'mocked message')\n    expect(messageListener).toHaveBeenNthCalledWith(2, 'original message')\n    expect(messageListener).toHaveBeenCalledTimes(2)\n  })\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.intercept.client.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { WebSocketServer } from '../../support/WebSocketServer'\n\nconst server = setupServer()\nconst wsServer = new WebSocketServer()\n\nconst service = ws.link('ws://*')\n\nbeforeAll(async () => {\n  server.listen()\n  await wsServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  wsServer.resetState()\n})\n\nafterAll(async () => {\n  server.close()\n  await wsServer.close()\n})\n\nit('intercepts outgoing client text message', async () => {\n  const mockMessageListener = vi.fn()\n  const realConnectionListener = vi.fn()\n\n  server.use(\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', mockMessageListener)\n    }),\n  )\n  wsServer.on('connection', realConnectionListener)\n\n  const socket = new WebSocket(wsServer.url)\n  socket.onopen = () => socket.send('hello')\n\n  await vi.waitFor(() => {\n    // Must intercept the outgoing client message event.\n    expect(mockMessageListener).toHaveBeenCalledTimes(1)\n\n    const messageEvent = mockMessageListener.mock.calls[0][0] as MessageEvent\n    expect(messageEvent.type).toBe('message')\n    expect(messageEvent.data).toBe('hello')\n    expect(messageEvent.target).toBe(socket)\n\n    // Must not connect to the actual server by default.\n    expect(realConnectionListener).not.toHaveBeenCalled()\n  })\n})\n\nit('intercepts outgoing client Blob message', async () => {\n  const mockMessageListener = vi.fn()\n  const realConnectionListener = vi.fn()\n\n  server.use(\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', mockMessageListener)\n    }),\n  )\n  wsServer.on('connection', realConnectionListener)\n\n  const socket = new WebSocket(wsServer.url)\n  socket.onopen = () => socket.send(new Blob(['hello']))\n\n  await vi.waitFor(() => {\n    expect(mockMessageListener).toHaveBeenCalledTimes(1)\n\n    const messageEvent = mockMessageListener.mock.calls[0][0] as MessageEvent\n    expect(messageEvent.type).toBe('message')\n    expect(messageEvent.data.size).toBe(5)\n    expect(messageEvent.target).toEqual(socket)\n\n    // Must not connect to the actual server by default.\n    expect(realConnectionListener).not.toHaveBeenCalled()\n  })\n})\n\nit('intercepts outgoing client ArrayBuffer message', async () => {\n  const mockMessageListener = vi.fn()\n  const realConnectionListener = vi.fn()\n\n  server.use(\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', mockMessageListener)\n    }),\n  )\n  wsServer.on('connection', realConnectionListener)\n\n  const socket = new WebSocket(wsServer.url)\n  socket.binaryType = 'arraybuffer'\n  socket.onopen = () => socket.send(new TextEncoder().encode('hello'))\n\n  await vi.waitFor(() => {\n    expect(mockMessageListener).toHaveBeenCalledTimes(1)\n\n    const messageEvent = mockMessageListener.mock.calls[0][0] as MessageEvent\n    expect(messageEvent.type).toBe('message')\n    expect(messageEvent.data).toEqual(new TextEncoder().encode('hello'))\n    expect(messageEvent.target).toEqual(socket)\n\n    // Must not connect to the actual server by default.\n    expect(realConnectionListener).not.toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.intercept.server.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { WebSocketServer } from '../../support/WebSocketServer'\n\nconst server = setupServer()\nconst originalServer = new WebSocketServer()\n\nconst service = ws.link('ws://*')\n\nbeforeAll(async () => {\n  server.listen()\n  await originalServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  originalServer.resetState()\n})\n\nafterAll(async () => {\n  server.close()\n  await originalServer.close()\n})\n\nit('intercepts incoming server text message', async () => {\n  const serverMessageListener = vi.fn()\n  const clientMessageListener = vi.fn()\n\n  originalServer.on('connection', (client) => {\n    client.send('hello')\n  })\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      server.connect()\n      server.addEventListener('message', serverMessageListener)\n    }),\n  )\n\n  const socket = new WebSocket(originalServer.url)\n  socket.addEventListener('message', clientMessageListener)\n\n  await vi.waitFor(() => {\n    expect(serverMessageListener).toHaveBeenCalledTimes(1)\n\n    const serverMessage = serverMessageListener.mock.calls[0][0] as MessageEvent\n    expect(serverMessage.type).toBe('message')\n    expect(serverMessage.data).toBe('hello')\n\n    expect(clientMessageListener).toHaveBeenCalledTimes(1)\n\n    const clientMessage = clientMessageListener.mock.calls[0][0] as MessageEvent\n    expect(clientMessage.type).toBe('message')\n    expect(clientMessage.data).toBe('hello')\n  })\n})\n\nit('intercepts incoming server Blob message', async () => {\n  const serverMessageListener = vi.fn()\n  const clientMessageListener = vi.fn()\n\n  originalServer.on('connection', async (client) => {\n    /**\n     * @note You should use plain `Blob` instead.\n     * For some reason, the \"ws\" package has trouble accepting\n     * it as an input (expects a Buffer).\n     */\n    client.send(await new Blob(['hello']).arrayBuffer())\n  })\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      server.connect()\n      server.addEventListener('message', serverMessageListener)\n    }),\n  )\n\n  const socket = new WebSocket(originalServer.url)\n  socket.addEventListener('message', clientMessageListener)\n\n  await vi.waitFor(() => {\n    expect(serverMessageListener).toHaveBeenCalledTimes(1)\n\n    const serverMessage = serverMessageListener.mock.calls[0][0] as MessageEvent\n    expect(serverMessage.type).toBe('message')\n    expect(serverMessage.data).toEqual(new Blob(['hello']))\n\n    expect(clientMessageListener).toHaveBeenCalledTimes(1)\n\n    const clientMessage = clientMessageListener.mock.calls[0][0] as MessageEvent\n    expect(clientMessage.type).toBe('message')\n    expect(clientMessage.data).toEqual(new Blob(['hello']))\n  })\n})\n\nit('intercepts incoming ArrayBuffer message', async () => {\n  const encoder = new TextEncoder()\n  const serverMessageListener = vi.fn()\n  const clientMessageListener = vi.fn()\n\n  originalServer.on('connection', async (client) => {\n    client.binaryType = 'arraybuffer'\n    client.send(encoder.encode('hello world'))\n  })\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      server.connect()\n      server.addEventListener('message', serverMessageListener)\n    }),\n  )\n\n  const socket = new WebSocket(originalServer.url)\n  socket.binaryType = 'arraybuffer'\n  socket.addEventListener('message', clientMessageListener)\n\n  await vi.waitFor(() => {\n    expect(serverMessageListener).toHaveBeenCalledTimes(1)\n\n    const serverMessage = serverMessageListener.mock.calls[0][0] as MessageEvent\n    expect(serverMessage.type).toBe('message')\n    expect(new TextDecoder().decode(serverMessage.data)).toBe('hello world')\n\n    expect(clientMessageListener).toHaveBeenCalledTimes(1)\n\n    const clientMessage = clientMessageListener.mock.calls[0][0] as MessageEvent\n    expect(clientMessage.type).toBe('message')\n    expect(new TextDecoder().decode(clientMessage.data)).toBe('hello world')\n  })\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.server.connect.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { WebSocketServer } from '../../support/WebSocketServer'\n\nconst service = ws.link('ws://*')\nconst originalServer = new WebSocketServer()\n\nconst server = setupServer()\n\nbeforeAll(async () => {\n  server.listen()\n  await originalServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  originalServer.resetState()\n})\n\nafterAll(async () => {\n  server.close()\n  await originalServer.close()\n})\n\nit('does not connect to the actual server by default', async () => {\n  const serverConnectionListener = vi.fn()\n  const mockConnectionListener = vi.fn()\n\n  originalServer.once('connection', serverConnectionListener)\n  server.use(service.addEventListener('connection', mockConnectionListener))\n\n  new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(mockConnectionListener).toHaveBeenCalledTimes(1)\n    expect(serverConnectionListener).not.toHaveBeenCalled()\n  })\n})\n\nit('connects to the actual server after calling \"server.connect()\"', async () => {\n  const serverConnectionListener = vi.fn()\n  const mockConnectionListener = vi.fn()\n\n  originalServer.once('connection', serverConnectionListener)\n\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      mockConnectionListener()\n      server.connect()\n    }),\n  )\n\n  new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(mockConnectionListener).toHaveBeenCalledTimes(1)\n    expect(serverConnectionListener).toHaveBeenCalledTimes(1)\n  })\n})\n\nit('forwards incoming server events to the client once connected', async () => {\n  originalServer.once('connection', (client) => client.send('hello'))\n\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      server.connect()\n    }),\n  )\n\n  const messageListener = vi.fn()\n  const ws = new WebSocket(originalServer.url)\n  ws.onmessage = (event) => messageListener(event.data)\n\n  await vi.waitFor(() => {\n    expect(messageListener).toHaveBeenNthCalledWith(1, 'hello')\n    expect(messageListener).toHaveBeenCalledTimes(1)\n  })\n})\n\nit('throws an error when connecting to a non-existing server', async () => {\n  server.use(\n    service.addEventListener('connection', ({ server }) => {\n      server.connect()\n    }),\n  )\n\n  const errorListener = vi.fn()\n  const ws = new WebSocket('ws://localhost:9876')\n  ws.onerror = errorListener\n\n  await vi.waitFor(() => {\n    expect(errorListener).toHaveBeenCalledTimes(1)\n  })\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.stop-propagation.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\nimport { WebSocketServer } from '../../support/WebSocketServer'\n\nconst server = setupServer()\nconst service = ws.link('ws://*')\n\nconst originalServer = new WebSocketServer()\n\nbeforeAll(async () => {\n  server.listen({\n    // We are intentionally connecting to non-existing WebSocket URLs.\n    // Skip the unhandled request warnings, they are intentional.\n    onUnhandledRequest: 'bypass',\n  })\n  await originalServer.listen()\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  originalServer.resetState()\n})\n\nafterAll(async () => {\n  server.close()\n  await originalServer.close()\n})\n\nit('stops propagation for client \"message\" event', async () => {\n  const clientMessageListener = vi.fn<(input: number) => void>()\n\n  server.use(\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', (event) => {\n        // Calling `stopPropagation` will prevent this event from being\n        // dispatched on the `client` belonging to a different event handler.\n        event.stopPropagation()\n        clientMessageListener(1)\n      })\n\n      client.addEventListener('message', () => {\n        clientMessageListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', () => {\n        clientMessageListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', () => {\n        clientMessageListener(4)\n      })\n\n      process.nextTick(() => {\n        client.close()\n      })\n    }),\n  )\n\n  const ws = new WebSocket('ws://localhost')\n  ws.onopen = () => ws.send('hello world')\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(clientMessageListener).toHaveBeenNthCalledWith(1, 1)\n  expect(clientMessageListener).toHaveBeenNthCalledWith(2, 2)\n  expect(clientMessageListener).toHaveBeenCalledTimes(2)\n})\n\nit('stops immediate propagation for client \"message\" event', async () => {\n  const clientMessageListener = vi.fn<(input: number) => void>()\n\n  server.use(\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', (event) => {\n        // Calling `stopPropagation` will prevent this event from being\n        // dispatched on the `client` belonging to a different event handler.\n        event.stopImmediatePropagation()\n        clientMessageListener(1)\n      })\n\n      client.addEventListener('message', () => {\n        clientMessageListener(2)\n      })\n\n      client.addEventListener('message', () => {\n        clientMessageListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ client }) => {\n      client.addEventListener('message', () => {\n        clientMessageListener(4)\n      })\n\n      process.nextTick(() => {\n        client.close()\n      })\n    }),\n  )\n\n  const ws = new WebSocket('ws://localhost')\n  ws.onopen = () => ws.send('hello world')\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(clientMessageListener).toHaveBeenNthCalledWith(1, 1)\n  expect(clientMessageListener).toHaveBeenCalledOnce()\n})\n\nit('stops propagation for server \"open\" event', async () => {\n  const serverOpenListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', () => {})\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('open', (event) => {\n        // Calling `stopPropagation` will prevent this event from being\n        // dispatched on the `server` belonging to a different event handler.\n        event.stopPropagation()\n        serverOpenListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('open', () => {\n        serverOpenListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('open', () => {\n        serverOpenListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('open', () => {\n        serverOpenListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverOpenListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverOpenListener).toHaveBeenNthCalledWith(2, 2)\n  expect(serverOpenListener).toHaveBeenCalledTimes(2)\n})\n\nit('stops immediate propagation for server \"open\" event', async () => {\n  const serverOpenListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', () => {})\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('open', (event) => {\n        event.stopImmediatePropagation()\n        serverOpenListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('open', () => {\n        serverOpenListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('open', () => {\n        serverOpenListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('open', () => {\n        serverOpenListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverOpenListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverOpenListener).toHaveBeenCalledOnce()\n})\n\nit('stops propagation for server \"message\" event', async () => {\n  const serverMessageListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', (ws) => {\n    // Send data from the original server to trigger the \"message\" event.\n    ws.send('hello')\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('message', (event) => {\n        // Calling `stopPropagation` will prevent this event from being\n        // dispatched on the `server` belonging to a different event handler.\n        event.stopPropagation()\n        serverMessageListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('message', () => {\n        serverMessageListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('message', () => {\n        serverMessageListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('message', () => {\n        serverMessageListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverMessageListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverMessageListener).toHaveBeenNthCalledWith(2, 2)\n  expect(serverMessageListener).toHaveBeenCalledTimes(2)\n})\n\nit('stops immediate propagation for server \"message\" event', async () => {\n  const serverMessageListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', (ws) => {\n    // Send data from the original server to trigger the \"message\" event.\n    ws.send('hello')\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('message', (event) => {\n        event.stopImmediatePropagation()\n        serverMessageListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('message', () => {\n        serverMessageListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('message', () => {\n        serverMessageListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('message', () => {\n        serverMessageListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverMessageListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverMessageListener).toHaveBeenCalledOnce()\n})\n\nit('stops propagation for server \"error\" event', async () => {\n  const serverErrorListener = vi.fn<(input: number) => void>()\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('error', (event) => {\n        event.stopPropagation()\n        serverErrorListener(1)\n      })\n\n      server.addEventListener('error', () => {\n        serverErrorListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('error', () => {\n        serverErrorListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('error', () => {\n        serverErrorListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket('ws://localhost/non-existing-path')\n\n  await vi.waitFor(() => {\n    /**\n     * @note Ideally, await the \"CLOSED\" ready state,\n     * but Node.js doesn't dispatch it correctly.\n     * @see https://github.com/nodejs/undici/issues/3697\n     */\n    return new Promise<void>((resolve) => {\n      ws.onerror = () => resolve()\n    })\n  })\n\n  expect(serverErrorListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverErrorListener).toHaveBeenNthCalledWith(2, 2)\n  expect(serverErrorListener).toHaveBeenCalledTimes(2)\n})\n\nit('stops immediate propagation for server \"error\" event', async () => {\n  const serverErrorListener = vi.fn<(input: number) => void>()\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('error', (event) => {\n        event.stopImmediatePropagation()\n        serverErrorListener(1)\n      })\n\n      server.addEventListener('error', () => {\n        serverErrorListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('error', () => {\n        serverErrorListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('error', () => {\n        serverErrorListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket('ws://localhost/non-existing-path')\n\n  await vi.waitFor(() => {\n    /**\n     * @note Ideally, await the \"CLOSED\" ready state, but Node.js doesn't dispatch it correctly.\n     * @see https://github.com/nodejs/undici/issues/3697\n     */\n    return new Promise<void>((resolve) => {\n      ws.onerror = () => resolve()\n    })\n  })\n\n  expect(serverErrorListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverErrorListener).toHaveBeenCalledOnce()\n})\n\nit('stops propagation for server \"close\" event', async () => {\n  const serverCloseListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', (ws) => {\n    ws.close()\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('close', (event) => {\n        event.stopPropagation()\n        serverCloseListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('close', () => {\n        serverCloseListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('close', () => {\n        serverCloseListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('close', () => {\n        serverCloseListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverCloseListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverCloseListener).toHaveBeenNthCalledWith(2, 2)\n  expect(serverCloseListener).toHaveBeenCalledTimes(2)\n})\n\nit('stops immediate propagation for server \"close\" event', async () => {\n  const serverCloseListener = vi.fn<(input: number) => void>()\n\n  originalServer.addListener('connection', (ws) => {\n    ws.close()\n  })\n\n  server.use(\n    service.addEventListener('connection', ({ client, server }) => {\n      server.connect()\n\n      server.addEventListener('close', (event) => {\n        event.stopImmediatePropagation()\n        serverCloseListener(1)\n\n        process.nextTick(() => client.close())\n      })\n\n      server.addEventListener('close', () => {\n        serverCloseListener(2)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('close', () => {\n        serverCloseListener(3)\n      })\n    }),\n\n    service.addEventListener('connection', ({ server }) => {\n      server.addEventListener('close', () => {\n        serverCloseListener(4)\n      })\n    }),\n  )\n\n  const ws = new WebSocket(originalServer.url)\n\n  await vi.waitFor(() => {\n    expect(ws.readyState).toBe(WebSocket.CLOSED)\n  })\n\n  expect(serverCloseListener).toHaveBeenNthCalledWith(1, 1)\n  expect(serverCloseListener).toHaveBeenCalledOnce()\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.unhandled-exception.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst server = setupServer()\nconst service = ws.link('ws://*')\n\nbeforeAll(() => {\n  server.listen()\n  vi.spyOn(console, 'error').mockImplementation(() => void 0)\n})\n\nafterEach(() => {\n  server.resetHandlers()\n  vi.clearAllMocks()\n})\n\nafterAll(() => {\n  server.close()\n  vi.restoreAllMocks()\n})\n\nit('dispatches a WebSocket error event on handler exception', async () => {\n  server.use(\n    service.addEventListener('connection', () => {\n      throw new Error('Handler exception')\n    }),\n  )\n\n  const socket = new WebSocket('ws://localhost:3000')\n\n  const closeListener = vi.fn()\n  const errorListener = vi.fn()\n  socket.onclose = closeListener\n  socket.onerror = errorListener\n  socket.onopen = () => {\n    expect.fail('Must not open the WebSocket connection')\n  }\n\n  await expect.poll(() => errorListener).toHaveBeenCalledOnce()\n  expect(closeListener).toHaveBeenCalledOnce()\n  expect(closeListener).toHaveBeenCalledWith(\n    expect.objectContaining({\n      code: 1011,\n      reason: 'Handler exception',\n    }),\n  )\n  expect(socket.readyState).toBe(WebSocket.CLOSED)\n\n  expect(console.error, 'Prints the error for the user').toHaveBeenCalledWith(\n    new Error('Handler exception'),\n  )\n})\n"
  },
  {
    "path": "test/node/ws-api/ws.use.test.ts",
    "content": "// @vitest-environment node-websocket\nimport { ws } from 'msw'\nimport { setupServer } from 'msw/node'\n\nconst service = ws.link('wss://*')\n\nconst server = setupServer(\n  service.addEventListener('connection', ({ client }) => {\n    client.addEventListener('message', (event) => {\n      if (event.data === 'hello') {\n        client.send('hello, client!')\n      }\n\n      if (event.data === 'fallthrough') {\n        client.send('ok')\n      }\n    })\n  }),\n)\n\nbeforeAll(() => {\n  server.listen()\n})\n\nafterAll(() => {\n  server.close()\n})\n\nit.concurrent(\n  'resolves outgoing events using initial handlers',\n  server.boundary(async () => {\n    const messageListener = vi.fn()\n    const ws = new WebSocket('wss://example.com')\n    ws.onmessage = (event) => messageListener(event.data)\n    ws.onopen = () => ws.send('hello')\n\n    await vi.waitFor(() => {\n      expect(messageListener).toHaveBeenCalledWith('hello, client!')\n      expect(messageListener).toHaveBeenCalledTimes(1)\n    })\n  }),\n)\n\nit.concurrent(\n  'overrides an outgoing event listener',\n  server.boundary(async () => {\n    server.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // Stopping immediate event propagation will prevent\n            // the same message listener in the initial handler\n            // from being called.\n            event.stopImmediatePropagation()\n            client.send('howdy, client!')\n          }\n        })\n      }),\n    )\n\n    const messageListener = vi.fn()\n    const ws = new WebSocket('wss://example.com')\n    ws.onmessage = (event) => messageListener(event.data)\n    ws.onopen = () => ws.send('hello')\n\n    await vi.waitFor(() => {\n      expect(messageListener).toHaveBeenCalledWith('howdy, client!')\n      expect(messageListener).toHaveBeenCalledTimes(1)\n    })\n  }),\n)\n\nit.concurrent(\n  'combines initial and override listeners',\n  server.boundary(async () => {\n    server.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // Not stopping the event propagation will result in both\n            // the override handler and the runtime handler sending\n            // data to the client in order. The override handler is\n            // prepended, so it will send data first.\n            client.send('override data')\n          }\n        })\n      }),\n    )\n\n    const messageListener = vi.fn()\n    const ws = new WebSocket('wss://example.com')\n    ws.onmessage = (event) => messageListener(event.data)\n    ws.onopen = () => ws.send('hello')\n\n    await vi.waitFor(() => {\n      // The runtime handler is executed first, so it sends its message first.\n      expect(messageListener).toHaveBeenNthCalledWith(1, 'override data')\n      // The initial handler will send its message next.\n      expect(messageListener).toHaveBeenNthCalledWith(2, 'hello, client!')\n      expect(messageListener).toHaveBeenCalledTimes(2)\n    })\n  }),\n)\n\nit.concurrent(\n  'combines initial and override listeners in the opposite order',\n  async () => {\n    server.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // Queuing the send to the next tick will ensure\n            // that the initial handler sends data first,\n            // and this override handler sends data next.\n            queueMicrotask(() => {\n              client.send('override data')\n            })\n          }\n        })\n      }),\n    )\n\n    const messageListener = vi.fn()\n    const ws = new WebSocket('wss://example.com')\n    ws.onmessage = (event) => messageListener(event.data)\n    ws.onopen = () => ws.send('hello')\n\n    await vi.waitFor(() => {\n      expect(messageListener).toHaveBeenNthCalledWith(1, 'hello, client!')\n      expect(messageListener).toHaveBeenNthCalledWith(2, 'override data')\n      expect(messageListener).toHaveBeenCalledTimes(2)\n    })\n  },\n)\n\nit.concurrent(\n  'does not affect unrelated events',\n  server.boundary(async () => {\n    server.use(\n      service.addEventListener('connection', ({ client }) => {\n        client.addEventListener('message', (event) => {\n          if (event.data === 'hello') {\n            // Stopping immediate event propagation will prevent\n            // the same message listener in the initial handler\n            // from being called.\n            event.stopImmediatePropagation()\n            client.send('howdy, client!')\n          }\n        })\n      }),\n    )\n\n    const messageListener = vi.fn()\n    const ws = new WebSocket('wss://example.com')\n    ws.onmessage = (event) => {\n      messageListener(event.data)\n\n      if (event.data === 'howdy, client!') {\n        ws.send('fallthrough')\n      }\n    }\n    ws.onopen = () => ws.send('hello')\n\n    await vi.waitFor(() => {\n      expect(messageListener).toHaveBeenNthCalledWith(1, 'howdy, client!')\n    })\n\n    await vi.waitFor(() => {\n      // The initial handler still sends data to unrelated events.\n      expect(messageListener).toHaveBeenNthCalledWith(2, 'ok')\n      expect(messageListener).toHaveBeenCalledTimes(2)\n    })\n  }),\n)\n"
  },
  {
    "path": "test/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "test/support/WebSocketServer.ts",
    "content": "import { invariant } from 'outvariant'\nimport { Emitter } from 'strict-event-emitter'\nimport fastify, { FastifyInstance } from 'fastify'\nimport fastifyWebSocket, {\n  type WebSocket as FastifySocket,\n} from '@fastify/websocket'\n\ntype WebSocketEventMap = {\n  connection: [client: FastifySocket]\n}\n\nexport class WebSocketServer extends Emitter<WebSocketEventMap> {\n  private _url?: string\n  private app: FastifyInstance\n  private clients: Set<FastifySocket>\n\n  constructor() {\n    super()\n    this.clients = new Set()\n\n    this.app = fastify()\n    this.app.register(fastifyWebSocket)\n    this.app.register(async (fastify) => {\n      fastify.get('/', { websocket: true }, (socket) => {\n        this.clients.add(socket)\n        socket.once('close', () => this.clients.delete(socket))\n\n        this.emit('connection', socket)\n      })\n    })\n  }\n\n  get url(): string {\n    invariant(\n      this._url,\n      'Failed to get \"url\" on WebSocketServer: server is not running. Did you forget to \"await server.listen()\"?',\n    )\n    return this._url\n  }\n\n  public async listen(port = 0): Promise<void> {\n    const address = await this.app.listen({\n      host: '127.0.0.1',\n      port,\n    })\n    const url = new URL(address)\n    url.protocol = url.protocol.replace(/^http/, 'ws')\n    this._url = url.href\n  }\n\n  public resetState(): void {\n    this.closeAllClients()\n    this.removeAllListeners()\n  }\n\n  public closeAllClients(): void {\n    this.clients.forEach((client) => {\n      client.close()\n    })\n  }\n\n  public async close(): Promise<void> {\n    return this.app.close()\n  }\n}\n"
  },
  {
    "path": "test/support/alias.ts",
    "content": "import url from 'node:url'\nimport path from 'node:path'\n\nconst ROOT_URL = new URL('../../', import.meta.url)\n\nexport function fromRoot(...paths: Array<string>): string {\n  return url.fileURLToPath(new URL(path.join(...paths), ROOT_URL))\n}\n\nexport const mswExports = {\n  'msw/node': fromRoot('./lib/node/index.mjs'),\n  'msw/native': fromRoot('./lib/native/index.mjs'),\n  'msw/browser': fromRoot('./lib/browser/index.mjs'),\n  msw: fromRoot('./lib/core/index.mjs'),\n}\n\nexport const customViteEnvironments = {\n  'vitest-environment-node-websocket': fromRoot(\n    './test/support/environments/vitest-environment-node-websocket',\n  ),\n}\n"
  },
  {
    "path": "test/support/environments/vitest-environment-node-websocket.ts",
    "content": "/**\n * Node.js environment superset that has a global WebSocket API.\n */\nimport type { Environment } from 'vitest'\nimport { builtinEnvironments } from 'vitest/environments'\nimport { WebSocket } from 'undici'\n\nexport default <Environment>{\n  name: 'node-with-websocket',\n  transformMode: 'ssr',\n  async setup(global, options) {\n    /**\n     * @note It's crucial this extend the Node.js environment.\n     * JSDOM polyfills the global \"Event\", making it unusable\n     * with Node's \"EventTarget\".\n     */\n    const { teardown } = await builtinEnvironments.node.setup(global, options)\n\n    Reflect.set(globalThis, 'WebSocket', WebSocket)\n\n    return {\n      teardown,\n    }\n  },\n}\n"
  },
  {
    "path": "test/support/graphql.ts",
    "content": "import { parse, type ExecutionResult } from 'graphql'\nimport {\n  DocumentTypeDecoration,\n  TypedDocumentNode,\n} from '@graphql-typed-document-node/core'\n\n/**\n * Identity function that returns a given template string array.\n * Provides GraphQL syntax highlighting without any extra transformations.\n */\nexport const gql = (str: TemplateStringsArray) => {\n  return str.join('')\n}\n\ninterface GraphQLClientOPtions {\n  uri: string\n  fetch?: (input: any, init?: any) => Promise<Response>\n}\n\ninterface GraphQLOperationInput {\n  query: TemplateStringsArray | string\n  variables?: Record<string, any>\n  headers?: Record<string, string>\n}\n\n/**\n * Create a new GraphQL client. Uses `fetch` to dispatch a\n * specification-compliant GraphQL request.\n */\nexport function createGraphQLClient(options: GraphQLClientOPtions) {\n  return async <Data extends Record<string, unknown>>(\n    input: GraphQLOperationInput,\n  ): Promise<ExecutionResult<Data> & { response: Response }> => {\n    const response = await fetch(options.uri, {\n      method: 'POST',\n      headers: {\n        accept: '*/*',\n        'content-type': 'application/json',\n        ...(input.headers || {}),\n      },\n      body: JSON.stringify(input),\n    })\n\n    // No need to transform the JSON into `ExecutionResult`,\n    // because that's the responsibility of an actual server\n    // or an MSW request handler.\n    const { data, errors, extensions } = await response.json()\n\n    return {\n      data,\n      errors,\n      extensions,\n      response,\n    }\n  }\n}\n\nexport class TypedDocumentString<TResult, TVariables>\n  extends String\n  implements DocumentTypeDecoration<TResult, TVariables>\n{\n  __apiType?: DocumentTypeDecoration<TResult, TVariables>['__apiType']\n\n  constructor(\n    private value: string,\n    public __meta__?: { hash: string },\n  ) {\n    super(value)\n  }\n\n  toString(): string & DocumentTypeDecoration<TResult, TVariables> {\n    return this.value\n  }\n}\n\nexport function createTypedDocumentString<TResult = any, TVariables = any>(\n  source: string,\n) {\n  return new TypedDocumentString<TResult, TVariables>(source)\n}\n\nexport function createTypedDocumentNode<TResult = any, TVariables = any>(\n  source: string,\n): TypedDocumentNode<TResult, TVariables> {\n  const doc = typeof source === 'string' ? parse(source) : source\n  return doc as TypedDocumentNode<TResult, TVariables>\n}\n"
  },
  {
    "path": "test/support/msw-esm/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"react-native\": {\n        \"import\": {\n          \"types\": \"./lib/core/index.d.mts\",\n          \"default\": \"./lib/core/index.mjs\"\n        },\n        \"default\": {\n          \"types\": \"./lib/core/index.d.ts\",\n          \"default\": \"./lib/core/index.js\"\n        }\n      },\n      \"import\": {\n        \"types\": \"./lib/core/index.d.mts\",\n        \"default\": \"./lib/core/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/index.d.ts\",\n        \"default\": \"./lib/core/index.js\"\n      }\n    },\n    \"./browser\": {\n      \"module-sync\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"browser\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/browser/index.d.mts\",\n        \"default\": \"./lib/browser/index.mjs\"\n      },\n      \"node\": null,\n      \"react-native\": null,\n      \"default\": {\n        \"types\": \"./lib/browser/index.d.ts\",\n        \"default\": \"./lib/browser/index.js\"\n      }\n    },\n    \"./node\": {\n      \"module-sync\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"node\": {\n        \"require\": \"./lib/node/index.js\",\n        \"import\": \"./lib/node/index.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/node/index.d.mts\",\n        \"default\": \"./lib/node/index.mjs\"\n      },\n      \"browser\": null,\n      \"react-native\": null,\n      \"default\": {\n        \"types\": \"./lib/node/index.d.ts\",\n        \"default\": \"./lib/node/index.js\"\n      }\n    },\n    \"./native\": {\n      \"react-native\": {\n        \"import\": {\n          \"types\": \"./lib/native/index.d.mts\",\n          \"default\": \"./lib/native/index.mjs\"\n        },\n        \"default\": {\n          \"types\": \"./lib/native/index.d.ts\",\n          \"default\": \"./lib/native/index.js\"\n        }\n      },\n      \"browser\": null,\n      \"import\": {\n        \"types\": \"./lib/native/index.d.mts\",\n        \"default\": \"./lib/native/index.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/native/index.d.ts\",\n        \"default\": \"./lib/native/index.js\"\n      }\n    },\n    \"./core/http\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/http.d.mts\",\n        \"default\": \"./lib/core/http.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/http.d.ts\",\n        \"default\": \"./lib/core/http.js\"\n      }\n    },\n    \"./core/graphql\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/graphql.d.mts\",\n        \"default\": \"./lib/core/graphql.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/graphql.d.ts\",\n        \"default\": \"./lib/core/graphql.js\"\n      }\n    },\n    \"./core/ws\": {\n      \"module-sync\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"module\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"import\": {\n        \"types\": \"./lib/core/ws.d.mts\",\n        \"default\": \"./lib/core/ws.mjs\"\n      },\n      \"default\": {\n        \"types\": \"./lib/core/ws.d.ts\",\n        \"default\": \"./lib/core/ws.js\"\n      }\n    },\n    \"./package.json\": \"./package.json\"\n  }\n}\n"
  },
  {
    "path": "test/support/utils.ts",
    "content": "import url from 'node:url'\nimport path from 'node:path'\nimport { ClientRequest, IncomingMessage } from 'http'\n\nexport function sleep(duration: number) {\n  return new Promise((resolve) => {\n    setTimeout(resolve, duration)\n  })\n}\n\nexport function fromTemp(...segments: string[]) {\n  return url.fileURLToPath(\n    new URL(path.join('../..', 'tmp', ...segments), import.meta.url),\n  )\n}\n\nexport async function waitForClientRequest(request: ClientRequest): Promise<{\n  response: IncomingMessage\n  responseText: string\n}> {\n  return new Promise((resolve, reject) => {\n    request.once('error', (error) => {\n      /**\n       * @note Since Node.js v20, Node.js may throw an AggregateError\n       * that doesn't have the `message` property and thus won't be handled\n       * here correctly. Instead, use the error's `code` as the rejection reason.\n       * The code stays consistent across Node.js versions.\n       */\n      reject('code' in error ? error.code : error)\n    })\n    request.once('abort', () => reject(new Error('Request was aborted')))\n\n    request.on('response', (response) => {\n      response.once('error', reject)\n\n      const responseChunks: Array<Buffer> = []\n\n      response.on('data', (chunk) => {\n        responseChunks.push(Buffer.from(chunk))\n      })\n      response.once('end', () => {\n        resolve({\n          response,\n          responseText: Buffer.concat(responseChunks).toString('utf8'),\n        })\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/support/waitFor.ts",
    "content": "import { sleep } from './utils'\n\nconst RETRY_INTERVAL = 500\nconst MAX_RETRIES = 5\n\nexport async function waitFor(fn: () => unknown): Promise<void> {\n  for (let retryCount = 1; retryCount <= MAX_RETRIES; retryCount++) {\n    try {\n      await fn()\n      return\n    } catch (error) {\n      if (retryCount === MAX_RETRIES) {\n        throw error\n      }\n\n      await sleep(RETRY_INTERVAL)\n    }\n  }\n}\n"
  },
  {
    "path": "test/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"module\": \"esnext\",\n    \"target\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    // Support default imports for modules that have no default exports.\n    // This way \"http\" imports stay \"import http from 'http'\".\n    // Using wildcard there breaks request interception since it\n    // encapsulates the values under the \".default\" key.\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": false,\n    \"noEmit\": true,\n    \"types\": [\"node\", \"vitest/globals\"]\n  },\n  \"include\": [\"**/*.ts\"]\n}\n"
  },
  {
    "path": "test/typings/custom-handler.test-d.ts",
    "content": "import { it } from 'vitest'\nimport { http, HttpRequestHandler, GraphQLRequestHandler, graphql } from 'msw'\nimport { setupWorker } from 'msw/browser'\nimport { setupServer } from 'msw/node'\n\nconst generateHttpHandler: HttpRequestHandler = (path, resolver, options) => {\n  return http.get(path, resolver, options)\n}\n\nconst generateGraphQLHandler: GraphQLRequestHandler = (\n  operationName,\n  resolver,\n) => {\n  return graphql.query(operationName, resolver)\n}\n\nit('accepts custom request handler (setupWorker)', () => {\n  setupWorker(\n    generateHttpHandler('/', () => {}),\n    generateGraphQLHandler('GetResource', () => {}),\n  )\n})\n\nit('accepts custom request handler (setupServer)', () => {\n  setupServer(\n    generateHttpHandler('/', () => {}),\n    generateGraphQLHandler('GetResource', () => {}),\n  )\n})\n"
  },
  {
    "path": "test/typings/custom-resolver.test-d.ts",
    "content": "import { it, expectTypeOf } from 'vitest'\nimport {\n  http,\n  HttpResponseResolver,\n  delay,\n  PathParams,\n  DefaultBodyType,\n  HttpResponse,\n  graphql,\n  GraphQLQuery,\n  GraphQLVariables,\n  GraphQLResponseResolver,\n} from 'msw'\n\nit('custom http resolver has correct parameters type', () => {\n  /**\n   * A higher-order resolver that injects a fixed\n   * delay before calling the provided resolver.\n   */\n  function withDelay<\n    // Recreate the generic signature of the default resolver\n    // so the arguments passed to \"http.get\" propagate here.\n    Params extends PathParams,\n    RequestBodyType extends DefaultBodyType,\n    ResponseBodyType extends DefaultBodyType,\n  >(\n    delayMs: number,\n    resolver: HttpResponseResolver<Params, RequestBodyType, ResponseBodyType>,\n  ): HttpResponseResolver<Params, RequestBodyType, ResponseBodyType> {\n    return async (...args) => {\n      await delay(delayMs)\n      return resolver(...args)\n    }\n  }\n\n  http.get<{ id: string }, never, 'hello'>(\n    '/user/:id',\n    withDelay(250, ({ params }) => {\n      expectTypeOf(params).toEqualTypeOf<{ id: string }>()\n      return HttpResponse.text(\n        // @ts-expect-error Response body doesn't match the response type.\n        'non-matching',\n      )\n    }),\n  )\n})\n\nfunction identityGraphQLResolver<\n  Query extends GraphQLQuery,\n  Variables extends GraphQLVariables,\n>(\n  resolver: GraphQLResponseResolver<Query, Variables>,\n): GraphQLResponseResolver<Query, Variables> {\n  return async (...args) => {\n    return resolver(...args)\n  }\n}\n\nit('custom graphql resolver has correct variables and response type', () => {\n  graphql.query<{ number: number }, { id: string }>(\n    'GetUser',\n    identityGraphQLResolver(({ variables }) => {\n      expectTypeOf(variables).toEqualTypeOf<{ id: string }>()\n\n      return HttpResponse.json({\n        data: {\n          number: 1,\n        },\n      })\n    }),\n  )\n})\n\nit('custom graphql resolver does not accept unknown variables', () => {\n  graphql.query<{ number: number }, { id: string }>(\n    'GetUser',\n    identityGraphQLResolver(({ variables }) => {\n      expectTypeOf(variables).toEqualTypeOf<{ id: string }>()\n\n      return HttpResponse.json({\n        data: {\n          // @ts-expect-error Incompatible response query type.\n          user: {\n            id: variables.id,\n          },\n        },\n      })\n    }),\n  )\n})\n"
  },
  {
    "path": "test/typings/graphql-custom-predicate.test-d.ts",
    "content": "import {\n  graphql,\n  type GraphQLOperationType,\n  type GraphQLVariables,\n  type GraphQLResponseResolver,\n} from 'msw'\n\nconst resolver: GraphQLResponseResolver<any, any> = () => void 0\n\nit('supports custom predicate', () => {\n  graphql.query<{ user: null }, { a: string }>(\n    ({ request, cookies, operationType, operationName, query, variables }) => {\n      expectTypeOf(request).toEqualTypeOf<Request>()\n      expectTypeOf(cookies).toEqualTypeOf<Record<string, string>>()\n      expectTypeOf(operationType).toEqualTypeOf<GraphQLOperationType>\n      expectTypeOf(operationName).toEqualTypeOf<string>()\n      /**\n       * @note Both query and variables do not infer the narrow type from the handler\n       * because this is the matching phase and values might be arbitrary.\n       */\n      expectTypeOf(query).toEqualTypeOf<string>()\n      expectTypeOf(variables).toEqualTypeOf<GraphQLVariables>()\n\n      return operationName === 'MyQuery'\n    },\n    resolver,\n  )\n\n  graphql.query(() => true, resolver)\n  graphql.query(() => false, resolver)\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => {},\n    resolver,\n  )\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => ({}),\n    resolver,\n  )\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => undefined,\n    resolver,\n  )\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => null,\n    resolver,\n  )\n})\n\nit('supports returning extended match result from a custom predicate', () => {\n  graphql.query(() => ({ matches: true }), resolver)\n  graphql.query(() => ({ matches: false }), resolver)\n\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => ({ matches: 2 }),\n    resolver,\n  )\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => ({ matches: undefined }),\n    resolver,\n  )\n  graphql.query(\n    // @ts-expect-error Invalid return type.\n    () => ({ matches: null }),\n    resolver,\n  )\n})\n"
  },
  {
    "path": "test/typings/graphql-typed-document-node.test-d.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { TypedDocumentNode } from '@graphql-typed-document-node/core'\n\nconst GetUserQuery = {} as TypedDocumentNode<\n  {\n    user: {\n      name: 'John'\n    }\n  },\n  { userId: string }\n>\n\nit('infers the result type', () => {\n  graphql.query(GetUserQuery, () => {\n    if (Math.random()) {\n      return HttpResponse.json({\n        data: {\n          user: {\n            // @ts-expect-error Invalid result type.\n            name: 123,\n          },\n        },\n      })\n    }\n\n    return HttpResponse.json({\n      data: {\n        user: { name: 'John' },\n      },\n    })\n  })\n})\n\nit('infers the query variables type', () => {\n  graphql.query(GetUserQuery, ({ query, variables }) => {\n    expectTypeOf(query).toBeString()\n    expectTypeOf(variables).toEqualTypeOf<{ userId: string }>()\n\n    return HttpResponse.json({\n      data: {\n        user: { name: 'John' },\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "test/typings/graphql-typed-document-string.test-d.ts",
    "content": "import { graphql, HttpResponse } from 'msw'\nimport { DocumentTypeDecoration } from '@graphql-typed-document-node/core'\n\ndeclare function createTypedDocumentString<TResult = any, TVariables = any>(\n  query: string,\n): DocumentTypeDecoration<TResult, TVariables>\n\nit('infers the result type', () => {\n  graphql.query(\n    createTypedDocumentString<{ user: { id: string; name: string } }>(''),\n    () => {\n      if (Math.random()) {\n        return HttpResponse.json({\n          data: {\n            user: {\n              // @ts-expect-error Invalid result type.\n              id: 123,\n              name: 'John Doe',\n            },\n          },\n        })\n      }\n\n      return HttpResponse.json({\n        data: { user: { id: '1', name: 'John Doe' } },\n      })\n    },\n  )\n})\n\nit('infers the variables type', () => {\n  graphql.query(\n    createTypedDocumentString<null, { id: string }>(''),\n    ({ variables }) => {\n      expectTypeOf(variables).toEqualTypeOf<{ id: string }>()\n    },\n  )\n})\n"
  },
  {
    "path": "test/typings/graphql.test-d.ts",
    "content": "import { it, expectTypeOf } from 'vitest'\nimport { parse } from 'graphql'\nimport { graphql, HttpResponse, passthrough } from 'msw'\n\nit('graphql mutation can be used without variables generic type', () => {\n  graphql.mutation('GetUser', () => {\n    return HttpResponse.json({ data: { id: '2' } })\n  })\n})\n\nit('graphql mutation accepts inline generic variables type', () => {\n  graphql.mutation<never, { id: string }>('GetUser', ({ variables }) => {\n    expectTypeOf(variables).toEqualTypeOf<{ id: string }>()\n  })\n})\n\nit('graphql mutation accepts inline generic variables never type', () => {\n  graphql.mutation<never, never>('CreateUser', ({ variables }) => {\n    expectTypeOf(variables).toEqualTypeOf<never>()\n  })\n})\n\nit(\"graphql mutation does not accept null as variables' generic mutation type\", () => {\n  graphql.mutation<\n    { key: string },\n    // @ts-expect-error `null` is not a valid variables type.\n    null\n  >('', () => {})\n})\n\nit('graphql mutation allows explicit null as the response body type for the mutation', () => {\n  graphql.mutation<{ key: string }>('MutateData', () => {\n    return HttpResponse.json({\n      // Explicit null in mutations must also be allowed.\n      data: null,\n    })\n  })\n})\nit('graphql mutation does not allow mismatched mutation response', () => {\n  graphql.mutation<{ key: string }>('MutateData', () => {\n    return HttpResponse.json({\n      // @ts-expect-error Response data doesn't match the query type.\n      data: {},\n    })\n  })\n})\n\nit(\"graphql query does not accept null as variables' generic query type \", () => {\n  graphql.query<\n    { key: string },\n    // @ts-expect-error `null` is not a valid variables type.\n    null\n  >('', () => {})\n})\n\nit(\"graphql query accepts the correct type for the variables' generic query type\", () => {\n  /**\n   * Response body type (GraphQL query type).\n   */\n  // Returned mocked response body must satisfy the\n  // GraphQL query generic.\n  graphql.query<{ id: string }>('GetUser', () => {\n    return HttpResponse.json({\n      data: { id: '2' },\n    })\n  })\n})\n\nit('graphql query allows explicit null as the response body type for the query', () => {\n  graphql.query<{ id: string }>('GetUser', () => {\n    return HttpResponse.json({\n      // Explicit null must be allowed.\n      data: null,\n    })\n  })\n})\n\nit('supports nullable queries', () => {\n  graphql.query<{ id: string } | null>('GetUser', () => {\n    return HttpResponse.json({\n      data: null,\n    })\n  })\n})\n\nit('supports nullable mutations', () => {\n  graphql.mutation<{ id: string } | null>('GetUser', () => {\n    return HttpResponse.json({\n      data: null,\n    })\n  })\n})\n\nit('graphql query does not accept invalid data type for the response body type for the query', () => {\n  graphql.query<{ id: string }>('GetUser', () => {\n    return HttpResponse.json({\n      data: {\n        // @ts-expect-error \"id\" type is incorrect\n        id: 123,\n      },\n    })\n  })\n})\n\nit('graphql query does not allow empty response when the query type is defined', () => {\n  graphql.query<{ id: string }>(\n    'GetUser',\n    // @ts-expect-error response json is empty\n    () => HttpResponse.json({ data: {} }),\n  )\n})\n\nit('graphql query does not allow incompatible response body type', () => {\n  graphql.query<{ id: string }>(\n    'GetUser',\n    // @ts-expect-error incompatible response body type\n    () => HttpResponse.text('hello'),\n  )\n})\n\nit('graphql operation does not accept null as variables type', () => {\n  graphql.operation<\n    { key: string },\n    // @ts-expect-error `null` is not a valid variables type.\n    null\n  >(() => {\n    return HttpResponse.json({ data: { key: 'a' } })\n  })\n})\n\nit('graphql operation does not allow mismatched operation response', () => {\n  graphql.operation<{ key: string }>(() => {\n    return HttpResponse.json({\n      // @ts-expect-error Response data doesn't match the query type.\n      data: {},\n    })\n  })\n})\n\nit('graphql operation allows explicit null as the response body type for the operation', () => {\n  graphql.operation<{ key: string }>(() => {\n    return HttpResponse.json({ data: null })\n  })\n})\n\nit('graphql handlers allow passthrough responses', () => {\n  // Passthrough responses.\n  graphql.query('GetUser', () => passthrough())\n  graphql.mutation('AddPost', () => passthrough())\n  graphql.operation(() => passthrough())\n  graphql.query('GetUser', ({ request }) => {\n    if (request.headers.has('cookie')) {\n      return passthrough()\n    }\n\n    return HttpResponse.json({ data: {} })\n  })\n})\n\nit('supports Response.error()', () => {\n  graphql.query<{ id: string }>('GetUser', () => HttpResponse.error())\n  graphql.mutation('UpdatePost', () => HttpResponse.error())\n  graphql.operation(() => HttpResponse.error())\n\n  graphql.query('GetUser', async () => HttpResponse.error())\n  graphql.query('GetUser', function* () {\n    return HttpResponse.error()\n  })\n\n  graphql.query('GetUser', () => Response.error())\n  graphql.query('GetUser', async () => Response.error())\n  graphql.query('GetUser', function* () {\n    return Response.error()\n  })\n})\n\nit(\"graphql variables cannot extract type from the runtime 'DocumentNode'\", () => {\n  /**\n   * Supports `DocumentNode` as the GraphQL operation name.\n   */\n  const getUser = parse(`\n        query GetUser {\n          user {\n            firstName\n          }\n        }\n      `)\n  graphql.query(getUser, () => {\n    return HttpResponse.json({\n      // Cannot extract query type from the runtime `DocumentNode`.\n      data: { arbitrary: true },\n    })\n  })\n})\n\nit('graphql query cannot extract variable and response types', () => {\n  const getUserById = parse(`\n      query GetUserById($userId: String!) {\n        user(id: $userId) {\n          firstName\n        }\n      }\n      `)\n  graphql.query(getUserById, ({ variables }) => {\n    // Cannot extract variables type from a DocumentNode.\n    expectTypeOf(variables).toEqualTypeOf<Record<string, any>>()\n\n    return HttpResponse.json({\n      data: {\n        user: {\n          firstName: 'John',\n          // Extracting a query body type from the \"DocumentNode\" is impossible.\n          lastName: 'Maverick',\n        },\n      },\n    })\n  })\n})\n\nit('graphql mutation cannot extract variable and response types', () => {\n  const createUser = parse(`\n        mutation CreateUser {\n          user {\n            id\n          }\n        }\n      `)\n  graphql.mutation(createUser, () => {\n    return HttpResponse.json({\n      data: { arbitrary: true },\n    })\n  })\n})\n\nit('graphql query allows extensions in the response body', () => {\n  graphql.query<{ id: string }>('GetUser', () => {\n    return HttpResponse.json({\n      data: { id: '2' },\n      extensions: {\n        requestId: '3',\n        runtime: 'foo',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "test/typings/http-custom-predicate.test-d.ts",
    "content": "import { http, HttpResponseResolver } from 'msw'\n\nconst resolver: HttpResponseResolver<any, any, any> = () => void 0\n\nit('supports custom predicate', () => {\n  http.get(({ request, cookies }) => {\n    expectTypeOf(request).toEqualTypeOf<Request>()\n    expectTypeOf(cookies).toEqualTypeOf<Record<string, string>>()\n\n    return request.url.includes('user')\n  }, resolver)\n\n  http.get(() => true, resolver)\n  http.get(() => false, resolver)\n  // @ts-expect-error Invalid return type.\n  http.get(() => {}, resolver)\n  // @ts-expect-error Invalid return type.\n  http.get(() => ({}), resolver)\n  // @ts-expect-error Invalid return type.\n  http.get(() => undefined, resolver)\n  // @ts-expect-error Invalid return type.\n  http.get(() => null, resolver)\n})\n\nit('supports returning path parameters from the custom predicate', () => {\n  // Implicit path parameters type.\n  http.get(\n    () => ({\n      matches: true,\n      params: { user: 'hello' },\n    }),\n    ({ params }) => {\n      expectTypeOf(params).toEqualTypeOf<{ user: string }>()\n    },\n  )\n\n  // Explicit path parameters type.\n  http.get<{ inferred: string }>(\n    () => ({\n      matches: true,\n      params: { inferred: '1' },\n    }),\n    ({ params }) => {\n      expectTypeOf(params).toEqualTypeOf<{ inferred: string }>()\n    },\n  )\n})\n\nit('supports returning extended match result from a custom predicate', () => {\n  http.get(() => ({ matches: true, params: {} }), resolver)\n  http.get(() => ({ matches: false, params: {} }), resolver)\n\n  // @ts-expect-error Invalid return type.\n  http.get(() => ({ matches: true }), resolver)\n  // @ts-expect-error Invalid return type.\n  http.get(() => ({ params: {} }), resolver)\n})\n"
  },
  {
    "path": "test/typings/http.test-d.ts",
    "content": "import { it, expectTypeOf } from 'vitest'\nimport { http, HttpResponse, passthrough } from 'msw'\n\nit('supports a single path parameter', () => {\n  http.get<{ id: string }>('/user/:id', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<{ id: string }>()\n  })\n})\n\nit('supports a repeating path parameter', () => {\n  http.get<{ id?: string }>('/user/id*', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<{ id?: string }>()\n  })\n})\n\nit('supports an optional path parameter', () => {\n  http.get<{ id?: string }>('/user/:id?', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<{ id?: string }>()\n  })\n})\n\nit('supports optional repeating path parameter', () => {\n  /**\n   * @note This is the newest \"path-to-regexp\" syntax.\n   * MSW doesn't support this quite yet.\n   */\n  http.get<{ path?: string[] }>('/user{/*path}', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<{ path?: string[] }>()\n  })\n})\n\nit('supports multiple path parameters', () => {\n  type Params = { a: string; b: string[] }\n  http.get<Params>('/user/:a/:b/:b', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<Params>()\n  })\n})\n\nit('supports path parameters declared via type', () => {\n  type Params = { id: string }\n  http.get<Params>('/user/:id', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<Params>()\n  })\n})\n\nit('supports path parameters declared via interface', () => {\n  interface PostPathParameters {\n    id: string\n  }\n  http.get<PostPathParameters>('/user/:id', ({ params }) => {\n    expectTypeOf(params).toEqualTypeOf<PostPathParameters>()\n  })\n})\n\nit('supports json as a request body type argument', () => {\n  http.post<never, { id: string }>('/user', async ({ request }) => {\n    const data = await request.json()\n\n    expectTypeOf(data).toEqualTypeOf<{ id: string }>()\n\n    const text = await request.text()\n    expectTypeOf(text).toEqualTypeOf<string>()\n    expectTypeOf(text).toEqualTypeOf<string>()\n  })\n})\n\nit('supports null as the request body type argument', () => {\n  http.get<never, null>('/user', async ({ request }) => {\n    const data = await request.json()\n    expectTypeOf(data).toEqualTypeOf<null>()\n  })\n})\n\nit('returns the same request type when cloning', () => {\n  http.post<never, { id: string }>('/user', async ({ request }) => {\n    const data = await request.clone().json()\n\n    expectTypeOf(data).toEqualTypeOf<{ id: string }>()\n  })\n\n  http.post<never, null>('/user', async ({ request }) => {\n    const data = await request.clone().json()\n\n    expectTypeOf(data).toEqualTypeOf<null>()\n  })\n})\n\nit('returns plain Response without explicit response body type argument', () => {\n  http.get('/user', () => {\n    return new Response('hello')\n  })\n})\n\nit('supports a text response without explicit response body type argument', () => {\n  http.get('/resource', () => {\n    return HttpResponse.text('hello world')\n  })\n})\n\nit('supports a json response without explicit response body type argument', () => {\n  http.get('/resource', () => {\n    return HttpResponse.json({ id: 1 })\n  })\n})\n\nit('supports an xml response without explicit response body type argument', () => {\n  http.get('/resource', () => {\n    return HttpResponse.xml('<hello>world</hello>')\n  })\n})\n\nit('supports a form data response without explicit response body type argument', () => {\n  http.get('/resource', () => {\n    return HttpResponse.formData(new FormData())\n  })\n})\n\nit('supports a stream response without explicit response body type argument', () => {\n  http.get('/resource', () => {\n    return new HttpResponse(new ReadableStream())\n  })\n})\n\nit('returns HttpResponse with URLSearchParams as response body', () => {\n  http.get('/', () => {\n    return new HttpResponse(new URLSearchParams())\n  })\n})\n\nit('returns HttpResponse with FormData as response body', () => {\n  http.get('/', () => {\n    return new HttpResponse(new FormData())\n  })\n})\n\nit('returns HttpResponse with ReadableStream as response body', () => {\n  http.get('/', () => {\n    return new HttpResponse(new ReadableStream())\n  })\n})\n\nit('returns HttpResponse with Blob as response body', () => {\n  http.get('/', () => {\n    return new HttpResponse(new Blob(['hello']))\n  })\n})\n\nit('returns HttpResponse with ArrayBuffer as response body', () => {\n  http.get('/', () => {\n    return new HttpResponse(new ArrayBuffer(5))\n  })\n})\n\nit('supports HttpResponse.arrayBuffer shorthand method', () => {\n  http.get('/', () => {\n    return HttpResponse.arrayBuffer(new ArrayBuffer(5))\n  })\n\n  http.get('/', async () => {\n    return HttpResponse.arrayBuffer(\n      await fetch('/image').then((response) => response.arrayBuffer()),\n    )\n  })\n\n  http.get<never, never, ArrayBuffer>('/', () => {\n    return HttpResponse.arrayBuffer(new ArrayBuffer(5))\n  })\n})\n\nit('supports null as a response body type argument', () => {\n  http.get<never, never, null>('/', () => {\n    return new HttpResponse()\n  })\n  http.get<never, never, null>('/', () => {\n    return new HttpResponse(\n      // @ts-expect-error Expected null, got a string.\n      'hello',\n    )\n  })\n  http.get<never, never, null>('/', () => {\n    return HttpResponse.json(\n      // @ts-expect-error Expected null, got an object.\n      { id: 1 },\n    )\n  })\n})\n\nit('supports string as a response body type argument', () => {\n  http.get<never, never, string>('/', ({ request }) => {\n    if (request.headers.has('x-foo')) {\n      return HttpResponse.text('conditional')\n    }\n\n    return HttpResponse.text('hello')\n  })\n})\n\nit('supports exact string as a response body type argument', () => {\n  http.get<never, never, 'hello'>('/', () => {\n    return HttpResponse.text('hello')\n  })\n\n  http.get<never, never, 'hello'>('/', () => {\n    // @ts-expect-error Non-matching response body type.\n    return HttpResponse.text('unexpected')\n  })\n})\n\nit('supports object as a response body type argument', () => {\n  http.get<never, never, { id: number }>('/user', () => {\n    return HttpResponse.json({ id: 1 })\n  })\n})\n\nit('supports narrow object as a response body type argument', () => {\n  http.get<never, never, { id: 123 }>('/user', () => {\n    return HttpResponse.json({ id: 123 })\n  })\n\n  http.get<never, never, { id: 123 }>('/user', () => {\n    return HttpResponse.json({\n      // @ts-expect-error Non-matching response body type.\n      id: 456,\n    })\n  })\n})\n\nit('supports object with extra keys as a response body type argument', () => {\n  type ResponseBody = {\n    [key: string]: number | string\n    id: 123\n  }\n\n  http.get<never, never, ResponseBody>('/user', () => {\n    return HttpResponse.json({\n      id: 123,\n      // Extra keys are allowed if they satisfy the index signature.\n      name: 'John',\n    })\n  })\n\n  http.get<never, never, ResponseBody>('/user', () => {\n    return HttpResponse.json({\n      // @ts-expect-error Must be 123.\n      id: 456,\n      name: 'John',\n    })\n  })\n\n  http.get<never, never, ResponseBody>('/user', () => {\n    return HttpResponse.json({\n      id: 123,\n      // @ts-expect-error Must satisfy the index signature.\n      name: { a: 1 },\n    })\n  })\n})\n\nit('supports response body type argument declared via type', () => {\n  type ResponseBodyType = { id: number }\n  http.get<never, never, ResponseBodyType>('/user', () => {\n    const data: ResponseBodyType = { id: 1 }\n    return HttpResponse.json(data)\n  })\n})\n\nit('supports response body type argument declared via interface', () => {\n  interface ResponseBodyInterface {\n    id: number\n  }\n  http.get<never, never, ResponseBodyInterface>('/user', () => {\n    const data: ResponseBodyInterface = { id: 1 }\n    return HttpResponse.json(data)\n  })\n})\n\nit('throws when returning a json response not matching the response body type argument', () => {\n  http.get<never, never, { id: number }>(\n    '/user',\n    // @ts-expect-error String not assignable to number\n    () => HttpResponse.json({ id: 'invalid' }),\n  )\n})\n\nit('throws when returning an empty json response not matching the response body type argument', () => {\n  http.get<never, never, { id: number }>(\n    '/user',\n    // @ts-expect-error Missing property \"id\"\n    () => HttpResponse.json({}),\n  )\n})\n\nit('accepts narrower type for response body', () => {\n  http.get<never, never, string | string[]>('/user', () =>\n    HttpResponse.json(['value']),\n  )\n})\n\nit('accepts more specific type for response body', () => {\n  http.get<never, never, { label: boolean }>('/user', () =>\n    HttpResponse.json({ label: true }),\n  )\n})\n\nit(\"accepts passthrough in HttpResponse's body\", () => {\n  // Passthrough responses.\n  http.all('/', () => passthrough())\n  http.get('/', () => passthrough())\n  http.get<never, never, { id: number }>('/', ({ request }) => {\n    if (request.headers.has('cookie')) {\n      return passthrough()\n    }\n\n    return HttpResponse.json({ id: 1 })\n  })\n})\n\nit('infers a narrower json response type', () => {\n  type ResponseBody = {\n    a: number\n  }\n\n  http.get<never, never, ResponseBody>('/', () => {\n    // @ts-expect-error Unknown property \"b\".\n    return HttpResponse.json({ a: 1, b: 2 })\n  })\n})\n\nit('errors when returning non-Response data from resolver', () => {\n  http.get(\n    '/resource',\n    // @ts-expect-error\n    () => 123,\n  )\n  http.get(\n    '/resource',\n    // @ts-expect-error\n    () => 'foo',\n  )\n  http.get(\n    '/resource',\n    // @ts-expect-error\n    () => ({}),\n  )\n})\n\nit('treats non-typed HttpResponse body type as matching', () => {\n  http.get<never, never, { id: string }>('/resource', () => {\n    /**\n     * @note When constructing a Response/HttpResponse instance,\n     * its body type must effectively be treated as `any`. You\n     * cannot provide or infer a narrower type because these classes\n     * operate on streams or strings, none of which are type-safe.\n     */\n    return new HttpResponse(null, { status: 500 })\n  })\n})\n\nit('supports returning Response.error()', () => {\n  http.get('/resource', () => Response.error())\n  http.get('/resource', async () => Response.error())\n  http.get('/resource', function* () {\n    return Response.error()\n  })\n\n  http.get<never, never, string>('/resource', () => HttpResponse.error())\n  http.get<never, never, string>('/resource', async () => HttpResponse.error())\n  http.get<never, never, string>('/resource', function* () {\n    return HttpResponse.error()\n  })\n})\n"
  },
  {
    "path": "test/typings/regressions/default-resolver-type.test-d.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/issues/2506\n */\nimport { http, HttpResponse, HttpResponseResolver } from 'msw'\n\nit('supports a union of the matching explicit and implicit response resolvers', () => {\n  function handle(resolver?: HttpResponseResolver<never, never, string>) {\n    const defaultResolver = () => HttpResponse.html('<div>test</div>')\n    http.get('/path', resolver || defaultResolver)\n  }\n})\n"
  },
  {
    "path": "test/typings/regressions/request-handler-type.test-d.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/discussions/498\n */\nimport { http, HttpResponse } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nit('does not conflict when passing request handlers to `setupWorker`', () => {\n  const resourceHandler = http.get('/resource', () => {\n    return HttpResponse.json({ data: 'abc-123' })\n  })\n\n  const handlers = [resourceHandler]\n  setupWorker(...handlers)\n})\n"
  },
  {
    "path": "test/typings/regressions/response-body-type.test-d.ts",
    "content": "/**\n * @see https://github.com/mswjs/msw/issues/1823\n */\nimport { http, Path, HttpResponse, DefaultBodyType } from 'msw'\n\nit('accepts custom response body generic argument', () => {\n  function myHandler<CustomResponseBodyType extends DefaultBodyType>(\n    path: Path,\n  ) {\n    return (response: CustomResponseBodyType) => {\n      http.get(path, () => HttpResponse.json(response))\n    }\n  }\n})\n"
  },
  {
    "path": "test/typings/resolver-generator.test-d.ts",
    "content": "import { it } from 'vitest'\nimport { http, HttpResponse } from 'msw'\n\nit('supports generator function as response resolver', () => {\n  http.get<never, never, { value: number }>('/', function* () {\n    yield HttpResponse.json({ value: 1 })\n    yield HttpResponse.json({ value: 2 })\n    return HttpResponse.json({ value: 3 })\n  })\n\n  http.get<never, never, { value: string }>('/', function* () {\n    yield HttpResponse.json({ value: 'one' })\n    yield HttpResponse.json({\n      // @ts-expect-error Expected string, got number.\n      value: 2,\n    })\n    return HttpResponse.json({ value: 'three' })\n  })\n})\n\nit('supports async generator function as response resolver', () => {\n  http.get<never, never, { value: number }>('/', async function* () {\n    yield HttpResponse.json({ value: 1 })\n    yield HttpResponse.json({ value: 2 })\n    return HttpResponse.json({ value: 3 })\n  })\n\n  http.get<never, never, { value: string }>('/', async function* () {\n    yield HttpResponse.json({ value: 'one' })\n    yield HttpResponse.json({\n      // @ts-expect-error Expected string, got number.\n      value: 2,\n    })\n    return HttpResponse.json({ value: 'three' })\n  })\n})\n\nit('supports returning nothing from generator resolvers', () => {\n  http.get<never, never, { value: string }>('/', function* () {})\n  http.get<never, never, { value: string }>('/', async function* () {})\n})\n\nit('supports returning undefined from generator resolvers', () => {\n  http.get<never, never, { value: string }>('/', function* () {\n    return undefined\n  })\n  http.get<never, never, { value: string }>('/', async function* () {\n    return undefined\n  })\n})\n"
  },
  {
    "path": "test/typings/server.boundary.test-d.ts",
    "content": "import { it, expectTypeOf } from 'vitest'\nimport { setupServer } from 'msw/node'\n\nconst fn = (args: { a: number }): string => 'hello'\n\nconst server = setupServer()\nconst bound = server.boundary(fn)\n\nit('infers the argument type of the callback', () => {\n  expectTypeOf(bound).toEqualTypeOf<(args: { a: number }) => string>()\n})\n\nit('infers the return type of the callback', () => {\n  expectTypeOf(bound({ a: 1 })).toEqualTypeOf<string>()\n})\n"
  },
  {
    "path": "test/typings/setup-server.test-d.ts",
    "content": "import { http, HttpResponse, graphql } from 'msw'\nimport { setupServer } from 'msw/node'\n\nit('does not produce a type error when called without arguments', () => {\n  setupServer()\n})\n\nit('accepts a single HTTP request handler', () => {\n  setupServer(\n    http.get('/user', () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  )\n  setupServer(\n    http.get('/user', async () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  )\n})\n\nit('accepts a single GraphQL request handler', () => {\n  setupServer(\n    graphql.query('GetUser', () => {\n      return HttpResponse.json({ data: { name: 'John Doe' } })\n    }),\n  )\n  setupServer(\n    graphql.query('GetUser', async () => {\n      return HttpResponse.json({ data: { name: 'John Doe' } })\n    }),\n  )\n})\n\nit('supports a list of request handlers defined elsewhere', () => {\n  const handlers = [\n    http.get('/user', () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  ]\n\n  setupServer(...handlers)\n})\n"
  },
  {
    "path": "test/typings/setup-worker.test-d.ts",
    "content": "import { http, HttpResponse, graphql } from 'msw'\nimport { setupWorker } from 'msw/browser'\n\nit('does not produce a type error when called without arguments', () => {\n  setupWorker()\n})\n\nit('accepts a single HTTP request handler', () => {\n  setupWorker(\n    http.get('/user', () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  )\n  setupWorker(\n    http.get('/user', async () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  )\n})\n\nit('accepts a single GraphQL request handler', () => {\n  setupWorker(\n    graphql.query('GetUser', () => {\n      return HttpResponse.json({ data: { name: 'John Doe' } })\n    }),\n  )\n  setupWorker(\n    graphql.query('GetUser', async () => {\n      return HttpResponse.json({ data: { name: 'John Doe' } })\n    }),\n  )\n})\n\nit('supports a list of request handlers defined elsewhere', () => {\n  const handlers = [\n    http.get('/user', () => {\n      return HttpResponse.json({ name: 'John Doe' })\n    }),\n  ]\n\n  setupWorker(...handlers)\n})\n"
  },
  {
    "path": "test/typings/sse.test-d.ts",
    "content": "import { it } from 'vitest'\nimport { sse } from 'msw'\n\n/**\n * @note Define the global property to simulate an EventSource-compatible environment.\n * MSW checks for that and throws to prevent incorrect usage.\n */\nObject.defineProperty(global, 'EventSource', { value: () => {} })\n\nit('supports sending anything without an explicit event map type', () => {\n  sse('/stream', ({ client }) => {\n    client.send({ data: 123 })\n    client.send({ data: 'hello' })\n  })\n})\n\nit('supports an optional \"id\" property', () => {\n  sse('/stream', ({ client }) => {\n    client.send({ id: '1', data: 'hello' })\n  })\n  sse<{ message: 'greeting' }>('/stream', ({ client }) => {\n    client.send({ id: '2', data: 'greeting' })\n  })\n  sse<{ custom: 'goodbye' }>('/stream', ({ client }) => {\n    client.send({\n      id: '2',\n      event: 'custom',\n      data: 'goodbye',\n    })\n  })\n})\n\nit('supports custom event map type', () => {\n  sse<{ myevent: string }>('/stream', ({ client }) => {\n    client.send({\n      event: 'myevent',\n      data: 'hello',\n    })\n\n    client.send({\n      // @ts-expect-error Unknown event type \"unknown\".\n      event: 'unknown',\n      data: 'hello',\n    })\n\n    client.send({\n      /**\n       * @note Sending anonymous events (\"message\" events)\n       * must still accept any data type unless narrowed down\n       * in the event map by the \"message\" key.\n       */\n      data: 'anything',\n    })\n  })\n})\n\nit('supports event map type argument for unnamed events', () => {\n  sse<{ message: number; custom: string; other: boolean }>(\n    '/stream',\n    ({ client }) => {\n      /**\n       * @note TS 5.0 reports errors at different locations\n       * to satisfy a wide range of TS versions in type tests formatting gets disabled here\n       * so that @ts-expect-error can assert the reported errors regardless of the location\n       * see: https://github.com/mswjs/msw/pull/2521#issuecomment-2931733565\n       */\n      // prettier-ignore-start\n      client.send({\n        data: 123,\n      })\n      // When no explicit \"event\" key is provided,\n      // threat it as if event was set to \"message\".\n      // @ts-expect-error Unexpected data type for \"message\" event.\n      client.send({ data: 'goodbye' })\n\n      client.send({\n        event: 'message',\n        data: 123,\n      })\n      // @ts-expect-error Unexpected data type for \"message\" event.\n      client.send({ event: 'message', data: 'invalid' })\n      // @ts-expect-error Unexpected data type for \"message\" event.\n      client.send({ event: 'message', data: 'goodbye' })\n\n      client.send({\n        event: 'custom',\n        data: 'goodbye',\n      })\n      // @ts-expect-error Unexpected data type for \"custom\" event\n      client.send({ event: 'custom', data: 123 })\n\n      // Sending unknown events must be forbidden\n      // if the EventMap type argument was provided.\n      // @ts-expect-error Unknown event type \"unknown\".\n      client.send({ event: 'invalid', data: 123 })\n\n      // boolean is only allowed for \"other\" event\n      // @ts-expect-error\n      client.send({ event: 'custom', data: true })\n\n      // boolean is only allowed for \"other\" event\n      // @ts-expect-error\n      client.send({ event: 'custom' as 'custom' | 'other', data: true })\n\n      // should error when required data is missing\n      // @ts-expect-error\n      client.send({ event: 'other' })\n\n      // prettier-ignore-end\n    },\n  )\n})\n\nit('supports optional mnessage data', () => {\n  sse<{ message?: string }>('/stream', ({ client }) => {\n    // No data is fine because data is optional.\n    client.send({})\n\n    // Allows explicit undefined as optional data.\n    client.send({ data: undefined })\n\n    // Data is still validated even if optional.\n    client.send({ data: 'hello' })\n    client.send({\n      // @ts-expect-error Invalid data type.\n      data: 123,\n    })\n\n    // No data is fine because data is optional.\n    client.send({ event: 'message' })\n\n    // Allows explicit undefined as optional data.\n    client.send({ event: 'message', data: undefined })\n\n    // Data is still validated even if optional.\n    client.send({ event: 'message', data: 'hello' })\n    client.send({\n      event: 'message',\n      // @ts-expect-error Invalid data type.\n      data: 123,\n    })\n  })\n})\n\nit('supports optional event data', () => {\n  sse<{ maybe?: string }>('/stream', ({ client }) => {\n    // No data is fine because data is optional.\n    client.send({ event: 'maybe' })\n\n    // Allows explicit undefined as optional data.\n    client.send({ event: 'maybe', data: undefined })\n\n    // Data is still validated even if optional.\n    client.send({ event: 'maybe', data: 'hello' })\n    client.send({\n      event: 'maybe',\n      // @ts-expect-error Invalid data type.\n      data: 123,\n    })\n  })\n})\n\nit('supports sending custom retry duration', () => {\n  sse<{ custom: 'goodbye' }>('/stream', ({ client }) => {\n    /**\n     * @note TS 5.0 reports errors at different locations\n     * to satisfy a wide range of TS versions in type tests formatting gets disabled here\n     * so that @ts-expect-error can assert the reported errors regardless of the location\n     * see: https://github.com/mswjs/msw/pull/2521#issuecomment-2931733565\n     */\n    // prettier-ignore-start\n    client.send({ retry: 1000 })\n\n    // @ts-expect-error Cannot use message properties with \"retry\".\n    client.send({ retry: 1000, id: '1' })\n    // @ts-expect-error Cannot use message properties with \"retry\".\n    client.send({ retry: 1000, data: 'hello' })\n    // @ts-expect-error Cannot use message properties with \"retry\".\n    client.send({ retry: 1000, event: 'custom', data: 'goodbye' })\n    // prettier-ignore-end\n  })\n})\n"
  },
  {
    "path": "test/typings/tsconfig.5.0.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"Node16\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.5.1.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"Node16\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.5.2.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.5.3.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.5.4.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.5.5.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"NodeNext\",\n    \"moduleResolution\": \"NodeNext\"\n  }\n}\n"
  },
  {
    "path": "test/typings/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    // Use non-strict TypeScript configuration because Vitest only ever\n    // generates a single \"tsconfig.json\" during the typecheck run\n    // but we are running against different versions of TypeScript.\n    // Keeping strict mode will error with \"Unknown compiler option\" errors.\n    \"strict\": false,\n    \"strictNullChecks\": true,\n    \"strictBindCallApply\": true,\n    \"strictFunctionTypes\": true,\n    \"rootDir\": \"../..\",\n    \"lib\": [\"dom\"]\n  },\n  \"include\": [\"../../global.d.ts\", \"**/*.test-d.ts\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "test/typings/vitest.config.ts",
    "content": "import fs from 'node:fs'\nimport url from 'node:url'\nimport path from 'node:path'\nimport { defineConfig } from 'vitest/config'\nimport { invariant } from 'outvariant'\nimport tsPackageJson from 'typescript/package.json' assert { type: 'json' }\nimport { mswExports } from '../support/alias'\n\nconst TEST_ROOT = url.fileURLToPath(new URL('./', import.meta.url))\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      ...mswExports,\n    },\n  },\n  test: {\n    root: TEST_ROOT,\n    globals: true,\n    typecheck: {\n      enabled: true,\n      checker: 'tsc',\n      include: ['**/*.test-d.ts'],\n      tsconfig: (() => {\n        const tsInstalledVersion = tsPackageJson.version\n        invariant(\n          tsInstalledVersion,\n          'Failed to run typings tests: unable to determine TypeScript version',\n        )\n\n        const tsVersionMajorMinor = tsInstalledVersion.substring(\n          0,\n          tsInstalledVersion.lastIndexOf('.'),\n        )\n\n        const tsConfigPaths = [\n          url.fileURLToPath(\n            new URL(`./tsconfig.${tsVersionMajorMinor}.json`, import.meta.url),\n          ),\n          url.fileURLToPath(new URL('./tsconfig.json', import.meta.url)),\n        ]\n        const tsConfigPath = tsConfigPaths.find((path) =>\n          fs.existsSync(path),\n        ) as string\n        const relativeTsConfigPath = path.relative(TEST_ROOT, tsConfigPath)\n\n        console.log('Using tsconfig at: %s', relativeTsConfigPath)\n\n        return relativeTsConfigPath\n      })(),\n    },\n  },\n})\n"
  },
  {
    "path": "test/typings/ws.test-d.ts",
    "content": "import { it, expectTypeOf } from 'vitest'\nimport {\n  WebSocketData,\n  WebSocketLink,\n  WebSocketHandlerConnection,\n  ws,\n} from 'msw'\nimport { WebSocketClientConnectionProtocol } from '@mswjs/interceptors/WebSocket'\n\nit('supports URL as the link argument', () => {\n  expectTypeOf(ws.link('ws://localhost')).toEqualTypeOf<WebSocketLink>()\n})\n\nit('supports RegExp as the link argument', () => {\n  expectTypeOf(ws.link(/\\/ws$/)).toEqualTypeOf<WebSocketLink>()\n})\n\nit('exposes root-level link APIs', () => {\n  const link = ws.link('ws://localhost')\n\n  expectTypeOf(link.addEventListener).toBeFunction()\n  expectTypeOf(link.broadcast).toBeFunction()\n  expectTypeOf(link.broadcastExcept).toBeFunction()\n  expectTypeOf(link.clients).toEqualTypeOf<\n    Set<WebSocketClientConnectionProtocol>\n  >()\n})\n\nit('supports \"connection\" event listener', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', (connection) => {\n    expectTypeOf(connection).toEqualTypeOf<WebSocketHandlerConnection>()\n  })\n})\n\nit('errors on arbitrary event names passed to the link', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener(\n    // @ts-expect-error Unknown event name \"abc\".\n    'abc',\n    () => {},\n  )\n})\n\n/**\n * Client API.\n */\n\nit('exposes root-level \"client\" APIs', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ client }) => {\n    expectTypeOf(client.id).toBeString()\n    expectTypeOf(client.url).toEqualTypeOf<URL>()\n\n    expectTypeOf(client.addEventListener).toBeFunction()\n    expectTypeOf(client.send).toBeFunction()\n    expectTypeOf(client.removeEventListener).toBeFunction()\n    expectTypeOf(client.close).toBeFunction()\n  })\n})\n\nit('supports \"message\" event listener on the client', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ client }) => {\n    client.addEventListener('message', (event) => {\n      expectTypeOf(event).toEqualTypeOf<MessageEvent<WebSocketData>>()\n    })\n  })\n})\n\nit('supports \"close\" event listener on the client', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ client }) => {\n    client.addEventListener('close', (event) => {\n      expectTypeOf(event).toMatchTypeOf<CloseEvent>()\n    })\n  })\n})\n\nit('errors on arbitrary event names passed to the client', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ client }) => {\n    client.addEventListener(\n      // @ts-expect-error Unknown event name \"abc\".\n      'abc',\n      () => {},\n    )\n  })\n})\n\n/**\n * Server API.\n */\n\nit('exposes root-level \"server\" APIs', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ server }) => {\n    expectTypeOf(server.connect).toEqualTypeOf<() => void>()\n    expectTypeOf(server.addEventListener).toBeFunction()\n    expectTypeOf(server.send).toBeFunction()\n    expectTypeOf(server.removeEventListener).toBeFunction()\n    expectTypeOf(server.close).toBeFunction()\n  })\n})\n\nit('supports \"message\" event listener on the server', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ server }) => {\n    server.addEventListener('message', (event) => {\n      expectTypeOf(event).toEqualTypeOf<MessageEvent<WebSocketData>>()\n    })\n  })\n})\n\nit('supports \"open\" event listener on the server', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ server }) => {\n    server.addEventListener('open', (event) => {\n      expectTypeOf(event).toMatchTypeOf<Event>()\n    })\n  })\n})\n\nit('supports \"close\" event listener on the server', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ server }) => {\n    server.addEventListener('close', (event) => {\n      expectTypeOf(event).toMatchTypeOf<CloseEvent>()\n    })\n  })\n})\n\nit('errors on arbitrary event names passed to the server', () => {\n  const link = ws.link('ws://localhost')\n\n  link.addEventListener('connection', ({ server }) => {\n    server.addEventListener(\n      // @ts-expect-error Unknown event name \"abc\".\n      'abc',\n      () => {},\n    )\n  })\n})\n"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"strictNullChecks\": true,\n    \"skipLibCheck\": true,\n    \"allowSyntheticDefaultImports\": false,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"~/core\": [\"src/core\"],\n      \"~/core/*\": [\"src/core/*\"]\n    }\n  },\n  \"include\": [\"./global.d.ts\"],\n  \"exclude\": [\"node_modules\", \"lib\"]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"references\": [\n    // Source.\n    {\n      \"path\": \"./src/browser/tsconfig.browser.json\"\n    },\n    {\n      \"path\": \"./src/tsconfig.node.json\"\n    },\n    {\n      \"path\": \"./src/tsconfig.worker.json\"\n    },\n\n    // Tests.\n    {\n      \"path\": \"./tsconfig.test.unit.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "tsconfig.test.unit.json",
    "content": "{\n  // Configuration for the unit tests living\n  // next to the source code.\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"types\": [\"vitest/globals\"]\n  },\n  \"include\": [\"./src/**/*.test.ts\", \"./test/support\"],\n  \"references\": [\n    {\n      \"path\": \"./src/tsconfig.src.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "tsup.config.ts",
    "content": "import * as path from 'node:path'\nimport { defineConfig, Options } from 'tsup'\nimport * as glob from 'glob'\nimport {\n  getWorkerChecksum,\n  copyWorkerPlugin,\n} from './config/plugins/esbuild/copyWorkerPlugin'\nimport { resolveCoreImportsPlugin } from './config/plugins/esbuild/resolveCoreImportsPlugin'\nimport { forceEsmExtensionsPlugin } from './config/plugins/esbuild/forceEsmExtensionsPlugin'\nimport { graphqlImportPlugin } from './config/plugins/esbuild/graphQLImportPlugin'\nimport packageJson from './package.json'\n\n// Externalize the in-house dependencies so that the user\n// would get the latest published version automatically.\nconst ecosystemDependencies = /^@mswjs\\/(.+)$/\n\n// Externalize the core functionality (reused across environments)\n// so that it can be shared between the environments.\nconst mswCore = /\\/core(\\/.+)?$/\n\nconst SERVICE_WORKER_CHECKSUM = getWorkerChecksum()\n\n/**\n * A designated configuration for CJS shims.\n * This bundles the shims so CJS modules could be used\n * in the browser.\n */\nconst shimConfig: Options = {\n  name: 'shims',\n  platform: 'neutral',\n  entry: glob.sync('./src/shims/**/*.ts'),\n  format: ['esm', 'cjs'],\n  noExternal: Object.keys(packageJson.dependencies),\n  outDir: './lib/shims',\n  bundle: true,\n  splitting: false,\n  sourcemap: false,\n  dts: true,\n}\n\nconst coreConfig: Options = {\n  name: 'core',\n  platform: 'neutral',\n  entry: glob.sync('./src/core/**/*.ts', {\n    ignore: '**/*.test.ts',\n  }),\n  external: [ecosystemDependencies],\n  noExternal: ['cookie'],\n  format: ['esm', 'cjs'],\n  outDir: './lib/core',\n  bundle: false,\n  splitting: false,\n  sourcemap: true,\n  dts: true,\n  tsconfig: path.resolve(__dirname, 'src/tsconfig.core.build.json'),\n  esbuildPlugins: [graphqlImportPlugin(), forceEsmExtensionsPlugin()],\n}\n\nconst nodeConfig: Options = {\n  name: 'node',\n  platform: 'node',\n  entry: ['./src/node/index.ts'],\n  inject: ['./config/polyfills-node.ts'],\n  external: [mswCore, ecosystemDependencies],\n  format: ['esm', 'cjs'],\n  outDir: './lib/node',\n  bundle: true,\n  splitting: false,\n  sourcemap: true,\n  dts: true,\n  tsconfig: path.resolve(__dirname, 'src/tsconfig.node.build.json'),\n  esbuildPlugins: [resolveCoreImportsPlugin(), forceEsmExtensionsPlugin()],\n}\n\nconst browserConfig: Options = {\n  name: 'browser',\n  platform: 'browser',\n  entry: ['./src/browser/index.ts'],\n  external: [mswCore, ecosystemDependencies],\n  format: ['esm', 'cjs'],\n  outDir: './lib/browser',\n  bundle: true,\n  splitting: false,\n  sourcemap: true,\n  dts: true,\n  noExternal: Object.keys(packageJson.dependencies).filter((packageName) => {\n    /**\n     * @note Never bundle MSW core so all builds reference the *same*\n     * JavaScript and TypeScript core files. This way types across\n     * export paths remain compatible:\n     * import { http } from 'msw' // <- core\n     * import { setupWorker } from 'msw/browser' // <- /browser\n     * setupWorker(http.get(path, resolver)) // OK\n     */\n    return !mswCore.test(packageName)\n  }),\n  /**\n   * @note Use a proxy TypeScript configuration where the \"compilerOptions.composite\"\n   * option is set to false.\n   * @see https://github.com/egoist/tsup/issues/571\n   */\n  tsconfig: path.resolve(__dirname, 'src/browser/tsconfig.browser.build.json'),\n  define: {\n    SERVICE_WORKER_CHECKSUM: JSON.stringify(SERVICE_WORKER_CHECKSUM),\n  },\n  esbuildPlugins: [\n    resolveCoreImportsPlugin(),\n    forceEsmExtensionsPlugin(),\n    copyWorkerPlugin(SERVICE_WORKER_CHECKSUM),\n  ],\n}\n\nconst reactNativeConfig: Options = {\n  name: 'react-native',\n  platform: 'node',\n  entry: ['./src/native/index.ts'],\n  external: ['picocolors', 'util', 'events', mswCore, ecosystemDependencies],\n  format: ['esm', 'cjs'],\n  outDir: './lib/native',\n  bundle: true,\n  splitting: false,\n  sourcemap: true,\n  dts: true,\n  tsconfig: path.resolve(__dirname, 'src/tsconfig.node.build.json'),\n  esbuildPlugins: [resolveCoreImportsPlugin(), forceEsmExtensionsPlugin()],\n}\n\nconst iifeConfig: Options = {\n  name: 'iife',\n  platform: 'browser',\n  globalName: 'MockServiceWorker',\n  entry: ['./src/iife/index.ts'],\n  /**\n   * @note Legacy output format will automatically create\n   * a \"iife\" directory under the \"outDir\".\n   */\n  outDir: './lib',\n  format: ['iife'],\n  legacyOutput: true,\n  bundle: true,\n  splitting: false,\n  sourcemap: true,\n  dts: false,\n  tsconfig: path.resolve(__dirname, 'src/browser/tsconfig.browser.build.json'),\n  define: {\n    // Sign the IIFE build as well because any bundle containing\n    // the worker API must have the the integrity checksum defined.\n    SERVICE_WORKER_CHECKSUM: JSON.stringify(SERVICE_WORKER_CHECKSUM),\n  },\n}\n\nexport default defineConfig([\n  shimConfig,\n  coreConfig,\n  nodeConfig,\n  reactNativeConfig,\n  browserConfig,\n  iifeConfig,\n])\n"
  },
  {
    "path": "vitest.config.mts",
    "content": "import { defineConfig } from 'vitest/config'\nimport {\n  mswExports,\n  customViteEnvironments,\n  fromRoot,\n} from './test/support/alias'\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    // Lookup the unit tests in the \"src\" directory because\n    // they are located next to the source code they are testing.\n    dir: './src',\n    alias: {\n      ...mswExports,\n      ...customViteEnvironments,\n      '~/core': fromRoot('src/core'),\n    },\n    typecheck: {\n      // Load the TypeScript configuration to the unit tests.\n      // Otherwise, Vitest will use the root-level \"tsconfig.json\",\n      // which includes way too more than the tests need.\n      tsconfig: './tsconfig.test.unit.json',\n    },\n    environmentOptions: {\n      jsdom: {\n        // Drop the 3000 port from the default \"location.href\"\n        // for backward-compatibility with the existing tests.\n        url: 'http://localhost/',\n      },\n    },\n  },\n})\n"
  }
]