diff --git a/.github/actions/common/setup-node-deps/action.yml b/.github/actions/common/setup-node-deps/action.yml new file mode 100644 index 000000000..f99758768 --- /dev/null +++ b/.github/actions/common/setup-node-deps/action.yml @@ -0,0 +1,26 @@ +name: 'Setup Node Dependencies' +description: 'Install Node.js and npm dependencies' +runs: + using: 'composite' + steps: + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: v22.17.0 + cache: 'npm' + cache-dependency-path: './package-lock.json' + + - name: Install node dependencies + shell: bash + run: npm ci --legacy-peer-deps + + - name: Build libraries + shell: bash + run: | + npm run build:graphql-docs + npm run build:bruno-query + npm run build:bruno-common + npm run sandbox:bundle-libraries --workspace=packages/bruno-js + npm run build:bruno-converters + npm run build:bruno-requests + npm run build:bruno-filestore diff --git a/.github/actions/ssl/linux/run-basic-ssl-cli-tests/action.yml b/.github/actions/ssl/linux/run-basic-ssl-cli-tests/action.yml new file mode 100644 index 000000000..e0d8c04eb --- /dev/null +++ b/.github/actions/ssl/linux/run-basic-ssl-cli-tests/action.yml @@ -0,0 +1,36 @@ +name: 'Run Basic SSL CLI Tests - Linux' +description: 'Run basic SSL CLI tests on Linux' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: bash + run: | + set -euo pipefail + + # navigate to basic SSL test collection directory + cd tests/ssl/basic-ssl/collections/badssl + + echo "basic ssl success" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit1.xml --insecure --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit1.xml | grep -q "^1$" || exit 1 + + echo "with default/system ca certs" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit2.xml --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit2.xml | grep -q "^1$" || exit 1 + + # navigate to self-signed SSL test collection directory + cd ../self-signed-badssl + + echo "self-signed ssl with validation disabled" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit3.xml --insecure --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit3.xml | grep -q "^1$" || exit 1 + + echo "self-signed ssl with default/system ca certs" + echo "request will error" + # should fail + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit4.xml --format junit 2>/dev/null || true + xmllint --xpath 'count(//testsuite[@errors="1"])' junit4.xml | grep -q "^1$" || exit 1 diff --git a/.github/actions/ssl/linux/run-custom-ca-certs-cli-tests/action.yml b/.github/actions/ssl/linux/run-custom-ca-certs-cli-tests/action.yml new file mode 100644 index 000000000..375a14228 --- /dev/null +++ b/.github/actions/ssl/linux/run-custom-ca-certs-cli-tests/action.yml @@ -0,0 +1,33 @@ +name: 'Run Custom CA Certs CLI Tests - Linux' +description: 'Run custom CA certs CLI tests on Linux' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: bash + run: | + set -euo pipefail + + # navigate to CA certificates test collection directory + cd tests/ssl/custom-ca-certs/collection + + echo "custom valid ca cert" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit1.xml --cacert ../server/certs/ca-cert.pem --ignore-truststore --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit1.xml | grep -q "^1$" || exit 1 + + echo "custom valid ca cert with defaults" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit2.xml --cacert ../server/certs/ca-cert.pem --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit2.xml | grep -q "^1$" || exit 1 + + echo "custom invalid ca cert" + echo "request will error" + # should fail + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit3.xml --cacert ../server/certs/ca-key.pem --ignore-truststore --format junit 2>/dev/null || true + xmllint --xpath 'count(//testsuite[@errors="1"])' junit3.xml | grep -q "^1$" || exit 1 + + echo "custom invalid ca cert with defaults" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit4.xml --cacert ../server/certs/ca-key.pem --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit4.xml | grep -q "^1$" || exit 1 diff --git a/.github/actions/ssl/linux/run-ssl-e2e-tests/action.yml b/.github/actions/ssl/linux/run-ssl-e2e-tests/action.yml new file mode 100644 index 000000000..bd8c7949e --- /dev/null +++ b/.github/actions/ssl/linux/run-ssl-e2e-tests/action.yml @@ -0,0 +1,19 @@ +name: 'Run SSL E2E Tests - Linux' +description: 'Run SSL E2E tests on Linux' +runs: + using: 'composite' + steps: + - name: Run E2E tests + shell: bash + run: | + set -euo pipefail + + xvfb-run npm run test:e2e:ssl + + - name: Upload Playwright Report + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: playwright-report-linux + path: playwright-report/ + retention-days: 30 diff --git a/.github/actions/ssl/linux/setup-ca-certs/action.yml b/.github/actions/ssl/linux/setup-ca-certs/action.yml new file mode 100644 index 000000000..9561ecf30 --- /dev/null +++ b/.github/actions/ssl/linux/setup-ca-certs/action.yml @@ -0,0 +1,26 @@ +name: 'Setup CA Certificates - Linux' +description: 'Setup CA certificates and start test server for custom CA certs tests on Linux' +runs: + using: 'composite' + steps: + - name: Setup CA certificates + shell: bash + run: | + set -euo pipefail + + cd tests/ssl/custom-ca-certs/server + + echo "running certificate setup" + node scripts/generate-certs.js + + - name: Start test server + shell: bash + run: | + set -euo pipefail + + cd tests/ssl/custom-ca-certs/server + + echo "starting server in background" + node index.js & + + echo "server started with PID: $!" diff --git a/.github/actions/ssl/linux/setup-feature-specific-deps/action.yml b/.github/actions/ssl/linux/setup-feature-specific-deps/action.yml new file mode 100644 index 000000000..475dac0a5 --- /dev/null +++ b/.github/actions/ssl/linux/setup-feature-specific-deps/action.yml @@ -0,0 +1,15 @@ +name: 'Setup Custom CA Certs Feature Dependencies - Linux' +description: 'Setup feature-specific dependencies for custom CA certs tests on Linux' +runs: + using: 'composite' + steps: + - name: Install additional OS dependencies for custom CA certs + shell: bash + run: | + sudo apt-get update + sudo apt-get --no-install-recommends install -y \ + libglib2.0-0 libnss3 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libgtk-3-0 libasound2t64 \ + xvfb libxml2-utils + + sudo chown root /home/runner/work/bruno/bruno/node_modules/electron/dist/chrome-sandbox + sudo chmod 4755 /home/runner/work/bruno/bruno/node_modules/electron/dist/chrome-sandbox diff --git a/.github/actions/ssl/macos/run-basic-ssl-cli-tests/action.yml b/.github/actions/ssl/macos/run-basic-ssl-cli-tests/action.yml new file mode 100644 index 000000000..6b60fc7a8 --- /dev/null +++ b/.github/actions/ssl/macos/run-basic-ssl-cli-tests/action.yml @@ -0,0 +1,36 @@ +name: 'Run Basic SSL CLI Tests - macOS' +description: 'Run basic SSL CLI tests on macOS' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: bash + run: | + set -euo pipefail + + # navigate to basic SSL test collection directory + cd tests/ssl/basic-ssl/collections/badssl + + echo "basic ssl success" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit1.xml --insecure --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit1.xml | grep -q "^1$" || exit 1 + + echo "with default/system ca certs" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit2.xml --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit2.xml | grep -q "^1$" || exit 1 + + # navigate to self-signed SSL test collection directory + cd ../self-signed-badssl + + echo "self-signed ssl with validation disabled" + # should pass + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit3.xml --insecure --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit3.xml | grep -q "^1$" || exit 1 + + echo "self-signed ssl with default/system ca certs" + echo "request will error" + # should fail + node ../../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit4.xml --format junit 2>/dev/null || true + xmllint --xpath 'count(//testsuite[@errors="1"])' junit4.xml | grep -q "^1$" || exit 1 diff --git a/.github/actions/ssl/macos/run-custom-ca-certs-cli-tests/action.yml b/.github/actions/ssl/macos/run-custom-ca-certs-cli-tests/action.yml new file mode 100644 index 000000000..634dca1fc --- /dev/null +++ b/.github/actions/ssl/macos/run-custom-ca-certs-cli-tests/action.yml @@ -0,0 +1,33 @@ +name: 'Run Custom CA Certs CLI Tests - macOS' +description: 'Run custom CA certs CLI tests on macOS' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: bash + run: | + set -euo pipefail + + # navigate to CA certificates test collection directory + cd tests/ssl/custom-ca-certs/collection + + echo "custom valid ca cert" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit1.xml --cacert ../server/certs/ca-cert.pem --ignore-truststore --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit1.xml | grep -q "^1$" || exit 1 + + echo "custom valid ca cert with defaults" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit2.xml --cacert ../server/certs/ca-cert.pem --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit2.xml | grep -q "^1$" || exit 1 + + echo "custom invalid ca cert" + echo "request will error" + # should fail + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit3.xml --cacert ../server/certs/ca-key.pem --ignore-truststore --format junit 2>/dev/null || true + xmllint --xpath 'count(//testsuite[@errors="1"])' junit3.xml | grep -q "^1$" || exit 1 + + echo "custom invalid ca cert with defaults" + # should pass + node ../../../../packages/bruno-cli/bin/bru.js run ./request.bru --output junit4.xml --cacert ../server/certs/ca-key.pem --format junit + xmllint --xpath 'count(//testsuite[@errors="0"])' junit4.xml | grep -q "^1$" || exit 1 diff --git a/.github/actions/ssl/macos/run-ssl-e2e-tests/action.yml b/.github/actions/ssl/macos/run-ssl-e2e-tests/action.yml new file mode 100644 index 000000000..b3fea6368 --- /dev/null +++ b/.github/actions/ssl/macos/run-ssl-e2e-tests/action.yml @@ -0,0 +1,17 @@ +name: 'Run SSL E2E Tests - macOS' +description: 'Run SSL E2E tests on macOS' +runs: + using: 'composite' + steps: + - name: Run E2E tests + shell: bash + run: | + npm run test:e2e:ssl + + - name: Upload Playwright Report + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: playwright-report-macos + path: playwright-report/ + retention-days: 30 diff --git a/.github/actions/ssl/macos/setup-ca-certs/action.yml b/.github/actions/ssl/macos/setup-ca-certs/action.yml new file mode 100644 index 000000000..89180e494 --- /dev/null +++ b/.github/actions/ssl/macos/setup-ca-certs/action.yml @@ -0,0 +1,26 @@ +name: 'Setup CA Certificates - macOS' +description: 'Setup CA certificates and start test server for custom CA certs tests on macOS' +runs: + using: 'composite' + steps: + - name: Setup CA certificates + shell: bash + run: | + set -euo pipefail + + cd tests/ssl/custom-ca-certs/server + + echo "running certificate setup" + node scripts/generate-certs.js + + - name: Start test server + shell: bash + run: | + set -euo pipefail + + cd tests/ssl/custom-ca-certs/server + + echo "starting server in background" + node index.js & + + echo "server started with PID: $!" diff --git a/.github/actions/ssl/macos/setup-feature-specific-deps/action.yml b/.github/actions/ssl/macos/setup-feature-specific-deps/action.yml new file mode 100644 index 000000000..676050509 --- /dev/null +++ b/.github/actions/ssl/macos/setup-feature-specific-deps/action.yml @@ -0,0 +1,9 @@ +name: 'Setup Custom CA Certs Feature Dependencies - macOS' +description: 'Setup feature-specific dependencies for custom CA certs tests on macOS' +runs: + using: 'composite' + steps: + - name: Install additional OS dependencies for custom CA certs + shell: bash + run: | + brew install libxml2 diff --git a/.github/actions/ssl/windows/run-basic-ssl-cli-tests/action.yml b/.github/actions/ssl/windows/run-basic-ssl-cli-tests/action.yml new file mode 100644 index 000000000..2d296b1f3 --- /dev/null +++ b/.github/actions/ssl/windows/run-basic-ssl-cli-tests/action.yml @@ -0,0 +1,50 @@ +name: 'Run Basic SSL CLI Tests - Windows' +description: 'Run basic SSL CLI tests on Windows' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: pwsh + run: | + Set-StrictMode -Version Latest + $ErrorActionPreference = "Stop" + + # navigate to basic SSL test collection directory + Set-Location tests\ssl\basic-ssl\collections\badssl + + Write-Host "basic ssl success" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit1.xml --insecure --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml1 = Get-Content junit1.xml + $testsuites1 = if ($xml1.testsuites) { $xml1.testsuites.testsuite } else { $xml1.testsuite } + $errorCount1 = ($testsuites1 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount1 -ne 1) { exit 1 } + + Write-Host "with default/system ca certs" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit2.xml --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml2 = Get-Content junit2.xml + $testsuites2 = if ($xml2.testsuites) { $xml2.testsuites.testsuite } else { $xml2.testsuite } + $errorCount2 = ($testsuites2 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount2 -ne 1) { exit 1 } + + # navigate to self-signed SSL test collection directory + Set-Location ..\self-signed-badssl + + Write-Host "self-signed ssl with validation disabled" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit3.xml --insecure --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml3 = Get-Content junit3.xml + $testsuites3 = if ($xml3.testsuites) { $xml3.testsuites.testsuite } else { $xml3.testsuite } + $errorCount3 = ($testsuites3 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount3 -ne 1) { exit 1 } + + Write-Host "self-signed ssl with default/system ca certs" + Write-Host "request will error" + # should fail + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit4.xml --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + # Ignore the exit code - we expect this to fail + [xml]$xml4 = Get-Content junit4.xml + $testsuites4 = if ($xml4.testsuites) { $xml4.testsuites.testsuite } else { $xml4.testsuite } + $errorCount4 = ($testsuites4 | Where-Object { $_.errors -eq "1" } | Measure-Object).Count + if ($errorCount4 -ne 1) { exit 1 } diff --git a/.github/actions/ssl/windows/run-custom-ca-certs-cli-tests/action.yml b/.github/actions/ssl/windows/run-custom-ca-certs-cli-tests/action.yml new file mode 100644 index 000000000..f35b7a65f --- /dev/null +++ b/.github/actions/ssl/windows/run-custom-ca-certs-cli-tests/action.yml @@ -0,0 +1,47 @@ +name: 'Run Custom CA Certs CLI Tests - Windows' +description: 'Run custom CA certs CLI tests on Windows' +runs: + using: 'composite' + steps: + - name: Run CLI tests + shell: pwsh + run: | + Set-StrictMode -Version Latest + $ErrorActionPreference = "Stop" + + # navigate to CA certificates test collection directory + Set-Location tests\ssl\custom-ca-certs\collection + + Write-Host "custom valid ca cert" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit1.xml --cacert ..\server\certs\ca-cert.pem --ignore-truststore --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml1 = Get-Content junit1.xml + $testsuites1 = if ($xml1.testsuites) { $xml1.testsuites.testsuite } else { $xml1.testsuite } + $errorCount1 = ($testsuites1 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount1 -ne 1) { exit 1 } + + Write-Host "custom valid ca cert with defaults" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit2.xml --cacert ..\server\certs\ca-cert.pem --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml2 = Get-Content junit2.xml + $testsuites2 = if ($xml2.testsuites) { $xml2.testsuites.testsuite } else { $xml2.testsuite } + $errorCount2 = ($testsuites2 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount2 -ne 1) { exit 1 } + + Write-Host "custom invalid ca cert" + Write-Host "request will error" + # should fail + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit3.xml --cacert ..\server\certs\ca-key.pem --ignore-truststore --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + # Ignore the exit code - we expect this to fail + [xml]$xml3 = Get-Content junit3.xml + $testsuites3 = if ($xml3.testsuites) { $xml3.testsuites.testsuite } else { $xml3.testsuite } + $errorCount3 = ($testsuites3 | Where-Object { $_.errors -eq "1" } | Measure-Object).Count + if ($errorCount3 -ne 1) { exit 1 } + + Write-Host "custom invalid ca cert with defaults" + # should pass + $process = Start-Process -FilePath "node" -ArgumentList "..\..\..\..\packages\bruno-cli\bin\bru.js run .\request.bru --output junit4.xml --cacert ..\server\certs\ca-key.pem --format junit" -NoNewWindow -Wait -PassThru -RedirectStandardError "nul" + [xml]$xml4 = Get-Content junit4.xml + $testsuites4 = if ($xml4.testsuites) { $xml4.testsuites.testsuite } else { $xml4.testsuite } + $errorCount4 = ($testsuites4 | Where-Object { $_.errors -eq "0" } | Measure-Object).Count + if ($errorCount4 -ne 1) { exit 1 } diff --git a/.github/actions/ssl/windows/run-ssl-e2e-tests/action.yml b/.github/actions/ssl/windows/run-ssl-e2e-tests/action.yml new file mode 100644 index 000000000..41140d80d --- /dev/null +++ b/.github/actions/ssl/windows/run-ssl-e2e-tests/action.yml @@ -0,0 +1,17 @@ +name: 'Run SSL E2E Tests - Windows' +description: 'Run SSL E2E tests on Windows' +runs: + using: 'composite' + steps: + - name: Run E2E tests + shell: pwsh + run: | + npm run test:e2e:ssl + + - name: Upload Playwright Report + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: playwright-report-windows + path: playwright-report/ + retention-days: 30 diff --git a/.github/actions/ssl/windows/setup-ca-certs/action.yml b/.github/actions/ssl/windows/setup-ca-certs/action.yml new file mode 100644 index 000000000..182a91896 --- /dev/null +++ b/.github/actions/ssl/windows/setup-ca-certs/action.yml @@ -0,0 +1,25 @@ +name: 'Setup CA Certificates - Windows' +description: 'Setup CA certificates and start test server for custom CA certs tests on Windows' +runs: + using: 'composite' + steps: + - name: Setup CA certificates + shell: pwsh + run: | + Set-StrictMode -Version Latest + $ErrorActionPreference = "Stop" + + Set-Location tests\ssl\custom-ca-certs\server + + Write-Host "running certificate setup" + node scripts/generate-certs.js + + - name: Start test server + shell: pwsh + run: | + Set-StrictMode -Version Latest + + Set-Location tests\ssl\custom-ca-certs\server + + Write-Host "starting server in background" + Start-Process -FilePath "node" -ArgumentList "index.js" -PassThru -WindowStyle Hidden diff --git a/.github/workflows/npm-bru-cli.yml b/.github/workflows/npm-bru-cli.yml index b489f1e43..a15260b7e 100644 --- a/.github/workflows/npm-bru-cli.yml +++ b/.github/workflows/npm-bru-cli.yml @@ -26,7 +26,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version-file: '.nvmrc' diff --git a/.github/workflows/ssl-tests.yml b/.github/workflows/ssl-tests.yml new file mode 100644 index 000000000..467a62ce9 --- /dev/null +++ b/.github/workflows/ssl-tests.yml @@ -0,0 +1,91 @@ +name: SSL Tests +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + tests-for-linux: + name: SSL Tests - Linux + timeout-minutes: 60 + runs-on: ubuntu-latest + permissions: + checks: write + pull-requests: write + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node Dependencies + uses: ./.github/actions/common/setup-node-deps + + - name: Setup Feature Dependencies + uses: ./.github/actions/ssl/linux/setup-feature-specific-deps + + - name: Setup CA Certificates + uses: ./.github/actions/ssl/linux/setup-ca-certs + + - name: Run Basic SSL CLI Tests + uses: ./.github/actions/ssl/linux/run-basic-ssl-cli-tests + + - name: Run Custom CA Certs CLI Tests + uses: ./.github/actions/ssl/linux/run-custom-ca-certs-cli-tests + + - name: Run Custom CA Certs E2E Tests + uses: ./.github/actions/ssl/linux/run-ssl-e2e-tests + + tests-for-macos: + name: SSL Tests - macOS + timeout-minutes: 60 + runs-on: macos-latest + permissions: + checks: write + pull-requests: write + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node Dependencies + uses: ./.github/actions/common/setup-node-deps + + - name: Setup Feature Dependencies + uses: ./.github/actions/ssl/macos/setup-feature-specific-deps + + - name: Setup CA Certificates + uses: ./.github/actions/ssl/macos/setup-ca-certs + + - name: Run Basic SSL CLI Tests + uses: ./.github/actions/ssl/macos/run-basic-ssl-cli-tests + + - name: Run Custom CA Certs CLI Tests + uses: ./.github/actions/ssl/macos/run-custom-ca-certs-cli-tests + + - name: Run Custom CA Certs E2E Tests + uses: ./.github/actions/ssl/macos/run-ssl-e2e-tests + + tests-for-windows: + name: SSL Tests - Windows + timeout-minutes: 60 + runs-on: windows-latest + permissions: + checks: write + pull-requests: write + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node Dependencies + uses: ./.github/actions/common/setup-node-deps + + - name: Setup CA Certificates + uses: ./.github/actions/ssl/windows/setup-ca-certs + + - name: Run Basic SSL CLI Tests + uses: ./.github/actions/ssl/windows/run-basic-ssl-cli-tests + + - name: Run Custom CA Certs CLI Tests + uses: ./.github/actions/ssl/windows/run-custom-ca-certs-cli-tests + + - name: Run Custom CA Certs E2E Tests + uses: ./.github/actions/ssl/windows/run-ssl-e2e-tests diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4bf2d753c..9ce5f5162 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: contents: read steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version-file: '.nvmrc' cache: 'npm' @@ -65,7 +65,7 @@ jobs: contents: read steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version-file: '.nvmrc' cache: 'npm' @@ -107,7 +107,7 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: v22.11.x - name: Install dependencies diff --git a/docs/playwright-testing-guide.md b/docs/playwright-testing-guide.md new file mode 100644 index 000000000..c0de8ad3d --- /dev/null +++ b/docs/playwright-testing-guide.md @@ -0,0 +1,470 @@ +# Playwright Testing Guide for Bruno + +This guide explains how to create and run Playwright test cases for the Bruno application using the UI. + +## Table of Contents + +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [Creating Tests Using Codegen](#creating-tests-using-codegen) +- [Manual Test Creation](#manual-test-creation) +- [Test Structure and Organization](#test-structure-and-organization) +- [Available Test Fixtures](#available-test-fixtures) +- [Running Tests](#running-tests) +- [Best Practices](#best-practices) +- [Examples](#examples) +- [Troubleshooting](#troubleshooting) + +## Overview + +Bruno uses Playwright for end-to-end testing of its Electron application. The testing setup includes custom fixtures for Electron app testing and utilities for managing test data. + +## Prerequisites + +- Node.js installed +- All dependencies installed (`npm install`) +- Electron app can be built and run + +## Creating Tests Using Codegen + +The easiest way to create tests is using Playwright's codegen feature, which records your UI interactions and generates test code. + +### Using the Built-in Codegen Script + +```bash +# Generate a test with a specific name +npm run test:codegen my-new-test + +# Generate a test without specifying a name (will prompt for input) +npm run test:codegen +``` + +### What Happens During Codegen + +1. The Electron app launches automatically +2. Playwright Inspector opens in a separate window +3. You interact with the Bruno UI +4. Actions are recorded and converted to test code +5. The generated test file is saved in `e2e-tests/` + +### Codegen Workflow + +1. **Start Recording**: Run the codegen command +2. **Interact with UI**: Perform the actions you want to test +3. **Add Assertions**: Use the inspector to add assertions +4. **Save Test**: The test file is automatically generated +5. **Review and Refine**: Edit the generated test as needed + +## Manual Test Creation + +You can also create tests manually by following the established patterns. + +### Basic Test Structure + +```typescript +import { test, expect } from '../../playwright'; + +test('Test description', async ({ page }) => { + // Test steps here + await page.getByLabel('Some Label').click(); + + // Assertions + await expect(page.getByText('Expected Text')).toBeVisible(); +}); +``` + +### Test with Temporary Data + +```typescript +import { test, expect } from '../../playwright'; + +test('Test with temporary data', async ({ page, createTmpDir }) => { + // Create temporary directory for test data + const testDir = await createTmpDir('test-collection'); + + // Test steps + await page.getByLabel('Create Collection').click(); + await page.getByLabel('Name').fill('test-collection'); + await page.getByLabel('Location').fill(testDir); + + // Assertions + await expect(page.getByText('test-collection')).toBeVisible(); +}); +``` + +## Test Structure and Organization + +### Directory Structure + +``` +e2e-tests/ +├── 001-sanity-tests/ # Basic functionality tests +│ ├── 001-home-screen.spec.ts +│ └── 002-create-new-collection-and-new-request.spec.ts +├── 002-feature-tests/ # Specific feature tests +├── 003-integration-tests/ # Complex workflow tests +└── bruno-testbench/ # Test utilities and helpers +``` + +### Naming Conventions + +- **Files**: Use descriptive names with `.spec.ts` extension +- **Tests**: Use clear, descriptive test names +- **Folders**: Use numbered prefixes for ordering + +### Test File Template + +```typescript +import { test, expect } from '../../playwright'; + +test.describe('Feature Name', () => { + test('should perform specific action', async ({ page }) => { + // Arrange + // Act + // Assert + }); + + test('should handle error case', async ({ page }) => { + // Test error scenarios + }); +}); +``` + +## Available Test Fixtures + +The Bruno Playwright setup provides several custom fixtures: + +### Core Fixtures + +- `page`: Main page for testing +- `context`: Browser context +- `electronApp`: Electron application instance + +### Utility Fixtures + +- `createTmpDir`: Creates temporary directories for test data +- `newPage`: Creates a new page instance +- `pageWithUserData`: Page with custom user data +- `launchElectronApp`: Launches a new Electron app instance +- `reuseOrLaunchElectronApp`: Reuses existing app or launches new one + +### Using Fixtures + +```typescript +test('Test with multiple fixtures', async ({ page, createTmpDir, electronApp }) => { + const testDir = await createTmpDir('test-data'); + + // Your test logic here +}); +``` + +## Running Tests + +### Basic Commands + +```bash +# Run all tests +npm run test:e2e + +# Run specific test file +npx playwright test e2e-tests/001-sanity-tests/001-home-screen.spec.ts + +# Run tests in a specific folder +npx playwright test e2e-tests/001-sanity-tests/ +``` + +### Advanced Options + +```bash +# Run with UI mode (for debugging) +npx playwright test --ui + +# Run in headed mode (see browser) +npx playwright test --headed + +# Run with specific browser +npx playwright test --project="Bruno Electron App" + +# Run with debugging +npx playwright test --debug + +# Run with trace recording +npx playwright test --trace on +``` + +### CI/CD Integration + +```bash +# Install browsers for CI +npx playwright install + +# Run tests in CI mode +npm run test:e2e +``` + +## Best Practices + +### 1. Use Semantic Selectors + +**Preferred:** + +```typescript +await page.getByRole('button', { name: 'Create' }).click(); +await page.getByLabel('Collection Name').fill('test'); +await page.getByText('Success message').toBeVisible(); +``` + +**Avoid:** + +```typescript +await page.locator('.btn-primary').click(); +await page.locator('#collection-name').fill('test'); +``` + +### 2. Create Isolated Tests + +Each test should be independent and not rely on other tests: + +```typescript +test('should create collection', async ({ page, createTmpDir }) => { + const testDir = await createTmpDir('collection-test'); + + // Test creates its own data + await page.getByLabel('Create Collection').click(); + await page.getByLabel('Name').fill('test-collection'); + await page.getByLabel('Location').fill(testDir); + + // Clean up happens automatically via createTmpDir +}); +``` + +### 3. Add Meaningful Assertions + +Always verify the expected outcomes: + +```typescript +test('should save request successfully', async ({ page }) => { + // Arrange + await page.getByLabel('Create Collection').click(); + + // Act + await page.getByRole('button', { name: 'Save' }).click(); + + // Assert + await expect(page.getByText('Request saved successfully')).toBeVisible(); + await expect(page.getByRole('tab', { name: 'GET request' })).toBeVisible(); +}); +``` + +### 4. Handle Async Operations + +```typescript +test('should wait for network requests', async ({ page }) => { + // Wait for specific network request + await page.waitForResponse((response) => response.url().includes('/api/endpoint')); + + // Or wait for element to be stable + await page.waitForSelector('[data-testid="loading"]', { state: 'hidden' }); +}); +``` + +### 5. Use Test Data Management + +```typescript +test('should work with test data', async ({ page, createTmpDir }) => { + const testDir = await createTmpDir('test-data'); + + // Create test files + await fs.writeFile(path.join(testDir, 'test.bru'), testContent); + + // Use in test + await page.getByLabel('Open Collection').click(); + await page.getByText(testDir).click(); +}); +``` + +## Examples + +### Example 1: Basic Collection Creation + +```typescript +import { test, expect } from '../../playwright'; + +test('should create a new collection', async ({ page, createTmpDir }) => { + const testDir = await createTmpDir('new-collection'); + + await page.getByLabel('Create Collection').click(); + await page.getByLabel('Name').fill('My Test Collection'); + await page.getByLabel('Location').fill(testDir); + await page.getByRole('button', { name: 'Create' }).click(); + + await expect(page.getByText('My Test Collection')).toBeVisible(); +}); +``` + +### Example 2: Request Creation and Execution + +```typescript +import { test, expect } from '../../playwright'; + +test('should create and execute HTTP request', async ({ page, createTmpDir }) => { + const testDir = await createTmpDir('request-test'); + + // Create collection + await page.getByLabel('Create Collection').click(); + await page.getByLabel('Name').fill('Request Test'); + await page.getByLabel('Location').fill(testDir); + await page.getByRole('button', { name: 'Create' }).click(); + + // Create request + await page.locator('#create-new-tab').getByRole('img').click(); + await page.getByPlaceholder('Request Name').fill('Test Request'); + await page.locator('#new-request-url .CodeMirror').click(); + await page.locator('textarea').fill('http://localhost:8081/ping'); + await page.getByRole('button', { name: 'Create' }).click(); + + // Execute request + await page.locator('#send-request').getByRole('img').nth(2).click(); + + // Verify response + await expect(page.getByRole('main')).toContainText('200 OK'); +}); +``` + +### Example 3: Environment Management + +```typescript +import { test, expect } from '../../playwright'; + +test('should create and use environment variables', async ({ page, createTmpDir }) => { + const testDir = await createTmpDir('env-test'); + + // Setup collection + await page.getByLabel('Create Collection').click(); + await page.getByLabel('Name').fill('Environment Test'); + await page.getByLabel('Location').fill(testDir); + await page.getByRole('button', { name: 'Create' }).click(); + + // Create environment + await page.getByRole('button', { name: 'Environments' }).click(); + await page.getByRole('button', { name: 'Add Environment' }).click(); + await page.getByLabel('Environment Name').fill('Development'); + await page.getByRole('button', { name: 'Create' }).click(); + + // Add variable + await page.getByRole('button', { name: 'Add Variable' }).click(); + await page.getByLabel('Variable Name').fill('API_URL'); + await page.getByLabel('Variable Value').fill('http://localhost:3000'); + await page.getByRole('button', { name: 'Save' }).click(); + + await expect(page.getByText('API_URL')).toBeVisible(); +}); +``` + +## Troubleshooting + +### Common Issues + +1. **Electron App Not Starting** + + ```bash + # Ensure dependencies are installed + npm install + + # Try running the app manually first + npm run dev:electron + ``` + +2. **Tests Timing Out** + + ```typescript + // Increase timeout for specific test + test('slow test', async ({ page }) => { + test.setTimeout(60000); // 60 seconds + // Test steps + }); + ``` + +3. **Element Not Found** + + ```typescript + // Wait for element to be present + await page.waitForSelector('[data-testid="element"]'); + + // Or use more specific selectors + await page.getByRole('button', { name: 'Exact Button Text' }).click(); + ``` + +4. **Flaky Tests** + + ```typescript + // Use stable selectors + await page.getByTestId('stable-id').click(); + + // Wait for state changes + await page.waitForLoadState('networkidle'); + ``` + +### Debug Mode + +```bash +# Run with debug mode +npx playwright test --debug + +# Run specific test in debug mode +npx playwright test --debug e2e-tests/001-sanity-tests/001-home-screen.spec.ts +``` + +### Trace Analysis + +```bash +# Run with trace recording +npx playwright test --trace on + +# View trace in browser +npx playwright show-trace test-results/trace-*.zip +``` + +## Configuration + +The Playwright configuration is in `playwright.config.ts`: + +```typescript +export default defineConfig({ + testDir: './e2e-tests', + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 1 : 0, + workers: process.env.CI ? undefined : 1, + + projects: [ + { + name: 'Bruno Electron App' + } + ], + + webServer: [ + { + command: 'npm run dev:web', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI + }, + { + command: 'npm start --workspace=packages/bruno-tests', + url: 'http://localhost:8081/ping', + reuseExistingServer: !process.env.CI + } + ] +}); +``` + +## Additional Resources + +- [Playwright Documentation](https://playwright.dev/) +- [Playwright Test API](https://playwright.dev/docs/api/class-test) +- [Electron Testing with Playwright](https://playwright.dev/docs/api/class-electronapplication) +- [Bruno Project Structure](../readme.md) + +--- + +For questions or issues with testing, please refer to the project's contributing guidelines or create an issue in the repository. diff --git a/e2e-tests/persistent-env-tests/001-persistent-env-test.spec.ts b/e2e-tests/persistent-env-tests/001-persistent-env-test.spec.ts deleted file mode 100644 index e319e178f..000000000 --- a/e2e-tests/persistent-env-tests/001-persistent-env-test.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { test, expect } from '../../playwright'; - -test.describe.serial('Persistent Environment Test', () => { - test.setTimeout(2 * 10 * 1000); - - test('add env using script', async ({ pageWithUserData: page, restartApp }) => { - await page.locator('#sidebar-collection-name').click(); - await page.getByRole('button', { name: 'Save' }).click(); - await page.getByText('ping', { exact: true }).click(); - await page.getByText('No Environment').click(); - await page.getByRole('tooltip').locator('div').filter({ hasText: 'Env' }).nth(3).click(); - await page.locator('#send-request').getByRole('img').nth(2).click(); - await page.waitForTimeout(1000); - await page.locator('div').filter({ hasText: /^Env$/ }).nth(3).click(); - await page.getByText('Configure', { exact: true }).click(); - await expect(page.getByRole('row', { name: 'persistent-env-test' }).getByRole('cell').nth(3)).toBeVisible(); - await page.getByText('×').click(); - - const newApp = await restartApp(); - const newPage = await newApp.firstWindow(); - await newPage.locator('#sidebar-collection-name').click(); - await newPage.getByRole('button', { name: 'Save' }).click(); - await newPage.getByText('ping', { exact: true }).click(); - await newPage.getByText('No Environment').click(); - await newPage.getByRole('tooltip').locator('div').filter({ hasText: 'Env' }).nth(3).click(); - await newPage.locator('div').filter({ hasText: /^Env$/ }).nth(3).click(); - await newPage.getByText('Configure', { exact: true }).click(); - await expect(newPage.getByRole('row', { name: 'persistent-env-test' }).getByRole('cell').nth(3)).toBeVisible(); - await newPage.getByText('×').click(); - await newPage.waitForTimeout(1000); - await newPage.close(); - }); -}); diff --git a/e2e-tests/persistent-env-tests/002-env-test-without-persistence.spec.ts b/e2e-tests/persistent-env-tests/002-env-test-without-persistence.spec.ts deleted file mode 100644 index 4be151bb0..000000000 --- a/e2e-tests/persistent-env-tests/002-env-test-without-persistence.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { test, expect } from '../../playwright'; - -test.describe.serial('Persistent Environment Test', () => { - test.setTimeout(2 * 10 * 1000); - - test('add env using script', async ({ pageWithUserData: page, restartApp }) => { - await page.locator('#sidebar-collection-name').click(); - await page.getByText('ping2', { exact: true }).click(); - await page.getByText('Env', { exact: true }).click(); - await page.getByText('Stage', { exact: true }).click(); - await page.locator('#send-request').getByRole('img').nth(2).click(); - await page.waitForTimeout(1000); - await page - .locator('div') - .filter({ hasText: /^Stage$/ }) - .nth(3) - .click(); - await page.getByText('Configure', { exact: true }).click(); - await expect(page.getByRole('row', { name: 'persistent-env-test' }).getByRole('cell').nth(3)).toBeVisible(); - await page.getByText('×').click(); - - const newApp = await restartApp(); - const newPage = await newApp.firstWindow(); - await newPage.locator('#sidebar-collection-name').click(); - await newPage.getByRole('button', { name: 'Save' }).click(); - await newPage.getByText('ping2', { exact: true }).click(); - await newPage.getByText('No Environment').click(); - await newPage.getByText('Stage').click(); - await newPage - .locator('div') - .filter({ hasText: /^Stage$/ }) - .nth(3) - .click(); - await newPage.getByText('Configure', { exact: true }).click(); - await expect(newPage.getByRole('row', { name: 'persistent-env-test' }).getByRole('cell').nth(3)).not.toBeVisible(); - await newPage.getByText('×').click(); - await newPage.waitForTimeout(1000); - await newPage.close(); - }); -}); diff --git a/e2e-tests/persistent-env-tests/collection/collection.bru b/e2e-tests/persistent-env-tests/collection/collection.bru deleted file mode 100644 index e69de29bb..000000000 diff --git a/e2e-tests/persistent-env-tests/collection/environments/Env.bru b/e2e-tests/persistent-env-tests/collection/environments/Env.bru deleted file mode 100644 index 909243fd2..000000000 --- a/e2e-tests/persistent-env-tests/collection/environments/Env.bru +++ /dev/null @@ -1,4 +0,0 @@ -vars { - host: https://testbench-sanity.usebruno.com - persistent-env-test: persistent-env-test-value -} diff --git a/e2e-tests/persistent-env-tests/init-user-data/preferences.json b/e2e-tests/persistent-env-tests/init-user-data/preferences.json deleted file mode 100644 index f9c1fdc7e..000000000 --- a/e2e-tests/persistent-env-tests/init-user-data/preferences.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "maximized": true, - "lastOpenedCollections": [ - "{{projectRoot}}/e2e-tests/persistent-env-tests/collection" - ] -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 55f483f47..f6c9ab83f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1605,7 +1605,7 @@ "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -1623,7 +1623,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -1640,7 +1640,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1658,7 +1658,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@babel/helper-member-expression-to-functions": { @@ -1729,7 +1729,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -1804,7 +1804,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", @@ -1847,7 +1847,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -1864,7 +1864,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1880,7 +1880,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -1896,7 +1896,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -1914,7 +1914,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -1949,7 +1949,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2048,7 +2048,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2064,7 +2064,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2246,7 +2246,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -2263,7 +2263,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2279,7 +2279,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -2297,7 +2297,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", @@ -2315,7 +2315,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2331,7 +2331,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2363,7 +2363,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", @@ -2380,7 +2380,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -2401,7 +2401,7 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -2411,7 +2411,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -2428,7 +2428,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2444,7 +2444,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -2461,7 +2461,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2477,7 +2477,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -2494,7 +2494,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2510,7 +2510,7 @@ "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2526,7 +2526,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2558,7 +2558,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -2575,7 +2575,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", @@ -2593,7 +2593,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2609,7 +2609,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2625,7 +2625,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2641,7 +2641,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2657,7 +2657,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.9", @@ -2690,7 +2690,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.9", @@ -2709,7 +2709,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.25.9", @@ -2726,7 +2726,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -2743,7 +2743,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2774,7 +2774,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2790,7 +2790,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", @@ -2808,7 +2808,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -2825,7 +2825,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2857,7 +2857,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2889,7 +2889,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -2907,7 +2907,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -2992,7 +2992,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -3009,7 +3009,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -3026,7 +3026,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3042,7 +3042,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3058,7 +3058,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", @@ -3075,7 +3075,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3091,7 +3091,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3107,7 +3107,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3142,7 +3142,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" @@ -3158,7 +3158,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -3175,7 +3175,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -3192,7 +3192,7 @@ "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", @@ -3209,7 +3209,7 @@ "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.26.0", @@ -3310,7 +3310,7 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -7904,8 +7904,8 @@ "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -7924,8 +7924,8 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -7937,8 +7937,8 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -7952,8 +7952,8 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "license": "MIT", - "peer": true + "dev": true, + "license": "MIT" }, "node_modules/@testing-library/jest-dom": { "version": "6.6.3", @@ -8033,6 +8033,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, "license": "MIT" }, "node_modules/@types/babel__core": { @@ -8287,6 +8288,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, "license": "MIT" }, "node_modules/@types/lodash": { @@ -8318,6 +8320,7 @@ "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/linkify-it": "*", @@ -8328,6 +8331,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, "license": "MIT" }, "node_modules/@types/ms": { @@ -9381,6 +9385,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "license": "Apache-2.0", "dependencies": { "dequal": "^2.0.3" @@ -9748,7 +9753,7 @@ "version": "0.4.12", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", @@ -9763,7 +9768,7 @@ "version": "0.10.6", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -9777,7 +9782,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3" @@ -9937,6 +9942,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -11527,7 +11542,7 @@ "version": "3.39.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.24.2" @@ -12577,6 +12592,7 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, "license": "MIT" }, "node_modules/dom-converter": { @@ -13568,7 +13584,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -14283,6 +14299,13 @@ "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", "license": "MIT" }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT", + "optional": true + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -16148,7 +16171,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -18399,7 +18422,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/lodash.flow": { @@ -18537,11 +18560,34 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "license": "MIT", "bin": { "lz-string": "bin/bin.js" } }, + "node_modules/macos-export-certificate-and-key": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/macos-export-certificate-and-key/-/macos-export-certificate-and-key-1.2.4.tgz", + "integrity": "sha512-y5QZEywlBNKd+EhPZ1Hz1FmDbbeQKtuVHJaTlawdl7vXw9bi/4tJB2xSMwX4sMVcddy3gbQ8K0IqXAi2TpDo2g==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^4.3.0" + } + }, + "node_modules/macos-export-certificate-and-key/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "license": "MIT", + "optional": true + }, "node_modules/magic-string": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", @@ -19965,7 +20011,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -22305,14 +22351,14 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -22331,7 +22377,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.4" @@ -22341,7 +22387,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", @@ -22359,14 +22405,14 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -22379,7 +22425,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -22535,7 +22581,7 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -24747,7 +24793,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -24827,6 +24873,16 @@ "jscat": "bundle.js" } }, + "node_modules/system-ca": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/system-ca/-/system-ca-2.0.1.tgz", + "integrity": "sha512-9ZDV9yl8ph6Op67wDGPr4LykX86usE9x3le+XZSHfVMiiVJ5IRgmCWjLgxyz35ju9H3GDIJJZm4ogAeIfN5cQQ==", + "license": "Apache-2.0", + "optionalDependencies": { + "macos-export-certificate-and-key": "^1.2.0", + "win-export-certificate-and-key": "^2.1.0" + } + }, "node_modules/tailwindcss": { "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", @@ -25614,7 +25670,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -25675,7 +25731,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -25685,7 +25741,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", @@ -25699,7 +25755,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -25709,7 +25765,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -26303,6 +26359,28 @@ "dev": true, "license": "MIT" }, + "node_modules/win-export-certificate-and-key": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/win-export-certificate-and-key/-/win-export-certificate-and-key-2.1.0.tgz", + "integrity": "sha512-WeMLa/2uNZcS/HWGKU2G1Gzeh3vHpV/UFvwLhJLKxPHYFAbubxxVcJbqmPXaqySWK1Ymymh16zKK5WYIJ3zgzA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^3.1.0" + } + }, + "node_modules/win-export-certificate-and-key/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "license": "MIT", + "optional": true + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -26676,7 +26754,7 @@ "@rsbuild/plugin-react": "^1.0.7", "@rsbuild/plugin-sass": "^1.1.0", "@rsbuild/plugin-styled-components": "1.1.0", - "@testing-library/dom": "^10.4.0", + "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "autoprefixer": "10.4.20", @@ -28006,26 +28084,6 @@ "semver": "bin/semver.js" } }, - "packages/bruno-app/node_modules/@testing-library/dom": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, "packages/bruno-app/node_modules/@testing-library/react": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", @@ -28122,23 +28180,6 @@ ], "license": "CC-BY-4.0" }, - "packages/bruno-app/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" - } - }, "packages/bruno-app/node_modules/cookie": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", @@ -28240,41 +28281,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "packages/bruno-app/node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "packages/bruno-app/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "packages/bruno-app/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "license": "MIT" - }, "packages/bruno-app/node_modules/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", @@ -31923,8 +31929,9 @@ "axios": "^1.9.0", "grpc-reflection-js": "^0.3.0", "is-ip": "^5.0.1", - "tough-cookie": "^6.0.0", - "ws": "^8.18.3" + "ws": "^8.18.3", + "system-ca": "^2.0.1", + "tough-cookie": "^6.0.0" }, "devDependencies": { "@babel/preset-env": "^7.22.0", diff --git a/package.json b/package.json index fe8dafdc9..695f0d3f5 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,8 @@ "build:electron:snap": "./scripts/build-electron.sh snap", "watch:common": "npm run watch --workspace=packages/bruno-common", "test:codegen": "node playwright/codegen.ts", - "test:e2e": "playwright test", + "test:e2e": "playwright test --project=default", + "test:e2e:ssl": "playwright test --project=ssl", "test:prettier:web": "npm run test:prettier --workspace=packages/bruno-app", "lint": "node --max_old_space_size=4096 $(npx which eslint)" }, diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index 6b5f8f798..25502d6b9 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -93,7 +93,7 @@ "@rsbuild/plugin-react": "^1.0.7", "@rsbuild/plugin-sass": "^1.1.0", "@rsbuild/plugin-styled-components": "1.1.0", - "@testing-library/dom": "^10.4.0", + "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "autoprefixer": "10.4.20", diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js index 848048c13..52053179f 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSelector/index.js @@ -18,8 +18,8 @@ const EnvironmentSelector = ({ collection }) => { const Icon = forwardRef((props, ref) => { return ( -
-

