Skip to content

v0.2

Latest

Choose a tag to compare

@progrium progrium released this 30 Oct 03:19
25c24cb

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, every WF_* variable in your environment became a window global on every page you opened, including untrusted ones. Now you name each variable you want to pass with -E, and pages read it from webframe.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.Globals is replaced by Options.Env, exposed to the page as webframe.env rather than as window globals.

  • -c waits 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 own load handlers 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 -x to 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, fetch hooks and test helpers.
  • Set the exit status from the page with webframe.exit(code). Pages also get a read-only webframe global, which holds env and exit.
  • 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 as undefined.
  • Timeout (-t DURATION). webframe exits 124 when the time runs out. It takes seconds or values like 500ms and 2m, so a hung test can't block CI.
  • Accept dialogs (-y). alert, confirm and prompt are 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. -c keeps 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. -h now lists all exit statuses.
  • Go library:
    • Options gains Init, AcceptDialogs, and Loaded, LoadFailed and Exit callbacks.
    • EvalContext stops waiting for a result when its context is cancelled or times out.
    • ErrIncomplete marks source that ended before a statement was complete.
  • New examples:
    • todo.html with todo.test.js and mock-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 requestAnimationFrame now 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-musl build crashed on Alpine; it now runs normally.
  • Failed page loads no longer hang. A failed load now exits instead of waiting forever (#3). -t limits 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 the linux-musl build

Known limitations

  • Windows:
    • Failed page loads aren't reported, so -e won't catch a bad URL and a failed load waits until -t. Use -t there.
    • -y and dialog logging work by replacing alert, confirm and prompt in the page, so a page can see or undo it.
    • -w WxH sizes the outer window, so the page's viewport is a little smaller.
  • One shared JavaScript world. Page scripts, -i/-x scripts and webframe's hooks all share one JavaScript context. A hostile page can read webframe.env, forge eval results, or call webframe.exit (#6, #9). Only pass secrets to pages you trust.
  • -i runs in the top frame only, not in iframes.
  • CSP pages: on pages that block eval, console input and -x scripts must each be a single expression. Multi-line console input doesn't work there.
  • Waiting for load: -c and -x wait for the page's load event, so a resource that never finishes loading holds them until -t.
  • Hidden error details: errors from file:// pages and cross-origin scripts show only Script 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:blank has an opaque origin, so cross-origin fetch and localStorage need a real page.