Chrome stopped the background worker about six minutes after a site's request even with the approval window open, and the approval and the site's waiting request went with it. While any approval is pending, the worker now calls runtime.getPlatformInfo() every 20 seconds; Chrome counts each extension call as activity. The timer is the worker's own, so a minimized window does not slow it, and it stops itself once nothing is pending. tests/e2e/slowApproval.js, run by make test-e2e, leaves a transaction and a signature approval open for seven minutes in minimized windows and requires the site to receive both results. It drives Chromium over the DevTools pipe without Playwright, because Playwright keeps DevTools attached to the worker and Chrome then never stops it. Model: opus-5-5
115 lines
4.8 KiB
Bash
Executable File
115 lines
4.8 KiB
Bash
Executable File
#!/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 60 seconds and a browser suite does not fit. Run it
|
|
# yourself before touching popup views. ESLint's no-undef now catches a
|
|
# used-but-not-imported identifier in make check, but only this suite sees
|
|
# what a view actually does when it runs.
|
|
# .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)..."
|
|
# --no-cache: the image build runs make build and its checks, and a
|
|
# cached layer is a check that did not run.
|
|
docker build --no-cache --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 — the JSON-RPC calls behind
|
|
# every approval the suite drives among them — goes to the real
|
|
# internet. The flag is experimental and Playwright may drop or
|
|
# rename it. It cannot break silently: the harness asks the worker
|
|
# for one request of its own at launch and aborts the whole suite
|
|
# if it does not reach the route handler (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
|
|
|
|
# Where chrome.storage.local lives, and what moves it: two unpacked loads
|
|
# from two different paths in one profile, with the shipped manifest and
|
|
# again with `key` stripped out. Its own browser sessions — four of them —
|
|
# because the whole subject is what happens ACROSS loads, which the suite
|
|
# above cannot express with one.
|
|
#
|
|
# No PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS here: this drives no
|
|
# RPC and installs no route handlers, and the browser is started with
|
|
# --host-resolver-rules=MAP * ~NOTFOUND so nothing it does can leave.
|
|
echo "Running the extension-id and storage-partition observations..."
|
|
docker run --rm \
|
|
--ipc=host \
|
|
-e HOME=/tmp \
|
|
"$(cat "$IIDFILE")" \
|
|
node tests/e2e/storagePartition.js
|
|
|
|
# Approvals left open for seven minutes in minimized windows, past the
|
|
# point where Chrome stopped the background worker when nothing kept it
|
|
# running. Its own program, without Playwright: Playwright keeps DevTools
|
|
# attached to the worker, and Chrome never stops a worker DevTools is
|
|
# attached to. It reaches nothing but its own loopback server.
|
|
echo "Running the approvals left open for seven minutes..."
|
|
docker run --rm \
|
|
--ipc=host \
|
|
-e HOME=/tmp \
|
|
"$(cat "$IIDFILE")" \
|
|
node tests/e2e/slowApproval.js
|
|
}
|
|
|
|
main "$@"
|