From 4caff30569ddd091944652f3ae91407ecdfcf797 Mon Sep 17 00:00:00 2001 From: Jozef Harag Date: Thu, 7 Nov 2024 13:47:32 +0100 Subject: [PATCH] chore: replace karma with playwright --- .github/actions/install-playwright/action.yml | 37 + .github/workflows/ci-main.yml | 4 + .github/workflows/ci.yml | 4 + .github/workflows/tests.yml | 118 ++ package-lock.json | 813 +++++++- package.json | 3 +- packages/integration-tests/.gitignore | 5 + packages/integration-tests/package-lock.json | 1697 +++++++++++++++++ packages/integration-tests/package.json | 28 + .../integration-tests/playwright.config.ts | 101 + .../src/pages/record-page.ts | 108 ++ .../src/server/render-agent.ts | 73 + .../src/server/server-timing.ts} | 26 +- .../integration-tests/src/server/server.ts | 108 ++ .../src}/tests/cdn/index.ejs | 4 +- .../src/tests/cdn/index.spec.ts | 61 + .../src}/tests/connectivity/connectivity.ejs | 0 .../tests/connectivity/connectivity.spec.ts | 66 + .../src}/tests/cookies/cookies-domain.ejs | 0 .../src}/tests/cookies/cookies.ejs | 0 .../src}/tests/cookies/cookies.iframe.ejs | 0 .../src/tests/cookies/cookies.spec.ts | 88 + .../src}/tests/cookies/iframe.ejs | 0 .../src}/tests/fetch/fetch-ignored.ejs | 0 .../src}/tests/fetch/fetch-post.ejs | 9 +- .../src}/tests/fetch/fetch.ejs | 0 .../src/tests/fetch/fetch.spec.ts | 146 ++ .../src}/tests/native/native.ejs | 0 .../src/tests/native/native.spec.ts | 33 + .../src}/tests/redacting-attributes/index.ejs | 0 .../tests/redacting-attributes/index.spec.ts | 33 + .../src}/tests/visibility/visibility.ejs | 0 .../src/tests/visibility/visibility.spec.ts | 38 + .../src/tests/xhr}/xhr-basic.ejs | 6 +- .../src/tests/xhr}/xhr-ignored.ejs | 6 +- .../src/tests/xhr/xhr.spec.ts | 68 + .../src/utils/test.ts} | 24 +- .../src/version.ts} | 14 +- packages/integration-tests/tsconfig.json | 8 + .../integration-tests/tests/cdn/index.spec.js | 60 - .../tests/connectivity/connectivity.spec.js | 60 - .../tests/cookies/cookies.spec.js | 102 - .../tests/fetch/fetch.spec.js | 121 -- .../tests/visibility/visibility.spec.js | 43 - .../tests/xhr/xhr-basic.spec.js | 84 - 45 files changed, 3631 insertions(+), 568 deletions(-) create mode 100644 .github/actions/install-playwright/action.yml create mode 100644 .github/workflows/tests.yml create mode 100644 packages/integration-tests/.gitignore create mode 100644 packages/integration-tests/package-lock.json create mode 100644 packages/integration-tests/package.json create mode 100644 packages/integration-tests/playwright.config.ts create mode 100644 packages/integration-tests/src/pages/record-page.ts create mode 100644 packages/integration-tests/src/server/render-agent.ts rename packages/{web/integration-tests/tests/xhr/xhr-ignored.spec.js => integration-tests/src/server/server-timing.ts} (51%) create mode 100644 packages/integration-tests/src/server/server.ts rename packages/{web/integration-tests => integration-tests/src}/tests/cdn/index.ejs (87%) create mode 100644 packages/integration-tests/src/tests/cdn/index.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/connectivity/connectivity.ejs (100%) create mode 100644 packages/integration-tests/src/tests/connectivity/connectivity.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/cookies/cookies-domain.ejs (100%) rename packages/{web/integration-tests => integration-tests/src}/tests/cookies/cookies.ejs (100%) rename packages/{web/integration-tests => integration-tests/src}/tests/cookies/cookies.iframe.ejs (100%) create mode 100644 packages/integration-tests/src/tests/cookies/cookies.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/cookies/iframe.ejs (100%) rename packages/{web/integration-tests => integration-tests/src}/tests/fetch/fetch-ignored.ejs (100%) rename packages/{web/integration-tests => integration-tests/src}/tests/fetch/fetch-post.ejs (77%) rename packages/{web/integration-tests => integration-tests/src}/tests/fetch/fetch.ejs (100%) create mode 100644 packages/integration-tests/src/tests/fetch/fetch.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/native/native.ejs (100%) create mode 100644 packages/integration-tests/src/tests/native/native.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/redacting-attributes/index.ejs (100%) create mode 100644 packages/integration-tests/src/tests/redacting-attributes/index.spec.ts rename packages/{web/integration-tests => integration-tests/src}/tests/visibility/visibility.ejs (100%) create mode 100644 packages/integration-tests/src/tests/visibility/visibility.spec.ts rename packages/{web/integration-tests/tests/xhr/views => integration-tests/src/tests/xhr}/xhr-basic.ejs (84%) rename packages/{web/integration-tests/tests/xhr/views => integration-tests/src/tests/xhr}/xhr-ignored.ejs (85%) create mode 100644 packages/integration-tests/src/tests/xhr/xhr.spec.ts rename packages/{web/integration-tests/tests/native/native.spec.js => integration-tests/src/utils/test.ts} (54%) rename packages/{web/integration-tests/tests/redacting-attributes/index.spec.js => integration-tests/src/version.ts} (58%) create mode 100644 packages/integration-tests/tsconfig.json delete mode 100644 packages/web/integration-tests/tests/cdn/index.spec.js delete mode 100644 packages/web/integration-tests/tests/connectivity/connectivity.spec.js delete mode 100644 packages/web/integration-tests/tests/cookies/cookies.spec.js delete mode 100644 packages/web/integration-tests/tests/fetch/fetch.spec.js delete mode 100644 packages/web/integration-tests/tests/visibility/visibility.spec.js delete mode 100644 packages/web/integration-tests/tests/xhr/xhr-basic.spec.js diff --git a/.github/actions/install-playwright/action.yml b/.github/actions/install-playwright/action.yml new file mode 100644 index 00000000..30b33b91 --- /dev/null +++ b/.github/actions/install-playwright/action.yml @@ -0,0 +1,37 @@ +name: 'Install playwright' +description: 'Install Playwright browser binaries and OS dependencies' +runs: + using: 'composite' + steps: + - name: Get installed Playwright version + id: playwright-version + shell: bash + working-directory: ./packages/integration-tests + run: | + PLAYWRIGHT_VERSION=$(npm ls --json "@playwright/test" | jq --raw-output '.dependencies["@playwright/test"].version') + echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV + + - name: Set up path for Playwright cache + shell: bash + run: echo "PLAYWRIGHT_CACHE_PATH=$(if [[ $RUNNER_OS == 'macOS' ]]; then echo '~/Library/Caches/ms-playwright'; else echo '~/.cache/ms-playwright'; fi)" >> $GITHUB_ENV + + - name: Cache Playwright binaries + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 + id: playwright-cache + with: + path: ${{ env.PLAYWRIGHT_CACHE_PATH }} + key: '${{ runner.os }}-playwright-cache-${{ env.PLAYWRIGHT_VERSION }}-splunk-otel-js-web-artifacts' + + - name: Install Playwright browser binaries + if: steps.playwright-cache.outputs.cache-hit != 'true' + shell: bash + run: | + npx playwright install --with-deps + npx playwright install chrome + npx playwright install msedge + npx playwright install webkit + + - name: Install Playwright OS dependencies + if: steps.playwright-cache.outputs.cache-hit != 'true' + shell: bash + run: npx playwright install-deps diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index a7fa6831..48baca63 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -38,3 +38,7 @@ jobs: uses: ./.github/actions/setup - name: Local integration tests using ${{ matrix.browser }} run: npm run test:integration:local:${{ matrix.browser }}:_execute + + playwright: + uses: ./.github/workflows/tests.yml + secrets: inherit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index beaa0aed..59528e15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,3 +82,7 @@ jobs: path: | packages/web/tests_output/ packages/web/logs/ + + playwright: + uses: ./.github/workflows/tests.yml + secrets: inherit diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..a3bc3909 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,118 @@ +name: Playwright tests +on: + workflow_call: + +jobs: + playwright: + timeout-minutes: 60 + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + browser: [chromium, firefox, chrome, edge] + name: Playwright Tests - ${{ matrix.browser }} + steps: + - name: Checkout + uses: actions/checkout@v4.2.1 + - uses: actions/setup-node@v4.0.3 + with: + node-version: '18' + cache: 'npm' + - run: npm ci + - run: npm run compile + + - name: Install playwright + uses: ./.github/actions/install-playwright + + - name: Run Playwright tests + run: | + npx playwright test --project=${{ matrix.browser }} + working-directory: ./packages/integration-tests + + - name: Upload blob report to GitHub Actions Artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a + with: + name: blob-report-${{ matrix.browser }}-attempt-${{ github.run_attempt }} + path: packages/integration-tests/blob-report + retention-days: 1 + + playwright-macos: + timeout-minutes: 60 + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + browser: [webkit] + steps: + - name: Checkout + uses: actions/checkout@v4.2.1 + - uses: actions/setup-node@v4.0.3 + with: + node-version: '18' + cache: 'npm' + - run: npm ci + - run: npm run compile + + - name: Install playwright + uses: ./.github/actions/install-playwright + + - name: Run Playwright tests + run: | + npx playwright test --project=${{ matrix.browser }} + working-directory: ./packages/integration-tests + + - name: Upload blob report to GitHub Actions Artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a + with: + name: blob-report-${{ matrix.browser }}-attempt-${{ github.run_attempt }} + path: packages/integration-tests/blob-report + retention-days: 1 + + merge-reports: + if: ${{ !cancelled() }} + needs: [playwright, playwright-macos] + + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.2.1 + - uses: actions/setup-node@v4.0.3 + with: + node-version: '18' + cache: 'npm' + - run: npm ci + - run: npm run compile + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 + with: + path: packages/integration-tests/all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: npx playwright merge-reports --reporter html ./all-blob-reports -c playwright.config.ts + working-directory: ./packages/integration-tests + + - name: Upload HTML report + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a + with: + name: playwright-report--attempt-${{ github.run_attempt }} + path: packages/integration-tests/playwright-report + retention-days: 14 + + check-failure: + needs: [playwright, playwright-macos, merge-reports] + runs-on: ubuntu-latest + if: ${{ always() }} + steps: + - name: Check if any playwright tests failed + run: | + if [ "${{ needs.playwright.result }}" != "success" ] || [ "${{ needs['playwright-macos'].result }}" != "success" ]; then + echo "One or more tests failed." + exit 1 + else + echo "All tests passed." + fi diff --git a/package-lock.json b/package-lock.json index 7b7698d3..399ac00a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.19.3", "workspaces": [ "packages/web", - "packages/session-recorder" + "packages/session-recorder", + "packages/integration-tests" ], "devDependencies": { "@aws-sdk/client-cloudfront": "^3.171.0", @@ -2919,6 +2920,390 @@ "fd-slicer2": "^1.2.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3960,6 +4345,22 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -5418,6 +5819,10 @@ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "dev": true }, + "node_modules/@splunk/otel-js-web-integration-tests": { + "resolved": "packages/integration-tests", + "link": true + }, "node_modules/@splunk/otel-web": { "resolved": "packages/web", "link": true @@ -5580,6 +5985,17 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -5598,6 +6014,16 @@ "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", "dev": true }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", @@ -5618,18 +6044,58 @@ "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==" }, + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -5668,6 +6134,13 @@ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -5687,13 +6160,28 @@ } }, "node_modules/@types/node": { - "version": "20.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.6.tgz", - "integrity": "sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.8" } }, + "node_modules/@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -5719,6 +6207,29 @@ "@types/ws": "*" } }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, "node_modules/@types/shimmer": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", @@ -6876,10 +7387,11 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -6889,7 +7401,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -7988,10 +8500,11 @@ "dev": true }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -9009,6 +9522,45 @@ "node": ">=0.12" } }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -9438,6 +9990,7 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -9459,37 +10012,38 @@ "dev": true }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -9509,6 +10063,16 @@ "ms": "2.0.0" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -9762,13 +10326,14 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -9784,15 +10349,27 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-cache-dir": { "version": "3.3.2", @@ -9968,6 +10545,7 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10022,7 +10600,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -10254,6 +10831,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-uri": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", @@ -12867,10 +13456,14 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge2": { "version": "1.4.1", @@ -14716,10 +15309,11 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "dev": true, + "license": "MIT" }, "node_modules/pathval": { "version": "1.1.1", @@ -14849,6 +15443,53 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -15112,12 +15753,13 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -15478,6 +16120,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -15829,10 +16480,11 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -15857,6 +16509,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -15865,13 +16518,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -15883,7 +16538,8 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sentence-case": { "version": "3.0.4", @@ -15906,20 +16562,31 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -17172,6 +17839,25 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "dev": true }, + "node_modules/tsx": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -17484,9 +18170,10 @@ "dev": true }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -18281,6 +18968,22 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "packages/integration-tests": { + "name": "@splunk/otel-js-web-integration-tests", + "version": "0.19.2", + "license": "Apache-2.0", + "dependencies": { + "tsx": "^4.19.2" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@types/ejs": "^3.1.5", + "@types/express": "^5.0.0", + "@types/node": "^22.9.0", + "ejs": "^3.1.10", + "express": "^4.21.1" + } + }, "packages/session-recorder": { "name": "@splunk/otel-web-session-recorder", "version": "0.19.3", diff --git a/package.json b/package.json index a6872a12..9964276e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "--workspaces": "Hardcoded so npm runs workspaces commands in order", "workspaces": [ "packages/web", - "packages/session-recorder" + "packages/session-recorder", + "packages/integration-tests" ], "engines": { "--": "Versions required for development only (recent enough to use npm workspaces)", diff --git a/packages/integration-tests/.gitignore b/packages/integration-tests/.gitignore new file mode 100644 index 00000000..68c5d18f --- /dev/null +++ b/packages/integration-tests/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/packages/integration-tests/package-lock.json b/packages/integration-tests/package-lock.json new file mode 100644 index 00000000..77c4445a --- /dev/null +++ b/packages/integration-tests/package-lock.json @@ -0,0 +1,1697 @@ +{ + "name": "@splunk/otel-js-web-integration-tests", + "version": "0.19.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@splunk/otel-js-web-integration-tests", + "version": "0.19.1", + "license": "Apache-2.0", + "dependencies": { + "tsx": "^4.19.2" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@types/ejs": "^3.1.5", + "@types/express": "^5.0.0", + "@types/node": "^22.9.0", + "ejs": "^3.1.10", + "express": "^4.21.1" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", + "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/qs": { + "version": "6.9.17", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", + "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "dev": true, + "license": "MIT" + }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tsx": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json new file mode 100644 index 00000000..28ed53a4 --- /dev/null +++ b/packages/integration-tests/package.json @@ -0,0 +1,28 @@ +{ + "name": "@splunk/otel-js-web-integration-tests", + "private": true, + "version": "0.19.2", + "repository": "github:signalfx/splunk-otel-js-browser", + "scripts": { + "server": "tsx src/server/server.ts", + "test": "npx playwright test", + "compile": "exit 0;" + }, + "author": "Splunk Observability Instrumentals Team ", + "license": "Apache-2.0", + "devDependencies": { + "@playwright/test": "^1.48.2", + "@types/ejs": "^3.1.5", + "@types/express": "^5.0.0", + "@types/node": "^22.9.0", + "ejs": "^3.1.10", + "express": "^4.21.1" + }, + "bugs": { + "url": "https://github.com/signalfx/splunk-otel-js-web/issues" + }, + "homepage": "https://github.com/signalfx/splunk-otel-js-web#readme", + "dependencies": { + "tsx": "^4.19.2" + } +} diff --git a/packages/integration-tests/playwright.config.ts b/packages/integration-tests/playwright.config.ts new file mode 100644 index 00000000..34d0a4e2 --- /dev/null +++ b/packages/integration-tests/playwright.config.ts @@ -0,0 +1,101 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { defineConfig, devices } from '@playwright/test' + +const REPORTERS = [] +if (process.env.CI) { + REPORTERS.push(['blob'], ['list']) +} else { + REPORTERS.push(['list'], ['html', { open: 'never' }]) +} + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './src/tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: REPORTERS, + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'], headless: true }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'], headless: true }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'], headless: true }, + }, + + { + name: 'edge', + use: { + ...devices['Desktop Edge'], + channel: 'msedge', + headless: true, + }, + }, + + { + name: 'chrome', + use: { + ...devices['Desktop Chrome'], + channel: 'chrome', + headless: true, + }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run server', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/packages/integration-tests/src/pages/record-page.ts b/packages/integration-tests/src/pages/record-page.ts new file mode 100644 index 00000000..52f47cde --- /dev/null +++ b/packages/integration-tests/src/pages/record-page.ts @@ -0,0 +1,108 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { BrowserContext, Page } from 'playwright' +import { Span } from '@opentelemetry/exporter-zipkin/build/src/types' + +export class RecordPage { + receivedSpans: Span[] = [] + + get receivedErrorSpans() { + return this.receivedSpans.filter((span) => span.name === 'onerror') + } + + constructor( + private readonly page: Page, + private readonly context: BrowserContext, + ) {} + + changeVisibilityInTab = async (state: 'visible' | 'hidden') => { + await this.page.evaluate((stateInner) => { + Object.defineProperty(document, 'visibilityState', { value: stateInner, writable: true }) + Object.defineProperty(document, 'hidden', { value: Boolean(stateInner === 'hidden'), writable: true }) + + window.dispatchEvent(new Event('visibilitychange')) + }, state) + } + + clearReceivedSpans() { + this.receivedSpans = [] + } + + async flushData() { + await this.page.evaluate(() => { + if (window.SplunkRum) { + window.SplunkRum._processor.forceFlush() + } + }) + } + + async getCookie(name: string) { + const cookies = await this.context.cookies() + return cookies.find((cookie) => cookie.name === name) + } + + goTo(url: string) { + const absoluteUrl = new URL(url, 'http://localhost:3000').toString() + return this.page.goto(absoluteUrl) + } + + get locator() { + return this.page.locator.bind(this.page) + } + + async mockNetwork() { + await this.page.route('*/**/api/v2/spans', async (route, request) => { + const spans = JSON.parse(request.postData()) + this.receivedSpans.push(...spans) + + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: '', + }) + }) + } + + setOffline() { + return this.context.setOffline(true) + } + + setOnline() { + return this.context.setOffline(false) + } + + waitForSpans: (predicate: (spans: Span[]) => boolean) => Promise = async (predicate) => + new Promise((resolve) => { + const intervalId = setInterval(async () => { + await this.flushData() + if (predicate(this.receivedSpans)) { + clearInterval(intervalId) + resolve() + } + }, 50) + }) + + waitForTimeout(timeout: number) { + return this.page.waitForTimeout(timeout) + } + + async waitForTimeoutAndFlushData(timeout: number) { + await this.waitForTimeout(timeout) + await this.flushData() + } +} diff --git a/packages/integration-tests/src/server/render-agent.ts b/packages/integration-tests/src/server/render-agent.ts new file mode 100644 index 00000000..953af2dc --- /dev/null +++ b/packages/integration-tests/src/server/render-agent.ts @@ -0,0 +1,73 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +export const RENDER_AGENT_TEMPLATE = ` + + + +` diff --git a/packages/web/integration-tests/tests/xhr/xhr-ignored.spec.js b/packages/integration-tests/src/server/server-timing.ts similarity index 51% rename from packages/web/integration-tests/tests/xhr/xhr-ignored.spec.js rename to packages/integration-tests/src/server/server-timing.ts index 336f9de5..401d9dfa 100644 --- a/packages/web/integration-tests/tests/xhr/xhr-ignored.spec.js +++ b/packages/integration-tests/src/server/server-timing.ts @@ -15,18 +15,22 @@ * limitations under the License. * */ +import { Response } from 'express' -module.exports = { - 'XHR request can be ignored': async function (browser) { - await browser.url(browser.globals.getUrl('/xhr/views/xhr-ignored.ejs')) +const generateHex = (length: number) => + [...Array(length).keys()].map(() => Math.floor(Math.random() * 16).toString(16)).join('') - await browser.globals.findSpan((span) => span.name === 'guard-span') +const generateServerTiming = () => { + const traceId = generateHex(32) + const spanId = generateHex(16) + const formatted = `traceparent;desc="00-${traceId}-${spanId}-01"` + return { + traceId, + spanId, + header: formatted, + } +} - await browser.assert.not.ok( - browser.globals.getReceivedSpans().find((span) => span.tags['http.url'] === '/some-data'), - ) - await browser.assert.not.ok( - browser.globals.getReceivedSpans().find((span) => span.tags['http.url'] === '/no-server-timings'), - ) - }, +export const setServerTimingHeader = (responseObject: Response, serverTiming = generateServerTiming()) => { + responseObject.set('Server-Timing', serverTiming.header) } diff --git a/packages/integration-tests/src/server/server.ts b/packages/integration-tests/src/server/server.ts new file mode 100644 index 00000000..654ada6b --- /dev/null +++ b/packages/integration-tests/src/server/server.ts @@ -0,0 +1,108 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import express from 'express' +import path from 'path' +import { RENDER_AGENT_TEMPLATE } from './render-agent' +import { render } from 'ejs' +import { setServerTimingHeader } from './server-timing' + +const GLOBAL_TEST_BUFFER_TIMEOUT = 20 + +const app = express() + +app.set('view engine', 'ejs') +app.set('views', path.join(__dirname, '../tests')) + +app.use(express.json()) +app.use(express.static(path.join(__dirname, '../../../web/dist'))) + +app.post('/api/v2/spans', (req, res) => { + res.send('') +}) + +app.post('/echo', (req, res) => { + console.log('echooooo', req.body) + res.send(req.body) +}) + +app.get('/some-data', (req, response) => { + setServerTimingHeader(response) + response.send({ + key1: 'value1', + key2: 'value2', + key3: 'value3', + }) +}) + +app.get('/no-server-timings', (_, res) => { + res.sendStatus(200) +}) + +app.get('*', (req, res) => { + const beaconUrl = new URL(`http://${req.headers.host}/api/v2/spans`) + const defaultFile = '/artifacts/splunk-otel-web.js' + + if (req.path.endsWith('.ejs')) { + res.render(req.path.slice(1), { + renderAgent(userOpts = {}, noInit = false, file = defaultFile, cdnVersion = null) { + const options: Record = { + beaconEndpoint: beaconUrl.toString(), + applicationName: 'splunk-otel-js-dummy-app', + debug: true, + bufferTimeout: GLOBAL_TEST_BUFFER_TIMEOUT, + ...userOpts, + } + + if (typeof req.query.disableInstrumentation === 'string') { + if (!options.instrumentations) { + options.instrumentations = {} + } + + req.query.disableInstrumentation.split(',').forEach((instrumentation) => { + options.instrumentations[instrumentation] = false + }) + } + + if (typeof req.query.beaconEndpoint === 'string') { + options.beaconEndpoint = req.query.beaconEndpoint + } + + if (cdnVersion) { + file = `https://cdn.signalfx.com/o11y-gdi-rum/${cdnVersion}/splunk-otel-web.js` + } + + return render(RENDER_AGENT_TEMPLATE, { + file, + noInit, + options: JSON.stringify(options), + otelApiGlobalsFile: '/artifacts/otel-api-globals.js', + }) + }, + }) + } else { + res.send('Error: Invalid URL') + } +}) + +app.listen(3000, () => { + console.log(`Server running on port 3000`) +}) + +app.listen(3001, () => { + console.log(`Server running on port 3001`) +}) diff --git a/packages/web/integration-tests/tests/cdn/index.ejs b/packages/integration-tests/src/tests/cdn/index.ejs similarity index 87% rename from packages/web/integration-tests/tests/cdn/index.ejs rename to packages/integration-tests/src/tests/cdn/index.ejs index 44b8027f..c16fa380 100644 --- a/packages/web/integration-tests/tests/cdn/index.ejs +++ b/packages/integration-tests/src/tests/cdn/index.ejs @@ -7,7 +7,7 @@ <%- renderAgent({}, false, null, 'latest' ) %> diff --git a/packages/integration-tests/src/tests/cdn/index.spec.ts b/packages/integration-tests/src/tests/cdn/index.spec.ts new file mode 100644 index 00000000..2da4624a --- /dev/null +++ b/packages/integration-tests/src/tests/cdn/index.spec.ts @@ -0,0 +1,61 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { expect } from '@playwright/test' +import { test } from '../../utils/test' + +test.describe('cdn', () => { + test('JS unhandled error', async ({ browserName, recordPage }) => { + await recordPage.goTo('/cdn/index.ejs') + + await recordPage.waitForSpans((spans) => spans.some((s) => s.name === 'onerror')) + const errorSpans = recordPage.receivedSpans.filter((s) => s.name === 'onerror') + + expect(errorSpans).toHaveLength(1) + + const errorSpan = errorSpans[0] + expect(errorSpan.tags['component']).toBe('error') + expect(errorSpan.tags['error']).toBe('true') + expect(errorSpan.tags['error.object']).toBe('TypeError') + + let expectedMessage = '' + + switch (browserName) { + case 'chromium': + expectedMessage = "Cannot set properties of null (setting 'prop1')" + break + case 'firefox': + expectedMessage = 'test is null' + break + case 'webkit': + expectedMessage = "null is not an object (evaluating 'test.prop1 = true')" + break + } + + expect(errorSpan.tags['error.message']).toBe(expectedMessage) + + const rumScriptFetchSpans = recordPage.receivedSpans.filter( + (s) => s.name === 'resourceFetch' && (s.tags['http.url']).includes('cdn.signalfx.com'), + ) + expect(rumScriptFetchSpans).toHaveLength(1) + const rumScriptFetchSpan = rumScriptFetchSpans[0] + expect(rumScriptFetchSpan.tags['http.url']).toBe( + 'https://cdn.signalfx.com/o11y-gdi-rum/latest/splunk-otel-web.js', + ) + expect(rumScriptFetchSpan.tags['splunk.rumVersion']).toBe('0.19.3') + }) +}) diff --git a/packages/web/integration-tests/tests/connectivity/connectivity.ejs b/packages/integration-tests/src/tests/connectivity/connectivity.ejs similarity index 100% rename from packages/web/integration-tests/tests/connectivity/connectivity.ejs rename to packages/integration-tests/src/tests/connectivity/connectivity.ejs diff --git a/packages/integration-tests/src/tests/connectivity/connectivity.spec.ts b/packages/integration-tests/src/tests/connectivity/connectivity.spec.ts new file mode 100644 index 00000000..920ae309 --- /dev/null +++ b/packages/integration-tests/src/tests/connectivity/connectivity.spec.ts @@ -0,0 +1,66 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { expect } from '@playwright/test' +import { test } from '../../utils/test' + +test.describe('connectivity', () => { + test('Connectivity events are captured', async ({ browserName, recordPage }) => { + if (browserName === 'firefox') { + // TODO: Investigate why setOffline is not working in firefox + test.skip() + } + + await recordPage.goTo('/connectivity/connectivity.ejs') + + await recordPage.waitForSpans((spans) => spans.some((s) => s.name === 'documentFetch')) + + // Wait some time to see if we get any connectivity spans + await recordPage.waitForTimeoutAndFlushData(1000) + const connectivitySpansBeforeOffline = recordPage.receivedSpans.filter((span) => span.name === 'connectivity') + + expect(connectivitySpansBeforeOffline.length).toBe(0) + + await recordPage.setOffline() + + await recordPage.waitForTimeoutAndFlushData(1000) + const connectivitySpansAfterOffline = recordPage.receivedSpans.filter((span) => span.name === 'connectivity') + + expect(connectivitySpansAfterOffline.length).toBe(0) + + await recordPage.setOnline() + await recordPage.waitForSpans((spans) => spans.filter((s) => s.name === 'connectivity').length >= 1) + const connectivitySpansAfterOnline = recordPage.receivedSpans.filter((span) => span.name === 'connectivity') + + expect(connectivitySpansAfterOnline).toHaveLength(2) + expect(connectivitySpansAfterOnline[0].tags['online']).toBe('false') + expect(connectivitySpansAfterOnline[1].tags['online']).toBe('true') + + expect(recordPage.receivedErrorSpans).toHaveLength(0) + + await recordPage.setOffline() + await recordPage.setOnline() + + await recordPage.waitForSpans((spans) => spans.filter((s) => s.name === 'connectivity').length >= 4) + const allConnectivitySpans = recordPage.receivedSpans.filter((span) => span.name === 'connectivity') + + expect(allConnectivitySpans).toHaveLength(4) + expect(allConnectivitySpans[2].tags['online']).toBe('false') + expect(allConnectivitySpans[3].tags['online']).toBe('true') + expect(recordPage.receivedErrorSpans).toHaveLength(0) + }) +}) diff --git a/packages/web/integration-tests/tests/cookies/cookies-domain.ejs b/packages/integration-tests/src/tests/cookies/cookies-domain.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies-domain.ejs rename to packages/integration-tests/src/tests/cookies/cookies-domain.ejs diff --git a/packages/web/integration-tests/tests/cookies/cookies.ejs b/packages/integration-tests/src/tests/cookies/cookies.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies.ejs rename to packages/integration-tests/src/tests/cookies/cookies.ejs diff --git a/packages/web/integration-tests/tests/cookies/cookies.iframe.ejs b/packages/integration-tests/src/tests/cookies/cookies.iframe.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies.iframe.ejs rename to packages/integration-tests/src/tests/cookies/cookies.iframe.ejs diff --git a/packages/integration-tests/src/tests/cookies/cookies.spec.ts b/packages/integration-tests/src/tests/cookies/cookies.spec.ts new file mode 100644 index 00000000..e602329a --- /dev/null +++ b/packages/integration-tests/src/tests/cookies/cookies.spec.ts @@ -0,0 +1,88 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { expect } from '@playwright/test' +import { test } from '../../utils/test' + +test.describe('cookies', () => { + test('Connectivity events are captured', async ({ recordPage }) => { + await recordPage.goTo('/cookies/cookies.ejs') + + // This should create two streams of documentLoad sequences, all with the same sessionId but having + // two scriptInstances (one from parent, one from iframe) + await recordPage.waitForSpans((spans) => spans.filter((s) => s.name === 'documentFetch').length === 2) + const documentFetchSpans = recordPage.receivedSpans.filter((span) => span.name === 'documentFetch') + expect(documentFetchSpans).toHaveLength(2) + + expect(documentFetchSpans[0].tags['location.href']).toBe('http://localhost:3000/cookies/iframe.ejs') + expect(documentFetchSpans[1].tags['location.href']).toBe('http://localhost:3000/cookies/cookies.ejs') + + // same sessionId& instanceId + expect(documentFetchSpans[0].tags['splunk.rumSessionId']).toBe( + documentFetchSpans[1].tags['splunk.rumSessionId'], + ) + expect(documentFetchSpans[0].tags['browser.instance.id']).toBe( + documentFetchSpans[1].tags['browser.instance.id'], + ) + + // different scriptInstance + expect(documentFetchSpans[0].tags['splunk.scriptInstance']).not.toBe( + documentFetchSpans[1].tags['splunk.scriptInstance'], + ) + + const cookie = await recordPage.getCookie('_splunk_rum_sid') + expect(cookie).toBeTruthy() + + expect(recordPage.receivedErrorSpans).toHaveLength(0) + }) + + test('setting session cookie in iframe should work', async ({ recordPage, browserName }) => { + await recordPage.goTo('/cookies/cookies.iframe.ejs') + if (browserName === 'webkit') { + // TODO: Does not work in webkit. Investigate + test.skip() + } + + await recordPage.waitForSpans((spans) => + spans.some((s) => s.name === 'documentFetch' && s.tags.app === 'iframe'), + ) + const documentFetchSpans = recordPage.receivedSpans.filter((span) => span.name === 'documentFetch') + expect(documentFetchSpans).toHaveLength(1) + expect(documentFetchSpans[0].tags['splunk.rumSessionId']).toBeTruthy() + + const cookie = await recordPage.getCookie('_splunk_rum_sid') + expect(cookie).toBeTruthy() + expect(cookie.secure).toBe(true) + expect(cookie.sameSite).toBe('None') + }) + + test('setting cookieDomain via config sets it on subdomains also', async ({ recordPage }) => { + await recordPage.goTo(`http://127.0.0.1.nip.io:3000/cookies/cookies-domain.ejs`) + const cookie1 = await recordPage.getCookie('_splunk_rum_sid') + + expect(cookie1).toBeTruthy() + + await recordPage.goTo(`http://test.127.0.0.1.nip.io:3000/cookies/cookies-domain.ejs`) + const cookie2 = await recordPage.getCookie('_splunk_rum_sid') + + expect(cookie2).toBeTruthy() + expect(cookie1.value).toBe(cookie2.value) + expect(cookie1.domain).toBe(cookie2.domain) + + expect(recordPage.receivedErrorSpans).toHaveLength(0) + }) +}) diff --git a/packages/web/integration-tests/tests/cookies/iframe.ejs b/packages/integration-tests/src/tests/cookies/iframe.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/iframe.ejs rename to packages/integration-tests/src/tests/cookies/iframe.ejs diff --git a/packages/web/integration-tests/tests/fetch/fetch-ignored.ejs b/packages/integration-tests/src/tests/fetch/fetch-ignored.ejs similarity index 100% rename from packages/web/integration-tests/tests/fetch/fetch-ignored.ejs rename to packages/integration-tests/src/tests/fetch/fetch-ignored.ejs diff --git a/packages/web/integration-tests/tests/fetch/fetch-post.ejs b/packages/integration-tests/src/tests/fetch/fetch-post.ejs similarity index 77% rename from packages/web/integration-tests/tests/fetch/fetch-post.ejs rename to packages/integration-tests/src/tests/fetch/fetch-post.ejs index a1ef30bc..3ccfe85a 100644 --- a/packages/web/integration-tests/tests/fetch/fetch-post.ejs +++ b/packages/integration-tests/src/tests/fetch/fetch-post.ejs @@ -10,15 +10,20 @@

FETCH post

- + diff --git a/packages/integration-tests/src/tests/xhr/xhr.spec.ts b/packages/integration-tests/src/tests/xhr/xhr.spec.ts new file mode 100644 index 00000000..34c2e0eb --- /dev/null +++ b/packages/integration-tests/src/tests/xhr/xhr.spec.ts @@ -0,0 +1,68 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { test } from '../../utils/test' +import { expect } from '@playwright/test' + +test.describe('xhr', () => { + test('XHR request is registered', async ({ recordPage }) => { + await recordPage.goTo('/xhr/xhr-basic.ejs') + await recordPage.waitForSpans( + (spans) => spans.filter((span) => span.tags['http.url'] === 'http://localhost:3000/some-data').length === 1, + ) + const xhrSpans = recordPage.receivedSpans.filter( + (span) => span.tags['http.url'] === 'http://localhost:3000/some-data', + ) + + expect(xhrSpans).toHaveLength(1) + expect(xhrSpans[0].tags['component']).toBe('xml-http-request') + expect(xhrSpans[0].tags['http.status_code']).toBe('200') + expect(xhrSpans[0].tags['http.status_text']).toBe('OK') + expect(xhrSpans[0].tags['http.method']).toBe('GET') + expect(xhrSpans[0].tags['http.url']).toBe('http://localhost:3000/some-data') + expect(xhrSpans[0].tags['http.response_content_length']).toBe('49') + expect(xhrSpans[0].tags['link.traceId']).toBeTruthy() + expect(xhrSpans[0].tags['link.spanId']).toBeTruthy() + }) + + test('module can be disabled', async ({ recordPage }) => { + await recordPage.goTo('/xhr/xhr-basic.ejs?disableInstrumentation=xhr') + await recordPage.waitForTimeout(1000) + + const xhrSpans = recordPage.receivedSpans.filter( + (span) => span.tags['http.url'] === 'http://localhost:3000/some-data', + ) + + expect(xhrSpans).toHaveLength(0) + }) + + test('XHR request can be ignored', async ({ recordPage }) => { + await recordPage.goTo('/xhr/xhr-ignored.ejs') + + await recordPage.waitForSpans((spans) => spans.filter((span) => span.name === 'guard-span').length === 1) + + const xhrSpans = recordPage.receivedSpans.filter((span) => + ['http://localhost:3000/some-data', 'http://localhost:3000/no-server-timings'].includes( + span.tags['http.url'] as string, + ), + ) + const guardSpans = recordPage.receivedSpans.filter((span) => span.name === 'guard-span') + + expect(xhrSpans).toHaveLength(0) + expect(guardSpans).toHaveLength(1) + }) +}) diff --git a/packages/web/integration-tests/tests/native/native.spec.js b/packages/integration-tests/src/utils/test.ts similarity index 54% rename from packages/web/integration-tests/tests/native/native.spec.js rename to packages/integration-tests/src/utils/test.ts index f82c74d9..1f6a35c4 100644 --- a/packages/web/integration-tests/tests/native/native.spec.js +++ b/packages/integration-tests/src/utils/test.ts @@ -16,16 +16,22 @@ * */ -module.exports = { - 'native session id integration': async function (browser) { - const url = browser.globals.getUrl('/native/native.ejs') - await browser.url(url) +import { test as base } from '@playwright/test' - const anySpan = await browser.globals.findSpan((span) => span.tags['splunk.rumSessionId'] !== undefined) +import { RecordPage } from '../pages/record-page' - await browser.assert.ok(anySpan) +type TestFixtures = { + recordPage: RecordPage +} + +export const test = base.extend({ + recordPage: async ({ browser }, use) => { + const recordingContext = await browser.newContext({ viewport: { height: 1080, width: 1920 } }) + const recordPage = new RecordPage(await recordingContext.newPage(), recordingContext) + await recordPage.mockNetwork() - await browser.assert.strictEqual(anySpan.tags['splunk.rumSessionId'], '12341234123412341234123412341234') - await browser.globals.assertNoErrorSpans() + await use(recordPage) + + await recordingContext.close() }, -} +}) diff --git a/packages/web/integration-tests/tests/redacting-attributes/index.spec.js b/packages/integration-tests/src/version.ts similarity index 58% rename from packages/web/integration-tests/tests/redacting-attributes/index.spec.js rename to packages/integration-tests/src/version.ts index cffd1b40..da50bef6 100644 --- a/packages/web/integration-tests/tests/redacting-attributes/index.spec.js +++ b/packages/integration-tests/src/version.ts @@ -16,15 +16,5 @@ * */ -module.exports = { - 'redacting attributes with custom exporter': async function (browser) { - const url = browser.globals.getUrl('/redacting-attributes/index.ejs') - await browser.url(url) - - await browser.click('#btnClick') - - const clickSpan = await browser.globals.findSpan((span) => span.name === 'click') - await browser.assert.ok(clickSpan) - await browser.assert.strictEqual(clickSpan.tags['http.url'], '[redacted]') - }, -} +// this is an autogenerated file, see scripts/version-update.js +export const VERSION = '0.19.2' diff --git a/packages/integration-tests/tsconfig.json b/packages/integration-tests/tsconfig.json new file mode 100644 index 00000000..0cd8a3bb --- /dev/null +++ b/packages/integration-tests/tsconfig.json @@ -0,0 +1,8 @@ +{ + "include": ["**/*.ts"], + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "target": "esnext", + "moduleResolution": "nodenext" + } +} diff --git a/packages/web/integration-tests/tests/cdn/index.spec.js b/packages/web/integration-tests/tests/cdn/index.spec.js deleted file mode 100644 index 41fbdf30..00000000 --- a/packages/web/integration-tests/tests/cdn/index.spec.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -module.exports = { - '@tags': ['skip-ie11'], - 'JS unhandled error': async function (browser) { - browser.globals.clearReceivedSpans() - await browser.url(browser.globals.getUrl('/cdn/index.ejs')) - - const errorSpan = await browser.globals.findSpan((s) => s.name === 'onerror') - await browser.assert.ok(!!errorSpan, 'Checking presence of error span.') - - const tags = errorSpan.tags - await browser.assert.strictEqual(tags['component'], 'error') - await browser.assert.strictEqual(tags['error'], 'true') - await browser.assert.strictEqual(tags['error.object'], 'TypeError') - - switch (browser.options.desiredCapabilities.browserName.toLowerCase()) { - case 'chrome': - await browser.assert.strictEqual( - tags['error.message'], - "Cannot set properties of null (setting 'prop1')", - ) - break - case 'firefox': - await browser.assert.strictEqual(tags['error.message'], 'test is null') - break - case 'safari': - await browser.assert.strictEqual( - tags['error.message'], - "null is not an object (evaluating 'test.prop1 = true')", - ) - break - } - - const rumScriptFetchSpan = await browser.globals.findSpan( - (s) => s.name === 'resourceFetch' && s.tags['http.url'].includes('cdn.signalfx.com'), - ) - await browser.assert.ok(!!rumScriptFetchSpan, 'Checking presence of splunk-otel-web fetch span.') - - const cdnUrl = 'https://cdn.signalfx.com/o11y-gdi-rum/latest/splunk-otel-web.js' - await browser.assert.strictEqual(rumScriptFetchSpan.tags['http.url'], cdnUrl) - await browser.assert.strictEqual(rumScriptFetchSpan.tags['splunk.rumVersion'], '0.19.3') - }, -} diff --git a/packages/web/integration-tests/tests/connectivity/connectivity.spec.js b/packages/web/integration-tests/tests/connectivity/connectivity.spec.js deleted file mode 100644 index be2e973d..00000000 --- a/packages/web/integration-tests/tests/connectivity/connectivity.spec.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -module.exports = { - 'Connectivity events are captured': async function (browser) { - // When we have a test run that supports chrome dev tools protocol we can properly emulate connectivity. - // Otherwise this could be an unit test. - // Should probably do some timing checks but don't want to add flakiness atm - - await browser.url(browser.globals.getUrl('/connectivity/connectivity.ejs')) - - await browser.globals.findSpan((span) => span.name === 'documentFetch') - const connectivitySpans = browser.globals.getReceivedSpans().filter((span) => span.name === 'connectivity') - await browser.assert.strictEqual(connectivitySpans.length, 0, 'No connectivity spans cause we are offline') - - await browser.globals.emulateOffline(true) - let offlineSpan = await browser.globals.findSpan( - (span) => span.name === 'connectivity' && span.tags['online'] === 'false', - ) - let onlineSpan = await browser.globals.findSpan( - (span) => span.name === 'connectivity' && span.tags['online'] === 'true', - ) - - await browser.assert.ok(!!onlineSpan, 'Offline span exists') - await browser.assert.ok(!!offlineSpan, 'Online span exists') - await browser.globals.assertNoErrorSpans() - - browser.globals.clearReceivedSpans() - - await browser.globals.emulateOffline(false) - await browser.globals.emulateOffline(true) - - offlineSpan = await browser.globals.findSpan( - (span) => span.name === 'connectivity' && span.tags['online'] === 'false', - ) - onlineSpan = await browser.globals.findSpan( - (span) => span.name === 'connectivity' && span.tags['online'] === 'true', - ) - - await browser.assert.ok(!!onlineSpan, 'Offline span exists') - await browser.assert.ok(!!offlineSpan, 'Online span exists') - - await browser.globals.assertNoErrorSpans() - }, -} diff --git a/packages/web/integration-tests/tests/cookies/cookies.spec.js b/packages/web/integration-tests/tests/cookies/cookies.spec.js deleted file mode 100644 index 2d6111eb..00000000 --- a/packages/web/integration-tests/tests/cookies/cookies.spec.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const { isBrowser } = require('../../utils/helpers') - -module.exports = { - 'afterEach': function (browser) { - browser.globals.clearReceivedSpans() - }, - 'setting session cookie should work': async function (browser) { - await browser.url(browser.globals.getUrl('/cookies/cookies.ejs')) - - // This should create two streams of documentLoad sequences, all with the same sessionId but having - // two scriptInstances (one from parent, one from iframe) - const parent = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags['location.href'].includes('cookies.ejs'), - ) - await browser.assert.ok(parent.tags['browser.instance.id']) - - await browser.assert.notEqual(parent.tags['splunk.scriptInstance'], parent.tags['splunk.rumSessionId']) - - const iframe = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags['location.href'].includes('iframe.ejs'), - ) - await browser.assert.ok(iframe.tags['splunk.rumSessionId']) - await browser.assert.notEqual(iframe.tags['splunk.scriptInstance'], iframe.tags['splunk.rumSessionId']) - - // same session id & instanceId - await browser.assert.equal(parent.tags['splunk.rumSessionId'], iframe.tags['splunk.rumSessionId']) - await browser.assert.equal(parent.tags['browser.instance.id'], iframe.tags['browser.instance.id']) - - // but different scriptInstance - await browser.assert.notEqual(parent.tags['splunk.scriptInstance'], iframe.tags['splunk.scriptInstance']) - - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - // FIXME we previously tested that the cookie was marked SameSite=Strict but new session implementation - // has a race between iframes and parents from the same domain. - - await browser.globals.assertNoErrorSpans() - }, - 'setting session cookie in iframe should work': async function (browser) { - await browser.url(browser.globals.getUrl('/cookies/cookies.iframe.ejs')) - - const fetchSpan = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags.app === 'iframe', - ) - await browser.assert.ok(fetchSpan.tags['splunk.rumSessionId']) - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - await browser.assert.ok(fetchSpan) - if (!isBrowser(browser, 'internet explorer') && browser.globals.enableHttps) { - await browser.assert.ok(cookie.secure) - } - - if (!isBrowser(browser, { 'internet explorer': true, 'safari': true })) { - await browser.assert.equal(cookie.sameSite, browser.globals.enableHttps ? 'None' : 'Strict') - } - }, - 'setting cookieDomain via config sets it on subdomains also': async function (browser) { - // chrome: too old to remember - // edge: doesnt' work in saucelab right now for some reason? - if (isBrowser(browser, { chrome: true, microsoftedge: true })) { - return - } - - /* - We are using nip.io to let us test subdomains not sure how reliable it is, so if - you are debugging flaky test then this should be your first guess. - cookies-domain.ejs has cookieDomain set to 127.0.0.1.nip.io, cookie set via cookieDomain - should be accessible for subdomains also so when we go to test. subdomain we should find the same - cookie. - */ - const protocol = browser.globals.enableHttps ? 'https' : 'http' - await browser.url(`${protocol}://127.0.0.1.nip.io:${browser.globals.httpPort}/cookies/cookies-domain.ejs`) - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - - await browser.url(`${protocol}://test.127.0.0.1.nip.io:${browser.globals.httpPort}/cookies/cookies-domain.ejs`) - - const cookie2 = await browser.getCookie('_splunk_rum_sid') - await browser.assert.strictEqual(cookie.domain, cookie2.domain) - await browser.assert.strictEqual(cookie.value, cookie2.value) - - await browser.globals.assertNoErrorSpans() - }, -} diff --git a/packages/web/integration-tests/tests/fetch/fetch.spec.js b/packages/web/integration-tests/tests/fetch/fetch.spec.js deleted file mode 100644 index 38abb2b6..00000000 --- a/packages/web/integration-tests/tests/fetch/fetch.spec.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -module.exports = { - '@tags': ['safari-10.1', 'skip-ie11'], - 'beforeEach': function (browser) { - browser.globals.clearReceivedSpans() - }, - 'span created for fetch includes all properties': async function (browser) { - await browser.url(browser.globals.getUrl('/fetch/fetch.ejs')) - - const fetchSpan = await browser.globals.findSpan( - (span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/some-data'), - ) - await browser.assert.ok(!!fetchSpan, 'Fetch span found.') - await browser.assert.strictEqual(fetchSpan.tags['component'], 'fetch') - await browser.assert.strictEqual(fetchSpan.tags['http.status_code'], '200') - await browser.assert.strictEqual(fetchSpan.tags['http.status_text'], 'OK') - await browser.assert.strictEqual(fetchSpan.tags['http.method'], 'GET') - - if (browser.options.desiredCapabilities.browserName !== 'Safari') { - await browser.assert.strictEqual(fetchSpan.tags['http.response_content_length'], '49') - } - - await browser.assert.ok(fetchSpan.tags['link.traceId'], 'got link.traceId') - await browser.assert.ok(fetchSpan.tags['link.spanId'], 'got link.spanId') - if ( - browser.options.desiredCapabilities.browserName !== 'Safari' && - browser.options.desiredCapabilities.browser_version !== '10.1' - ) { - await browser.timesMakeSense(fetchSpan.annotations, 'domainLookupStart', 'domainLookupEnd') - await browser.timesMakeSense(fetchSpan.annotations, 'connectStart', 'connectEnd') - if (browser.globals.enableHttps) { - await browser.timesMakeSense(fetchSpan.annotations, 'secureConnectionStart', 'connectEnd') - } - - await browser.timesMakeSense(fetchSpan.annotations, 'requestStart', 'responseStart') - await browser.timesMakeSense(fetchSpan.annotations, 'responseStart', 'responseEnd') - await browser.timesMakeSense(fetchSpan.annotations, 'fetchStart', 'responseEnd') - } - - await browser.globals.assertNoErrorSpans() - }, - 'fetch request can be ignored': async function (browser) { - await browser.url(browser.globals.getUrl('/fetch/fetch-ignored.ejs')) - - await browser.globals.findSpan((span) => span.name === 'guard-span') - await browser.globals.assertNoErrorSpans() - - await browser.assert.not.ok( - browser.globals - .getReceivedSpans() - .find((span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/some-data')), - ) - await browser.assert.not.ok( - browser.globals - .getReceivedSpans() - .find((span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/no-server-timings')), - ) - }, - 'fetch reported over CORS': async function (browser) { - const backend2 = await browser.globals.buildInstrumentationBackend() - await browser.url( - backend2.getUrl('/fetch/fetch.ejs', undefined, { beaconPort: browser.globals.httpPort }).toString(), - ) - - const fetchSpan = await browser.globals.findSpan( - (span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/some-data'), - ) - await browser.assert.ok(!!fetchSpan, 'Fetch span found.') - await browser.assert.strictEqual(fetchSpan.tags['component'], 'fetch') - await browser.assert.strictEqual(fetchSpan.tags['http.status_code'], '200') - await browser.assert.strictEqual(fetchSpan.tags['http.status_text'], 'OK') - await browser.assert.strictEqual(fetchSpan.tags['http.method'], 'GET') - await browser.assert.strictEqual(fetchSpan.tags['http.host'], `${backend2.httpHostname}:${backend2.httpPort}`) - - await browser.globals.assertNoErrorSpans() - await backend2.close() - }, - 'request body exists in request object (open-telemetry/opentelemetry-js#2411)': async function (browser) { - await browser.url(browser.globals.getUrl('/fetch/fetch-post.ejs')) - await browser.globals.findSpan((span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/echo')) - - browser.expect.element('#result').text.to.equal('{"test":true}') - }, - 'can be disabled (with xhr switch)': async function (browser) { - await browser.url(browser.globals.getUrl('/fetch/fetch.ejs')) - await browser.globals.waitForTestToFinish() - - await browser.assert.ok( - !!browser.globals - .getReceivedSpans() - .find((span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/some-data')), - ) - - browser.globals.clearReceivedSpans() - await browser.url(browser.globals.getUrl('/fetch/fetch.ejs?disableInstrumentation=xhr,fetch')) - await browser.globals.waitForTestToFinish() - - await browser.assert.not.ok( - browser.globals - .getReceivedSpans() - .find((span) => span.tags['http.url'] && span.tags['http.url'].endsWith('/some-data')), - ) - }, -} diff --git a/packages/web/integration-tests/tests/visibility/visibility.spec.js b/packages/web/integration-tests/tests/visibility/visibility.spec.js deleted file mode 100644 index ab9c7c8a..00000000 --- a/packages/web/integration-tests/tests/visibility/visibility.spec.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -module.exports = { - 'visibility events are captured': async function (browser) { - await browser.url(browser.globals.getUrl('/visibility/visibility.ejs')) - browser.globals.emulateTabSwitching(true) - - const tabHiddenSpan = await browser.globals.findSpan( - (span) => span.name === 'visibility' && span.tags['hidden'] === 'true', - ) - const hiddenSpans = browser.globals.getReceivedSpans().filter((span) => span.name === 'visibility') - await browser.assert.ok(!!tabHiddenSpan, 'Visibility event for hidden tab exists') - await browser.assert.strictEqual(hiddenSpans.length, 1, 'There is only one visibility event') - - browser.globals.clearReceivedSpans() - - browser.globals.emulateTabSwitching(false) - const tabVisibileSpan = await browser.globals.findSpan( - (span) => span.name === 'visibility' && span.tags['hidden'] === 'false', - ) - const visibleSpans = browser.globals.getReceivedSpans().filter((span) => span.name === 'visibility') - await browser.assert.ok(!!tabVisibileSpan, 'Visibility event for visible tab exists') - await browser.assert.strictEqual(visibleSpans.length, 1, 'There is only one visibility event') - - await browser.globals.assertNoErrorSpans() - }, -} diff --git a/packages/web/integration-tests/tests/xhr/xhr-basic.spec.js b/packages/web/integration-tests/tests/xhr/xhr-basic.spec.js deleted file mode 100644 index 408a9a9b..00000000 --- a/packages/web/integration-tests/tests/xhr/xhr-basic.spec.js +++ /dev/null @@ -1,84 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const { isBrowser } = require('../../utils/helpers') - -module.exports = { - '@tags': ['safari-10.1'], - 'beforeEach': function (browser) { - browser.globals.clearReceivedSpans() - }, - 'XHR request is registered': async function (browser) { - await browser.url(browser.globals.getUrl('/xhr/views/xhr-basic.ejs')) - const xhrSpan = await browser.globals.findSpan( - (span) => span.tags['http.url'] === browser.globals.getUrl('/some-data', []), - ) - await browser.assert.ok(xhrSpan, 'got an xhr span') - await browser.assert.strictEqual(xhrSpan.tags['component'], 'xml-http-request') - await browser.assert.strictEqual(xhrSpan.tags['http.status_code'], '200') - await browser.assert.strictEqual(xhrSpan.tags['http.status_text'], 'OK') - await browser.assert.strictEqual(xhrSpan.tags['http.method'], 'GET') - await browser.assert.strictEqual(xhrSpan.tags['http.url'], browser.globals.getUrl('/some-data', [])) - if (!isBrowser(browser, { safari: true, ie: true })) { - await browser.assert.strictEqual(xhrSpan.tags['http.response_content_length'], '49') - } - - await browser.assert.ok(xhrSpan.tags['link.traceId'], 'got link.traceId') - await browser.assert.ok(xhrSpan.tags['link.spanId'], 'got link.spanId') - - if ( - !isBrowser(browser, { - safari: { max: 10 }, - ie: true, - }) - ) { - await browser.timesMakeSense(xhrSpan.annotations, 'domainLookupStart', 'domainLookupEnd') - await browser.timesMakeSense(xhrSpan.annotations, 'connectStart', 'connectEnd') - if (browser.globals.enableHttps) { - await browser.timesMakeSense(xhrSpan.annotations, 'secureConnectionStart', 'connectEnd') - } - - await browser.timesMakeSense(xhrSpan.annotations, 'requestStart', 'responseStart') - await browser.timesMakeSense(xhrSpan.annotations, 'responseStart', 'responseEnd') - await browser.timesMakeSense(xhrSpan.annotations, 'fetchStart', 'responseEnd') - } - - await browser.timesMakeSense(xhrSpan.annotations, 'open', 'send') - await browser.timesMakeSense(xhrSpan.annotations, 'send', 'loaded') - await browser.globals.assertNoErrorSpans() - }, - 'module can be disabled': async function (browser) { - await browser.url(browser.globals.getUrl('/xhr/views/xhr-basic.ejs')) - await browser.globals.waitForTestToFinish() - - const awaitedUrl = browser.globals.getUrl('/some-data', []) - browser.assert.ok( - !!browser.globals.getReceivedSpans().find((span) => span.tags['http.url'] === awaitedUrl), - 'Checking presence of xhr span.', - ) - - browser.globals.clearReceivedSpans() - await browser.url(browser.globals.getUrl('/xhr/views/xhr-basic.ejs?disableInstrumentation=xhr')) - await browser.globals.waitForTestToFinish() - - browser.assert.not.ok( - browser.globals.getReceivedSpans().find((span) => span.tags['http.url'] === awaitedUrl), - 'Checking lack of xhr span.', - ) - }, -}