From bf8646e62d83f94a9645d6c674c5fe5d52cb781d Mon Sep 17 00:00:00 2001 From: galargh Date: Mon, 19 Dec 2022 17:20:50 +0100 Subject: [PATCH 1/9] feat: add E2E tests for chromium and firefox --- Dockerfile | 9 +- ci/access-control-allow-all.sh | 5 + ci/download-release-artifacts.sh | 11 +++ docker-compose.e2e.yml | 39 ++++++++ package-lock.json | 56 +++++++++++ package.json | 8 +- test/e2e/ipfs-companion.test.js | 155 +++++++++++++++++++++++++++++++ 7 files changed, 279 insertions(+), 4 deletions(-) create mode 100755 ci/access-control-allow-all.sh create mode 100755 ci/download-release-artifacts.sh create mode 100644 docker-compose.e2e.yml create mode 100644 test/e2e/ipfs-companion.test.js diff --git a/Dockerfile b/Dockerfile index 57ebc305d..8100ddc36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,19 +6,22 @@ ARG GROUP_ID RUN curl -s https://ipfs.io/ipfs/QmbukYcmtyU6ZEKt6fepnvrTNa9F6VqsUPMUgNxQjEmphH > /usr/local/bin/jq && chmod +x /usr/local/bin/jq RUN mkdir -p /home/node/app -WORKDIR /home/node/app - RUN if [ ${USER_ID:-0} -ne 0 ] && [ ${GROUP_ID:-0} -ne 0 ]; then \ userdel -f node && \ if getent group node ; then groupdel node; fi && \ groupadd -g ${GROUP_ID} node && \ useradd -l -u ${USER_ID} -g node node && \ chown -fhR ${USER_ID}:${GROUP_ID} /home/node; fi +RUN chown node:node /home/node/app -COPY --chown=${USER_ID}:${GROUP_ID} . /home/node/app +WORKDIR /home/node/app + +COPY --chown=node:node ./package.json ./package-lock.json /home/node/app/ USER node RUN npm run ci:install +COPY --chown=node:node . /home/node/app + ENV PATH="/home/node/app/node_modules/.bin:${PATH}" diff --git a/ci/access-control-allow-all.sh b/ci/access-control-allow-all.sh new file mode 100755 index 000000000..4b7426327 --- /dev/null +++ b/ci/access-control-allow-all.sh @@ -0,0 +1,5 @@ +#!/bin/sh +set -ex + +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]' +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["*"]' diff --git a/ci/download-release-artifacts.sh b/ci/download-release-artifacts.sh new file mode 100755 index 000000000..d4615c400 --- /dev/null +++ b/ci/download-release-artifacts.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -ex + +IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION:-$(jq -r '.version' ./add-on/manifest.common.json)} + +id="$(curl --retry 5 --no-progress-meter "https://api.github.com/repos/ipfs/ipfs-companion/releases/tags/v$IPFS_COMPANION_VERSION" | jq '.id')" +assets="$(curl --retry 5 --no-progress-meter --location "https://api.github.com/repos/ipfs/ipfs-companion/releases/$id/assets" | jq -r '.[].name')" + +for asset in $assets; do + curl --retry 5 --no-progress-meter --location --output "build/$asset" "https://github.com/ipfs/ipfs-companion/releases/download/v$IPFS_COMPANION_VERSION/$asset" +done diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml new file mode 100644 index 000000000..fe5675f1c --- /dev/null +++ b/docker-compose.e2e.yml @@ -0,0 +1,39 @@ +version: "3.9" +services: + firefox: + image: selenium/standalone-firefox:${FIREFOX_VERSION:-latest} + shm_size: 2g + ports: + - 4444 + - 7900 + chromium: + # WARN: `standalone-chrome` does NOT work on ARM-based machines; + # see https://github.com/SeleniumHQ/docker-selenium#experimental-mult-arch-aarch64armhfamd64-images; + # try using `seleniarm/standalone-chromium` instead + # export CHROMIUM_IMAGE=seleniarm/standalone-chromium + image: ${CHROMIUM_IMAGE:-selenium/standalone-chrome}:${CHROMIUM_VERSION:-latest} + shm_size: 2g + ports: + - 4444 + - 7900 + kubo: + image: ipfs/kubo:${KUBO_VERSION:-latest} + ports: + - 4001 + - 5001 + - 8080 + volumes: + - ./ci/access-control-allow-all.sh:/container-init.d/001-access-control-allow-all.sh + e2e: + build: + dockerfile: ./Dockerfile + environment: + - SELENIUM_REMOTE_CHROMIUM_URL=http://chromium:4444 + - SELENIUM_REMOTE_FIREFOX_URL=http://firefox:4444 + - IPFS_API_URL=http://kubo:5001 + - CUSTOM_GATEWAY_URL=http://kubo:8080 + - TEST_E2E=1 + - TEST_HEADLESS=${TEST_HEADLESS} + - IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION} + volumes: + - ./build:/home/node/app/build diff --git a/package-lock.json b/package-lock.json index 169c5660d..0b9457ad3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "path": "0.12.7", "raw-loader": "4.0.2", "request-progress": "3.0.0", + "selenium-webdriver": "^4.7.1", "shx": "0.3.4", "sinon": "13.0.1", "sinon-chrome": "3.0.1", @@ -18260,6 +18261,41 @@ "seek-table": "bin/seek-bzip-table" } }, + "node_modules/selenium-webdriver": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.7.1.tgz", + "integrity": "sha512-IfTM9OE8HtCKjOJwyudbAVtAHQKOJK8mu2qrXXbKyj4lqgXF+2lYW4rSZXCV6SLQRWZ+DVGkomCmFzq5orD/ZA==", + "dev": true, + "dependencies": { + "jszip": "^3.10.0", + "tmp": "^0.2.1", + "ws": ">=8.7.0" + }, + "engines": { + "node": ">= 14.20.0" + } + }, + "node_modules/selenium-webdriver/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "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/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -35430,6 +35466,26 @@ "commander": "^2.8.1" } }, + "selenium-webdriver": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.7.1.tgz", + "integrity": "sha512-IfTM9OE8HtCKjOJwyudbAVtAHQKOJK8mu2qrXXbKyj4lqgXF+2lYW4rSZXCV6SLQRWZ+DVGkomCmFzq5orD/ZA==", + "dev": true, + "requires": { + "jszip": "^3.10.0", + "tmp": "^0.2.1", + "ws": ">=8.7.0" + }, + "dependencies": { + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "requires": {} + } + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", diff --git a/package.json b/package.json index 1925c0413..edd4d2cac 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "watch:js": "run-p watch:js:*", "watch:js:webpack": "webpack --watch --mode development --devtool inline-source-map --config ./webpack.config.js", "test": "run-s test:*", + "test:e2e": "mocha --timeout 300000 --exit --require ignore-styles \"test/e2e/**/*.test.js\"", "test:functional": "c8 mocha --timeout 5000 --exit --require ignore-styles \"test/functional/**/*.test.js\"", "lint": "run-s lint:*", "lint:standard": "standard -v \"*.js\" \"add-on/src/**/*.js\" \"test/**/*.js\" \"scripts/**/*.js\"", @@ -59,7 +60,11 @@ "beta-build": "docker rmi -f ipfs-companion-beta-build && docker build -t ipfs-companion-beta-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm -it --net=host -e RELEASE_CHANNEL=beta -v $(pwd)/build:/home/node/app/build ipfs-companion-beta-build npm run ci:build", "release-build": "docker rmi -f ipfs-companion-release-build && docker build -t ipfs-companion-release-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm -it --net=host -e RELEASE_CHANNEL=stable -v $(pwd)/build:/home/node/app/build ipfs-companion-release-build npm run ci:build", "dev-build": "npm ci && npm run build", - "yarn-build": "npm run dev-build" + "yarn-build": "npm run dev-build", + "compose:e2e:build": "docker compose --file docker-compose.e2e.yml build", + "compose:e2e:up": "docker compose --file docker-compose.e2e.yml up --remove-orphans --detach kubo chromium firefox", + "compose:e2e:test": "docker compose --file docker-compose.e2e.yml run e2e npm run test:e2e", + "compose:e2e:stop": "docker compose --file docker-compose.e2e.yml stop" }, "private": true, "preferGlobal": false, @@ -101,6 +106,7 @@ "path": "0.12.7", "raw-loader": "4.0.2", "request-progress": "3.0.0", + "selenium-webdriver": "^4.7.1", "shx": "0.3.4", "sinon": "13.0.1", "sinon-chrome": "3.0.1", diff --git a/test/e2e/ipfs-companion.test.js b/test/e2e/ipfs-companion.test.js new file mode 100644 index 000000000..30c1bcaf5 --- /dev/null +++ b/test/e2e/ipfs-companion.test.js @@ -0,0 +1,155 @@ +import { Builder, By, Key } from 'selenium-webdriver' +import { describe, it, before } from 'mocha' +import { expect } from 'chai' +import fs from 'fs' +import chrome from 'selenium-webdriver/chrome.js' +import firefox from 'selenium-webdriver/firefox.js' + +async function delay (ms) { + return new Promise(res => setTimeout(res, ms), _ => {}) +} + +function getVersion () { + return process.env.IPFS_COMPANION_VERSION || JSON.parse(fs.readFileSync('add-on/manifest.common.json')).version +} + +async function openChromiumBrowser () { + console.info('Opening Chromium browser') + const extension = `build/ipfs_companion-${getVersion()}_chromium.zip` + console.info(`Checking if ${extension} exists`) + expect(fs.existsSync(extension)).to.be.true // eslint-disable-line no-unused-expressions + const options = new chrome.Options() + options.addExtensions(extension) + options.addArguments('--lang=en-GB,en-US') + if (process.env.TEST_HEADLESS === '1') { + options.addArguments('--headless=chrome') + } + const builder = new Builder() + .forBrowser('chrome') + .setChromeOptions(options) + if (process.env.SELENIUM_REMOTE_CHROMIUM_URL !== undefined) { + console.info(`Using remote webdriver: ${process.env.SELENIUM_REMOTE_CHROMIUM_URL}`) + builder.usingServer(process.env.SELENIUM_REMOTE_CHROMIUM_URL) + } + console.info('Starting Chromium') + const browser = await builder.build() + await delay(5000) // waiting for the browser/extension to load + console.info('Chromium is ready') + return browser +} + +async function openFirefoxBrowser () { + console.info('Opening Firefox browser') + const extension = `build/ipfs_companion-${getVersion()}_firefox.zip` + console.info(`Checking if ${extension} exists`) + expect(fs.existsSync(extension)).to.be.true // eslint-disable-line no-unused-expressions + const options = new firefox.Options() + options.setPreference('intl.accept_languages', 'en-gb,en-us') + options.setPreference('intl.locale.requested', 'en-GB,en-US') + if (process.env.TEST_HEADLESS === '1') { + options.addArguments('--headless') + } + const builder = new Builder() + .forBrowser('firefox') + .setFirefoxOptions(options) + if (process.env.SELENIUM_REMOTE_FIREFOX_URL !== undefined) { + console.info(`Using remote webdriver: ${process.env.SELENIUM_REMOTE_FIREFOX_URL}`) + builder.usingServer(process.env.SELENIUM_REMOTE_FIREFOX_URL) + } + console.info('Starting Firefox') + const browser = builder.build() + console.info('Installing the extension') + await browser.installAddon(extension, true) + await delay(5000) // waiting for the browser/extension to load + console.info('Firefox is ready') + return browser +} + +const ExtensionURLRegex = /^(moz|chrome)-extension:\/\/[^\/]+/ // eslint-disable-line no-useless-escape +async function findExtensionUrl (browser) { + console.info('Looking for an open extension tab') + const handles = await browser.getAllWindowHandles() + console.info(`Found ${handles.length} candidates`) + + for (const handle of handles) { + console.info('Switching tabs') + await browser.switchTo().window(handle) + const url = await browser.getCurrentUrl() + console.info(`The current URL is: ${url}`) + const extensionURL = ExtensionURLRegex.exec(url)?.at(0) + if (extensionURL !== undefined) { + console.info(`Found the extension URL: ${extensionURL}`) + return extensionURL + } + } + console.error('No extension URL found') +} + +async function updateExtensionSettings (browser, url, id, value) { + console.info('Updating extension setting') + console.info(`Going to: ${url}/dist/options/options.html`) + await browser.get(`${url}/dist/options/options.html`) + console.info(`Looking for an element: ${id}`) + let element = browser.findElement(By.id(id)) + console.info(`Setting new value to: ${value}`) + await element.sendKeys('') + await delay(1000) // waiting for focus to be acquired + await element.clear() + await delay(1000) // waiting for input to be cleared + await element.sendKeys(value) + await element.sendKeys(Key.TAB) + await delay(5000) // waiting for the setting to be applied + console.info('Checking if the update worked') + element = browser.findElement(By.id(id)) + const v = await element.getAttribute('value') + expect(v).to.equal(value) + console.info('The setting update is complete') +} + +async function getNumberOfConnectedPeers (browser, url) { + console.info('Checking the number of connected peers') + console.info(`Going to: ${url}/dist/landing-pages/welcome/index.html`) + await browser.get(`${url}/dist/landing-pages/welcome/index.html`) + await delay(5000) // waiting for the connection number to appear + const html = await browser.getPageSource() + console.debug(html) + console.info('Looking for an element with text: \'Your node is connected to ...\'') + const p = browser.findElement(By.xpath("//p[text()='Your node is connected to ']")) + const span = p.findElement(By.css('span')) + const peers = await span.getText() + console.info(`There are ${peers} connected peers`) + return parseInt(peers) +} + +async function runTest (browser) { + const url = await findExtensionUrl(browser) + expect(url).not.to.be.undefined // eslint-disable-line no-unused-expressions + await updateExtensionSettings(browser, url, 'ipfsApiUrl', process.env.IPFS_API_URL || 'http://127.0.0.1:5001') + await updateExtensionSettings(browser, url, 'customGatewayUrl', process.env.CUSTOM_GATEWAY_URL || 'http://localhost:8080') + const peers = await getNumberOfConnectedPeers(browser, url) + expect(peers).not.to.equal(0) +} + +describe('ipfs-companion', function () { + before(() => { + if (process.env.TEST_E2E !== '1') { + this.skip() + } + }) + it('should be able to discover peers in Chromium', async function () { + const browser = await openChromiumBrowser() + try { + await runTest(browser) + } finally { + await browser.quit() + } + }) + it('should be able to discover peers in Firefox', async function () { + const browser = await openFirefoxBrowser() + try { + await runTest(browser) + } finally { + await browser.quit() + } + }) +}) From 00d14ea37a3e197344fb72f3257e55dafd833740 Mon Sep 17 00:00:00 2001 From: galargh Date: Tue, 20 Dec 2022 09:36:22 +0100 Subject: [PATCH 2/9] fix: do not use arrow functions in mocha --- test/e2e/ipfs-companion.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/ipfs-companion.test.js b/test/e2e/ipfs-companion.test.js index 30c1bcaf5..53fd28749 100644 --- a/test/e2e/ipfs-companion.test.js +++ b/test/e2e/ipfs-companion.test.js @@ -131,7 +131,7 @@ async function runTest (browser) { } describe('ipfs-companion', function () { - before(() => { + before(function () { if (process.env.TEST_E2E !== '1') { this.skip() } From 5a933cde9a6320225fa9779ec19b4903924c9c89 Mon Sep 17 00:00:00 2001 From: galargh Date: Tue, 20 Dec 2022 10:01:36 +0100 Subject: [PATCH 3/9] feat: create a workflow for running e2e tests --- .github/workflows/e2e.yml | 59 ++++++++++++++++++++++++++++++++ ci/download-release-artifacts.sh | 2 ++ docker-compose.e2e.yml | 1 + package.json | 8 ++--- test/e2e/ipfs-companion.test.js | 6 ++-- 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/e2e.yml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 000000000..0e74b6cfa --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,59 @@ +name: e2e +on: + workflow_dispatch: + inputs: + firefox-version: + description: The version of selenium/standalone-firefox image to use + default: latest + required: true + chromium-version: + description: The version of selenium/standalone-chrome image to use + default: latest + required: true + kubo-version: + description: The version of ipfs/kubo image to use + default: latest + required: true + ipfs-companion-version: + description: The version of ipfs-companion extension to use (defaults to building the extension from source) + default: '' + required: false + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v3 + - name: Set up node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Download ipfs-companion + if: inputs.ipfs-companion-version != '' + run: ./ci/download-release-artifacts.sh + env: + IPFS_COMPANION_VERSION: ${{ inputs.ipfs-companion-version }} + - name: Build ipfs-companion + if: inputs.ipfs-companion-version == '' + run: npm run release-build + - name: Prepare E2E env + run: npm run compose:e2e:prepare + env: + FIREFOX_VERSION: ${{ inputs.firefox-version }} + CHROMIUM_VERSION: ${{ inputs.chromium-version }} + KUBO_VERSION: ${{ inputs.kubo-version }} + - name: Start E2E env + run: npm run compose:e2e:up + env: + FIREFOX_VERSION: ${{ inputs.firefox-version }} + CHROMIUM_VERSION: ${{ inputs.chromium-version }} + KUBO_VERSION: ${{ inputs.kubo-version }} + - name: Wait for E2E env set up to complete + run: sleep 60 + - name: Run E2E tests + run: npm run compose:e2e:test + env: + IPFS_COMPANION_VERSION: ${{ inputs.ipfs-companion-version }} + - name: Stop E2E env + run: npm run compose:e2e:down diff --git a/ci/download-release-artifacts.sh b/ci/download-release-artifacts.sh index d4615c400..362a9bf2d 100755 --- a/ci/download-release-artifacts.sh +++ b/ci/download-release-artifacts.sh @@ -6,6 +6,8 @@ IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION:-$(jq -r '.version' ./add-on/man id="$(curl --retry 5 --no-progress-meter "https://api.github.com/repos/ipfs/ipfs-companion/releases/tags/v$IPFS_COMPANION_VERSION" | jq '.id')" assets="$(curl --retry 5 --no-progress-meter --location "https://api.github.com/repos/ipfs/ipfs-companion/releases/$id/assets" | jq -r '.[].name')" +mkdir build + for asset in $assets; do curl --retry 5 --no-progress-meter --location --output "build/$asset" "https://github.com/ipfs/ipfs-companion/releases/download/v$IPFS_COMPANION_VERSION/$asset" done diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml index fe5675f1c..f71b9c4c0 100644 --- a/docker-compose.e2e.yml +++ b/docker-compose.e2e.yml @@ -34,6 +34,7 @@ services: - CUSTOM_GATEWAY_URL=http://kubo:8080 - TEST_E2E=1 - TEST_HEADLESS=${TEST_HEADLESS} + - TEST_DEBUG=${TEST_DEBUG} - IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION} volumes: - ./build:/home/node/app/build diff --git a/package.json b/package.json index edd4d2cac..163c930fc 100644 --- a/package.json +++ b/package.json @@ -57,14 +57,14 @@ "ci:build": "npm run build", "ci:test": "npm test", "ci:lint": "npm run lint", - "beta-build": "docker rmi -f ipfs-companion-beta-build && docker build -t ipfs-companion-beta-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm -it --net=host -e RELEASE_CHANNEL=beta -v $(pwd)/build:/home/node/app/build ipfs-companion-beta-build npm run ci:build", - "release-build": "docker rmi -f ipfs-companion-release-build && docker build -t ipfs-companion-release-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm -it --net=host -e RELEASE_CHANNEL=stable -v $(pwd)/build:/home/node/app/build ipfs-companion-release-build npm run ci:build", + "beta-build": "docker rmi -f ipfs-companion-beta-build && docker build -t ipfs-companion-beta-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm --net=host -e RELEASE_CHANNEL=beta -v $(pwd)/build:/home/node/app/build ipfs-companion-beta-build npm run ci:build", + "release-build": "docker rmi -f ipfs-companion-release-build && docker build -t ipfs-companion-release-build --build-arg USER_ID=$(id -u ${USER}) --build-arg GROUP_ID=$(id -g ${USER}) . && mkdir -p build && docker run --rm --net=host -e RELEASE_CHANNEL=stable -v $(pwd)/build:/home/node/app/build ipfs-companion-release-build npm run ci:build", "dev-build": "npm ci && npm run build", "yarn-build": "npm run dev-build", - "compose:e2e:build": "docker compose --file docker-compose.e2e.yml build", + "compose:e2e:prepare": "docker compose --file docker-compose.e2e.yml pull && docker compose --file docker-compose.e2e.yml build", "compose:e2e:up": "docker compose --file docker-compose.e2e.yml up --remove-orphans --detach kubo chromium firefox", "compose:e2e:test": "docker compose --file docker-compose.e2e.yml run e2e npm run test:e2e", - "compose:e2e:stop": "docker compose --file docker-compose.e2e.yml stop" + "compose:e2e:down": "docker compose --file docker-compose.e2e.yml down" }, "private": true, "preferGlobal": false, diff --git a/test/e2e/ipfs-companion.test.js b/test/e2e/ipfs-companion.test.js index 53fd28749..8853625ac 100644 --- a/test/e2e/ipfs-companion.test.js +++ b/test/e2e/ipfs-companion.test.js @@ -111,8 +111,10 @@ async function getNumberOfConnectedPeers (browser, url) { console.info(`Going to: ${url}/dist/landing-pages/welcome/index.html`) await browser.get(`${url}/dist/landing-pages/welcome/index.html`) await delay(5000) // waiting for the connection number to appear - const html = await browser.getPageSource() - console.debug(html) + if (process.env.TEST_DEBUG === '1') { + const html = await browser.getPageSource() + console.debug(html) + } console.info('Looking for an element with text: \'Your node is connected to ...\'') const p = browser.findElement(By.xpath("//p[text()='Your node is connected to ']")) const span = p.findElement(By.css('span')) From d8c660360ecbe31480d2548f70bdea5081f14451 Mon Sep 17 00:00:00 2001 From: galargh Date: Wed, 21 Dec 2022 10:52:17 +0100 Subject: [PATCH 4/9] chore: apply review comments --- docker-compose.e2e.yml | 2 +- test/e2e/ipfs-companion.test.js | 103 +++++++++++++++++++------------- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml index f71b9c4c0..64a6a58fd 100644 --- a/docker-compose.e2e.yml +++ b/docker-compose.e2e.yml @@ -32,7 +32,7 @@ services: - SELENIUM_REMOTE_FIREFOX_URL=http://firefox:4444 - IPFS_API_URL=http://kubo:5001 - CUSTOM_GATEWAY_URL=http://kubo:8080 - - TEST_E2E=1 + - TEST_E2E=true - TEST_HEADLESS=${TEST_HEADLESS} - TEST_DEBUG=${TEST_DEBUG} - IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION} diff --git a/test/e2e/ipfs-companion.test.js b/test/e2e/ipfs-companion.test.js index 8853625ac..e84fb9fb1 100644 --- a/test/e2e/ipfs-companion.test.js +++ b/test/e2e/ipfs-companion.test.js @@ -4,24 +4,25 @@ import { expect } from 'chai' import fs from 'fs' import chrome from 'selenium-webdriver/chrome.js' import firefox from 'selenium-webdriver/firefox.js' +import { fail } from 'assert' -async function delay (ms) { +function delay (ms) { return new Promise(res => setTimeout(res, ms), _ => {}) } -function getVersion () { - return process.env.IPFS_COMPANION_VERSION || JSON.parse(fs.readFileSync('add-on/manifest.common.json')).version +function getExtension (browserName) { + const version = process.env.IPFS_COMPANION_VERSION || JSON.parse(fs.readFileSync('add-on/manifest.common.json')).version + return `build/ipfs_companion-${version}_${browserName}.zip` } -async function openChromiumBrowser () { +async function openChromium (extension) { console.info('Opening Chromium browser') - const extension = `build/ipfs_companion-${getVersion()}_chromium.zip` - console.info(`Checking if ${extension} exists`) - expect(fs.existsSync(extension)).to.be.true // eslint-disable-line no-unused-expressions const options = new chrome.Options() - options.addExtensions(extension) + if (extension !== undefined) { + options.addExtensions(extension) + } options.addArguments('--lang=en-GB,en-US') - if (process.env.TEST_HEADLESS === '1') { + if (process.env.TEST_HEADLESS === 'true') { options.addArguments('--headless=chrome') } const builder = new Builder() @@ -33,20 +34,17 @@ async function openChromiumBrowser () { } console.info('Starting Chromium') const browser = await builder.build() - await delay(5000) // waiting for the browser/extension to load + await delay(5000) // waiting for the extension to load console.info('Chromium is ready') return browser } -async function openFirefoxBrowser () { +async function openFirefox (extension) { console.info('Opening Firefox browser') - const extension = `build/ipfs_companion-${getVersion()}_firefox.zip` - console.info(`Checking if ${extension} exists`) - expect(fs.existsSync(extension)).to.be.true // eslint-disable-line no-unused-expressions const options = new firefox.Options() options.setPreference('intl.accept_languages', 'en-gb,en-us') options.setPreference('intl.locale.requested', 'en-GB,en-US') - if (process.env.TEST_HEADLESS === '1') { + if (process.env.TEST_HEADLESS === 'true') { options.addArguments('--headless') } const builder = new Builder() @@ -57,10 +55,12 @@ async function openFirefoxBrowser () { builder.usingServer(process.env.SELENIUM_REMOTE_FIREFOX_URL) } console.info('Starting Firefox') - const browser = builder.build() - console.info('Installing the extension') - await browser.installAddon(extension, true) - await delay(5000) // waiting for the browser/extension to load + const browser = await builder.build() + if (extension !== undefined) { + console.info('Installing the extension') + await browser.installAddon(extension, true) + await delay(5000) // waiting for the extension to load + } console.info('Firefox is ready') return browser } @@ -82,7 +82,7 @@ async function findExtensionUrl (browser) { return extensionURL } } - console.error('No extension URL found') + console.warn('No extension URL found') } async function updateExtensionSettings (browser, url, id, value) { @@ -102,8 +102,8 @@ async function updateExtensionSettings (browser, url, id, value) { console.info('Checking if the update worked') element = browser.findElement(By.id(id)) const v = await element.getAttribute('value') - expect(v).to.equal(value) console.info('The setting update is complete') + return v } async function getNumberOfConnectedPeers (browser, url) { @@ -111,7 +111,7 @@ async function getNumberOfConnectedPeers (browser, url) { console.info(`Going to: ${url}/dist/landing-pages/welcome/index.html`) await browser.get(`${url}/dist/landing-pages/welcome/index.html`) await delay(5000) // waiting for the connection number to appear - if (process.env.TEST_DEBUG === '1') { + if (process.env.TEST_DEBUG === 'true') { const html = await browser.getPageSource() console.debug(html) } @@ -123,35 +123,54 @@ async function getNumberOfConnectedPeers (browser, url) { return parseInt(peers) } -async function runTest (browser) { - const url = await findExtensionUrl(browser) - expect(url).not.to.be.undefined // eslint-disable-line no-unused-expressions - await updateExtensionSettings(browser, url, 'ipfsApiUrl', process.env.IPFS_API_URL || 'http://127.0.0.1:5001') - await updateExtensionSettings(browser, url, 'customGatewayUrl', process.env.CUSTOM_GATEWAY_URL || 'http://localhost:8080') - const peers = await getNumberOfConnectedPeers(browser, url) - expect(peers).not.to.equal(0) +async function runTest (browserName) { + const extension = getExtension(browserName) + + console.info(`Checking if ${extension} exists`) + expect(fs.existsSync(extension)).to.be.true // eslint-disable-line no-unused-expressions + + let browser + if (browserName === 'chromium') { + browser = await openChromium(extension) + } else if (browserName === 'firefox') { + browser = await openFirefox(extension) + } else { + fail(`unknown browser name: ${browserName}`) + } + + try { + const url = await findExtensionUrl(browser) + + expect(url).not.to.be.undefined // eslint-disable-line no-unused-expressions + + const ipfsApiUrl = process.env.IPFS_API_URL || 'http://127.0.0.1:5001' + const updatedIpfsApiUrl = await updateExtensionSettings(browser, url, 'ipfsApiUrl', ipfsApiUrl) + + expect(updatedIpfsApiUrl).to.equal(ipfsApiUrl) + + const customGatewayUrl = process.env.CUSTOM_GATEWAY_URL || 'http://localhost:8080' + const updatedCustomGatewayUrl = await updateExtensionSettings(browser, url, 'customGatewayUrl', customGatewayUrl) + + expect(updatedCustomGatewayUrl).to.equal(customGatewayUrl) + + const peers = await getNumberOfConnectedPeers(browser, url) + + expect(peers).not.to.equal(0) + } finally { + await browser.quit() + } } describe('ipfs-companion', function () { before(function () { - if (process.env.TEST_E2E !== '1') { + if (process.env.TEST_E2E !== 'true') { this.skip() } }) it('should be able to discover peers in Chromium', async function () { - const browser = await openChromiumBrowser() - try { - await runTest(browser) - } finally { - await browser.quit() - } + await runTest('chromium') }) it('should be able to discover peers in Firefox', async function () { - const browser = await openFirefoxBrowser() - try { - await runTest(browser) - } finally { - await browser.quit() - } + await runTest('firefox') }) }) From 416cb1a84d4afd8d4017bf97ac1839cbeff9efff Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:44:05 -0800 Subject: [PATCH 5/9] chore: support override of firefox image --- docker-compose.e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml index 64a6a58fd..aa60092c3 100644 --- a/docker-compose.e2e.yml +++ b/docker-compose.e2e.yml @@ -1,7 +1,7 @@ version: "3.9" services: firefox: - image: selenium/standalone-firefox:${FIREFOX_VERSION:-latest} + image: ${FIREFOX_IMAGE:-selenium/standalone-firefox}:${FIREFOX_VERSION:-latest} shm_size: 2g ports: - 4444 From 2807670c8e7d5dde10cd3b99bd8a2d5da8153a98 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:49:55 -0800 Subject: [PATCH 6/9] fix(test): await async destroy operation --- test/functional/lib/ipfs-companion.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/lib/ipfs-companion.test.js b/test/functional/lib/ipfs-companion.test.js index 17dbd4e39..d59aee680 100644 --- a/test/functional/lib/ipfs-companion.test.js +++ b/test/functional/lib/ipfs-companion.test.js @@ -32,7 +32,7 @@ describe('lib/ipfs-companion.js', function () { browser.storage.local.set.resolves() const ipfsCompanion = await init() expect(browser.storage.local.get.calledWith(optionDefaults)).to.equal(true) - return ipfsCompanion.destroy() + return await ipfsCompanion.destroy() }) after(function () { From ba30b87b9e1db0a6d9dd2a77dc5f1645122e8394 Mon Sep 17 00:00:00 2001 From: galargh Date: Mon, 16 Jan 2023 16:23:45 +0100 Subject: [PATCH 7/9] chore: address review comments - replace fixed delays with exponential backoff - make download-release-artifacts.sh work even if build dir already exists - document how to run e2e tests locally - delete user/group if it already exists during release build in docker - make it easier to add new e2e test cases in the future --- Dockerfile | 7 +-- ci/download-release-artifacts.sh | 4 +- docker-compose.e2e.yml | 3 +- docs/CONTRIBUTING.md | 2 +- docs/DEVELOPER-NOTES.md | 87 ++++++++++++++++++++++++++++++ package-lock.json | 13 +++++ package.json | 1 + test/e2e/ipfs-companion.test.js | 93 +++++++++++++++++++------------- 8 files changed, 166 insertions(+), 44 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8100ddc36..b75b87849 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,10 +9,11 @@ RUN mkdir -p /home/node/app RUN if [ ${USER_ID:-0} -ne 0 ] && [ ${GROUP_ID:-0} -ne 0 ]; then \ userdel -f node && \ if getent group node ; then groupdel node; fi && \ + if getent passwd ${USER_ID} ; then userdel -f $(getent passwd ${USER_ID} | cut -d: -f1); fi && \ + if getent group ${GROUP_ID} ; then groupdel $(getent group ${GROUP_ID} | cut -d: -f1); fi && \ groupadd -g ${GROUP_ID} node && \ - useradd -l -u ${USER_ID} -g node node && \ - chown -fhR ${USER_ID}:${GROUP_ID} /home/node; fi -RUN chown node:node /home/node/app + useradd -l -u ${USER_ID} -g node node; fi +RUN chown -fhR node:node /home/node WORKDIR /home/node/app diff --git a/ci/download-release-artifacts.sh b/ci/download-release-artifacts.sh index 362a9bf2d..2645208ed 100755 --- a/ci/download-release-artifacts.sh +++ b/ci/download-release-artifacts.sh @@ -6,7 +6,9 @@ IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION:-$(jq -r '.version' ./add-on/man id="$(curl --retry 5 --no-progress-meter "https://api.github.com/repos/ipfs/ipfs-companion/releases/tags/v$IPFS_COMPANION_VERSION" | jq '.id')" assets="$(curl --retry 5 --no-progress-meter --location "https://api.github.com/repos/ipfs/ipfs-companion/releases/$id/assets" | jq -r '.[].name')" -mkdir build +if [[ ! -d build ]]; then + mkdir build +fi for asset in $assets; do curl --retry 5 --no-progress-meter --location --output "build/$asset" "https://github.com/ipfs/ipfs-companion/releases/download/v$IPFS_COMPANION_VERSION/$asset" diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml index aa60092c3..8ea5a2239 100644 --- a/docker-compose.e2e.yml +++ b/docker-compose.e2e.yml @@ -33,8 +33,7 @@ services: - IPFS_API_URL=http://kubo:5001 - CUSTOM_GATEWAY_URL=http://kubo:8080 - TEST_E2E=true - - TEST_HEADLESS=${TEST_HEADLESS} - - TEST_DEBUG=${TEST_DEBUG} + - TEST_HEADLESS=${TEST_HEADLESS:-false} - IPFS_COMPANION_VERSION=${IPFS_COMPANION_VERSION} volumes: - ./build:/home/node/app/build diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index c14520cbc..62200444f 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -32,7 +32,7 @@ If you want to download translations from Transifex and run them locally, make s ## Writing Code -**If you plan to write code make sure to read [Developer Notes](./docs/DEVELOPER-NOTES.md) to get familiar with tools and commands that will make your work easier.** +**If you plan to write code make sure to read [Developer Notes](DEVELOPER-NOTES.md) to get familiar with tools and commands that will make your work easier.** ## How to Help with Things Beyond Browser Extension? diff --git a/docs/DEVELOPER-NOTES.md b/docs/DEVELOPER-NOTES.md index 9519c5ccf..87d14fb74 100644 --- a/docs/DEVELOPER-NOTES.md +++ b/docs/DEVELOPER-NOTES.md @@ -137,6 +137,93 @@ Release build shortcuts: - `npm run dev-build`: All-in-one: fast dependency install, build with yarn (updates `yarn.lock` if needed) - `npm run release-build`: Reproducible release build in docker with frozen `yarn.lock` +E2E tests: + +- `npm run compose:e2e:prepare`: Pull and build docker images for e2e tests +- `npm run compose:e2e:up`: Start e2e test docker environment +- `npm run compose:e2e:test`: Run e2e tests in the docker environment +- `npm run compose:e2e:down`: Stop e2e test docker environment + +## Running E2E tests + +E2E tests are run in a docker environment, so you need to have docker installed. + +### Preparing extension builds + +You can run the tests against either release or dev builds of the extension. + +To download release builds of the extension, run: + +```sh +./ci/e2e/download-release-builds.sh +``` + +_NOTE_: When using release builds, you can control the version of the extension by setting the `IPFS_COMPANION_VERSION` environment variable: + +```sh +export IPFS_COMPANION_VERSION=x.y.z +``` + +To build dev versions of the extension, run: + +```sh +npm run build +``` + +or (to perform the build inside a docker container): + +```sh +npm run release-build +``` + +### Preparing the docker environment + +You need to pull docker images for [Kubo](https://github.com/ipfs/kubo), [Chromium](https://hub.docker.com/r/selenium/standalone-chrome/) and [Firefox](https://hub.docker.com/r/selenium/standalone-firefox/) before running the tests. + +You also need to build the docker image containing the e2e tests. + +To do all of this, run: + +```sh +npm run compose:e2e:prepare +``` + +_NOTE_: You can control the versions of Kubo, Chromium and Firefox by setting the following environment variables: + +```sh +export KUBO_VERSION=x.y.z +export CHROMIUM_VERSION=x.y.z +export FIREFOX_VERSION=x.y.z +``` + +**IMPORTANT**: If you are running the tests on a ARM machine, you need to use a different Chromium image. To do this, run: + +```sh +export CHROMIUM_IMAGE=seleniarm/standalone-chromium +``` + +### Running the tests + +To run the tests, run: + +```sh +npm run compose:e2e:test +``` + +_NOTE_: You can control whether the browsers operate in headless mode as follows: + +```sh +export TEST_HEADLESS=true +``` + +### Stopping the docker environment + +To stop the docker environment, run: + +```sh +npm run compose:e2e:down +``` + ## Other tips - You can switch to an alternative Firefox version by overriding your `PATH`: diff --git a/package-lock.json b/package-lock.json index f8864c378..fdf9689b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "cross-env": "7.0.3", "css-loader": "6.7.2", "download-cli": "1.1.1", + "exponential-backoff": "^3.1.0", "file-loader": "6.2.0", "fs-promise": "2.0.3", "get-firefox": "5.0.0", @@ -9583,6 +9584,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/exponential-backoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.0.tgz", + "integrity": "sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA==", + "dev": true + }, "node_modules/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -29787,6 +29794,12 @@ } } }, + "exponential-backoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.0.tgz", + "integrity": "sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA==", + "dev": true + }, "ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", diff --git a/package.json b/package.json index 12aae7c50..0c67dc974 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "cross-env": "7.0.3", "css-loader": "6.7.2", "download-cli": "1.1.1", + "exponential-backoff": "^3.1.0", "file-loader": "6.2.0", "fs-promise": "2.0.3", "get-firefox": "5.0.0", diff --git a/test/e2e/ipfs-companion.test.js b/test/e2e/ipfs-companion.test.js index e84fb9fb1..71cdba5cd 100644 --- a/test/e2e/ipfs-companion.test.js +++ b/test/e2e/ipfs-companion.test.js @@ -4,11 +4,8 @@ import { expect } from 'chai' import fs from 'fs' import chrome from 'selenium-webdriver/chrome.js' import firefox from 'selenium-webdriver/firefox.js' -import { fail } from 'assert' - -function delay (ms) { - return new Promise(res => setTimeout(res, ms), _ => {}) -} +import { fail, equal, notEqual } from 'assert' +import { backOff } from 'exponential-backoff' function getExtension (browserName) { const version = process.env.IPFS_COMPANION_VERSION || JSON.parse(fs.readFileSync('add-on/manifest.common.json')).version @@ -34,7 +31,6 @@ async function openChromium (extension) { } console.info('Starting Chromium') const browser = await builder.build() - await delay(5000) // waiting for the extension to load console.info('Chromium is ready') return browser } @@ -59,7 +55,6 @@ async function openFirefox (extension) { if (extension !== undefined) { console.info('Installing the extension') await browser.installAddon(extension, true) - await delay(5000) // waiting for the extension to load } console.info('Firefox is ready') return browser @@ -90,40 +85,59 @@ async function updateExtensionSettings (browser, url, id, value) { console.info(`Going to: ${url}/dist/options/options.html`) await browser.get(`${url}/dist/options/options.html`) console.info(`Looking for an element: ${id}`) - let element = browser.findElement(By.id(id)) + const element = browser.findElement(By.id(id)) console.info(`Setting new value to: ${value}`) await element.sendKeys('') - await delay(1000) // waiting for focus to be acquired + await backOff(async () => { + const activeElement = await browser.switchTo().activeElement() + const activeElementID = await activeElement.getAttribute('id') + equal(activeElementID, id, 'The element is not focused yet') + }, { + numOfAttempts: 5, + startingDelay: 500 + }) await element.clear() - await delay(1000) // waiting for input to be cleared + await backOff(async () => { + const v = await element.getAttribute('value') + equal(v, '', 'The element is not cleared yet') + }, { + numOfAttempts: 5, + startingDelay: 500 + }) await element.sendKeys(value) await element.sendKeys(Key.TAB) - await delay(5000) // waiting for the setting to be applied console.info('Checking if the update worked') - element = browser.findElement(By.id(id)) - const v = await element.getAttribute('value') + backOff(async () => { + const e = browser.findElement(By.id(id)) + const v = await e.getAttribute('value') + equal(v, value, 'The element is not updated yet') + }, { + delayFirstAttempt: true, + numOfAttempts: 5, + startingDelay: 500 + }) console.info('The setting update is complete') - return v } async function getNumberOfConnectedPeers (browser, url) { console.info('Checking the number of connected peers') console.info(`Going to: ${url}/dist/landing-pages/welcome/index.html`) await browser.get(`${url}/dist/landing-pages/welcome/index.html`) - await delay(5000) // waiting for the connection number to appear - if (process.env.TEST_DEBUG === 'true') { - const html = await browser.getPageSource() - console.debug(html) - } console.info('Looking for an element with text: \'Your node is connected to ...\'') - const p = browser.findElement(By.xpath("//p[text()='Your node is connected to ']")) - const span = p.findElement(By.css('span')) - const peers = await span.getText() + const peers = await backOff(async () => { + const p = browser.findElement(By.xpath("//p[text()='Your node is connected to ']")) + const span = p.findElement(By.css('span')) + return span.getText() + }, { + delayFirstAttempt: true, + numOfAttempts: 5, + startingDelay: 500 + }) console.info(`There are ${peers} connected peers`) return parseInt(peers) } -async function runTest (browserName) { +async function runBrowserTest (browserName, testFunc) { const extension = getExtension(browserName) console.info(`Checking if ${extension} exists`) @@ -139,28 +153,33 @@ async function runTest (browserName) { } try { - const url = await findExtensionUrl(browser) - - expect(url).not.to.be.undefined // eslint-disable-line no-unused-expressions + const url = await backOff(async () => { + const u = await findExtensionUrl(browser) + notEqual(u, undefined, 'Extension URL not found yet') + return u + }, { + delayFirstAttempt: true, + numOfAttempts: 5, + startingDelay: 500 + }) const ipfsApiUrl = process.env.IPFS_API_URL || 'http://127.0.0.1:5001' - const updatedIpfsApiUrl = await updateExtensionSettings(browser, url, 'ipfsApiUrl', ipfsApiUrl) - - expect(updatedIpfsApiUrl).to.equal(ipfsApiUrl) + await updateExtensionSettings(browser, url, 'ipfsApiUrl', ipfsApiUrl) const customGatewayUrl = process.env.CUSTOM_GATEWAY_URL || 'http://localhost:8080' - const updatedCustomGatewayUrl = await updateExtensionSettings(browser, url, 'customGatewayUrl', customGatewayUrl) - - expect(updatedCustomGatewayUrl).to.equal(customGatewayUrl) + await updateExtensionSettings(browser, url, 'customGatewayUrl', customGatewayUrl) - const peers = await getNumberOfConnectedPeers(browser, url) - - expect(peers).not.to.equal(0) + return await testFunc(browser, url) } finally { await browser.quit() } } +async function checkNumberOfConnectedPeers (browser, url) { + const peers = await getNumberOfConnectedPeers(browser, url) + expect(peers).not.to.equal(0) +} + describe('ipfs-companion', function () { before(function () { if (process.env.TEST_E2E !== 'true') { @@ -168,9 +187,9 @@ describe('ipfs-companion', function () { } }) it('should be able to discover peers in Chromium', async function () { - await runTest('chromium') + await runBrowserTest('chromium', checkNumberOfConnectedPeers) }) it('should be able to discover peers in Firefox', async function () { - await runTest('firefox') + await runBrowserTest('firefox', checkNumberOfConnectedPeers) }) }) From 4bf55b68ed49e6b9f4bb6be92b2b856d4e3941d4 Mon Sep 17 00:00:00 2001 From: galargh Date: Tue, 17 Jan 2023 10:10:36 +0100 Subject: [PATCH 8/9] chore: allow overriding access control settings through env --- ci/access-control-allow-all.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/access-control-allow-all.sh b/ci/access-control-allow-all.sh index 4b7426327..18262c87e 100755 --- a/ci/access-control-allow-all.sh +++ b/ci/access-control-allow-all.sh @@ -1,5 +1,5 @@ #!/bin/sh set -ex -ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]' -ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["*"]' +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "${ACCESS_CONTROL_ALLOW_ORIGIN:-[\"*\"]}" +ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "${ACCESS_CONTROL_ALLOW_METHODS:-[\"*\"]}" From 25a4760138ac21fdfdf198a6476a88b92bd09c4c Mon Sep 17 00:00:00 2001 From: Piotr Galar Date: Tue, 17 Jan 2023 10:12:45 +0100 Subject: [PATCH 9/9] Update docs/DEVELOPER-NOTES.md Co-authored-by: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> --- docs/DEVELOPER-NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DEVELOPER-NOTES.md b/docs/DEVELOPER-NOTES.md index 87d14fb74..f84251ae8 100644 --- a/docs/DEVELOPER-NOTES.md +++ b/docs/DEVELOPER-NOTES.md @@ -200,6 +200,7 @@ export FIREFOX_VERSION=x.y.z ```sh export CHROMIUM_IMAGE=seleniarm/standalone-chromium +export FIREFOX_IMAGE=seleniarm/standalone-firefox ``` ### Running the tests