#!/bin/sh # script/test-e2e: build the extension and drive the real popup in a real # Chromium inside a pinned container. Our own extension to # scripts-to-rule-them-all. # # Deliberately NOT called by script/check or script/test: REPO_POLICIES.md # caps make test at 20 seconds and a browser suite does not fit. Run it # yourself before touching popup views; it is the only check that can see # a used-but-not-imported identifier blow up at runtime. # .gitea/workflows/e2e.yml also runs it on every push, in a job separate # from check so that cap and the local fast path both stay intact. # # Docker is the only prerequisite. The repo reaches the container as a # build context and the extension is built inside it (see # tests/e2e/Dockerfile), so nothing here depends on the node, yarn or make # on the machine that starts the run. That is not a convenience: a bind # mount cannot work under Gitea Actions, and the runner image's node is too # old to install this repo's dependencies. set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" IMAGE="$("$SCRIPT_DIR/projectname")-e2e-chrome" IIDFILE="" cleanup() { if [ -n "$IIDFILE" ]; then rm -f "$IIDFILE" fi } main() { cd "$ROOT" if ! command -v docker >/dev/null 2>&1; then echo "test-e2e: docker is required to run the e2e suite" >&2 exit 1 fi IIDFILE="$(mktemp)" trap cleanup EXIT trap 'cleanup; exit 130' INT TERM echo "Building the Chrome e2e image (extension included)..." docker build --iidfile "$IIDFILE" -t "$IMAGE" -f tests/e2e/Dockerfile . echo "Running e2e suite in the pinned Playwright container..." # The image is run by ID, not by tag: where two clones of this repo run # the suite at once, the other build can move the tag between this # build and this run, and the suite would then silently test the other # checkout. # # --ipc=host: Chromium's shared-memory needs more than the default # 64MB /dev/shm or renderers crash. # HOME=/tmp: the image's root home is not a reliable place for the # browser profile. # PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1: without it, # ctx.route() intercepts page requests only, and every fetch made by # the MV3 background service worker — including the phishing # blocklist fetch that src/background/index.js issues at worker # startup — goes to the real internet. The flag is experimental and # Playwright may drop or rename it. It cannot break silently: the # harness probes service-worker interception at launch and aborts # the whole suite if it is not in effect (see the interception # canary in tests/e2e/harness.js). If a future Playwright removes # the flag, that probe is what will fail, and the fix is either a # replacement mechanism or an honest downgrade of the isolation # claim in tests/e2e/network.js and README.md — not deleting the # probe. The image is pinned by digest, so this can only ever bite # on a deliberate bump. docker run --rm \ --ipc=host \ -e HOME=/tmp \ -e PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 \ -e "E2E_TRACE_NETWORK=${E2E_TRACE_NETWORK:-0}" \ "$(cat "$IIDFILE")" \ node tests/e2e/run.js } main "$@"