From 59f9d8ca7eacf77ea1a7bfe91d1bbb17a0f5befe Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Sat, 29 Jun 2024 19:55:40 +0100 Subject: [PATCH 01/34] Run compatibility tests once per day and on PR changes --- .github/workflows/compatibilityTest.yml | 42 +++++++++++++++++++++++++ package.json | 3 +- test/compatibility.test.js | 13 ++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/compatibilityTest.yml create mode 100644 test/compatibility.test.js diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml new file mode 100644 index 00000000..3d86f7fb --- /dev/null +++ b/.github/workflows/compatibilityTest.yml @@ -0,0 +1,42 @@ +name: Run Compatibility Tests + +on: + schedule: + - cron: '0 0 * * *' + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + CompatibilityTest: + runs-on: ubuntu-latest + steps: + - name: Set up Git repository + uses: actions/checkout@v3 + + - name: Set up node + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Cache node modules + id: cache-npm + uses: actions/cache@v3 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install dependencies + run: npm install + + - name: Run compatibility tests + run: npm run test:compatibility diff --git a/package.json b/package.json index 6da0c8f2..7dcfc590 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "build:firefox": "webpack --env browser=firefox --config webpack.prod.cjs", "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", - "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --require mocha-suppress-logs" + "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility.test.js --require mocha-suppress-logs", + "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility.test.js --require mocha-suppress-logs" }, "type": "module", "devDependencies": { diff --git a/test/compatibility.test.js b/test/compatibility.test.js new file mode 100644 index 00000000..00dab61d --- /dev/null +++ b/test/compatibility.test.js @@ -0,0 +1,13 @@ +import expect from 'expect.js'; + +describe('compatibility', function () { + context('YouTube', function () { + it('should redirect multiple videos to a temporary playlist URL', async function () { + const watchVideosUrl = 'https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ'; + const redirectedUrl = (await fetch(watchVideosUrl)).url; + + // The playlist is temporary, indicated by a TL start in the ID + expect(redirectedUrl).to.contain('https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL'); + }); + }); +}); \ No newline at end of file From b1bcd49a6909baa1868b8ec2e64964946f1e39e0 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Sun, 30 Jun 2024 15:03:06 +0100 Subject: [PATCH 02/34] Updated test description --- test/compatibility.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compatibility.test.js b/test/compatibility.test.js index 00dab61d..a7c47c37 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.test.js @@ -2,7 +2,7 @@ import expect from 'expect.js'; describe('compatibility', function () { context('YouTube', function () { - it('should redirect multiple videos to a temporary playlist URL', async function () { + it('should redirect a watch_videos URL to a temporary playlist URL', async function () { const watchVideosUrl = 'https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ'; const redirectedUrl = (await fetch(watchVideosUrl)).url; From 4cb6b68d310997e58d79c79db3ba6063d19fbca0 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Sun, 30 Jun 2024 16:16:15 +0100 Subject: [PATCH 03/34] Fixed typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2dc1415..3a91eac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## v3.1.7 -- The extensions's news page can now be updated with breaking changes or other important information without the need to update the extension itself. +- The extension's news page can now be updated with breaking changes or other important information without the need to update the extension itself. - Fixed some dynamic content on the News page. - Added a hint in the popup if no channel has yet been visited. - Removed some unneeded scripts from the extension's pages. From 1572419a4306a010361617c8351731103d739f19 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:58:09 +0100 Subject: [PATCH 04/34] Added puppeteer test for the yt-navigate-finish event --- .github/workflows/compatibilityTest.yml | 22 +- package-lock.json | 873 +++++++++++++++++++++++- package.json | 5 +- test/compatibility.test.js | 70 +- 4 files changed, 941 insertions(+), 29 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 3d86f7fb..c37581a5 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -2,7 +2,7 @@ name: Run Compatibility Tests on: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" push: branches: - main @@ -16,12 +16,12 @@ jobs: steps: - name: Set up Git repository uses: actions/checkout@v3 - - - name: Set up node + + - name: Set up node uses: actions/setup-node@v3 with: node-version: 18 - + - name: Cache node modules id: cache-npm uses: actions/cache@v3 @@ -34,9 +34,21 @@ jobs: ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - + + - name: Cache Puppeteer Chrome + uses: actions/cache@v3 + with: + path: | + node_modules/puppeteer/.local-chromium + key: ${{ runner.os }}-puppeteer-chrome-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-puppeteer-chrome- + - name: Install dependencies run: npm install + - name: Setup Chrome for Puppeteer + run: npx puppeteer browsers install chrome + - name: Run compatibility tests run: npm run test:compatibility diff --git a/package-lock.json b/package-lock.json index afcae838..64703b08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", + "puppeteer": "^22.12.1", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", @@ -3327,6 +3328,198 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, + "node_modules/@puppeteer/browsers": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.3.tgz", + "integrity": "sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==", + "dev": true, + "dependencies": { + "debug": "4.3.4", + "extract-zip": "2.0.1", + "progress": "2.0.3", + "proxy-agent": "6.4.0", + "semver": "7.6.0", + "tar-fs": "3.0.5", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@puppeteer/browsers/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@puppeteer/browsers/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@puppeteer/browsers/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@puppeteer/browsers/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@puppeteer/browsers/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@sindresorhus/is": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", @@ -3445,6 +3638,12 @@ "node": ">= 10" } }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true + }, "node_modules/@types/chrome": { "version": "0.0.193", "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.193.tgz", @@ -4745,6 +4944,18 @@ "node": ">=8" } }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -4777,6 +4988,12 @@ "node": ">=8.0.0" } }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true + }, "node_modules/babel-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", @@ -4846,6 +5063,52 @@ "dev": true, "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", + "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "dev": true, + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", + "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "dev": true, + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "dev": true, + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", + "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "dev": true, + "optional": true, + "dependencies": { + "streamx": "^2.18.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -4866,6 +5129,15 @@ } ] }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", @@ -5345,6 +5617,20 @@ "node": ">=6.0" } }, + "node_modules/chromium-bidi": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.24.tgz", + "integrity": "sha512-5xQNN2SVBdZv4TxeMLaI+PelrnZsHDhn8h2JtyriLr+0qHcZS8BMuo93qN6J1VmtmrgYP+rmcLHcbpnA8QJh+w==", + "dev": true, + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -6048,6 +6334,56 @@ "dev": true, "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6391,6 +6727,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -6401,6 +6751,12 @@ "node": ">=0.4.0" } }, + "node_modules/devtools-protocol": { + "version": "0.0.1299070", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1299070.tgz", + "integrity": "sha512-+qtL3eX50qsJ7c+qVyagqi7AWMoQCBGNfoyJZMwm/NSXVqLYbuitrWEEIzxfUmTNy7//Xe8yhMmQ+elj3uAqSg==", + "dev": true + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -6640,6 +6996,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/envinfo": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", @@ -6707,6 +7072,36 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/eslint": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", @@ -7169,29 +7564,64 @@ "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expect.js": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", + "integrity": "sha512-okDF/FAPEul1ZFLae4hrgpIqAeapoo5TRdcg/lD0iN9S3GWrBFIJwNezGH1DMtIz+RxU4RrFmMq7WUUvDg3J6A==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=8" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/expect.js": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", - "integrity": "sha512-okDF/FAPEul1ZFLae4hrgpIqAeapoo5TRdcg/lD0iN9S3GWrBFIJwNezGH1DMtIz+RxU4RrFmMq7WUUvDg3J6A==", - "dev": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7199,6 +7629,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -7680,6 +8116,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "dev": true, + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -8188,6 +8648,19 @@ "url": "https://github.com/sindresorhus/invert-kv?sponsor=1" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/is-absolute": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", @@ -8707,6 +9180,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsdom": { "version": "22.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", @@ -9535,6 +10014,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", @@ -9891,6 +10376,15 @@ "dev": true, "license": "MIT" }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/nise": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", @@ -10347,6 +10841,76 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "dev": true, + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/package-json": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", @@ -10857,6 +11421,15 @@ "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", "dev": true }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/promise-toolbox": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/promise-toolbox/-/promise-toolbox-0.21.0.tgz", @@ -10903,6 +11476,78 @@ "pbts": "bin/pbts" } }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -10946,6 +11591,41 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/puppeteer": { + "version": "22.12.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.12.1.tgz", + "integrity": "sha512-1GxY8dnEnHr1SLzdSDr0FCjM6JQfAh2E2I/EqzeF8a58DbGVk9oVjj4lFdqNoVbpgFSpAbz7VER9St7S1wDpNg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "2.2.3", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1299070", + "puppeteer-core": "22.12.1" + }, + "bin": { + "puppeteer": "lib/esm/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "22.12.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.12.1.tgz", + "integrity": "sha512-XmqeDPVdC5/3nGJys1jbgeoZ02wP0WV1GBlPtr/ULRbGXJFuqgXMcKQ3eeNtFpBzGRbpeoCGWHge1ZWKWl0Exw==", + "dev": true, + "dependencies": { + "@puppeteer/browsers": "2.2.3", + "chromium-bidi": "0.5.24", + "debug": "^4.3.5", + "devtools-protocol": "0.0.1299070", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -10983,6 +11663,12 @@ ], "license": "MIT" }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", @@ -11981,6 +12667,56 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/sonic-boom": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", @@ -12060,6 +12796,26 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, + "node_modules/streamx": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", + "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "dev": true, + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -12288,6 +13044,31 @@ "node": ">=6" } }, + "node_modules/tar-fs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.5.tgz", + "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", + "dev": true, + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/terser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", @@ -12446,6 +13227,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/text-decoder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", + "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12678,6 +13468,40 @@ "node": ">=14.17" } }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -12887,6 +13711,12 @@ "requires-port": "^1.0.0" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13859,6 +14689,15 @@ "async": "^3.2.0", "jszip": "^3.2.2" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index f75cb4d2..80c5e22b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "3.1.7", "description": "Customize, shuffle and play random videos from any YouTube channel.", "scripts": { - "dev": "concurrently \"npm run dev:chromium\" \"npm run dev:firefox\"", + "dev": "concurrently \"npm run dev:chromium\" \"npm run dev:firefox\"", "dev:chromium": "webpack --env browser=chromium --watch --config webpack.dev.cjs", "dev:firefox": "concurrently --kill-others \"webpack --env browser=firefox --watch --config webpack.dev.cjs\" \"web-ext run --source-dir ./dist/firefox\"", "dev:android": "concurrently --kill-others \"webpack --env browser=firefox --watch --config webpack.dev.cjs\" \"web-ext run --source-dir ./dist/firefox -t firefox-android --adb-device emulator-5554 --firefox-apk org.mozilla.fenix\"", @@ -13,7 +13,7 @@ "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility.test.js --require mocha-suppress-logs", - "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility.test.js --require mocha-suppress-logs" + "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility.test.js" }, "type": "module", "devDependencies": { @@ -39,6 +39,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", + "puppeteer": "^22.12.1", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", diff --git a/test/compatibility.test.js b/test/compatibility.test.js index a7c47c37..a00326b6 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.test.js @@ -1,13 +1,73 @@ import expect from 'expect.js'; +import puppeteer from 'puppeteer'; describe('compatibility', function () { context('YouTube', function () { - it('should redirect a watch_videos URL to a temporary playlist URL', async function () { - const watchVideosUrl = 'https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ'; - const redirectedUrl = (await fetch(watchVideosUrl)).url; + context('URLs', function () { + it('should redirect a watch_videos URL to a temporary playlist URL', async function () { + const watchVideosUrl = 'https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ'; + const redirectedUrl = (await fetch(watchVideosUrl)).url; - // The playlist is temporary, indicated by a TL start in the ID - expect(redirectedUrl).to.contain('https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL'); + // The playlist is temporary, indicated by a TL start in the ID + expect(redirectedUrl).to.contain('https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL'); + }); + }); + + context('events', function () { + it('should contain required data in the yt-navigate-finish event', async function () { + this.timeout(10000); + + const browser = await puppeteer.launch({ headless: true }); + const page = await browser.newPage(); + + let event = {}; + + // Create a promise that listens for the 'yt-navigate-finish' event + const waitForNavigateFinish = new Promise((resolve, reject) => { + page.on('console', msg => { + if (msg.text().includes('yt-navigate-finish')) { + // Remove the yt-navigate-finish from the string and parse the rest to event + event = JSON.parse(msg.text().replace('yt-navigate-finish ', '')); + resolve(); + } + }); + }); + + await page.evaluateOnNewDocument(() => { + document.addEventListener('yt-navigate-finish', function (e) { + const serializableEvent = { + channelId: e.detail?.response?.playerResponse?.videoDetails?.channelId, + channelName: e.detail?.response?.playerResponse?.videoDetails?.author + }; + // Now, this object can be safely serialized to JSON + console.log('yt-navigate-finish', JSON.stringify(serializableEvent)); + }); + }); + + // Navigate to a YouTube page + await page.goto('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + + const timeout = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error('Timed out waiting for yt-navigate-finish event')); + }, 5000); + }); + + // Wait for either the event to fire or the timeout + try { + await Promise.race([waitForNavigateFinish, timeout]); + } catch (error) { + console.error(error.message); + } + + await browser.close(); + + console.log("The following data was extracted from the yt-navigate-finish event:"); + console.log(event); + + expect(event.channelId).to.be('UCuAXFkgsw1L7xaCfnd5JJOw'); + expect(event.channelName).to.be('Rick Astley'); + }); }); }); }); \ No newline at end of file From 8eb09e2d4d724e1f2519bd17ce9536a1efe13253 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:07:17 +0100 Subject: [PATCH 05/34] Updated cache task --- .github/workflows/compatibilityTest.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index c37581a5..9a060a55 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -37,6 +37,8 @@ jobs: - name: Cache Puppeteer Chrome uses: actions/cache@v3 + env: + cache-name: cache-puppeteer-chrome with: path: | node_modules/puppeteer/.local-chromium From 91395be3f97643c563dda4a1a2124cf7305a994d Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:11:27 +0100 Subject: [PATCH 06/34] Updated path --- .github/workflows/compatibilityTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 9a060a55..1d59ed7c 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -41,7 +41,7 @@ jobs: cache-name: cache-puppeteer-chrome with: path: | - node_modules/puppeteer/.local-chromium + ~/.cache/puppeteer key: ${{ runner.os }}-puppeteer-chrome-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-puppeteer-chrome- From 3ae88437593c1205485f9a8552e9d20a1f9f73f8 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:40:31 +0100 Subject: [PATCH 07/34] Updated tests, added test for channel page navigation --- test/compatibility.test.js | 127 +++++++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 28 deletions(-) diff --git a/test/compatibility.test.js b/test/compatibility.test.js index a00326b6..6f2bdb8d 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.test.js @@ -1,55 +1,71 @@ -import expect from 'expect.js'; -import puppeteer from 'puppeteer'; - -describe('compatibility', function () { - context('YouTube', function () { - context('URLs', function () { - it('should redirect a watch_videos URL to a temporary playlist URL', async function () { - const watchVideosUrl = 'https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ'; +import expect from "expect.js"; +import puppeteer from "puppeteer"; + +describe("compatibility", function () { + context("YouTube", function () { + context("URLs", function () { + it("should redirect a watch_videos URL to a temporary playlist URL", async function () { + const watchVideosUrl = "https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ"; const redirectedUrl = (await fetch(watchVideosUrl)).url; // The playlist is temporary, indicated by a TL start in the ID - expect(redirectedUrl).to.contain('https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL'); + expect(redirectedUrl).to.contain("https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL"); }); }); - context('events', function () { - it('should contain required data in the yt-navigate-finish event', async function () { - this.timeout(10000); + context("events", function () { + let browser, page; + + beforeEach(async () => { + // Common setup: launching a browser and opening a new page + browser = await puppeteer.launch({ headless: true }); + page = await browser.newPage(); + + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false + }); + }); - const browser = await puppeteer.launch({ headless: true }); - const page = await browser.newPage(); + afterEach(async () => { + await browser.close(); + }); + it("should contain required data in the yt-navigate-finish event for video pages", async function () { + this.timeout(10000); let event = {}; - // Create a promise that listens for the 'yt-navigate-finish' event + // Create a promise that listens for the "yt-navigate-finish" event const waitForNavigateFinish = new Promise((resolve, reject) => { - page.on('console', msg => { - if (msg.text().includes('yt-navigate-finish')) { - // Remove the yt-navigate-finish from the string and parse the rest to event - event = JSON.parse(msg.text().replace('yt-navigate-finish ', '')); + page.on("console", msg => { + if (msg.text().includes("yt-navigate-finish")) { + event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); resolve(); } }); }); await page.evaluateOnNewDocument(() => { - document.addEventListener('yt-navigate-finish', function (e) { + document.addEventListener("yt-navigate-finish", function (e) { const serializableEvent = { channelId: e.detail?.response?.playerResponse?.videoDetails?.channelId, channelName: e.detail?.response?.playerResponse?.videoDetails?.author }; - // Now, this object can be safely serialized to JSON - console.log('yt-navigate-finish', JSON.stringify(serializableEvent)); + console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); }); }); - // Navigate to a YouTube page - await page.goto('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); + // Navigate to a YouTube video page + await page.goto("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); const timeout = new Promise((resolve, reject) => { setTimeout(() => { - reject(new Error('Timed out waiting for yt-navigate-finish event')); + reject(new Error("Timed out waiting for yt-navigate-finish event")); }, 5000); }); @@ -60,13 +76,68 @@ describe('compatibility', function () { console.error(error.message); } - await browser.close(); + console.log("The following data was extracted from the yt-navigate-finish event:"); + console.log(event); + + expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); + expect(event.channelName).to.be("Rick Astley"); + }); + + it("should contain required data in the yt-navigate-finish event for channel pages", async function () { + this.timeout(10000); + let event = {}; + + // Create a promise that listens for the "yt-navigate-finish" event + const waitForNavigateFinish = new Promise((resolve, reject) => { + page.on("console", msg => { + if (msg.text().includes("yt-navigate-finish")) { + event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); + resolve(); + } + }); + }); + + await page.evaluateOnNewDocument(() => { + document.addEventListener("yt-navigate-finish", function (e) { + const serializableEvent = { + eventVersion: "default", + channelId: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.channelId, + channelName: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.title + }; + if (!serializableEvent.channelId) { + serializableEvent.eventVersion = "20240521"; + serializableEvent.channelId = e.detail?.endpoint?.browseEndpoint?.browseId; + } + if (!serializableEvent.channelName) { + serializableEvent.eventVersion = "20240521"; + serializableEvent.channelName = e.detail?.response?.response?.header?.pageHeaderRenderer?.pageTitle; + } + + console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); + }); + }); + + // Navigate to a YouTube video page + await page.goto("https://www.youtube.com/@RickAstleyYT"); + + const timeout = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error("Timed out waiting for yt-navigate-finish event")); + }, 5000); + }); + + // Wait for either the event to fire or the timeout + try { + await Promise.race([waitForNavigateFinish, timeout]); + } catch (error) { + console.error(error.message); + } console.log("The following data was extracted from the yt-navigate-finish event:"); console.log(event); - expect(event.channelId).to.be('UCuAXFkgsw1L7xaCfnd5JJOw'); - expect(event.channelName).to.be('Rick Astley'); + expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); + expect(event.channelName).to.be("Rick Astley"); }); }); }); From 575000c9e2ca39fd5a5f541f16426307a7cd1e31 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:57:15 +0100 Subject: [PATCH 08/34] Added test for adding shuffle button to channel header, install extension --- test/compatibility.test.js | 77 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/test/compatibility.test.js b/test/compatibility.test.js index 6f2bdb8d..6a3c9a4d 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.test.js @@ -1,7 +1,13 @@ import expect from "expect.js"; import puppeteer from "puppeteer"; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { + this.timeout(15000); + context("YouTube", function () { context("URLs", function () { it("should redirect a watch_videos URL to a temporary playlist URL", async function () { @@ -17,7 +23,6 @@ describe("compatibility", function () { let browser, page; beforeEach(async () => { - // Common setup: launching a browser and opening a new page browser = await puppeteer.launch({ headless: true }); page = await browser.newPage(); @@ -37,7 +42,6 @@ describe("compatibility", function () { }); it("should contain required data in the yt-navigate-finish event for video pages", async function () { - this.timeout(10000); let event = {}; // Create a promise that listens for the "yt-navigate-finish" event @@ -84,7 +88,6 @@ describe("compatibility", function () { }); it("should contain required data in the yt-navigate-finish event for channel pages", async function () { - this.timeout(10000); let event = {}; // Create a promise that listens for the "yt-navigate-finish" event @@ -140,5 +143,73 @@ describe("compatibility", function () { expect(event.channelName).to.be("Rick Astley"); }); }); + + context("DOM elements", function () { + let browser, page; + + beforeEach(async () => { + browser = await puppeteer.launch({ headless: true }); + page = await browser.newPage(); + + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false + }); + }); + + afterEach(async () => { + await browser.close(); + }); + + it("should contain the expected channel header elements to insert the button into", async function () { + }); + }); + + context("shuffle button insertion", function () { + let browser, page; + + beforeEach(async () => { + const extensionPath = join(__dirname, "../dist/chromium"); + + browser = await puppeteer.launch({ + headless: false, // Extensions only work in head-full mode + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}` + ] + }); + page = await browser.newPage(); + + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false + }); + // For these tests, we need to install the dist/chromium directory as an extension in the browser + + }); + + afterEach(async () => { + await browser.close(); + }); + + it('should insert the shuffle button into the channel header', async function () { + await page.goto("https://www.youtube.com/@RickAstleyYT"); + + await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); + const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); + + expect(shuffleButton).to.not.be(null); + }); + }); }); }); \ No newline at end of file From 37c0a9affcf77d0bfd64a18af99bcd754bbf97b8 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:59:13 +0100 Subject: [PATCH 09/34] add display adapter --- .github/workflows/compatibilityTest.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 1d59ed7c..a7468fc2 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -52,5 +52,10 @@ jobs: - name: Setup Chrome for Puppeteer run: npx puppeteer browsers install chrome - - name: Run compatibility tests - run: npm run test:compatibility + - name: Setup Xvfb and run tests + uses: GabrielBB/xvfb-action@v1.5 + with: + run: npm run test:compatibility + + # - name: Run compatibility tests + # run: npm run test:compatibility From eda903099cbdd0a12a50ec755aec9337a199fc91 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:02:02 +0100 Subject: [PATCH 10/34] Split headfull and headless tests --- .github/workflows/compatibilityTest.yml | 17 ++++-- package.json | 4 +- test/compatibility.headfull.test.js | 58 +++++++++++++++++++ ...test.js => compatibility.headless.test.js} | 41 ------------- 4 files changed, 72 insertions(+), 48 deletions(-) create mode 100644 test/compatibility.headfull.test.js rename test/{compatibility.test.js => compatibility.headless.test.js} (81%) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index a7468fc2..340851ed 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -19,8 +19,11 @@ jobs: - name: Set up node uses: actions/setup-node@v3 + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 + # args: install - name: Cache node modules id: cache-npm @@ -52,10 +55,12 @@ jobs: - name: Setup Chrome for Puppeteer run: npx puppeteer browsers install chrome - - name: Setup Xvfb and run tests - uses: GabrielBB/xvfb-action@v1.5 - with: - run: npm run test:compatibility + - name: Run headless compatibility tests + run: npm run test:compatibility:headless - # - name: Run compatibility tests - # run: npm run test:compatibility + - name: Run headfull compatibility tests + uses: mujo-code/puppeteer-headful@18.9.0 + env: + CI: "true" + with: + args: npm run test:compatibility:headfull diff --git a/package.json b/package.json index 80c5e22b..3b04caae 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility.test.js --require mocha-suppress-logs", - "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility.test.js" + "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js", + "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js", + "test:compatibility:headfull": "mocha ./test/testSetup.js ./test/compatibility.headfull.test.js" }, "type": "module", "devDependencies": { diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js new file mode 100644 index 00000000..9c891b5c --- /dev/null +++ b/test/compatibility.headfull.test.js @@ -0,0 +1,58 @@ +import expect from "expect.js"; +import puppeteer from "puppeteer"; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe("compatibility", function () { + this.timeout(15000); + + context("YouTube", function () { + context("shuffle button insertion", function () { + let browser, page; + + beforeEach(async () => { + const extensionPath = join(__dirname, "../dist/chromium"); + + browser = await puppeteer.launch({ + headless: false, // Extensions only work in head-full mode + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}` + ] + }); + page = await browser.newPage(); + + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false + }); + // For these tests, we need to install the dist/chromium directory as an extension in the browser + + }); + + afterEach(async () => { + await browser.close(); + }); + + it('should insert the shuffle button into the channel header', async function () { + // Wait for 1 second to allow the extension to load + await new Promise(resolve => setTimeout(resolve, 1000)); + + await page.goto("https://www.youtube.com/@RickAstleyYT"); + + await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); + const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); + + expect(shuffleButton).to.not.be(null); + + }); + }); + }); +}); \ No newline at end of file diff --git a/test/compatibility.test.js b/test/compatibility.headless.test.js similarity index 81% rename from test/compatibility.test.js rename to test/compatibility.headless.test.js index 6a3c9a4d..ca0a85ae 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.headless.test.js @@ -170,46 +170,5 @@ describe("compatibility", function () { }); }); - context("shuffle button insertion", function () { - let browser, page; - - beforeEach(async () => { - const extensionPath = join(__dirname, "../dist/chromium"); - - browser = await puppeteer.launch({ - headless: false, // Extensions only work in head-full mode - args: [ - `--disable-extensions-except=${extensionPath}`, - `--load-extension=${extensionPath}` - ] - }); - page = await browser.newPage(); - - // Set the SOCS cookie for YouTube (cookie banner) - await page.setCookie({ - 'name': 'SOCS', - 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value - 'domain': '.youtube.com', - 'path': '/', - 'secure': true, - 'httpOnly': false - }); - // For these tests, we need to install the dist/chromium directory as an extension in the browser - - }); - - afterEach(async () => { - await browser.close(); - }); - - it('should insert the shuffle button into the channel header', async function () { - await page.goto("https://www.youtube.com/@RickAstleyYT"); - - await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); - const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); - - expect(shuffleButton).to.not.be(null); - }); - }); }); }); \ No newline at end of file From 384a3d9dcaf91fb07448e1fc8f5ea1e68577a0a2 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:08:10 +0100 Subject: [PATCH 11/34] Updated browser initialization --- test/compatibility.headfull.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js index 9c891b5c..d5f511b8 100644 --- a/test/compatibility.headfull.test.js +++ b/test/compatibility.headfull.test.js @@ -18,9 +18,11 @@ describe("compatibility", function () { browser = await puppeteer.launch({ headless: false, // Extensions only work in head-full mode args: [ + '--no-sandbox', `--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}` - ] + ], + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container }); page = await browser.newPage(); @@ -33,8 +35,6 @@ describe("compatibility", function () { 'secure': true, 'httpOnly': false }); - // For these tests, we need to install the dist/chromium directory as an extension in the browser - }); afterEach(async () => { From 213c6c4e850db6fc06730aad8b1ccf92975be218 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:14:39 +0100 Subject: [PATCH 12/34] Updated puppeteer version --- package-lock.json | 262 +++++++++++++++------------- package.json | 2 +- test/compatibility.headfull.test.js | 2 +- 3 files changed, 138 insertions(+), 128 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64703b08..83e0a96b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", - "puppeteer": "^22.12.1", + "puppeteer": "^21.11.0", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", @@ -3329,17 +3329,16 @@ "license": "BSD-3-Clause" }, "node_modules/@puppeteer/browsers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.3.tgz", - "integrity": "sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", + "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", "dev": true, "dependencies": { "debug": "4.3.4", "extract-zip": "2.0.1", "progress": "2.0.3", - "proxy-agent": "6.4.0", - "semver": "7.6.0", - "tar-fs": "3.0.5", + "proxy-agent": "6.3.1", + "tar-fs": "3.0.4", "unbzip2-stream": "1.4.3", "yargs": "17.7.2" }, @@ -3347,7 +3346,7 @@ "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=18" + "node": ">=16.3.0" } }, "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { @@ -3429,33 +3428,6 @@ "node": ">=8" } }, - "node_modules/@puppeteer/browsers/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@puppeteer/browsers/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@puppeteer/browsers/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3487,12 +3459,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@puppeteer/browsers/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@puppeteer/browsers/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -5070,45 +5036,6 @@ "dev": true, "optional": true }, - "node_modules/bare-fs": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", - "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", - "dev": true, - "optional": true, - "dependencies": { - "bare-events": "^2.0.0", - "bare-path": "^2.0.0", - "bare-stream": "^2.0.0" - } - }, - "node_modules/bare-os": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", - "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", - "dev": true, - "optional": true - }, - "node_modules/bare-path": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", - "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", - "dev": true, - "optional": true, - "dependencies": { - "bare-os": "^2.1.0" - } - }, - "node_modules/bare-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", - "dev": true, - "optional": true, - "dependencies": { - "streamx": "^2.18.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5618,14 +5545,13 @@ } }, "node_modules/chromium-bidi": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.24.tgz", - "integrity": "sha512-5xQNN2SVBdZv4TxeMLaI+PelrnZsHDhn8h2JtyriLr+0qHcZS8BMuo93qN6J1VmtmrgYP+rmcLHcbpnA8QJh+w==", + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.8.tgz", + "integrity": "sha512-blqh+1cEQbHBKmok3rVJkBlBxt9beKBgOsxbFgs7UJcoVbbeZ+K7+6liAsjgpc8l1Xd55cQUy14fXZdGSb4zIw==", "dev": true, "dependencies": { "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", - "zod": "3.23.8" + "urlpattern-polyfill": "10.0.0" }, "peerDependencies": { "devtools-protocol": "*" @@ -6384,6 +6310,57 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/cross-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/cross-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6752,9 +6729,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1299070", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1299070.tgz", - "integrity": "sha512-+qtL3eX50qsJ7c+qVyagqi7AWMoQCBGNfoyJZMwm/NSXVqLYbuitrWEEIzxfUmTNy7//Xe8yhMmQ+elj3uAqSg==", + "version": "0.0.1232444", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz", + "integrity": "sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==", "dev": true }, "node_modules/diff": { @@ -10035,6 +10012,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, "node_modules/mocha": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", @@ -11477,15 +11460,15 @@ } }, "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.0.1", "proxy-from-env": "^1.1.0", @@ -11592,38 +11575,77 @@ } }, "node_modules/puppeteer": { - "version": "22.12.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.12.1.tgz", - "integrity": "sha512-1GxY8dnEnHr1SLzdSDr0FCjM6JQfAh2E2I/EqzeF8a58DbGVk9oVjj4lFdqNoVbpgFSpAbz7VER9St7S1wDpNg==", + "version": "21.11.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.11.0.tgz", + "integrity": "sha512-9jTHuYe22TD3sNxy0nEIzC7ZrlRnDgeX3xPkbS7PnbdwYjl2o/z/YuCrRBwezdKpbTDTJ4VqIggzNyeRcKq3cg==", + "deprecated": "< 22.6.4 is no longer supported", "dev": true, "hasInstallScript": true, "dependencies": { - "@puppeteer/browsers": "2.2.3", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1299070", - "puppeteer-core": "22.12.1" + "@puppeteer/browsers": "1.9.1", + "cosmiconfig": "9.0.0", + "puppeteer-core": "21.11.0" }, "bin": { "puppeteer": "lib/esm/puppeteer/node/cli.js" }, "engines": { - "node": ">=18" + "node": ">=16.13.2" } }, "node_modules/puppeteer-core": { - "version": "22.12.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.12.1.tgz", - "integrity": "sha512-XmqeDPVdC5/3nGJys1jbgeoZ02wP0WV1GBlPtr/ULRbGXJFuqgXMcKQ3eeNtFpBzGRbpeoCGWHge1ZWKWl0Exw==", + "version": "21.11.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.11.0.tgz", + "integrity": "sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q==", "dev": true, "dependencies": { - "@puppeteer/browsers": "2.2.3", - "chromium-bidi": "0.5.24", - "debug": "^4.3.5", - "devtools-protocol": "0.0.1299070", - "ws": "^8.17.1" + "@puppeteer/browsers": "1.9.1", + "chromium-bidi": "0.5.8", + "cross-fetch": "4.0.0", + "debug": "4.3.4", + "devtools-protocol": "0.0.1232444", + "ws": "8.16.0" }, "engines": { - "node": ">=18" + "node": ">=16.13.2" + } + }, + "node_modules/puppeteer-core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/puppeteer-core/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/querystringify": { @@ -13045,17 +13067,14 @@ } }, "node_modules/tar-fs": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.5.tgz", - "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", "dev": true, "dependencies": { + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0" } }, "node_modules/tar-stream": { @@ -14689,15 +14708,6 @@ "async": "^3.2.0", "jszip": "^3.2.2" } - }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index 3b04caae..dc05247e 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", - "puppeteer": "^22.12.1", + "puppeteer": "^21.11.0", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js index d5f511b8..cbbfb18f 100644 --- a/test/compatibility.headfull.test.js +++ b/test/compatibility.headfull.test.js @@ -43,7 +43,7 @@ describe("compatibility", function () { it('should insert the shuffle button into the channel header', async function () { // Wait for 1 second to allow the extension to load - await new Promise(resolve => setTimeout(resolve, 1000)); + await new Promise(resolve => setTimeout(resolve, 1500)); await page.goto("https://www.youtube.com/@RickAstleyYT"); From c714a35dda0e73c2fbfc3ef321013531b122bb56 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:17:18 +0100 Subject: [PATCH 13/34] Exclude compatibility tests correctly --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dc05247e..db99d78b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build:firefox": "webpack --env browser=firefox --config webpack.prod.cjs", "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", - "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility.test.js --require mocha-suppress-logs", + "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility*.test.js --require mocha-suppress-logs", "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js", "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js", "test:compatibility:headfull": "mocha ./test/testSetup.js ./test/compatibility.headfull.test.js" From a664417c5413941af5b0ab1fe06c65456c202e94 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:50:08 +0100 Subject: [PATCH 14/34] Fixed getting the buttonDivOwner for new YouTube layout --- CHANGELOG.md | 1 + src/content.js | 8 ++++---- src/domManipulation.js | 2 +- test/compatibility.headfull.test.js | 6 +----- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d58cba38..4305e398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Fixed a bug where the shuffle button would sometimes not be added to the page if it was opened directly from a new tab. - Fixed a bug where the playlist created by the extension would sometimes not be renamed correctly. - Fixed an animation bug when ignoring shorts and shuffling a channel with many videos from a shorts page. +- Fixed the shuffle button not being added to the channel page with a new YouTube UI. ## v3.1.7 diff --git a/src/content.js b/src/content.js index 161e24ca..e9a6d02d 100644 --- a/src/content.js +++ b/src/content.js @@ -66,16 +66,16 @@ async function startDOMObserver(event) { if (pageType === "channel") { switch (eventVersion) { case "default": - channelPageRequiredElementLoadComplete = document.getElementById("channel-header"); + channelPageRequiredElementLoadComplete = document.getElementById("channel-header")?.querySelector("#inner-header-container")?.children?.namedItem("buttons"); break; case "20240521": - channelPageRequiredElementLoadComplete = document.getElementById("page-header"); + channelPageRequiredElementLoadComplete = document.getElementById("page-header")?.getElementsByTagName("yt-flexible-actions-view-model")[0]; break; } } else if (pageType === "video") { - videoPageRequiredElementLoadComplete = document.getElementById("player") && document.getElementById("above-the-fold"); + videoPageRequiredElementLoadComplete = document.getElementById("above-the-fold")?.children?.namedItem("top-row")?.children?.namedItem("owner"); } else if (pageType === "short") { - shortsPageRequiredElementLoadComplete = true; + shortsPageRequiredElementLoadComplete = document.querySelectorAll("ytd-reel-video-renderer ytd-reel-player-overlay-renderer #actions");// true; } // If the required element has loaded, add the shuffle button diff --git a/src/domManipulation.js b/src/domManipulation.js index 5b90c2ac..799788a7 100644 --- a/src/domManipulation.js +++ b/src/domManipulation.js @@ -22,7 +22,7 @@ export function buildShuffleButton(pageType, channelId, eventVersion, clickHandl buttonDivExtraStyle = "margin-left: 8px;"; break; case "20240521": - buttonDivOwner = [document.getElementById("page-header").querySelector(".page-header-view-model-wiz__page-header-headline-info").getElementsByTagName("yt-flexible-actions-view-model")[0]]; + buttonDivOwner = [document.getElementById("page-header").getElementsByTagName("yt-flexible-actions-view-model")[0]]; break; } break; diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js index cbbfb18f..336d1419 100644 --- a/test/compatibility.headfull.test.js +++ b/test/compatibility.headfull.test.js @@ -6,7 +6,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { - this.timeout(15000); + this.timeout(20000); context("YouTube", function () { context("shuffle button insertion", function () { @@ -42,16 +42,12 @@ describe("compatibility", function () { }); it('should insert the shuffle button into the channel header', async function () { - // Wait for 1 second to allow the extension to load - await new Promise(resolve => setTimeout(resolve, 1500)); - await page.goto("https://www.youtube.com/@RickAstleyYT"); await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); expect(shuffleButton).to.not.be(null); - }); }); }); From d075ab2f9081b91fad5663b9a0c8b982cecfedb7 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:55:28 +0100 Subject: [PATCH 15/34] Bumped puppeteer, removed headull tests from CI --- .github/workflows/compatibilityTest.yml | 12 +- package-lock.json | 262 ++++++++++++------------ package.json | 2 +- test/compatibility.headfull.test.js | 6 +- 4 files changed, 132 insertions(+), 150 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 340851ed..31443500 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -19,11 +19,8 @@ jobs: - name: Set up node uses: actions/setup-node@v3 - env: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 - # args: install - name: Cache node modules id: cache-npm @@ -58,9 +55,6 @@ jobs: - name: Run headless compatibility tests run: npm run test:compatibility:headless - - name: Run headfull compatibility tests - uses: mujo-code/puppeteer-headful@18.9.0 - env: - CI: "true" - with: - args: npm run test:compatibility:headfull + # TODO: Find way to run headfull tests in GitHub Actions + # - name: Run headfull compatibility tests + # run: npm run test:compatibility:headfull diff --git a/package-lock.json b/package-lock.json index 83e0a96b..64703b08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", - "puppeteer": "^21.11.0", + "puppeteer": "^22.12.1", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", @@ -3329,16 +3329,17 @@ "license": "BSD-3-Clause" }, "node_modules/@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.3.tgz", + "integrity": "sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==", "dev": true, "dependencies": { "debug": "4.3.4", "extract-zip": "2.0.1", "progress": "2.0.3", - "proxy-agent": "6.3.1", - "tar-fs": "3.0.4", + "proxy-agent": "6.4.0", + "semver": "7.6.0", + "tar-fs": "3.0.5", "unbzip2-stream": "1.4.3", "yargs": "17.7.2" }, @@ -3346,7 +3347,7 @@ "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=16.3.0" + "node": ">=18" } }, "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { @@ -3428,6 +3429,33 @@ "node": ">=8" } }, + "node_modules/@puppeteer/browsers/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@puppeteer/browsers/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3459,6 +3487,12 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@puppeteer/browsers/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@puppeteer/browsers/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -5036,6 +5070,45 @@ "dev": true, "optional": true }, + "node_modules/bare-fs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", + "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "dev": true, + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", + "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "dev": true, + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "dev": true, + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", + "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "dev": true, + "optional": true, + "dependencies": { + "streamx": "^2.18.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5545,13 +5618,14 @@ } }, "node_modules/chromium-bidi": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.8.tgz", - "integrity": "sha512-blqh+1cEQbHBKmok3rVJkBlBxt9beKBgOsxbFgs7UJcoVbbeZ+K7+6liAsjgpc8l1Xd55cQUy14fXZdGSb4zIw==", + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.24.tgz", + "integrity": "sha512-5xQNN2SVBdZv4TxeMLaI+PelrnZsHDhn8h2JtyriLr+0qHcZS8BMuo93qN6J1VmtmrgYP+rmcLHcbpnA8QJh+w==", "dev": true, "dependencies": { "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0" + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" @@ -6310,57 +6384,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.12" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/cross-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/cross-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6729,9 +6752,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1232444", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz", - "integrity": "sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==", + "version": "0.0.1299070", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1299070.tgz", + "integrity": "sha512-+qtL3eX50qsJ7c+qVyagqi7AWMoQCBGNfoyJZMwm/NSXVqLYbuitrWEEIzxfUmTNy7//Xe8yhMmQ+elj3uAqSg==", "dev": true }, "node_modules/diff": { @@ -10012,12 +10035,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, "node_modules/mocha": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", @@ -11460,15 +11477,15 @@ } }, "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.0.1", "proxy-from-env": "^1.1.0", @@ -11575,77 +11592,38 @@ } }, "node_modules/puppeteer": { - "version": "21.11.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.11.0.tgz", - "integrity": "sha512-9jTHuYe22TD3sNxy0nEIzC7ZrlRnDgeX3xPkbS7PnbdwYjl2o/z/YuCrRBwezdKpbTDTJ4VqIggzNyeRcKq3cg==", - "deprecated": "< 22.6.4 is no longer supported", + "version": "22.12.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.12.1.tgz", + "integrity": "sha512-1GxY8dnEnHr1SLzdSDr0FCjM6JQfAh2E2I/EqzeF8a58DbGVk9oVjj4lFdqNoVbpgFSpAbz7VER9St7S1wDpNg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@puppeteer/browsers": "1.9.1", - "cosmiconfig": "9.0.0", - "puppeteer-core": "21.11.0" + "@puppeteer/browsers": "2.2.3", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1299070", + "puppeteer-core": "22.12.1" }, "bin": { "puppeteer": "lib/esm/puppeteer/node/cli.js" }, "engines": { - "node": ">=16.13.2" + "node": ">=18" } }, "node_modules/puppeteer-core": { - "version": "21.11.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.11.0.tgz", - "integrity": "sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q==", + "version": "22.12.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.12.1.tgz", + "integrity": "sha512-XmqeDPVdC5/3nGJys1jbgeoZ02wP0WV1GBlPtr/ULRbGXJFuqgXMcKQ3eeNtFpBzGRbpeoCGWHge1ZWKWl0Exw==", "dev": true, "dependencies": { - "@puppeteer/browsers": "1.9.1", - "chromium-bidi": "0.5.8", - "cross-fetch": "4.0.0", - "debug": "4.3.4", - "devtools-protocol": "0.0.1232444", - "ws": "8.16.0" + "@puppeteer/browsers": "2.2.3", + "chromium-bidi": "0.5.24", + "debug": "^4.3.5", + "devtools-protocol": "0.0.1299070", + "ws": "^8.17.1" }, "engines": { - "node": ">=16.13.2" - } - }, - "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=18" } }, "node_modules/querystringify": { @@ -13067,14 +13045,17 @@ } }, "node_modules/tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.5.tgz", + "integrity": "sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==", "dev": true, "dependencies": { - "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" } }, "node_modules/tar-stream": { @@ -14708,6 +14689,15 @@ "async": "^3.2.0", "jszip": "^3.2.2" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index db99d78b..e3b894f0 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "mocha": "^10.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.7.1", - "puppeteer": "^21.11.0", + "puppeteer": "^22.12.1", "sinon": "^15.1.0", "sinon-chrome": "^3.0.1", "web-ext": "^8.0.0", diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js index 336d1419..5275e870 100644 --- a/test/compatibility.headfull.test.js +++ b/test/compatibility.headfull.test.js @@ -6,7 +6,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { - this.timeout(20000); + this.timeout(15000); context("YouTube", function () { context("shuffle button insertion", function () { @@ -18,11 +18,9 @@ describe("compatibility", function () { browser = await puppeteer.launch({ headless: false, // Extensions only work in head-full mode args: [ - '--no-sandbox', `--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}` - ], - executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container + ] }); page = await browser.newPage(); From 2a35dffe31cc0bad288c548bd3e0e197520895ff Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:58:12 +0100 Subject: [PATCH 16/34] Use new headfull action --- .github/workflows/compatibilityTest.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 31443500..5c5f5a94 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -19,8 +19,11 @@ jobs: - name: Set up node uses: actions/setup-node@v3 + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 + args: install - name: Cache node modules id: cache-npm @@ -56,5 +59,10 @@ jobs: run: npm run test:compatibility:headless # TODO: Find way to run headfull tests in GitHub Actions - # - name: Run headfull compatibility tests + - name: Run headfull compatibility tests + uses: elliottback/puppeteer-headful@20.12.0 + env: + CI: "true" + with: + args: npm run test:compatibility:headfull # run: npm run test:compatibility:headfull From 90d08391367cb1dd1d0cfd8ccbaba7deed53fe89 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Tue, 2 Jul 2024 22:00:15 +0100 Subject: [PATCH 17/34] Fix for headull CI action --- test/compatibility.headfull.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headfull.test.js index 5275e870..336d1419 100644 --- a/test/compatibility.headfull.test.js +++ b/test/compatibility.headfull.test.js @@ -6,7 +6,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { - this.timeout(15000); + this.timeout(20000); context("YouTube", function () { context("shuffle button insertion", function () { @@ -18,9 +18,11 @@ describe("compatibility", function () { browser = await puppeteer.launch({ headless: false, // Extensions only work in head-full mode args: [ + '--no-sandbox', `--disable-extensions-except=${extensionPath}`, `--load-extension=${extensionPath}` - ] + ], + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container }); page = await browser.newPage(); From dbfaf9b365312ef2bb623af5b023851162d3d284 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:52:48 +0100 Subject: [PATCH 18/34] Updated uses clause --- .github/workflows/compatibilityTest.yml | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 5c5f5a94..2f9d82c3 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -58,11 +58,11 @@ jobs: - name: Run headless compatibility tests run: npm run test:compatibility:headless - # TODO: Find way to run headfull tests in GitHub Actions - - name: Run headfull compatibility tests - uses: elliottback/puppeteer-headful@20.12.0 + # TODO: Find way to run headful tests in GitHub Actions + - name: Run headful compatibility tests + uses: nikkelm/puppeteer-headful@v1.0.0 env: CI: "true" with: - args: npm run test:compatibility:headfull - # run: npm run test:compatibility:headfull + args: npm run test:compatibility:headful + # run: npm run test:compatibility:headful diff --git a/package.json b/package.json index e3b894f0..25579ab5 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility*.test.js --require mocha-suppress-logs", "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js", "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js", - "test:compatibility:headfull": "mocha ./test/testSetup.js ./test/compatibility.headfull.test.js" + "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js" }, "type": "module", "devDependencies": { From f3d5129e5ed49684746ea36d7ffba2b6d3f0e046 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:54:02 +0100 Subject: [PATCH 19/34] Fixed filename --- ...mpatibility.headfull.test.js => compatibility.headful.test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{compatibility.headfull.test.js => compatibility.headful.test.js} (100%) diff --git a/test/compatibility.headfull.test.js b/test/compatibility.headful.test.js similarity index 100% rename from test/compatibility.headfull.test.js rename to test/compatibility.headful.test.js From 15bf5c026eac979a45e93a912d0ebb0d9aa2145e Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:56:20 +0100 Subject: [PATCH 20/34] Updated timeout --- .github/workflows/compatibilityTest.yml | 3 +-- test/compatibility.headful.test.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 2f9d82c3..ab11aba0 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -23,7 +23,6 @@ jobs: PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 - args: install - name: Cache node modules id: cache-npm @@ -64,5 +63,5 @@ jobs: env: CI: "true" with: - args: npm run test:compatibility:headful + args: npm run test:compatibility # run: npm run test:compatibility:headful diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index 336d1419..f29698b8 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -1,3 +1,4 @@ +// Puppeteer browser tests that install the extension and therefore require a headful browser to run. import expect from "expect.js"; import puppeteer from "puppeteer"; import { fileURLToPath } from 'url'; @@ -6,7 +7,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { - this.timeout(20000); + this.timeout(50000); context("YouTube", function () { context("shuffle button insertion", function () { From 6bd5dcf9491878d0e25b02a8b82c412ba2f26b68 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:59:40 +0100 Subject: [PATCH 21/34] Remove other tasks for debugging --- .github/workflows/compatibilityTest.yml | 58 ++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index ab11aba0..bcc9d708 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -24,41 +24,41 @@ jobs: with: node-version: 18 - - name: Cache node modules - id: cache-npm - uses: actions/cache@v3 - env: - cache-name: cache-node-modules - with: - path: ~/.npm - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- + # - name: Cache node modules + # id: cache-npm + # uses: actions/cache@v3 + # env: + # cache-name: cache-node-modules + # with: + # path: ~/.npm + # key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-build-${{ env.cache-name }}- + # ${{ runner.os }}-build- + # ${{ runner.os }}- - - name: Cache Puppeteer Chrome - uses: actions/cache@v3 - env: - cache-name: cache-puppeteer-chrome - with: - path: | - ~/.cache/puppeteer - key: ${{ runner.os }}-puppeteer-chrome-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-puppeteer-chrome- + # - name: Cache Puppeteer Chrome + # uses: actions/cache@v3 + # env: + # cache-name: cache-puppeteer-chrome + # with: + # path: | + # ~/.cache/puppeteer + # key: ${{ runner.os }}-puppeteer-chrome-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.os }}-puppeteer-chrome- - - name: Install dependencies - run: npm install + # - name: Install dependencies + # run: npm install - - name: Setup Chrome for Puppeteer - run: npx puppeteer browsers install chrome + # - name: Setup Chrome for Puppeteer + # run: npx puppeteer browsers install chrome - - name: Run headless compatibility tests - run: npm run test:compatibility:headless + # - name: Run headless compatibility tests + # run: npm run test:compatibility:headless # TODO: Find way to run headful tests in GitHub Actions - - name: Run headful compatibility tests + - name: Run compatibility tests uses: nikkelm/puppeteer-headful@v1.0.0 env: CI: "true" From 487ab79bb9c351ec17c1149707eacafedc86eec9 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:01:05 +0100 Subject: [PATCH 22/34] Install dependencies --- .github/workflows/compatibilityTest.yml | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index bcc9d708..68a1be1a 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -24,18 +24,18 @@ jobs: with: node-version: 18 - # - name: Cache node modules - # id: cache-npm - # uses: actions/cache@v3 - # env: - # cache-name: cache-node-modules - # with: - # path: ~/.npm - # key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} - # restore-keys: | - # ${{ runner.os }}-build-${{ env.cache-name }}- - # ${{ runner.os }}-build- - # ${{ runner.os }}- + - name: Cache node modules + id: cache-npm + uses: actions/cache@v3 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- # - name: Cache Puppeteer Chrome # uses: actions/cache@v3 @@ -48,8 +48,8 @@ jobs: # restore-keys: | # ${{ runner.os }}-puppeteer-chrome- - # - name: Install dependencies - # run: npm install + - name: Install dependencies + run: npm install # - name: Setup Chrome for Puppeteer # run: npx puppeteer browsers install chrome From 376503a90a63df2fd05c6e52dbac155ff6c70027 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:05:29 +0100 Subject: [PATCH 23/34] Added args --- .github/workflows/compatibilityTest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 68a1be1a..62568952 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -23,6 +23,7 @@ jobs: PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 + args: install - name: Cache node modules id: cache-npm From 1e7612cb0a68c3e0b423a0f964457f829913d1ae Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:14:35 +0100 Subject: [PATCH 24/34] Updated browser initialization --- .github/workflows/compatibilityTest.yml | 2 +- test/compatibility.headless.test.js | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 62568952..09c90742 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -60,7 +60,7 @@ jobs: # TODO: Find way to run headful tests in GitHub Actions - name: Run compatibility tests - uses: nikkelm/puppeteer-headful@v1.0.0 + uses: nikkelm/puppeteer-headful@master env: CI: "true" with: diff --git a/test/compatibility.headless.test.js b/test/compatibility.headless.test.js index ca0a85ae..ce0f9f4e 100644 --- a/test/compatibility.headless.test.js +++ b/test/compatibility.headless.test.js @@ -23,7 +23,11 @@ describe("compatibility", function () { let browser, page; beforeEach(async () => { - browser = await puppeteer.launch({ headless: true }); + browser = await puppeteer.launch({ + headless: true, // Extensions only work in head-full mode + args: ['--no-sandbox'], + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container + }); page = await browser.newPage(); // Set the SOCS cookie for YouTube (cookie banner) @@ -148,7 +152,11 @@ describe("compatibility", function () { let browser, page; beforeEach(async () => { - browser = await puppeteer.launch({ headless: true }); + browser = await puppeteer.launch({ + headless: true, // Extensions only work in head-full mode + args: ['--no-sandbox'], + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container + }); page = await browser.newPage(); // Set the SOCS cookie for YouTube (cookie banner) From 4224390cb2046653bf320a88ecf01898e8c6094b Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:21:22 +0100 Subject: [PATCH 25/34] Updated timeout --- test/compatibility.headful.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index f29698b8..b0b9c485 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -7,7 +7,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe("compatibility", function () { - this.timeout(50000); + this.timeout(30000); context("YouTube", function () { context("shuffle button insertion", function () { From 9daaf28b2b8be55f62f02d8239e36192df460cad Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:42:49 +0100 Subject: [PATCH 26/34] Build extension before running tests --- .github/workflows/compatibilityTest.yml | 2 +- test/compatibility.headful.test.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 09c90742..32dc934b 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -64,5 +64,5 @@ jobs: env: CI: "true" with: - args: npm run test:compatibility + args: npm run build:chromium && npm run test:compatibility # run: npm run test:compatibility:headful diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index b0b9c485..37ea469d 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -19,9 +19,9 @@ describe("compatibility", function () { browser = await puppeteer.launch({ headless: false, // Extensions only work in head-full mode args: [ - '--no-sandbox', `--disable-extensions-except=${extensionPath}`, - `--load-extension=${extensionPath}` + `--load-extension=${extensionPath}`, + '--no-sandbox' ], executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container }); From 85db7d9739b6d4d799a9c213652a2f2f7677f586 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:48:04 +0100 Subject: [PATCH 27/34] Build outside of container --- .github/workflows/compatibilityTest.yml | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 32dc934b..2a917a6a 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -38,31 +38,15 @@ jobs: ${{ runner.os }}-build- ${{ runner.os }}- - # - name: Cache Puppeteer Chrome - # uses: actions/cache@v3 - # env: - # cache-name: cache-puppeteer-chrome - # with: - # path: | - # ~/.cache/puppeteer - # key: ${{ runner.os }}-puppeteer-chrome-${{ hashFiles('**/package-lock.json') }} - # restore-keys: | - # ${{ runner.os }}-puppeteer-chrome- - - name: Install dependencies run: npm install + + - name: Build extension + run: npm run build:chromium - # - name: Setup Chrome for Puppeteer - # run: npx puppeteer browsers install chrome - - # - name: Run headless compatibility tests - # run: npm run test:compatibility:headless - - # TODO: Find way to run headful tests in GitHub Actions - name: Run compatibility tests uses: nikkelm/puppeteer-headful@master env: CI: "true" with: - args: npm run build:chromium && npm run test:compatibility - # run: npm run test:compatibility:headful + args: npm run test:compatibility From 2d4e4f0f4e78f247869e1b65ee52c84c9770035b Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:52:56 +0100 Subject: [PATCH 28/34] Cleanup --- package.json | 6 +++--- test/compatibility.headful.test.js | 2 +- test/compatibility.headless.test.js | 6 +----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 25579ab5..c641f876 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility*.test.js --require mocha-suppress-logs", - "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js", - "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js", - "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js" + "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js --require mocha-suppress-logs", + "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js --require mocha-suppress-logs", + "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js --require mocha-suppress-logs" }, "type": "module", "devDependencies": { diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index 37ea469d..1e873b6e 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -6,7 +6,7 @@ import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); -describe("compatibility", function () { +describe("headful compatibility", function () { this.timeout(30000); context("YouTube", function () { diff --git a/test/compatibility.headless.test.js b/test/compatibility.headless.test.js index ce0f9f4e..67e75979 100644 --- a/test/compatibility.headless.test.js +++ b/test/compatibility.headless.test.js @@ -1,11 +1,7 @@ import expect from "expect.js"; import puppeteer from "puppeteer"; -import { fileURLToPath } from 'url'; -import { dirname, join } from 'path'; -const __dirname = dirname(fileURLToPath(import.meta.url)); - -describe("compatibility", function () { +describe("headless compatibility", function () { this.timeout(15000); context("YouTube", function () { From fcd4ca6b104e595ae0d3d7f142a777ac02cc3e3e Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:53:36 +0100 Subject: [PATCH 29/34] Removed install command --- .github/workflows/compatibilityTest.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 2a917a6a..2607d6e7 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -23,7 +23,6 @@ jobs: PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" with: node-version: 18 - args: install - name: Cache node modules id: cache-npm From db43f4e5c8fee0e76b44ee946a1fbd4f444ae78c Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:13:53 +0100 Subject: [PATCH 30/34] Fix version --- .github/workflows/compatibilityTest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compatibilityTest.yml b/.github/workflows/compatibilityTest.yml index 2607d6e7..ef72257e 100644 --- a/.github/workflows/compatibilityTest.yml +++ b/.github/workflows/compatibilityTest.yml @@ -44,7 +44,7 @@ jobs: run: npm run build:chromium - name: Run compatibility tests - uses: nikkelm/puppeteer-headful@master + uses: nikkelm/puppeteer-headful@1.0.0 env: CI: "true" with: From 062d674471444e124d5972cec209963c9a31e8a7 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:30:48 +0100 Subject: [PATCH 31/34] Cleaner separations between tests, test cleanup afterEach, allow retries --- package.json | 6 +- test/compatibility.headful.test.js | 91 +++++---- test/compatibility.headless.test.js | 284 ++++++++++++++-------------- test/compatibility.test.js | 13 ++ 4 files changed, 219 insertions(+), 175 deletions(-) create mode 100644 test/compatibility.test.js diff --git a/package.json b/package.json index c641f876..cdbf382d 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility*.test.js --require mocha-suppress-logs", - "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js --require mocha-suppress-logs", - "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.headless.test.js --require mocha-suppress-logs", - "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js --require mocha-suppress-logs" + "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js --require mocha-suppress-logs --retries 3", + "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.test.js ./test/compatibility.headless.test.js --require mocha-suppress-logs --retries 3", + "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js --require mocha-suppress-logs --retries 3" }, "type": "module", "devDependencies": { diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index 1e873b6e..27d4699e 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -9,47 +9,68 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); describe("headful compatibility", function () { this.timeout(30000); - context("YouTube", function () { - context("shuffle button insertion", function () { - let browser, page; - - beforeEach(async () => { - const extensionPath = join(__dirname, "../dist/chromium"); - - browser = await puppeteer.launch({ - headless: false, // Extensions only work in head-full mode - args: [ - `--disable-extensions-except=${extensionPath}`, - `--load-extension=${extensionPath}`, - '--no-sandbox' - ], - executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container - }); - page = await browser.newPage(); - - // Set the SOCS cookie for YouTube (cookie banner) - await page.setCookie({ - 'name': 'SOCS', - 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value - 'domain': '.youtube.com', - 'path': '/', - 'secure': true, - 'httpOnly': false - }); + context("shuffle button insertion", function () { + let browser, page; + + before(async () => { + const extensionPath = join(__dirname, "../dist/chromium"); + + browser = await puppeteer.launch({ + headless: false, // Extensions only work in head-full mode + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}`, + '--no-sandbox' + ], + executablePath: process.env.PUPPETEER_EXEC_PATH, }); + page = await browser.newPage(); - afterEach(async () => { - await browser.close(); + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false }); + }); + + after(async () => { + await browser.close(); + }); + + afterEach(async () => { + await page.close(); + page = await browser.newPage(); + }); - it('should insert the shuffle button into the channel header', async function () { - await page.goto("https://www.youtube.com/@RickAstleyYT"); + it('should insert the shuffle button into channel pages', async function () { + await page.goto("https://www.youtube.com/@RickAstleyYT"); - await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); - const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); + await page.waitForSelector("#youtube-random-video-large-shuffle-button-channel"); + const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-channel"); - expect(shuffleButton).to.not.be(null); - }); + expect(shuffleButton).to.not.be(null); + }); + + it('should insert the shuffle button into video pages', async function () { + await page.goto("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); + + await page.waitForSelector("#youtube-random-video-large-shuffle-button-video"); + const shuffleButton = await page.$("#youtube-random-video-large-shuffle-button-video"); + + expect(shuffleButton).to.not.be(null); + }); + + it('should insert the shuffle button into shorts pages', async function () { + await page.goto("https://www.youtube.com/shorts/vOSD7vSreXA"); + + await page.waitForSelector("#youtube-random-video-small-shuffle-button-short"); + const shuffleButton = await page.$("#youtube-random-video-small-shuffle-button-short"); + + expect(shuffleButton).to.not.be(null); }); }); }); \ No newline at end of file diff --git a/test/compatibility.headless.test.js b/test/compatibility.headless.test.js index 67e75979..d927e63a 100644 --- a/test/compatibility.headless.test.js +++ b/test/compatibility.headless.test.js @@ -3,176 +3,186 @@ import puppeteer from "puppeteer"; describe("headless compatibility", function () { this.timeout(15000); + let browser, page; - context("YouTube", function () { - context("URLs", function () { - it("should redirect a watch_videos URL to a temporary playlist URL", async function () { - const watchVideosUrl = "https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ"; - const redirectedUrl = (await fetch(watchVideosUrl)).url; - - // The playlist is temporary, indicated by a TL start in the ID - expect(redirectedUrl).to.contain("https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL"); - }); + before(async () => { + browser = await puppeteer.launch({ + headless: true, // Extensions only work in head-full mode + args: ['--no-sandbox'], + executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container }); + page = await browser.newPage(); + + // Set the SOCS cookie for YouTube (cookie banner) + await page.setCookie({ + 'name': 'SOCS', + 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value + 'domain': '.youtube.com', + 'path': '/', + 'secure': true, + 'httpOnly': false + }); + }); - context("events", function () { - let browser, page; + after(async () => { + await browser.close(); + }); - beforeEach(async () => { - browser = await puppeteer.launch({ - headless: true, // Extensions only work in head-full mode - args: ['--no-sandbox'], - executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container - }); - page = await browser.newPage(); - - // Set the SOCS cookie for YouTube (cookie banner) - await page.setCookie({ - 'name': 'SOCS', - 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value - 'domain': '.youtube.com', - 'path': '/', - 'secure': true, - 'httpOnly': false + afterEach(async () => { + await page.close(); + page = await browser.newPage(); + }); + + context("events", function () { + it("should contain required data in the yt-navigate-finish event for video pages", async function () { + let event = {}; + + // Create a promise that listens for the "yt-navigate-finish" event + const waitForNavigateFinish = new Promise((resolve, reject) => { + page.on("console", msg => { + if (msg.text().includes("yt-navigate-finish")) { + event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); + resolve(); + } }); }); - afterEach(async () => { - await browser.close(); + await page.evaluateOnNewDocument(() => { + document.addEventListener("yt-navigate-finish", function (e) { + const serializableEvent = { + channelId: e.detail?.response?.playerResponse?.videoDetails?.channelId, + channelName: e.detail?.response?.playerResponse?.videoDetails?.author + }; + console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); + }); }); - it("should contain required data in the yt-navigate-finish event for video pages", async function () { - let event = {}; - - // Create a promise that listens for the "yt-navigate-finish" event - const waitForNavigateFinish = new Promise((resolve, reject) => { - page.on("console", msg => { - if (msg.text().includes("yt-navigate-finish")) { - event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); - resolve(); - } - }); - }); + await page.goto("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); - await page.evaluateOnNewDocument(() => { - document.addEventListener("yt-navigate-finish", function (e) { - const serializableEvent = { - channelId: e.detail?.response?.playerResponse?.videoDetails?.channelId, - channelName: e.detail?.response?.playerResponse?.videoDetails?.author - }; - console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); - }); - }); + const timeout = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error("Timed out waiting for yt-navigate-finish event")); + }, 5000); + }); - // Navigate to a YouTube video page - await page.goto("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); + // Wait for either the event to fire or the timeout + try { + await Promise.race([waitForNavigateFinish, timeout]); + } catch (error) { + console.error(error.message); + } - const timeout = new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error("Timed out waiting for yt-navigate-finish event")); - }, 5000); - }); + console.log("The following data was extracted from the yt-navigate-finish event:"); + console.log(event); - // Wait for either the event to fire or the timeout - try { - await Promise.race([waitForNavigateFinish, timeout]); - } catch (error) { - console.error(error.message); - } + expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); + expect(event.channelName).to.be("Rick Astley"); + }); - console.log("The following data was extracted from the yt-navigate-finish event:"); - console.log(event); + it("should contain required data in the yt-navigate-finish event for channel pages", async function () { + let event = {}; - expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); - expect(event.channelName).to.be("Rick Astley"); - }); - - it("should contain required data in the yt-navigate-finish event for channel pages", async function () { - let event = {}; - - // Create a promise that listens for the "yt-navigate-finish" event - const waitForNavigateFinish = new Promise((resolve, reject) => { - page.on("console", msg => { - if (msg.text().includes("yt-navigate-finish")) { - event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); - resolve(); - } - }); + // Create a promise that listens for the "yt-navigate-finish" event + const waitForNavigateFinish = new Promise((resolve, reject) => { + page.on("console", msg => { + if (msg.text().includes("yt-navigate-finish")) { + event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); + resolve(); + } }); + }); - await page.evaluateOnNewDocument(() => { - document.addEventListener("yt-navigate-finish", function (e) { - const serializableEvent = { - eventVersion: "default", - channelId: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.channelId, - channelName: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.title - }; - if (!serializableEvent.channelId) { - serializableEvent.eventVersion = "20240521"; - serializableEvent.channelId = e.detail?.endpoint?.browseEndpoint?.browseId; - } - if (!serializableEvent.channelName) { - serializableEvent.eventVersion = "20240521"; - serializableEvent.channelName = e.detail?.response?.response?.header?.pageHeaderRenderer?.pageTitle; - } - - console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); - }); + await page.evaluateOnNewDocument(() => { + document.addEventListener("yt-navigate-finish", function (e) { + const serializableEvent = { + eventVersion: "default", + channelId: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.channelId, + channelName: e.detail?.response?.response?.header?.c4TabbedHeaderRenderer?.title + }; + if (!serializableEvent.channelId) { + serializableEvent.eventVersion = "20240521"; + serializableEvent.channelId = e.detail?.endpoint?.browseEndpoint?.browseId; + } + if (!serializableEvent.channelName) { + serializableEvent.eventVersion = "20240521"; + serializableEvent.channelName = e.detail?.response?.response?.header?.pageHeaderRenderer?.pageTitle; + } + + console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); }); + }); - // Navigate to a YouTube video page - await page.goto("https://www.youtube.com/@RickAstleyYT"); + // Navigate to a YouTube video page + await page.goto("https://www.youtube.com/@RickAstleyYT"); - const timeout = new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error("Timed out waiting for yt-navigate-finish event")); - }, 5000); - }); + const timeout = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error("Timed out waiting for yt-navigate-finish event")); + }, 5000); + }); - // Wait for either the event to fire or the timeout - try { - await Promise.race([waitForNavigateFinish, timeout]); - } catch (error) { - console.error(error.message); - } + // Wait for either the event to fire or the timeout + try { + await Promise.race([waitForNavigateFinish, timeout]); + } catch (error) { + console.error(error.message); + } - console.log("The following data was extracted from the yt-navigate-finish event:"); - console.log(event); + console.log("The following data was extracted from the yt-navigate-finish event:"); + console.log(event); - expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); - expect(event.channelName).to.be("Rick Astley"); - }); + expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); + expect(event.channelName).to.be("Rick Astley"); }); - context("DOM elements", function () { - let browser, page; + it("should contain required data in the yt-navigate-finish event for shorts pages", async function () { + let event = {}; - beforeEach(async () => { - browser = await puppeteer.launch({ - headless: true, // Extensions only work in head-full mode - args: ['--no-sandbox'], - executablePath: process.env.PUPPETEER_EXEC_PATH, // set by docker container - }); - page = await browser.newPage(); - - // Set the SOCS cookie for YouTube (cookie banner) - await page.setCookie({ - 'name': 'SOCS', - 'value': 'CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg', // base64 encoded value - 'domain': '.youtube.com', - 'path': '/', - 'secure': true, - 'httpOnly': false + // Create a promise that listens for the "yt-navigate-finish" event + const waitForNavigateFinish = new Promise((resolve, reject) => { + page.on("console", msg => { + if (msg.text().includes("yt-navigate-finish")) { + event = JSON.parse(msg.text().replace("yt-navigate-finish ", "")); + resolve(); + } }); }); - afterEach(async () => { - await browser.close(); + await page.evaluateOnNewDocument(() => { + document.addEventListener("yt-navigate-finish", function (e) { + const serializableEvent = { + channelId: e.detail?.response?.playerResponse?.videoDetails?.channelId, + channelName: e.detail?.response?.playerResponse?.videoDetails?.author + }; + console.log("yt-navigate-finish", JSON.stringify(serializableEvent)); + }); }); - it("should contain the expected channel header elements to insert the button into", async function () { + await page.goto("https://www.youtube.com/shorts/vOSD7vSreXA"); + + const timeout = new Promise((resolve, reject) => { + setTimeout(() => { + reject(new Error("Timed out waiting for yt-navigate-finish event")); + }, 5000); }); + + // Wait for either the event to fire or the timeout + try { + await Promise.race([waitForNavigateFinish, timeout]); + } catch (error) { + console.error(error.message); + } + + console.log("The following data was extracted from the yt-navigate-finish event:"); + console.log(event); + + expect(event.channelId).to.be("UCuAXFkgsw1L7xaCfnd5JJOw"); + expect(event.channelName).to.be("Rick Astley"); }); + }); + context("DOM elements", function () { + it("should contain the expected channel header elements to insert the button into", async function () { + }); }); }); \ No newline at end of file diff --git a/test/compatibility.test.js b/test/compatibility.test.js new file mode 100644 index 00000000..6085fbef --- /dev/null +++ b/test/compatibility.test.js @@ -0,0 +1,13 @@ +import expect from "expect.js"; + +describe("compatibility", function () { + context("YouTube URLs", function () { + it("should redirect a watch_videos URL to a temporary playlist URL", async function () { + const watchVideosUrl = "https://www.youtube.com/watch_videos?video_ids=dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ,dQw4w9WgXcQ"; + const redirectedUrl = (await fetch(watchVideosUrl)).url; + + // The playlist is temporary, indicated by a TL start in the ID + expect(redirectedUrl).to.contain("https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=TL"); + }); + }); +}); \ No newline at end of file From 90fbf33837559d7c2caa9cbefa7b30c8fe633714 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:32:27 +0100 Subject: [PATCH 32/34] Added new test:all command --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index cdbf382d..59c9fe5d 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "lint": "eslint --ext .ts,.js --max-warnings=0 . --ignore-path .eslintignore", "lint:firefox": "web-ext lint --source-dir ./dist/firefox", "test": "c8 --reporter=lcov --reporter=text mocha ./test/testSetup.js ./test/chromeStorage.test.js ./test/**/*.test.js --exclude ./test/compatibility*.test.js --require mocha-suppress-logs", + "test:all": "npm run test && npm run test:compatibility", "test:compatibility": "mocha ./test/testSetup.js ./test/compatibility*.test.js --require mocha-suppress-logs --retries 3", "test:compatibility:headless": "mocha ./test/testSetup.js ./test/compatibility.test.js ./test/compatibility.headless.test.js --require mocha-suppress-logs --retries 3", "test:compatibility:headful": "mocha ./test/testSetup.js ./test/compatibility.headful.test.js --require mocha-suppress-logs --retries 3" From b6b7189aea83c7fac3a3a5184cd9acd4e4661f1f Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:37:07 +0100 Subject: [PATCH 33/34] Removed empty test --- test/compatibility.headful.test.js | 2 +- test/compatibility.headless.test.js | 6 +----- test/compatibility.test.js | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/test/compatibility.headful.test.js b/test/compatibility.headful.test.js index 27d4699e..74c75fcc 100644 --- a/test/compatibility.headful.test.js +++ b/test/compatibility.headful.test.js @@ -1,4 +1,4 @@ -// Puppeteer browser tests that install the extension and therefore require a headful browser to run. +// Puppeteer browser tests that install the extension and therefore require a headful browser. import expect from "expect.js"; import puppeteer from "puppeteer"; import { fileURLToPath } from 'url'; diff --git a/test/compatibility.headless.test.js b/test/compatibility.headless.test.js index d927e63a..d72df5bf 100644 --- a/test/compatibility.headless.test.js +++ b/test/compatibility.headless.test.js @@ -1,3 +1,4 @@ +// Tests that can be run in a headless puppeteer browser. import expect from "expect.js"; import puppeteer from "puppeteer"; @@ -180,9 +181,4 @@ describe("headless compatibility", function () { expect(event.channelName).to.be("Rick Astley"); }); }); - - context("DOM elements", function () { - it("should contain the expected channel header elements to insert the button into", async function () { - }); - }); }); \ No newline at end of file diff --git a/test/compatibility.test.js b/test/compatibility.test.js index 6085fbef..6ab0bafd 100644 --- a/test/compatibility.test.js +++ b/test/compatibility.test.js @@ -1,3 +1,4 @@ +// Compatibility tests that do not need puppeteer/a mocked browser environment import expect from "expect.js"; describe("compatibility", function () { From a91d0b0827a7dd7ef99b450bcbce798d198b8e02 Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:39:03 +0100 Subject: [PATCH 34/34] Updated changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4305e398..40d89818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ - Fixed a bug where the shuffle button would sometimes not be added to the page if it was opened directly from a new tab. - Fixed a bug where the playlist created by the extension would sometimes not be renamed correctly. - Fixed an animation bug when ignoring shorts and shuffling a channel with many videos from a shorts page. -- Fixed the shuffle button not being added to the channel page with a new YouTube UI. +- Fixed the shuffle button not being added to the channel page if the browser is using a new YouTube UI. ## v3.1.7