Repository navigation
webframe 0.2
This release makes webframe a tool for scripting and testing pages, not just watching them. You can inject stubs, run a test file once the page loads, pass in secrets, and have the page set the exit status. Hidden pages now run at full speed on every platform.
$ webframe -y -t 30 -i mock-fetch.js -x todo.test.js todo.html
ok loads saved todos
ok adds a todo
ok deletes after confirm
$ echo $?
0
Breaking changes
-
WF_*environment variables are no longer exposed to pages. In 0.1, everyWF_*variable in your environment became awindowglobal on every page you opened, including untrusted ones. Now you name each variable you want to pass with-E, and pages read it fromwebframe.env:# 0.1 WF_API_KEY=abc webframe app.html # window.API_KEY # 0.2 API_KEY=abc webframe -E API_KEY app.html # webframe.env.API_KEY -
Go library:
Options.Globalsis replaced byOptions.Env, exposed to the page aswebframe.envrather than aswindowglobals. -
-cwaits for the page to load. It used to start reading stdin as soon as the page began loading. Now it waits until the page's ownloadhandlers have run. -
A failed first page load exits 1 instead of waiting forever, even without
-e. This doesn't apply on Windows; see Known limitations.
New
- Run a script after load (
-x FILE). The file can span many lines, and if it ends in a promise webframe waits for it. If it throws or rejects, webframe exits 1. Repeat-xto run several files in order. - Inject scripts before the page's scripts (
-i FILE). This runs on every page, including after navigations and reloads. Use it for stubs,fetchhooks and test helpers. - Set the exit status from the page with
webframe.exit(code). Pages also get a read-onlywebframeglobal, which holdsenvandexit. - Pass environment variables in (
-E NAME[=VALUE]). Secrets can stay in the environment rather than in scripts. A named variable that isn't set exits 2, so a missing secret fails loudly instead of showing up asundefined. - Timeout (
-t DURATION). webframe exits 124 when the time runs out. It takes seconds or values like500msand2m, so a hung test can't block CI. - Accept dialogs (
-y).alert,confirmandpromptare accepted instead of dismissed. - Private mode (
-p). Cookies, storage and cache are kept in memory only, so nothing is shared with other runs. (#11) - Multi-line console input.
-ckeeps reading lines until a statement is complete, so you can paste functions and blocks. On a terminal, an empty line ends a statement early. - Pages whose Content-Security-Policy blocks
eval. Console and eval input now runs as a single expression on these pages instead of failing. (#12) - Flags can come after the URL, as in
webframe page.html -t 30.-hnow lists all exit statuses. - Go library:
OptionsgainsInit,AcceptDialogs, andLoaded,LoadFailedandExitcallbacks.EvalContextstops waiting for a result when its context is cancelled or times out.ErrIncompletemarks source that ended before a statement was complete.
- New examples:
todo.htmlwithtodo.test.jsandmock-fetch.js: a page tested without a server.links.js: prints every link on a page.status.js: a smoke test to run after a deploy.timers.html: checks that a hidden page isn't throttled.
Fixed
- Hidden pages are no longer throttled on Linux or Windows. Timers and
requestAnimationFramenow run at full speed on every platform, and the page sees itself as visible with a real viewport. (#2, #10) - Alpine crash fixed. The
linux-muslbuild crashed on Alpine; it now runs normally. - Failed page loads no longer hang. A failed load now exits instead of waiting forever (#3).
-tlimits any other hang, including an eval that never finishes (#5). WF_*variables no longer leak to every page. (#7)
Downloads
| Platform | arm64 | amd64 |
|---|---|---|
| macOS | webframe_v0.2_darwin_arm64.zip |
webframe_v0.2_darwin_amd64.zip |
| Windows | webframe_v0.2_windows_arm64.zip |
webframe_v0.2_windows_amd64.zip |
| Linux (glibc) | webframe_v0.2_linux_arm64.zip |
webframe_v0.2_linux_amd64.zip |
| Linux (musl/Alpine) | webframe_v0.2_linux-musl_arm64.zip |
webframe_v0.2_linux-musl_amd64.zip |
There's also a Dockerfile for an Alpine-based image: docker build -t webframe .
To build from source, clone the repo and run make build. go install doesn't work, because the module points glaze at a fork.
macOS
The macOS binaries aren't signed with a Developer ID or notarized yet, so if you download a zip with a browser, macOS will block webframe the first time you run it. Remove the quarantine flag after unzipping:
xattr -d com.apple.quarantine ./webframe
Or right-click the binary in Finder, choose Open, and confirm. On recent macOS, go to System Settings → Privacy & Security and click "Open Anyway". Downloads with curl or wget aren't quarantined and run as-is.
Requirements
- macOS: nothing.
- Windows: the Edge WebView2 Runtime, which comes preinstalled on Windows 10/11.
- Linux: WebKitGTK and Xvfb if you have no display.
- Debian/Ubuntu:
apt install libwebkit2gtk-4.1-0 xvfb - Alpine:
apk add webkit2gtk-4.1 xvfb, plus thelinux-muslbuild
- Debian/Ubuntu:
Known limitations
- Windows:
- Failed page loads aren't reported, so
-ewon't catch a bad URL and a failed load waits until-t. Use-tthere. -yand dialog logging work by replacingalert,confirmandpromptin the page, so a page can see or undo it.-w WxHsizes the outer window, so the page's viewport is a little smaller.
- Failed page loads aren't reported, so
- One shared JavaScript world. Page scripts,
-i/-xscripts and webframe's hooks all share one JavaScript context. A hostile page can readwebframe.env, forge eval results, or callwebframe.exit(#6, #9). Only pass secrets to pages you trust. -iruns in the top frame only, not in iframes.- CSP pages: on pages that block
eval, console input and-xscripts must each be a single expression. Multi-line console input doesn't work there. - Waiting for load:
-cand-xwait for the page'sloadevent, so a resource that never finishes loading holds them until-t. - Hidden error details: errors from
file://pages and cross-origin scripts show onlyScript error.because the engine hides the details.- Serve the page over http to see them.
- Web Workers: console output from workers isn't captured.
about:blankhas an opaque origin, so cross-originfetchandlocalStorageneed a real page.