From 920a5423bea3716f28d209ebd2d808a5b84724db Mon Sep 17 00:00:00 2001 From: Tian Feng Date: Mon, 23 Oct 2023 16:42:03 -0700 Subject: [PATCH] feat: setup OS proxy (#207) * feat: setup OS proxy * Update src/network-proxy.ts Co-authored-by: Alex Plischke * Update src/testcafe-runner.ts Co-authored-by: Alex Plischke * Update src/testcafe-runner.ts Co-authored-by: Alex Plischke * Update src/network-proxy.ts Co-authored-by: Alex Plischke * add comments to explain why we need the os proxy * add type for proxy * add e2e test for proxy * add comments for isCDPDisabled * update e2e tests for sauce-connect and proxy * revert npm ci changes * add comment and do checks more precisely * revert settings * cleanup pipeline * save pipeline * update comments and revert sc tests * only run sc for proxy check * Update src/testcafe-runner.ts Co-authored-by: Alex Plischke * revised --------- Co-authored-by: Alex Plischke --- .github/workflows/release.yml | 14 +- .github/workflows/test.yml | 67 +++++++- package-lock.json | 239 +++++++++++++++------------- package.json | 2 + scripts/bundle.sh | 2 + scripts/win-refresh-wininet.ps1 | 16 ++ src/network-proxy.ts | 88 ++++++++++ src/testcafe-runner.ts | 34 +++- src/type.ts | 5 + tests/cloud/.sauce/config-proxy.yml | 32 ++++ 10 files changed, 373 insertions(+), 126 deletions(-) create mode 100644 scripts/win-refresh-wininet.ps1 create mode 100644 src/network-proxy.ts create mode 100644 tests/cloud/.sauce/config-proxy.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87f0aa8..1f3165a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: ${{ steps.prep.outputs.tag_name == '' }} with: ref: ${{ github.ref }} @@ -121,7 +121,7 @@ jobs: - run: Write-Output "${{ steps.prep.outputs.release_id }} - ${{ steps.prep.outputs.version }} - ${{ steps.prep.outputs.asset_id }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: ${{ steps.prep.outputs.asset_id == '' }} with: ref: ${{ steps.prep.outputs.version }} @@ -195,7 +195,7 @@ jobs: - run: echo "${{ steps.prep.outputs.release_id }} - ${{ steps.prep.outputs.version }} - ${{ steps.prep.outputs.asset_id }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: ${{ steps.prep.outputs.asset_id == '' }} with: ref: ${{ steps.prep.outputs.version }} @@ -275,10 +275,10 @@ jobs: SAUCE_USERNAME: ${{secrets.SAUCE_USERNAME}} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup saucectl - uses: saucelabs/saucectl-run-action@v3 + uses: saucelabs/saucectl-run-action@v4 env: GITHUB_TOKEN: ${{ github.token }} with: @@ -308,10 +308,10 @@ jobs: SAUCE_USERNAME: ${{secrets.SAUCE_USERNAME}} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup saucectl - uses: saucelabs/saucectl-run-action@v3 + uses: saucelabs/saucectl-run-action@v4 env: GITHUB_TOKEN: ${{ github.token }} with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5ef0cc4..2744a2c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v3 @@ -50,7 +50,7 @@ jobs: needs: [test] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v3 @@ -108,7 +108,7 @@ jobs: needs: [test] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Node uses: actions/setup-node@v3 @@ -179,10 +179,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup saucectl - uses: saucelabs/saucectl-run-action@v3 + uses: saucelabs/saucectl-run-action@v4 env: GITHUB_TOKEN: ${{ github.token }} with: @@ -223,7 +223,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v4 @@ -231,7 +231,7 @@ jobs: python-version: '3.11' - name: Setup saucectl - uses: saucelabs/saucectl-run-action@v3 + uses: saucelabs/saucectl-run-action@v4 env: GITHUB_TOKEN: ${{ github.token }} with: @@ -248,7 +248,7 @@ jobs: username: ${{ secrets.SAUCE_USERNAME }} accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} tunnelName: github-testcafe-sc-check-tunnel-${{ matrix.os }}-${{ matrix.browser }} - scVersion: 4.8.1 + scVersion: 4.9.1 - name: Test on Sauce working-directory: ./tests/cloud/ @@ -263,3 +263,54 @@ jobs: --config ./.sauce/config-sc.yml \ --tunnel-name github-testcafe-sc-check-tunnel-${{ matrix.os }}-${{ matrix.browser }} \ --select-suite "${{ matrix.os }} - ${{ matrix.browser }}" + + bundle-test-proxy: + needs: [build-windows-bundle, build-mac-bundle] + strategy: + max-parallel: 3 + fail-fast: false + matrix: + os: [Win11, macOS13] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Setup saucectl + uses: saucelabs/saucectl-run-action@v4 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + skip-run: true + + - name: Run web-page + run: | + python -m http.server 8000 & + working-directory: ./tests/cloud/www/ + + - name: Start sauce-connect + uses: saucelabs/sauce-connect-action@v2 + with: + username: ${{ secrets.SAUCE_USERNAME }} + accessKey: ${{ secrets.SAUCE_ACCESS_KEY }} + tunnelName: github-testcafe-sc-check-tunnel-${{ matrix.os }} + scVersion: 4.9.1 + + - name: Test on Sauce + working-directory: ./tests/cloud/ + run: | + BUNDLE_URL=https://storage.googleapis.com/${{ secrets.GCS_RUNNER_BUCKET }}/testcafe-windows-amd64-${{ github.run_id }}.zip + if [[ ${{ matrix.os }} =~ ^mac ]];then + BUNDLE_URL=https://storage.googleapis.com/${{ secrets.GCS_RUNNER_BUCKET }}/testcafe-macos-amd64-${{ github.run_id }}.zip + fi + + saucectl run \ + --runner-version "url: ${BUNDLE_URL}" \ + --config ./.sauce/config-proxy.yml \ + --tunnel-name github-testcafe-sc-check-tunnel-${{ matrix.os }} \ + --select-suite "Proxy - ${{ matrix.os }}" diff --git a/package-lock.json b/package-lock.json index 2fda668..aab905a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,12 @@ "dependencies": { "@saucelabs/testcomposer": "^2.0.0", "@tsconfig/node20": "20.1.2", + "@types/shelljs": "^0.8.14", "dotenv": "16.3.1", "lodash": "^4.17.21", "mocha-junit-reporter": "^2.2.1", "sauce-testrunner-utils": "2.0.0", + "shelljs": "^0.8.5", "testcafe": "3.3.0", "testcafe-browser-provider-ios": "0.5.0", "testcafe-reporter-saucelabs": "3.1.0", @@ -2107,12 +2109,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.12.tgz", + "integrity": "sha512-NlGesA1usRNn6ctHCZ21M4/dKPgW9Nn1FypRdIKKgZOKzkVV4T1FlK5mBiLhHBCDmEbdQG0idrcXlbZfksJ+RA==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.0", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -2134,9 +2136,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.0.tgz", + "integrity": "sha512-9S9QrXY2K0L4AGDcSgTi9vgiCcG8VcBv4Mp7/1hDPYoswIy6Z6KO5blYto82BT8M0MZNRWmCFLpCs3HlpYGGdw==", "dev": true }, "node_modules/@iarna/toml": { @@ -2882,9 +2884,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3277,9 +3279,9 @@ "integrity": "sha512-madaWq2k+LYMEhmcp0fs+OGaLFk0OenpHa4gmI4VEmCKX4PJntQ6fnnGADVFrVkBj0wIdAlQnK/MrlYTHsa1gQ==" }, "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -3290,18 +3292,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -3309,18 +3311,18 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/chai": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.8.tgz", - "integrity": "sha512-yW/qTM4mRBBcsA9Xw9FbcImYtFPY7sgr+G/O5RDYVmxiy9a+pE5FyoFUi8JYCZY5nicj8atrr1pcfPiYpeNGOA==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", + "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==", "dev": true }, "node_modules/@types/estree": { @@ -3338,48 +3340,48 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", - "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz", - "integrity": "sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==", "dev": true }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.5", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", - "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3387,18 +3389,18 @@ } }, "node_modules/@types/jquery": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.22.tgz", - "integrity": "sha512-ISQFeUK5GwRftLK4PVvKTWEVCxZ2BpaqBz0TWkIq5w4vGojxZP9+XkqgcPjxoqmPeew+HLyWthCBvK7GdF5NYA==", + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.24.tgz", + "integrity": "sha512-V/TG69ge5amcr8Ap7vY3SObqKfZlV7ttqcYnNcYnndI77ySIRi05+3GjvfwRtE2qalAC2ySLIL1ker512sI20g==", "dev": true, "dependencies": { "@types/sizzle": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/json5": { @@ -3408,9 +3410,9 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.199", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", - "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==" + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==" }, "node_modules/@types/minimatch": { "version": "5.1.2", @@ -3418,50 +3420,59 @@ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" }, "node_modules/@types/mocha": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", - "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.3.tgz", + "integrity": "sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dependencies": { "undici-types": "~5.25.1" } }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, + "node_modules/@types/shelljs": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.14.tgz", + "integrity": "sha512-eqKaGPi60riuxI9pUVeCT02EGo94Y6HT119h7w5bXSELsis6+JqzdEy6H/w2xXl881wcN3VDnb/D0WlgSety5w==", + "dependencies": { + "@types/glob": "~7.2.0", + "@types/node": "*" + } + }, "node_modules/@types/sizzle": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.4.tgz", - "integrity": "sha512-jA2llq2zNkg8HrALI7DtWzhALcVH0l7i89yhY3iBdOz6cBPeACoFq+fkQrjHA39t1hnSFOboZ7A/AY5MMZSlag==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.5.tgz", + "integrity": "sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ==", "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.28", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", - "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -4804,9 +4815,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001549", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", - "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", + "version": "1.0.30001551", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", + "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", "funding": [ { "type": "opencollective", @@ -4943,6 +4954,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, "funding": [ { "type": "github", @@ -5926,9 +5938,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.555", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.555.tgz", - "integrity": "sha512-k1wGC7UXDTyCWcONkEMRG/w6Jvrxi+SVEU+IeqUKUKjv2lGJ1b+jf1mqrloyxVTG5WYYjNQ+F6+Cb1fGrLvNcA==" + "version": "1.4.559", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.559.tgz", + "integrity": "sha512-iS7KhLYCSJbdo3rUSkhDTVuFNCV34RKs2UaB9Ecr7VlqzjjWW//0nfsFF5dtDmyXlZQaDYYtID5fjtC/6lpRug==" }, "node_modules/elegant-spinner": { "version": "1.0.1", @@ -6318,6 +6330,12 @@ "node": ">=10.10.0" } }, + "node_modules/eslint-config-appium/node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/eslint-config-appium/node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -8246,6 +8264,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { "node": ">=0.8.19" } @@ -8284,6 +8303,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, "engines": { "node": ">=10" } @@ -8481,7 +8501,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -10798,7 +10817,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -11780,9 +11800,9 @@ } }, "node_modules/npm": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.2.0.tgz", - "integrity": "sha512-Auyq6d4cfg/SY4URjZE2aePLOPzK4lUD+qyMxY/7HbxAvCnOCKtMlyLPcbLSOq9lhEGBZN800S1o+UmfjA5dTg==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.2.1.tgz", + "integrity": "sha512-YVh8UDw5lR2bPS6rrS0aPG9ZXKDWeaeO/zMoZMp7g3Thrho9cqEnSrcvg4Pic2QhDAQptAynx5KgrPgCSRscqg==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -11859,7 +11879,7 @@ "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^7.2.0", - "@npmcli/config": "^8.0.0", + "@npmcli/config": "^8.0.1", "@npmcli/fs": "^3.1.0", "@npmcli/map-workspaces": "^3.0.4", "@npmcli/package-json": "^5.0.0", @@ -11870,7 +11890,7 @@ "archy": "~1.0.0", "cacache": "^18.0.0", "chalk": "^5.3.0", - "ci-info": "^3.8.0", + "ci-info": "^3.9.0", "cli-columns": "^4.0.0", "cli-table3": "^0.6.3", "columnify": "^1.6.0", @@ -11903,11 +11923,11 @@ "nopt": "^7.2.0", "normalize-package-data": "^6.0.0", "npm-audit-report": "^5.0.0", - "npm-install-checks": "^6.2.0", + "npm-install-checks": "^6.3.0", "npm-package-arg": "^11.0.1", "npm-pick-manifest": "^9.0.0", "npm-profile": "^9.0.0", - "npm-registry-fetch": "^16.0.0", + "npm-registry-fetch": "^16.1.0", "npm-user-validate": "^2.0.0", "npmlog": "^7.0.1", "p-map": "^4.0.0", @@ -12063,7 +12083,7 @@ } }, "node_modules/npm/node_modules/@npmcli/agent/node_modules/https-proxy-agent": { - "version": "7.0.1", + "version": "7.0.2", "inBundle": true, "license": "MIT", "dependencies": { @@ -12075,11 +12095,11 @@ } }, "node_modules/npm/node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { - "version": "8.0.1", + "version": "8.0.2", "inBundle": true, "license": "MIT", "dependencies": { - "agent-base": "^7.0.1", + "agent-base": "^7.0.2", "debug": "^4.3.4", "socks": "^2.7.1" }, @@ -12134,7 +12154,7 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "8.0.0", + "version": "8.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12471,7 +12491,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/are-we-there-yet": { - "version": "4.0.0", + "version": "4.0.1", "inBundle": true, "license": "ISC", "dependencies": { @@ -12507,7 +12527,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/bin-links": { - "version": "4.0.2", + "version": "4.0.3", "inBundle": true, "license": "ISC", "dependencies": { @@ -12609,7 +12629,7 @@ } }, "node_modules/npm/node_modules/ci-info": { - "version": "3.8.0", + "version": "3.9.0", "funding": [ { "type": "github", @@ -12676,7 +12696,7 @@ } }, "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.1", + "version": "6.0.2", "inBundle": true, "license": "ISC", "engines": { @@ -13145,7 +13165,7 @@ } }, "node_modules/npm/node_modules/is-core-module": { - "version": "2.12.1", + "version": "2.13.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -13727,7 +13747,7 @@ } }, "node_modules/npm/node_modules/node-gyp/node_modules/cacache/node_modules/minipass": { - "version": "7.0.3", + "version": "7.0.4", "inBundle": true, "license": "ISC", "engines": { @@ -13931,7 +13951,7 @@ } }, "node_modules/npm/node_modules/npm-install-checks": { - "version": "6.2.0", + "version": "6.3.0", "inBundle": true, "license": "BSD-2-Clause", "dependencies": { @@ -14001,7 +14021,7 @@ } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "16.0.0", + "version": "16.1.0", "inBundle": true, "license": "ISC", "dependencies": { @@ -14261,14 +14281,15 @@ } }, "node_modules/npm/node_modules/readable-stream": { - "version": "4.4.0", + "version": "4.4.2", "inBundle": true, "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -14493,7 +14514,7 @@ } }, "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.13", + "version": "3.0.16", "inBundle": true, "license": "CC0-1.0" }, @@ -15066,9 +15087,9 @@ } }, "node_modules/ora/node_modules/emoji-regex": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, "node_modules/ora/node_modules/is-unicode-supported": { @@ -15927,7 +15948,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, "dependencies": { "resolve": "^1.1.6" }, @@ -16692,7 +16712,6 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -17903,7 +17922,8 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/time-limit-promise": { "version": "1.0.4", @@ -18850,6 +18870,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" diff --git a/package.json b/package.json index 7d5cffc..34d5298 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,12 @@ "dependencies": { "@saucelabs/testcomposer": "^2.0.0", "@tsconfig/node20": "20.1.2", + "@types/shelljs": "^0.8.14", "dotenv": "16.3.1", "lodash": "^4.17.21", "mocha-junit-reporter": "^2.2.1", "sauce-testrunner-utils": "2.0.0", + "shelljs": "^0.8.5", "testcafe": "3.3.0", "testcafe-browser-provider-ios": "0.5.0", "testcafe-reporter-saucelabs": "3.1.0", diff --git a/scripts/bundle.sh b/scripts/bundle.sh index c553432..de2d53d 100644 --- a/scripts/bundle.sh +++ b/scripts/bundle.sh @@ -1,12 +1,14 @@ set -e rm -rf ./bundle/ mkdir ./bundle/ +mkdir -p ./bundle/scripts cp -r ./src/ ./bundle/src/ cp -r ./bin/ bundle/bin/ cp package.json bundle/package.json cp package-lock.json bundle/package-lock.json cp tsconfig.json bundle/tsconfig.json cp "$(which node)" bundle/ +cp ./scripts/win-refresh-wininet.ps1 bundle/scripts/win-refresh-wininet.ps1 pushd bundle/ npm cache clean --force diff --git a/scripts/win-refresh-wininet.ps1 b/scripts/win-refresh-wininet.ps1 new file mode 100644 index 0000000..c08e5e8 --- /dev/null +++ b/scripts/win-refresh-wininet.ps1 @@ -0,0 +1,16 @@ +# adapted from https://gist.github.com/mikeperri/36e656f28e42aa9cee18ce88361f6c16 +# refreshes wininet so it is aware of new registry changes + +$signature = @' +[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)] +public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); +'@ + +$INTERNET_OPTION_SETTINGS_CHANGED = 39 +$INTERNET_OPTION_REFRESH = 37 + +$type = Add-Type -MemberDefinition $signature -Name wininet -Namespace pinvoke -PassThru +$a = $type::InternetSetOption(0, $INTERNET_OPTION_SETTINGS_CHANGED, 0, 0) +$b = $type::InternetSetOption(0, $INTERNET_OPTION_REFRESH, 0, 0) + +$a -and $b diff --git a/src/network-proxy.ts b/src/network-proxy.ts new file mode 100644 index 0000000..93c62b5 --- /dev/null +++ b/src/network-proxy.ts @@ -0,0 +1,88 @@ +import * as shell from "shelljs"; +import path from 'path'; +import { proxy as ProxySettings } from './type'; + +const networkSetup = '/usr/sbin/networksetup'; + +export function isProxyAvailable() { + const proxy = process.env.HTTP_PROXY; + return proxy && Array.isArray(proxy.split(':')) && proxy.split(':').length > 2; +} + +function getProxySetting() : ProxySettings | undefined { + // HTTP_PROXY is like http://host:port + const proxy = process.env.HTTP_PROXY?.split(':') || []; + if (proxy?.length < 3) { + return undefined; + } + return { + proxyHost: proxy[1].replaceAll('/', ''), + proxyPort: proxy[2], + } +} + +function findNetworkServiceOnMac() : string { + const networkInfo = shell.exec(`${networkSetup} -listnetworkserviceorder`, {async: false}).stdout; + const lines = networkInfo.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (line.includes('Device: en')) { + // Network service name would be shown like: (1) Wi-Fi. + // Extract "Wi-Fi" from this line. + const service = lines[i-1].substring(4); + const serviceInfo = shell.exec(`${networkSetup} -getinfo "${service}"`, {async: false}).stdout; + for (const l of serviceInfo.split('\n')) { + if (l.includes('IP address') && !l.includes('IPv6') && !l.includes('none')) { + return service; + } + } + } + } + return 'Ethernet'; +} + +function setupMacProxy(proxy: ProxySettings) { + const { + proxyHost, + proxyPort, + } = proxy; + const networkService = findNetworkServiceOnMac(); + shell.exec(`sudo ${networkSetup} -setwebproxy "${networkService}" ${proxyHost} ${proxyPort}`, {async: false}); + shell.exec(`sudo ${networkSetup} -setsecurewebproxy "${networkService}" ${proxyHost} ${proxyPort}`, {async: false}); +} + +function setupWinProxy(proxy: ProxySettings) { + const { + proxyHost, + proxyPort, + } = proxy; + const prefix = + 'reg add "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" /v '; + const opts = { async: false }; + shell.exec(`${prefix} MigrateProxy /t REG_DWORD /d 1 /f`, opts) + shell.exec(`${prefix} ProxyEnable /t REG_DWORD /d 1 /f`, opts) + shell.exec(`${prefix} ProxyHttp1.1 /t REG_DWORD /d 1 /f`, opts) + shell.exec(`${prefix} EnableLegacyAutoProxyFeatures /t REG_DWORD /d 1 /f`, opts) + shell.exec(`${prefix} ProxyServer /t REG_SZ /d "${proxyHost}:${proxyPort}" /f`, opts) + shell.exec(`${prefix} ProxyOverride /t REG_SZ /d "localhost;127.0.0.1" /f`, opts) + + // Registry changes won't take effect immediately; we need to refresh wininet. + const refreshScript = path.join(__dirname, '../', 'scripts', 'win-refresh-wininet.ps1'); + shell.exec(`powershell.exe -ExecutionPolicy Bypass ${refreshScript}`, opts); +} + +export function setupProxy() { + const proxy = getProxySetting(); + if (!proxy) { + return; + } + console.log(`Setting system proxy settings: ${proxy.proxyHost}:${proxy.proxyPort}`); + switch (process.platform) { + case 'darwin': + setupMacProxy(proxy); + break; + case 'win32': + setupWinProxy(proxy); + break; + } +} \ No newline at end of file diff --git a/src/testcafe-runner.ts b/src/testcafe-runner.ts index 57245ac..a6f8370 100644 --- a/src/testcafe-runner.ts +++ b/src/testcafe-runner.ts @@ -1,8 +1,6 @@ import {spawn} from 'child_process'; import path from 'path'; import fs from 'fs'; -import {TestCafeConfig, Suite, CompilerOptions, second} from './type'; - import { getArgs, loadRunConfig, @@ -11,9 +9,15 @@ import { prepareNpmEnv, preExec, } from 'sauce-testrunner-utils'; + +import {TestCafeConfig, Suite, CompilerOptions, second} from './type'; import { generateJunitFile } from './sauce-testreporter'; +import { + setupProxy, + isProxyAvailable, +} from './network-proxy'; async function prepareConfiguration(nodeBin: string, runCfgPath: string, suiteName: string) { runCfgPath = getAbsolutePath(runCfgPath); @@ -225,6 +229,22 @@ export function buildCommandLine(suite: Suite | undefined, projectPath: string, return cli; } +// isCDPDisabled checks if TestCafe has CDP disabled. +// Starting from TestCafe version 3.0.0 and beyond, it employs Native Automation +// to automate Chromium-based browsers using the native CDP protocol. +// If the 'disableNativeAutomation' setting is enabled in the configuration, +// it indicates that the CDP connection is disabled, and TestCafe uses its own +// proxy to communicate with the browser. +function isCDPDisabled() { + const cfg = require(path.join(__dirname, 'sauce-testcafe-config.cjs')) + return cfg.disableNativeAutomation; +} + +// Chrome and Edge are both Chromium-based browsers. +function isChromiumBased(browser: string) { + return browser === 'chrome' || browser === 'microsoftedge'; +} + async function runTestCafe(tcCommandLine: (string | number)[], projectPath: string, timeout: second) { const nodeBin = process.argv[0]; const testcafeBin = path.join(__dirname, '..', 'node_modules', 'testcafe', 'lib', 'cli'); @@ -266,6 +286,16 @@ async function run(nodeBin: string, runCfgPath: string, suiteName: string) { suite } = await prepareConfiguration(nodeBin, runCfgPath, suiteName); + // TestCafe used a reverse proxy for browser automation before. + // With TestCafe 3.0.0 and later, native automation mode was enabled by default, + // see https://testcafe.io/documentation/404237/guides/intermediate-guides/native-automation-mode, + // introducing CDP support for Chrome and Edge. + // This means that HTTP requests can't be routed through the reverse proxy anymore. + // Now, we need to set up an OS-level proxy connection. + if (isChromiumBased(suite.browserName) && !isCDPDisabled() && isProxyAvailable()) { + setupProxy(); + } + if (!await preExec.run({preExec: suite.preExec}, preExecTimeout)) { return false; } diff --git a/src/type.ts b/src/type.ts index 490f59c..0060c71 100644 --- a/src/type.ts +++ b/src/type.ts @@ -2,6 +2,11 @@ import { Region } from '@saucelabs/testcomposer'; export type second = number; +export type proxy = { + proxyHost: string, + proxyPort: string, +}; + export type Metadata = { tags?: string[], build?: string, diff --git a/tests/cloud/.sauce/config-proxy.yml b/tests/cloud/.sauce/config-proxy.yml new file mode 100644 index 0000000..89ff3a4 --- /dev/null +++ b/tests/cloud/.sauce/config-proxy.yml @@ -0,0 +1,32 @@ +apiVersion: v1alpha +rootDir: ./ +kind: testcafe +sauce: + region: us-west-1 + concurrency: 1 + metadata: + tags: + - e2e + - release team + - other tag + build: Release $CI_COMMIT_SHORT_SHA + +testcafe: + version: 3.2.0 + +suites: + - name: "Proxy - macOS13" + platformName: "macOS 13" + browserName: "chrome" + timeout: 2m + src: + - "tests/sc/*.test.js" + speed: 1 + - name: "Proxy - Win11" + platformName: "Windows 11" + browserName: "chrome" + timeout: 2m + src: + - "tests/sc/*.test.js" + speed: 1 +