@ultimat3/testing 27.16.0 → 28.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  Tier 5. May import tiers 0–4. Imported by every package's tests and by generated apps.
4
4
 
5
- Deps: `core` (tier 0), plus `time`, `jobs`, `mail`, `db`, `entity`, `render` and `http` — imported **dynamically
6
- inside the fixture factories only** (`render` inside `render-view.ts`, `http` inside `auth-request.ts`), so a test that never destructures `mail` never loads the mail
7
- package and a `packages/core` test never loads the entity registry. `entity` is a dependency for
8
- exactly one call: `nPlusOne()`, so the strict fixture reports the error `x dev` reports, with the
9
- `fix:` the schema's own relations spell. A second N+1 code owned here would be a second answer to
10
- one condition. The one static `entity` import is `registry-isolation.ts`, which is why that module
11
- is its own entry point and not part of the barrel.
5
+ Deps (15): `core`; `cache` `db` `i18n` `time`; `entity` `http` `policy`; `action` `jobs`
6
+ `query` `realtime`; `mail` `pwa` `render`. Static in `.`: `cache`
7
+ (`registry-leak-guard.ts:7`), `i18n`, `jobs`, `policy` (`registry-snapshot.ts:29-38`), `db`
8
+ (`reusable-database.ts:20`), `realtime/server` (`fixture-subscribe.ts:13`). Dynamic-only:
9
+ `action`, `http`, `mail`, `pwa`, `query`, `render`, `time` — no `mail` destructure, no mail
10
+ package; a `packages/core` import never loads `@ultimat3/entity`. `entity` exists for exactly
11
+ one call, `nPlusOne()`: the strict fixture reports `x dev`'s error, with the `fix:` the schema's
12
+ own relations spell — a second N+1 code here would be a second answer to one condition. Its one
13
+ static import: `registry-isolation.ts`, own entry point, off the barrel.
12
14
 
13
15
  | Rule | Detail |
14
16
  |---|---|
@@ -37,7 +39,7 @@ is its own entry point and not part of the barrel.
37
39
  | One body shape, five registrars | `test` (= `fixtureTest`), `unitTest`, `contractTest`, `liveTest`, `jobTest` all take `FixtureBody` + `{ timeoutMs }`: `unitTest('…', async ({ runJobs }) => …)`. Never `describe(testName('unit', …))` + `test` to get a fixture |
38
40
  | `runJobs` says who and what | `{ actor }` is the WORKER's identity (the org stays the job's declared tenant), `{ tenantId }` the enqueuer's row; `executions[n].result` is the body's return. A fresh event bus per fixture |
39
41
  | A `runJobs` pass is a real worker's `tick()` | `fixture-jobs.ts` builds an unstarted `jobWorker` per pass, so admission runs: `concurrency` waits and `whenBusy: 'fail'` refuses (`X_JOB_KEY_BUSY`) exactly as in a fleet. Never `executeJob` on a bare `claim()`. The lease and slot renew every 1 ms of TEST time (`RENEW_MS`, `frozen-scheduler.ts` on `onClockMoved`), never on a wall-clock interval: cancel, `clock.advance(1)`, and the body hears `X_JOB_LEASE_LOST` — no hand-built worker |
40
- | Per-test state is `per-test-reset.ts` | the app preload's `beforeEach` resets the jobs event bus — only when `@ultimat3/jobs` is already loaded, so a core test never loads it |
42
+ | Per-test state is `per-test-reset.ts` | the app preload's `beforeEach` resets the jobs event bus — only when `@ultimat3/jobs` is already loaded, so the reset never loads it |
41
43
  | An island test is `describeIslandState` | one block per declared state: mounted in `beforeAll` (60 s), disposed in `afterAll`, one build per file. `mountIslandState` + `using` for one test's own mount; an undeclared id is `X_TEST_ISLAND_STATE_UNKNOWN` |
42
44
  | An authenticator is tested with `authRequest()` | the hook's own two arguments, real — never `as unknown as Parameters<…>` |
43
45
  | `LOG_LEVEL` above `info` filters the TERMINAL | `quiet-logs.ts` pins the logger at `info` while core loads, so a collecting `setLogSink` still sees `warn` under `LOG_LEVEL=error`. It stays the preload's FIRST import |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/testing",
3
- "version": "27.16.0",
3
+ "version": "28.0.0",
4
4
  "description": "Test harness: cloned template DBs per worker, frozen clock, sealed network, 6 test types",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,27 +29,27 @@
