Skip to content

Commit 4b84834

Browse files
os-elonclaude
andauthored
test(objectql): collapse the twelve ./registry module-mocks into one factory (#10634)
`vi.mock('./registry', …)` was hand-copied into twelve test files in `packages/objectql/src`, and the copies had drifted: eleven declared twelve members, `engine-count-read-filter.test.ts` declared eleven and omitted `getAllObjects` — the #9002 shape, inert only because no path its suite drives reaches one of the thirteen `getAllObjects` call sites in this package. The deciding evidence for collapsing rather than adding the missing line is the two lesson comments themselves: the #9002 explanation lived in exactly one copy and the #9154 explanation in nine others, and neither could reach the rest because there was no shared factory to write them in. Both now live in `registry-module-mock.ts`, which every call site inherits. `engine.test.ts` keeps its stateful in-memory registry as per-member overrides over the shared member set, so it too fails when the shared factory loses a member. The `async` factory form is what makes importing the shared module legal under `vi.mock` hoisting. Test infrastructure only — no production source is touched. Claude-Session: https://claude.ai/code/session_019yDEhPBC3tcGkW9bkce1HM Co-authored-by: Claude <noreply@anthropic.com>
1 parent 78ac958 commit 4b84834

13 files changed

Lines changed: 288 additions & 419 deletions

packages/objectql/src/engine-autonumber-default-format.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -46,41 +46,12 @@ import { ObjectQL } from './engine';
4646
import { SchemaRegistry } from './registry';
4747
import type { IDataDriver } from '@objectstack/spec/contracts';
4848

49-
vi.mock('./registry', () => {
50-
const instance: any = {
51-
getObject: vi.fn(),
52-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
53-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
54-
// passed anyway: the engine's roll-up summary index read it as
55-
// `getAllObjects?.() ?? []`, so a double that does not model the method
56-
// was indistinguishable from a registry with nothing in it — the write
57-
// path silently skipped the insert-time roll-up seed (#5749) and the
58-
// post-write recompute. With the optional call gone the omission is a
59-
// hard `TypeError`, which is the point: the double now has to model the
60-
// method the engine actually calls. Empty is the truthful body for THIS
61-
// suite — it declares no `summary` field, so the roll-up index over it is
62-
// empty either way, and now it says so instead of the engine inventing it.
63-
getAllObjects: vi.fn(() => []),
64-
registerObject: vi.fn(),
65-
getObjectOwner: vi.fn(),
66-
registerNamespace: vi.fn(),
67-
registerKind: vi.fn(),
68-
registerItem: vi.fn(),
69-
registerApp: vi.fn(),
70-
installPackage: vi.fn(),
71-
reset: vi.fn(),
72-
metadata: { get: vi.fn(() => new Map()) },
73-
};
74-
function SchemaRegistry() {
75-
return instance;
76-
}
77-
Object.assign(SchemaRegistry, instance);
78-
return {
79-
SchemaRegistry,
80-
computeFQN: (_ns: string | undefined, name: string) => name,
81-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
82-
RESERVED_NAMESPACES: new Set(['base', 'system']),
83-
};
49+
vi.mock('./registry', async () => {
50+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
51+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
52+
// form is what makes this import legal under `vi.mock` hoisting.
53+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
54+
return createRegistryModuleMock();
8455
});
8556

8657
/** Date tokens render from the wall clock, so the clock is pinned. Only `Date`. */

packages/objectql/src/engine-autonumber-defer.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,41 +18,12 @@ import type { IDataDriver } from '@objectstack/spec/contracts';
1818
* A `required` autonumber must pass insert-validation in BOTH cases (the value
1919
* is runtime-owned, assigned after validation in the native-driver case).
2020
*/
21-
vi.mock('./registry', () => {
22-
const instance: any = {
23-
getObject: vi.fn(),
24-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
25-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
26-
// passed anyway: the engine's roll-up summary index read it as
27-
// `getAllObjects?.() ?? []`, so a double that does not model the method
28-
// was indistinguishable from a registry with nothing in it — the write
29-
// path silently skipped the insert-time roll-up seed (#5749) and the
30-
// post-write recompute. With the optional call gone the omission is a
31-
// hard `TypeError`, which is the point: the double now has to model the
32-
// method the engine actually calls. Empty is the truthful body for THIS
33-
// suite — it declares no `summary` field, so the roll-up index over it is
34-
// empty either way, and now it says so instead of the engine inventing it.
35-
getAllObjects: vi.fn(() => []),
36-
registerObject: vi.fn(),
37-
getObjectOwner: vi.fn(),
38-
registerNamespace: vi.fn(),
39-
registerKind: vi.fn(),
40-
registerItem: vi.fn(),
41-
registerApp: vi.fn(),
42-
installPackage: vi.fn(),
43-
reset: vi.fn(),
44-
metadata: { get: vi.fn(() => new Map()) },
45-
};
46-
function SchemaRegistry() {
47-
return instance;
48-
}
49-
Object.assign(SchemaRegistry, instance);
50-
return {
51-
SchemaRegistry,
52-
computeFQN: (_ns: string | undefined, name: string) => name,
53-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
54-
RESERVED_NAMESPACES: new Set(['base', 'system']),
55-
};
21+
vi.mock('./registry', async () => {
22+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
23+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
24+
// form is what makes this import legal under `vi.mock` hoisting.
25+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
26+
return createRegistryModuleMock();
5627
});
5728

5829
function makeDriver(supportsAutonumber: boolean): IDataDriver & { created: any[] } {

packages/objectql/src/engine-autonumber-resync.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -91,41 +91,12 @@ import { ObjectQL } from './engine';
9191
import { SchemaRegistry } from './registry';
9292
import type { IDataDriver } from '@objectstack/spec/contracts';
9393

94-
vi.mock('./registry', () => {
95-
const instance: any = {
96-
getObject: vi.fn(),
97-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
98-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
99-
// passed anyway: the engine's roll-up summary index read it as
100-
// `getAllObjects?.() ?? []`, so a double that does not model the method
101-
// was indistinguishable from a registry with nothing in it — the write
102-
// path silently skipped the insert-time roll-up seed (#5749) and the
103-
// post-write recompute. With the optional call gone the omission is a
104-
// hard `TypeError`, which is the point: the double now has to model the
105-
// method the engine actually calls. Empty is the truthful body for THIS
106-
// suite — it declares no `summary` field, so the roll-up index over it is
107-
// empty either way, and now it says so instead of the engine inventing it.
108-
getAllObjects: vi.fn(() => []),
109-
registerObject: vi.fn(),
110-
getObjectOwner: vi.fn(),
111-
registerNamespace: vi.fn(),
112-
registerKind: vi.fn(),
113-
registerItem: vi.fn(),
114-
registerApp: vi.fn(),
115-
installPackage: vi.fn(),
116-
reset: vi.fn(),
117-
metadata: { get: vi.fn(() => new Map()) },
118-
};
119-
function SchemaRegistry() {
120-
return instance;
121-
}
122-
Object.assign(SchemaRegistry, instance);
123-
return {
124-
SchemaRegistry,
125-
computeFQN: (_ns: string | undefined, name: string) => name,
126-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
127-
RESERVED_NAMESPACES: new Set(['base', 'system']),
128-
};
94+
vi.mock('./registry', async () => {
95+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
96+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
97+
// form is what makes this import legal under `vi.mock` hoisting.
98+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
99+
return createRegistryModuleMock();
129100
});
130101

131102
/** Date tokens render from the wall clock, so the clock is pinned. */

packages/objectql/src/engine-autonumber-seed-outage.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,12 @@ import { ObjectQL } from './engine';
3737
import { SchemaRegistry } from './registry';
3838
import type { IDataDriver } from '@objectstack/spec/contracts';
3939

40-
vi.mock('./registry', () => {
41-
const instance: any = {
42-
getObject: vi.fn(),
43-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
44-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
45-
// passed anyway: the engine's roll-up summary index read it as
46-
// `getAllObjects?.() ?? []`, so a double that does not model the method
47-
// was indistinguishable from a registry with nothing in it — the write
48-
// path silently skipped the insert-time roll-up seed (#5749) and the
49-
// post-write recompute. With the optional call gone the omission is a
50-
// hard `TypeError`, which is the point: the double now has to model the
51-
// method the engine actually calls. Empty is the truthful body for THIS
52-
// suite — it declares no `summary` field, so the roll-up index over it is
53-
// empty either way, and now it says so instead of the engine inventing it.
54-
getAllObjects: vi.fn(() => []),
55-
registerObject: vi.fn(),
56-
getObjectOwner: vi.fn(),
57-
registerNamespace: vi.fn(),
58-
registerKind: vi.fn(),
59-
registerItem: vi.fn(),
60-
registerApp: vi.fn(),
61-
installPackage: vi.fn(),
62-
reset: vi.fn(),
63-
metadata: { get: vi.fn(() => new Map()) },
64-
};
65-
function SchemaRegistry() {
66-
return instance;
67-
}
68-
Object.assign(SchemaRegistry, instance);
69-
return {
70-
SchemaRegistry,
71-
computeFQN: (_ns: string | undefined, name: string) => name,
72-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
73-
RESERVED_NAMESPACES: new Set(['base', 'system']),
74-
};
40+
vi.mock('./registry', async () => {
41+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
42+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
43+
// form is what makes this import legal under `vi.mock` hoisting.
44+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
45+
return createRegistryModuleMock();
7546
});
7647

7748
const DOC_SCHEMA = {

packages/objectql/src/engine-autonumber-seed-scan.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,41 +41,12 @@ import { ObjectQL } from './engine';
4141
import { SchemaRegistry } from './registry';
4242
import type { IDataDriver } from '@objectstack/spec/contracts';
4343

44-
vi.mock('./registry', () => {
45-
const instance: any = {
46-
getObject: vi.fn(),
47-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
48-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
49-
// passed anyway: the engine's roll-up summary index read it as
50-
// `getAllObjects?.() ?? []`, so a double that does not model the method
51-
// was indistinguishable from a registry with nothing in it — the write
52-
// path silently skipped the insert-time roll-up seed (#5749) and the
53-
// post-write recompute. With the optional call gone the omission is a
54-
// hard `TypeError`, which is the point: the double now has to model the
55-
// method the engine actually calls. Empty is the truthful body for THIS
56-
// suite — it declares no `summary` field, so the roll-up index over it is
57-
// empty either way, and now it says so instead of the engine inventing it.
58-
getAllObjects: vi.fn(() => []),
59-
registerObject: vi.fn(),
60-
getObjectOwner: vi.fn(),
61-
registerNamespace: vi.fn(),
62-
registerKind: vi.fn(),
63-
registerItem: vi.fn(),
64-
registerApp: vi.fn(),
65-
installPackage: vi.fn(),
66-
reset: vi.fn(),
67-
metadata: { get: vi.fn(() => new Map()) },
68-
};
69-
function SchemaRegistry() {
70-
return instance;
71-
}
72-
Object.assign(SchemaRegistry, instance);
73-
return {
74-
SchemaRegistry,
75-
computeFQN: (_ns: string | undefined, name: string) => name,
76-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
77-
RESERVED_NAMESPACES: new Set(['base', 'system']),
78-
};
44+
vi.mock('./registry', async () => {
45+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
46+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
47+
// form is what makes this import legal under `vi.mock` hoisting.
48+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
49+
return createRegistryModuleMock();
7950
});
8051

8152
/** The page size the seeding walk uses — a PAGE, not a cap, since #6249. */

packages/objectql/src/engine-autonumber-seed-suffix.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,41 +38,12 @@ import { ObjectQL } from './engine';
3838
import { SchemaRegistry } from './registry';
3939
import type { IDataDriver } from '@objectstack/spec/contracts';
4040

41-
vi.mock('./registry', () => {
42-
const instance: any = {
43-
getObject: vi.fn(),
44-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
45-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
46-
// passed anyway: the engine's roll-up summary index read it as
47-
// `getAllObjects?.() ?? []`, so a double that does not model the method
48-
// was indistinguishable from a registry with nothing in it — the write
49-
// path silently skipped the insert-time roll-up seed (#5749) and the
50-
// post-write recompute. With the optional call gone the omission is a
51-
// hard `TypeError`, which is the point: the double now has to model the
52-
// method the engine actually calls. Empty is the truthful body for THIS
53-
// suite — it declares no `summary` field, so the roll-up index over it is
54-
// empty either way, and now it says so instead of the engine inventing it.
55-
getAllObjects: vi.fn(() => []),
56-
registerObject: vi.fn(),
57-
getObjectOwner: vi.fn(),
58-
registerNamespace: vi.fn(),
59-
registerKind: vi.fn(),
60-
registerItem: vi.fn(),
61-
registerApp: vi.fn(),
62-
installPackage: vi.fn(),
63-
reset: vi.fn(),
64-
metadata: { get: vi.fn(() => new Map()) },
65-
};
66-
function SchemaRegistry() {
67-
return instance;
68-
}
69-
Object.assign(SchemaRegistry, instance);
70-
return {
71-
SchemaRegistry,
72-
computeFQN: (_ns: string | undefined, name: string) => name,
73-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
74-
RESERVED_NAMESPACES: new Set(['base', 'system']),
75-
};
41+
vi.mock('./registry', async () => {
42+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
43+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
44+
// form is what makes this import legal under `vi.mock` hoisting.
45+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
46+
return createRegistryModuleMock();
7647
});
7748

7849
/**

packages/objectql/src/engine-count-read-filter.test.ts

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,12 @@ import { SchemaRegistry } from './registry';
1717
* These tests assert on what the DRIVER receives: the middleware's filter
1818
* must be present in the ast that reaches driver.count / driver.aggregate.
1919
*/
20-
vi.mock('./registry', () => {
21-
const instance: any = {
22-
getObject: vi.fn(),
23-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
24-
registerObject: vi.fn(),
25-
getObjectOwner: vi.fn(),
26-
registerNamespace: vi.fn(),
27-
registerKind: vi.fn(),
28-
registerItem: vi.fn(),
29-
registerApp: vi.fn(),
30-
installPackage: vi.fn(),
31-
reset: vi.fn(),
32-
metadata: { get: vi.fn(() => new Map()) },
33-
};
34-
function SchemaRegistry() {
35-
return instance;
36-
}
37-
Object.assign(SchemaRegistry, instance);
38-
return {
39-
SchemaRegistry,
40-
computeFQN: (_ns: string | undefined, name: string) => name,
41-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
42-
RESERVED_NAMESPACES: new Set(['base', 'system']),
43-
};
20+
vi.mock('./registry', async () => {
21+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
22+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
23+
// form is what makes this import legal under `vi.mock` hoisting.
24+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
25+
return createRegistryModuleMock();
4426
});
4527

4628
const NOTE_SCHEMA = {

packages/objectql/src/engine-filter-tokens.test.ts

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,12 @@ import { SchemaRegistry } from './registry';
1717
* These tests assert on what the DRIVER receives: no `{token}` may survive to
1818
* the driver AST, and an unresolvable one must throw rather than pass through.
1919
*/
20-
vi.mock('./registry', () => {
21-
const instance: any = {
22-
getObject: vi.fn(),
23-
resolveObject: vi.fn((n: string) => instance.getObject(n)),
24-
// [#9154] This double used to OMIT `getAllObjects`, and every test here
25-
// passed anyway: the engine's roll-up summary index read it as
26-
// `getAllObjects?.() ?? []`, so a double that does not model the method
27-
// was indistinguishable from a registry with nothing in it — the write
28-
// path silently skipped the insert-time roll-up seed (#5749) and the
29-
// post-write recompute. With the optional call gone the omission is a
30-
// hard `TypeError`, which is the point: the double now has to model the
31-
// method the engine actually calls. Empty is the truthful body for THIS
32-
// suite — it declares no `summary` field, so the roll-up index over it is
33-
// empty either way, and now it says so instead of the engine inventing it.
34-
getAllObjects: vi.fn(() => []),
35-
registerObject: vi.fn(),
36-
getObjectOwner: vi.fn(),
37-
registerNamespace: vi.fn(),
38-
registerKind: vi.fn(),
39-
registerItem: vi.fn(),
40-
registerApp: vi.fn(),
41-
installPackage: vi.fn(),
42-
reset: vi.fn(),
43-
metadata: { get: vi.fn(() => new Map()) },
44-
};
45-
function SchemaRegistry() {
46-
return instance;
47-
}
48-
Object.assign(SchemaRegistry, instance);
49-
return {
50-
SchemaRegistry,
51-
computeFQN: (_ns: string | undefined, name: string) => name,
52-
parseFQN: (fqn: string) => ({ namespace: undefined, shortName: fqn }),
53-
RESERVED_NAMESPACES: new Set(['base', 'system']),
54-
};
20+
vi.mock('./registry', async () => {
21+
// [#10551] The one shared factory — see `registry-module-mock.ts` for the
22+
// member set, the #9002 / #9154 lessons it carries, and why the async factory
23+
// form is what makes this import legal under `vi.mock` hoisting.
24+
const { createRegistryModuleMock } = await import('./registry-module-mock.js');
25+
return createRegistryModuleMock();
5526
});
5627

5728
const DEAL_SCHEMA = {

0 commit comments

Comments
 (0)