A page that only takes notes
The parent's test target cannot make a web view, so it brings its own engine. Tests/VoyagerCoreTests/FakeEngine.swift is 242 lines, and its first comment says why it exists: "The parent runs against this instead of WebKit: every rule of tabs, sessions, identity and trust is a plain value here."
Three small classes fill the contract. FakePage conforms to EnginePage and writes things down: every address it is told to load goes into loads, the state it was restored from into restoredFrom, a close into closed. It also has knobs a test turns. finish(title:) pretends the page finished loading, busy is what it answers when the sleep policy asks, context is what Pippa will read. Its captureState() writes the page's address as bytes and tags them "fake". FakePanel keeps every message delivered to Pippa's panel. FakeEngine keeps every page and panel it made, and a cookie jar for each identity.
Then Bench wires a fake engine, a BrowserServices and one BrowserWindowModel together. A test starts with let bench = Bench() and has a working browser with no browser in it.
Reading a test as a specification
The second block below is one session test, and it reads like a sentence about the product. Open three tabs, put the second in front, take a snapshot. Restore that snapshot into a fresh bench. Then the claims: the tab ids come back in order; only the tab in front is awake ([true, false, true] for asleep); every title is kept, even for tabs that have no page; the front tab came back from its stored bytes and loaded nothing; the engine made exactly one page. Select the first tab, and the engine makes a second page, restored from that tab's own bytes.
In executable form, that says a window with forty tabs restores one page, not forty. Real WebKit would add nothing to this test, because the claim is about the parent's decision, and the fake simply writes down what it was asked to do.
How much of the suite needs the fake at all
The parent's target holds 242 tests in 48 suites across 21 test files. Only 11 of those files reach for the fake engine: tab commands, the window model, sessions, settings, privacy, passwords, Pippa's host, the catalog model and a few more. The other 10 need no engine of any kind: trust and departures, address resolution, history, bookmarks, suggestions, the Chromium import, the mouse's history step. Trust, for one, is tested by building a PermissionRequest by hand and asking the policy, which is where the previous lesson's plain values pay off.
What a fake cannot prove
A fake is the parent's description of an engine. It proves the parent behaves correctly toward an engine that behaves the way the fake does. Whether WebKit behaves that way is a different claim, and the fake is the one instrument that can never test it.
| Claim | Proved by |
|---|---|
| A restored window wakes only the tab in front | Parent suite, fake engine |
| A stored state written by another engine is ignored and the address loaded | Parent suite, fake engine |
| WebKit's bytes really bring a scroll position back | Real WebKit suite, aPlaceComesBackFromBytes |
| The child answers every selector WebKit looks for, so a misnamed delegate method cannot hide | Real WebKit suite, the selector test (lesson 4), which asks responds(to:) and never waits for a call |
| WebKit really calls the capture method with a page's request | The gate's browser probe, scripts/probes/run-gate-browser.sh --auto (W6), because a page's microphone request is answered only in a visible window |
| A page presents Safari's token in its user agent | Real WebKit suite, itPresentsSafarisToken |
| The window, the tab strip and the keyboard work together | The verification build's walk through its own screens, scripts/smoke.sh |
The table also tells you when to stop extending a fake. When a test needs the fake to imitate WebKit in some detail, that test belongs in the other target.
One rule, held on both sides
The third block is the parent's half of a rule from the contract: a PageState written by another engine is ignored, and the tab loads the address instead. The child holds the other half with a real-WebKit test, anotherEnginesBytesAreNotFedToWebKit, which makes a page from bytes tagged not-webkit and expects it to stay empty. The parent checks the tag before it hands the bytes over, and the child checks again before it believes them. Two tests in two targets, for one sentence of the contract.