29
29
  "LICENSE"
30
30
  ],
31
31
  "engines": {
32
- "bun": ">=1.4.2"
32
+ "bun": ">=1.4.3"
33
33
  },
34
34
  "scripts": {
35
35
  "typecheck": "tsc --noEmit -p tsconfig.json",
36
36
  "test": "bun test"
37
37
  },
38
38
  "dependencies": {
39
- "@ultimat3/action": "27.16.0",
40
- "@ultimat3/cache": "27.16.0",
41
- "@ultimat3/core": "27.16.0",
42
- "@ultimat3/db": "27.16.0",
43
- "@ultimat3/entity": "27.16.0",
44
- "@ultimat3/http": "27.16.0",
45
- "@ultimat3/i18n": "27.16.0",
46
- "@ultimat3/jobs": "27.16.0",
47
- "@ultimat3/mail": "27.16.0",
48
- "@ultimat3/policy": "27.16.0",
49
- "@ultimat3/pwa": "27.16.0",
50
- "@ultimat3/query": "27.16.0",
51
- "@ultimat3/realtime": "27.16.0",
52
- "@ultimat3/render": "27.16.0",
53
- "@ultimat3/time": "27.16.0"
39
+ "@ultimat3/action": "28.0.0",
40
+ "@ultimat3/cache": "28.0.0",
41
+ "@ultimat3/core": "28.0.0",
42
+ "@ultimat3/db": "28.0.0",
43
+ "@ultimat3/entity": "28.0.0",
44
+ "@ultimat3/http": "28.0.0",
45
+ "@ultimat3/i18n": "28.0.0",
46
+ "@ultimat3/jobs": "28.0.0",
47
+ "@ultimat3/mail": "28.0.0",
48
+ "@ultimat3/policy": "28.0.0",
49
+ "@ultimat3/pwa": "28.0.0",
50
+ "@ultimat3/query": "28.0.0",
51
+ "@ultimat3/realtime": "28.0.0",
52
+ "@ultimat3/render": "28.0.0",
53
+ "@ultimat3/time": "28.0.0"
54
54
  }
55
55
  }
@@ -0,0 +1,13 @@
1
+ // Whether this test run's root is an APP — an `app.config.ts` beside it. The registry leak guard
2
+ // restores an app's lazily declared registries as a union, and the framework's own suites exactly.
3
+
4
+ // why: Bun ships no synchronous file-exists check; Bun.file().exists() is async and a preload
5
+ // decides this before any test file loads.
6
+ import { existsSync } from 'node:fs';
7
+ // why: Bun ships no path-join primitive.
8
+ import { join } from 'node:path';
9
+
10
+ export const APP_CONFIG = 'app.config.ts';
11
+
12
+ export const isAppRoot = (root: string = process.cwd()): boolean =>
13
+ existsSync(join(root, APP_CONFIG));
package/src/preload.ts CHANGED
@@ -10,7 +10,6 @@ import './quiet-logs';
10
10
  import { installDeterminism } from './determinism';
11
11
  import { registerFrameworkFixtures } from './framework-fixtures';
12
12
  import './matchers';
13
- import { installAppJsxLoader } from './app-jsx-loader';
14
13
  import { onFileBoundary } from './file-boundary';
15
14
  import { ISOLATED_ENV, releasePluginsAfterIsolatedFile } from './isolated-plugins';
16
15
  import { installPerTestReset } from './per-test-reset';
