From a2749ad8109c7f8cf262098a4deb74360deeae32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 13:49:08 +0000 Subject: [PATCH 01/13] Initial plan From 80d31c5f43570fd79ef163e3e1726e1a924dcc72 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 13:50:24 +0000 Subject: [PATCH 02/13] Fix CI: upload/download npm tarball artifact between build and test jobs Agent-Logs-Url: https://github.com/DevExpress/testcafe-browser-provider-browserstack/sessions/401193be-b017-479a-b361-92fab77525ca Co-authored-by: aleks-pro <14822473+aleks-pro@users.noreply.github.com> --- .github/workflows/test.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d306cdf..f79f588 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,13 +14,22 @@ jobs: - uses: DevExpress/testcafe-build-system/actions/prepare@main - uses: DevExpress/testcafe-build-system/actions/build@main - + + - uses: actions/upload-artifact@v4 + with: + name: npm-package + path: .builds/*.tgz test: runs-on: ubuntu-latest needs: [build] steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main + + - uses: actions/download-artifact@v4 + with: + name: npm-package + path: .builds - uses: DevExpress/testcafe-build-system/actions/test-npm@main env: From d3ca0f9d0d661a8dae673c3750a8360f56643c85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 12 May 2026 13:52:37 +0000 Subject: [PATCH 03/13] Fix CVE: pin actions/download-artifact to v4.3.0 to avoid Arbitrary File Write vulnerability Agent-Logs-Url: https://github.com/DevExpress/testcafe-browser-provider-browserstack/sessions/401193be-b017-479a-b361-92fab77525ca Co-authored-by: aleks-pro <14822473+aleks-pro@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f79f588..1513ec1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v4.3.0 with: name: npm-package path: .builds From 32487904a330fd9bea8d24ae8be3f5f4af4a3952 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Wed, 13 May 2026 19:49:52 +0400 Subject: [PATCH 04/13] fix: use correct artifact name and remove redundant upload step The build@main action already uploads the artifact as 'npm'. The explicit upload-artifact step found no .builds/*.tgz files so no artifact was created, causing the download in the test job to fail with 'Artifact not found for name: npm-package'. - Remove redundant upload-artifact step from build job - Download artifact as 'npm' (matching what build@main uploads) - Bump download-artifact to v4 (latest major) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1513ec1..330f892 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,11 +14,6 @@ jobs: - uses: DevExpress/testcafe-build-system/actions/prepare@main - uses: DevExpress/testcafe-build-system/actions/build@main - - - uses: actions/upload-artifact@v4 - with: - name: npm-package - path: .builds/*.tgz test: runs-on: ubuntu-latest @@ -26,9 +21,9 @@ jobs: steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main - - uses: actions/download-artifact@v4.3.0 + - uses: actions/download-artifact@v4 with: - name: npm-package + name: npm path: .builds - uses: DevExpress/testcafe-build-system/actions/test-npm@main From f3c0f5610936ecbe3e4d4c3d052ba59496a68132 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Thu, 14 May 2026 11:31:03 +0400 Subject: [PATCH 05/13] fix: remove redundant download-artifact step from test job The test-npm@main action internally calls load-artifacts-npm@main which already downloads the 'npm' artifact. The explicit download step was causing a path conflict: it placed files at .builds/.builds/{name}.tgz instead of .builds/{name}.tgz, breaking the extraction step inside load-artifacts-npm@main. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 330f892..55eb1c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,11 +20,6 @@ jobs: needs: [build] steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main - - - uses: actions/download-artifact@v4 - with: - name: npm - path: .builds - uses: DevExpress/testcafe-build-system/actions/test-npm@main env: From eba9bf854987103ef907423b467d803fd8e96c18 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Thu, 14 May 2026 16:29:27 +0400 Subject: [PATCH 06/13] fix: inline test steps to work around broken detect-package-metadata actions/github-script@v3 in detect-package-metadata@main relies on the deprecated ::set-output:: workflow command which GitHub has disabled on runners. This causes pack-name and version outputs to be silently empty, making the tar extraction attempt '.builds/-.tgz' and fail with exit code 2. Replace test-npm@main with equivalent inline steps that use a bash node one-liner with GITHUB_OUTPUT to safely read package metadata. Also pins download-artifact to v4 (addresses the original CVE intent) and moves env vars to the specific run step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 45 ++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 55eb1c7..106164b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,11 +20,48 @@ jobs: needs: [build] steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main - - - uses: DevExpress/testcafe-build-system/actions/test-npm@main + + # Inline replacement for test-npm@main + load-artifacts-npm@main. + # Workaround: detect-package-metadata@main uses actions/github-script@v3 + # which relies on the deprecated ::set-output:: command (now disabled by GitHub), + # causing pack-name/version outputs to be empty and the tar extraction to fail. + - name: Get package metadata + id: pkg + shell: bash + run: | + PACK_NAME=$(node -e "const p=require('./package.json'); console.log(p.name.replace('@','').replace(/\//g,'-'))") + VERSION=$(node -e "console.log(require('./package.json').version)") + echo "pack-name=$PACK_NAME" >> "$GITHUB_OUTPUT" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - uses: actions/download-artifact@v4 + with: + name: npm + + - name: Extract npm package + shell: bash + run: tar --strip-components=1 -xzf ".builds/${{ steps.pkg.outputs.pack-name }}-${{ steps.pkg.outputs.version }}.tgz" + + - name: Get npm cache dir + id: npm-cache-dir + shell: bash + run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT" + + - uses: actions/cache@v4 + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + shell: bash + run: npm ci --legacy-peer-deps + + - name: Run tests + shell: bash env: BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - with: - task: test + run: npm run test From 95c8af35e78cda8165c072c59804dc579fc5e4bd Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Thu, 14 May 2026 16:54:47 +0400 Subject: [PATCH 07/13] debug: add step to list .builds/ contents after download Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 106164b..e7bfe3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,14 @@ jobs: with: name: npm + - name: Debug - list workspace after download + shell: bash + run: | + echo "=== .builds/ contents ===" + ls -la .builds/ || echo ".builds/ not found" + echo "=== pack-name: ${{ steps.pkg.outputs.pack-name }} ===" + echo "=== version: ${{ steps.pkg.outputs.version }} ===" + - name: Extract npm package shell: bash run: tar --strip-components=1 -xzf ".builds/${{ steps.pkg.outputs.pack-name }}-${{ steps.pkg.outputs.version }}.tgz" From fedca416efbeabeaa55ab38db94195e30d2d544f Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Thu, 14 May 2026 17:00:21 +0400 Subject: [PATCH 08/13] fix: use glob to find .tgz instead of constructing filename Instead of constructing the filename from pack-name/version outputs, glob for the first .tgz in .builds/. This is more robust and avoids any potential issues with output variable resolution. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e7bfe3e..c81ac9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,30 +25,21 @@ jobs: # Workaround: detect-package-metadata@main uses actions/github-script@v3 # which relies on the deprecated ::set-output:: command (now disabled by GitHub), # causing pack-name/version outputs to be empty and the tar extraction to fail. - - name: Get package metadata - id: pkg - shell: bash - run: | - PACK_NAME=$(node -e "const p=require('./package.json'); console.log(p.name.replace('@','').replace(/\//g,'-'))") - VERSION=$(node -e "console.log(require('./package.json').version)") - echo "pack-name=$PACK_NAME" >> "$GITHUB_OUTPUT" - echo "version=$VERSION" >> "$GITHUB_OUTPUT" - - uses: actions/download-artifact@v4 with: name: npm - - name: Debug - list workspace after download - shell: bash - run: | - echo "=== .builds/ contents ===" - ls -la .builds/ || echo ".builds/ not found" - echo "=== pack-name: ${{ steps.pkg.outputs.pack-name }} ===" - echo "=== version: ${{ steps.pkg.outputs.version }} ===" - - name: Extract npm package shell: bash - run: tar --strip-components=1 -xzf ".builds/${{ steps.pkg.outputs.pack-name }}-${{ steps.pkg.outputs.version }}.tgz" + run: | + TGZ=$(ls .builds/*.tgz 2>/dev/null | head -1) + if [ -z "$TGZ" ]; then + echo "ERROR: No .tgz found in .builds/. Workspace contents:" + find . -maxdepth 3 -not -path '*/node_modules/*' | sort + exit 1 + fi + echo "Extracting: $TGZ" + tar --strip-components=1 -xzf "$TGZ" - name: Get npm cache dir id: npm-cache-dir From 0a5dc097d92b268e5f3ca16614874025d2744a81 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Thu, 14 May 2026 17:06:01 +0400 Subject: [PATCH 09/13] fix: simplify test job - skip artifact extraction, rely on npm run test to build npm run test (gulp test) already runs the build step first, so there is no need to download and extract the packed artifact from the build job. The test job now simply checks out, installs deps, and runs tests. This also eliminates the broken detect-package-metadata/load-artifacts-npm dependency chain from testcafe-build-system which fails due to actions/github-script@v3 using the deprecated ::set-output:: command. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/test.yml | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c81ac9a..ff4fe6a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,38 +21,6 @@ jobs: steps: - uses: DevExpress/testcafe-build-system/actions/prepare@main - # Inline replacement for test-npm@main + load-artifacts-npm@main. - # Workaround: detect-package-metadata@main uses actions/github-script@v3 - # which relies on the deprecated ::set-output:: command (now disabled by GitHub), - # causing pack-name/version outputs to be empty and the tar extraction to fail. - - uses: actions/download-artifact@v4 - with: - name: npm - - - name: Extract npm package - shell: bash - run: | - TGZ=$(ls .builds/*.tgz 2>/dev/null | head -1) - if [ -z "$TGZ" ]; then - echo "ERROR: No .tgz found in .builds/. Workspace contents:" - find . -maxdepth 3 -not -path '*/node_modules/*' | sort - exit 1 - fi - echo "Extracting: $TGZ" - tar --strip-components=1 -xzf "$TGZ" - - - name: Get npm cache dir - id: npm-cache-dir - shell: bash - run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT" - - - uses: actions/cache@v4 - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: Install dependencies shell: bash run: npm ci --legacy-peer-deps From 484cc14f7c3fcdcc7a00a746e06d359890e9ad02 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Fri, 15 May 2026 11:41:12 +0400 Subject: [PATCH 10/13] fix: update stale BrowserStack device names in tests Replace iPhone SE 2020@13 (iOS 13 no longer available in BrowserStack JS Testing API) with iPhone SE 2022@15 in REST_BROWSER_NAMES and browserNameResults validation. Also proactively replace iPhone 7@10 (iOS 10, 2016) with iPhone 14@16 in AUTOMATE_BROWSER_NAMES to prevent the same issue in Automate mode tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/mocha/browser-names-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/mocha/browser-names-test.js b/test/mocha/browser-names-test.js index e6f9792..c088d12 100644 --- a/test/mocha/browser-names-test.js +++ b/test/mocha/browser-names-test.js @@ -27,7 +27,7 @@ describe('Browser names', function () { 'ie@10.0:Windows 8', 'ie@11.0:Windows 8.1', 'edge@15.0:Windows 10', - 'iPhone SE 2020@13', + 'iPhone SE 2022@15', 'iPhone XR@15', 'Google Pixel 7@13.0' ]; @@ -40,8 +40,8 @@ describe('Browser names', function () { 'ie@10.0:Windows 8', 'ie@11.0:Windows 8.1', 'edge@15.0:Windows 10', - 'iPhone 7@10', - 'iPhone SE 2020@13', + 'iPhone 14@16', + 'iPhone SE 2022@15', 'iPhone XR@15', ]; @@ -62,7 +62,7 @@ describe('Browser names', function () { 'ie@9.0:Windows 7': true, 'ie@10.0:Windows 8': true, 'ie@11.0:Windows 10': true, - 'iPhone SE 2020': true, + 'iPhone SE 2022': true, 'Google Pixel 7': true, 'ie@5.0': false, 'ie@11:os x': false From 17bba727758260507d0595b83c094a964dbbe562 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Fri, 15 May 2026 13:11:47 +0400 Subject: [PATCH 11/13] debug: improve missing browser names assertion to show exact items Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/mocha/browser-names-test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/mocha/browser-names-test.js b/test/mocha/browser-names-test.js index c088d12..7d13039 100644 --- a/test/mocha/browser-names-test.js +++ b/test/mocha/browser-names-test.js @@ -48,7 +48,10 @@ describe('Browser names', function () { return browserStackProvider .getBrowserList() .then(function (list) { - expect(list).to.include.members(IS_AUTOMATE ? AUTOMATE_BROWSER_NAMES : REST_BROWSER_NAMES); + const expectedList = IS_AUTOMATE ? AUTOMATE_BROWSER_NAMES : REST_BROWSER_NAMES; + const missingItems = expectedList.filter(item => !list.includes(item)); + + expect(missingItems, `Missing from browser list: ${missingItems.join(', ')}`).to.be.empty; }); }); From cf72004ea8499c77c7ff238315c3a64a73ea02c4 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Fri, 15 May 2026 13:44:53 +0400 Subject: [PATCH 12/13] fix: avoid max-nested-callbacks ESLint error in browser-names test Replace .filter() arrow callback (4 nesting levels) with a for-of loop to stay within the max-nested-callbacks limit of 3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/mocha/browser-names-test.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/mocha/browser-names-test.js b/test/mocha/browser-names-test.js index 7d13039..44db69a 100644 --- a/test/mocha/browser-names-test.js +++ b/test/mocha/browser-names-test.js @@ -48,8 +48,13 @@ describe('Browser names', function () { return browserStackProvider .getBrowserList() .then(function (list) { - const expectedList = IS_AUTOMATE ? AUTOMATE_BROWSER_NAMES : REST_BROWSER_NAMES; - const missingItems = expectedList.filter(item => !list.includes(item)); + const expectedList = IS_AUTOMATE ? AUTOMATE_BROWSER_NAMES : REST_BROWSER_NAMES; + const missingItems = []; + + for (const item of expectedList) { + if (!list.includes(item)) + missingItems.push(item); + } expect(missingItems, `Missing from browser list: ${missingItems.join(', ')}`).to.be.empty; }); From e1db672ea3d4ecf2879ac49d16f6b54bb3693ee4 Mon Sep 17 00:00:00 2001 From: Alexander Prokhorov Date: Fri, 15 May 2026 14:17:04 +0400 Subject: [PATCH 13/13] fix: replace stale iPhone XR@15 with iPhone 12@14 in browser names test iPhone XR@15 is no longer available in BrowserStack JS Testing API. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/mocha/browser-names-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/mocha/browser-names-test.js b/test/mocha/browser-names-test.js index 44db69a..98009b6 100644 --- a/test/mocha/browser-names-test.js +++ b/test/mocha/browser-names-test.js @@ -28,7 +28,7 @@ describe('Browser names', function () { 'ie@11.0:Windows 8.1', 'edge@15.0:Windows 10', 'iPhone SE 2022@15', - 'iPhone XR@15', + 'iPhone 12@14', 'Google Pixel 7@13.0' ]; @@ -42,7 +42,7 @@ describe('Browser names', function () { 'edge@15.0:Windows 10', 'iPhone 14@16', 'iPhone SE 2022@15', - 'iPhone XR@15', + 'iPhone 12@14', ]; return browserStackProvider