{activeEnvironment ? activeEnvironment.name : 'No Environment'}

+
+

{activeEnvironment ? activeEnvironment.name : 'No Environment'}

); @@ -82,7 +82,7 @@ const EnvironmentSelector = ({ collection }) => { handleSettingsIconClick(); dropdownTippyRef.current.hide(); }}> -
+
Configure diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 5ba3b0797..1050d68b6 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -5,7 +5,7 @@ import { IconTrash, IconAlertCircle, IconDeviceFloppy, IconRefresh, IconCircleCh import { useTheme } from 'providers/Theme'; import { useDispatch, useSelector } from 'react-redux'; import { selectEnvironment } from 'providers/ReduxStore/slices/collections/actions'; -import SingleLineEditor from 'components/SingleLineEditor'; +import MultiLineEditor from 'components/MultiLineEditor'; import StyledWrapper from './StyledWrapper'; import { uuid } from 'utils/common'; import { useFormik } from 'formik'; @@ -173,7 +173,7 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original return (
- +
@@ -214,7 +214,7 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
Enabled
- + Add Variable diff --git a/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSelector/index.js b/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSelector/index.js index b0042bcbf..77094e0d4 100644 --- a/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSelector/index.js +++ b/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSelector/index.js @@ -19,7 +19,7 @@ const EnvironmentSelector = () => { const Icon = forwardRef((props, ref) => { return ( -
+
{ diff --git a/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 10ab9fba3..f539543dd 100644 --- a/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/GlobalEnvironments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -3,7 +3,7 @@ import cloneDeep from 'lodash/cloneDeep'; import { IconTrash, IconAlertCircle } from '@tabler/icons'; import { useTheme } from 'providers/Theme'; import { useDispatch } from 'react-redux'; -import SingleLineEditor from 'components/SingleLineEditor'; +import MultiLineEditor from 'components/MultiLineEditor'; import StyledWrapper from './StyledWrapper'; import { uuid } from 'utils/common'; import { useFormik } from 'formik'; @@ -147,7 +147,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
- { .catch((err) => console.log(err) && toast.error('Failed to update beta preferences')); }; - const hasAnyBetaFeatures = Object.values(formik.values).length > 0; + const hasAnyBetaFeatures = BETA_FEATURES.length > 0; return ( diff --git a/packages/bruno-app/src/components/Preferences/General/index.js b/packages/bruno-app/src/components/Preferences/General/index.js index 554dd0d72..0f72e6b07 100644 --- a/packages/bruno-app/src/components/Preferences/General/index.js +++ b/packages/bruno-app/src/components/Preferences/General/index.js @@ -176,11 +176,11 @@ const General = ({ close }) => { name="keepDefaultCaCertificates.enabled" checked={formik.values.keepDefaultCaCertificates.enabled} onChange={formik.handleChange} - className={`mousetrap mr-0 ${formik.values.customCaCertificate.enabled ? '' : 'opacity-25'}`} - disabled={formik.values.customCaCertificate.enabled ? false : true} + className={`mousetrap mr-0 ${formik.values.customCaCertificate.enabled && formik.values.customCaCertificate.filePath ? '' : 'opacity-25'}`} + disabled={formik.values.customCaCertificate.enabled && formik.values.customCaCertificate.filePath ? false : true} />