@@ -72,8 +71,15 @@ if (Bun.env[ISOLATED_ENV] !== '1') {
72
71
  // 8 files, 1 -> 8 live global objects (this file's own leak fixture).
73
72
  releasePluginsAfterIsolatedFile();
74
73
 
75
- // An app's `.tsx` compiles with the app's JSX factory on the first file, never cached classic.
76
- await installAppJsxLoader();
74
+ // Every `.tsx` compiles with the framework's JSX factory from the first file on, in every test
75
+ // process — an app root or any workspace below it. Bun's own compile of a `.tsx` is wrong on every
76
+ // Bun (`@ultimat3/render`'s `module-loader.ts`): through 1.4.2 a cached `React.createElement`
77
+ // (`React is not defined`, 18 notificado.co tests), from 1.4.3 a link-time `SyntaxError: Export
78
+ // named 'jsxDEV' not found` in any file that merely imports a component (issue #883). It was
79
+ // installed only where `app.config.ts` sat beside the run, so a workspace package's own tests
80
+ // needed a hand-written preload (castlefight.online, ai-maxxing).
81
+ const { installRenderLoader } = await import('@ultimat3/render/server');
82
+ installRenderLoader();
77
83
 
78
84
  // Opt-out exists for one case: a test that deliberately exercises a real integration in a job the
79
85
  // team runs on purpose. It is an env var, not an API, so it cannot be set from inside a test file.
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { afterAll } from 'bun:test';
7
7
  import { knownTags, registeredTiers } from '@ultimat3/cache';
8
- import { isAppRoot } from './app-jsx-loader';
8
+ import { isAppRoot } from './app-root';
9
9
  import { RegistryLeakError } from './errors';
10
10
  import { runBoundaryHooks, runFileBoundary } from './file-boundary';
11
11
  import type { ProcessRegistrySnapshot } from './registry-snapshot';
@@ -196,16 +196,12 @@ export function installRegistryLeakGuard(): void {
196
196
  name: 'ultimate-registry-leak-guard',
197
197
  setup(build) {
198
198
  // `.test.ts` only, never `.test.tsx`. A load handler that answered `loader: 'tsx'` would
199
- // compile JSX with Bun's CLASSIC React fallback — the very factory `@ultimat3/render`'s own
200
- // loader exists to replace — and, because the first matching handler wins and this one is
201
- // registered from the preload, it would shadow render's transform for that file. Routing
202
- // `.tsx` through `transformTsx` is not the alternative either: it needs `@ultimat3/render`,
203
- // and the transform itself is on `@ultimat3/render/server`, whose import installs that global
204
- // loader into every test process in the repo. (The `.` barrel does NOT — `installRenderLoader()`
205
- // moved to `server.ts:15` in the 9.0.0 split, and this comment claimed otherwise until
206
- // 2026-08-23. The `server` half is still the one that would have to be imported.) Zero
207
- // `.test.tsx` files exist and the convention is `<file>.test.ts`, so the narrower filter
208
- // costs nothing today; a `.test.tsx` added later is unguarded rather than mis-compiled.
199
+ // compile JSX with Bun's own transform — the one `@ultimat3/render`'s loader exists to
200
+ // replace, a link-time `jsxDEV` error from Bun 1.4.3 (issue #883) — and, because the first
201
+ // matching handler wins and this one is registered from the preload, it would shadow
202
+ // render's transform for that file. Zero `.test.tsx` files exist and the convention is
203
+ // `<file>.test.ts`, so the narrower filter costs nothing today; a `.test.tsx` added later is
204
+ // unguarded rather than mis-compiled.
209
205
  build.onLoad({ filter: /\.test\.ts$/ }, async (args) => {
210
206
  // Before the registry restore: an island disposed here still needs its fake DOM.
211
207
  runFileBoundary();
@@ -1,30 +0,0 @@
1
- // An APP's tests compile every `.tsx` with the app's JSX factory from the first file on.
2
- //
3
- // Since 22.7 a worker runs many files in one module registry (no `--isolate`), so a `.tsx` module
4
- // is compiled ONCE per worker and cached. `@ultimat3/render`'s loader is installed by importing
5
- // `@ultimat3/render/server`; a file that reached a page component before any file had imported it
6
- // cached the page compiled with Bun's classic factory, and every later file on that worker failed
7
- // with `React is not defined` (18 notificado.co tests, measured). Installing the loader in the
8
- // preload makes the first compile the right one.
9
- //
10
- // Only in an app (an `app.config.ts` at the run's root): the framework repository's own tests
11
- // include suites that pin what a process WITHOUT the loader does, and they keep that process.
12
-
13
- // why: Bun ships no synchronous file-exists check; Bun.file().exists() is async and a preload
14
- // decides this before any test file loads.
15
- import { existsSync } from 'node:fs';
16
- // why: Bun ships no path-join primitive.
17
- import { join } from 'node:path';
18
-
19
- export const APP_CONFIG = 'app.config.ts';
20
-
21
- export const isAppRoot = (root: string = process.cwd()): boolean =>
22
- existsSync(join(root, APP_CONFIG));
23
-
24
- /** Install the render loader when this run's root is an app. Returns whether it did. */
25
- export async function installAppJsxLoader(root: string = process.cwd()): Promise<boolean> {
26
- if (!isAppRoot(root)) return false;
27
- const { installRenderLoader } = await import('@ultimat3/render/server');
28
- installRenderLoader();
29
- return true;
30
- }