@ultimat3/testing
Advanced tools
+1
-1
@@ -38,3 +38,3 @@ # @ultimat3/testing — boundary | ||
| | `page` HAS a driver now, and the other three still do not, `As of 2026-08-25` | `installE2eDriver({ page, baseUrl })` registers `page` over its declaration and leaves `budget`, `signIn` and `deploy` refusing, on purpose: byte counts come off a built `dist/`, a sign-in route is the APP's, and a new build id is a fact about the SERVER — a page port can answer for none of the three, and a fixture that silently no-opped would make the assertion after it read as proof | | ||
| | `network` is THIS process's fetch, and an e2e page is not in this process | `sealed-network.ts` patches `globalThis.fetch` here; a browser's requests never pass through it. So `network.offline()` in a test that also destructures `page` is a **no-op on the browser** — the app's online page passing an offline test. `E2eFixtures.offline()` is the browser-side spelling and the CDP driver REFUSES it (`X_TEST_FIXTURE_UNAVAILABLE`), because `CdpPageLike` declares no `setOfflineMode`. Two words, two mechanisms, and only one of them can put a browser offline | | ||
| | `network` is THIS process's fetch, and an e2e page is not in this process | `sealed-network.ts` patches `globalThis.fetch` here; a browser's requests never pass through it. So `network.offline()` in a test that also destructures `page` is a **no-op on the browser** — the app's online page passing an offline test. `E2eFixtures.offline()` is the browser-side spelling, and `As of 2026-08-27` it FORWARDS — through `E2eBrowserPage.offline()` to `ScrapePage.offline()` to `CdpPageLike.setOfflineMode`, which `cdp-port.ts` has declared since #351. This row said the CDP driver refused it "because `CdpPageLike` declares no `setOfflineMode`", and that was untrue in the commit that wrote it; the refusal it describes now fires only for a hand-rolled `E2eBrowserPage` with no `offline()`, and names that. Two words, two mechanisms, and only one of them can put a browser offline | | ||
| | `subscribe` is a whole `sync` node | `live-node.ts` assembles what `x dev --role sync` assembles minus the listener — real `LiveQueryRegistry`, real `liveQueryDefinition` bridge, real per-subscriber gate, real cursor — over a socket that is two objects handing each other the JSON a WebSocket would. `live-replicator.ts` feeds it from `@ultimat3/entity`'s `setRowObserver`, which is the change SOURCE a test process never had: PGlite has no walsender and the memory driver no log, so `InMemoryChangeFeed` had nothing upstream of it. The WAL decoder is the only thing substituted; everything downstream of it is production code | | ||
@@ -41,0 +41,0 @@ | What `subscribe` does NOT hold | a client store, an offline queue or a rebase log — so `feed.local()` answers `undefined` rather than the server row. A twin reported as applied whether or not a mutator ran is coverage that reads as proof, which is worse than none. That half is `useMutation` / `useMutationQueue` and an e2e | |
+12
-12
| { | ||
| "name": "@ultimat3/testing", | ||
| "version": "18.0.0", | ||
| "version": "19.0.0", | ||
| "description": "Test harness: cloned template DBs per worker, frozen clock, sealed network, 6 test types", | ||
@@ -36,14 +36,14 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "@ultimat3/cache": "18.0.0", | ||
| "@ultimat3/core": "18.0.0", | ||
| "@ultimat3/db": "18.0.0", | ||
| "@ultimat3/entity": "18.0.0", | ||
| "@ultimat3/i18n": "18.0.0", | ||
| "@ultimat3/jobs": "18.0.0", | ||
| "@ultimat3/mail": "18.0.0", | ||
| "@ultimat3/policy": "18.0.0", | ||
| "@ultimat3/query": "18.0.0", | ||
| "@ultimat3/realtime": "18.0.0", | ||
| "@ultimat3/time": "18.0.0" | ||
| "@ultimat3/cache": "19.0.0", | ||
| "@ultimat3/core": "19.0.0", | ||
| "@ultimat3/db": "19.0.0", | ||
| "@ultimat3/entity": "19.0.0", | ||
| "@ultimat3/i18n": "19.0.0", | ||
| "@ultimat3/jobs": "19.0.0", | ||
| "@ultimat3/mail": "19.0.0", | ||
| "@ultimat3/policy": "19.0.0", | ||
| "@ultimat3/query": "19.0.0", | ||
| "@ultimat3/realtime": "19.0.0", | ||
| "@ultimat3/time": "19.0.0" | ||
| } | ||
| } |
@@ -25,4 +25,14 @@ // Build one island, import the chunk the way the hydration runtime does, and run its `mount` over | ||
| /** `buildIslands` from `@ultimat3/cli` satisfies this structurally — no import, no new tier edge. */ | ||
| export type IslandBuilder = (root: string) => Promise<IslandBundleLike>; | ||
| /** | ||
| * `buildIslands` from `@ultimat3/cli` satisfies this structurally — no import, no new tier edge. | ||
| * | ||
| * The second parameter is OPTIONAL on both sides, `As of 2026-08-27`, which is what keeps that true: | ||
| * a builder of your own written as `(root) => …` is still assignable, and `buildIslands`' own | ||
| * `options` argument is already optional. Widening it is what lets `mountIsland` name the one island | ||
| * it is about to mount — see the call site for what building all of them was costing. | ||
| */ | ||
| export type IslandBuilder = ( | ||
| root: string, | ||
| options?: { readonly only?: string }, | ||
| ) => Promise<IslandBundleLike>; | ||
@@ -172,3 +182,16 @@ export interface MountIslandOptions { | ||
| export async function mountIsland(options: MountIslandOptions): Promise<MountedIsland> { | ||
| const bundle = await options.build(options.root); | ||
| // `only`, because this fixture has always KNOWN which island it wants and asked for all of them | ||
| // anyway — `island-bundle.ts` added the option for exactly this caller ("a test that mounts a | ||
| // single island otherwise pays every OTHER island's Babel pass and `Bun.build` on every file, and | ||
| // the reference app is the one that feels it") and nothing ever passed it. | ||
| // | ||
| // It is also the difference between green and red on Bun 1.3.14, which is how it was found: | ||
| // building the reference app's four islands in a test process that has already imported | ||
| // `@ultimat3/realtime` at module scope makes `Bun.build` throw `Unexpected reading file: | ||
| // packages/realtime/src/index.ts`. One island does not, and neither does `x build` — measured, | ||
| // `x build --target static` is green on 1.3.14 — so this is a bundler defect confined to | ||
| // `bun test`, fixed in 1.4.0, and asking for the island we actually want walks around it while | ||
| // being the faster and more honest call regardless. A builder that ignores the argument still | ||
| // works: the `find` below is unchanged. | ||
| const bundle = await options.build(options.root, { only: options.file }); | ||
| const chunk = bundle.chunks.find((each) => each.file === options.file); | ||
@@ -175,0 +198,0 @@ if (chunk === undefined) { |
325032
0.58%5459
0.42%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated
Updated