Skip to content

Commit 881c31f

Browse files
committed
test(objectql): picklist test doubles honour the caller's limit and look services up by contract type
Claude-Session: https://claude.ai/code/session_01MZu5JqVPacMktogpMxq9Xu Co-authored-by: Claude <noreply@anthropic.com>
1 parent a1e3908 commit 881c31f

2 files changed

Lines changed: 24 additions & 12 deletions

File tree

‎packages/objectql/src/plugin-picklist-boot-audit.test.ts‎

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
import { describe, it, expect, afterEach } from 'vitest';
1515
import { ObjectKernel, type PluginContext } from '@objectstack/core';
1616
import { ObjectQLPlugin } from './plugin.js';
17+
import type { ObjectQL } from './engine.js';
18+
19+
/** The slice of the `manifest` service these cases call. */
20+
interface ManifestService {
21+
register(artifact: unknown): Promise<void> | void;
22+
}
1723

1824
const kernels: ObjectKernel[] = [];
1925
afterEach(async () => {
@@ -29,7 +35,7 @@ function registering(name: string, artifacts: unknown[]) {
2935
name,
3036
dependencies: ['com.objectstack.engine.objectql'],
3137
init: async (ctx: PluginContext) => {
32-
const manifest = ctx.getService<{ register(a: unknown): unknown }>('manifest');
38+
const manifest = ctx.getService<ManifestService>('manifest');
3339
for (const artifact of artifacts) await manifest.register(artifact);
3440
},
3541
};
@@ -41,6 +47,11 @@ function kernelWith(...plugins: any[]) {
4147
return { kernel, use: async () => { for (const p of plugins) await kernel.use(p); } };
4248
}
4349

50+
/** The option values a registered object's field is served with. */
51+
const servedValues = (ql: ObjectQL, object: string, field: string): unknown[] =>
52+
((ql.registry.getObject(object)?.fields?.[field] as { options?: Array<{ value: unknown }> } | undefined)?.options ?? [])
53+
.map((o) => o.value);
54+
4455
const INDUSTRY = { name: 'industry', label: 'Industry', options: [{ label: 'Technology', value: 'technology' }] };
4556
const ACCOUNT = {
4657
name: 'pb_account',
@@ -76,45 +87,45 @@ describe('the picklist boot audit', () => {
7687
);
7788
await use();
7889
await kernel.bootstrap();
79-
const ql: any = kernel.getService('objectql');
80-
expect(ql.registry.getObject('pb_account').fields.industry.options.map((o: any) => o.value)).toEqual(['technology']);
90+
const ql = kernel.getService<ObjectQL>('objectql');
91+
expect(servedValues(ql, 'pb_account', 'industry')).toEqual(['technology']);
8192
});
8293

8394
it('after the boot, an artifact naming an unknown list is refused before ANY of it registers', async () => {
8495
const { kernel, use } = kernelWith(new ObjectQLPlugin());
8596
await use();
8697
await kernel.bootstrap();
87-
const manifest: any = kernel.getService('manifest');
98+
const manifest = kernel.getService<ManifestService>('manifest');
8899
expect(() => manifest.register({ id: 'com.test.late', name: 'late', objects: [ACCOUNT] }))
89100
.toThrow(/field 'pb_account\.industry' \(package 'com\.test\.late'\) references picklist 'industry'/);
90-
const ql: any = kernel.getService('objectql');
101+
const ql = kernel.getService<ObjectQL>('objectql');
91102
expect(ql.registry.getObject('pb_account')).toBeUndefined();
92103
});
93104

94105
it('after the boot, an artifact extending an unknown list is refused before ANY of it registers', async () => {
95106
const { kernel, use } = kernelWith(new ObjectQLPlugin());
96107
await use();
97108
await kernel.bootstrap();
98-
const manifest: any = kernel.getService('manifest');
109+
const manifest = kernel.getService<ManifestService>('manifest');
99110
expect(() => manifest.register({ id: 'com.test.late', name: 'late', picklistExtensions: [{ extend: 'industy', options: [{ label: 'X', value: 'x' }] }] }))
100111
.toThrow(/extends picklist 'industy'/);
101-
const ql: any = kernel.getService('objectql');
112+
const ql = kernel.getService<ObjectQL>('objectql');
102113
expect(ql.registry.findOrphanPicklistExtensions()).toEqual([]);
103114
});
104115

105116
it('after the boot, an artifact that brings its own list — or names a registered one — registers', async () => {
106117
const { kernel, use } = kernelWith(new ObjectQLPlugin(), registering('lists', [{ id: 'com.test.boot.lists', name: 'lists', picklists: [INDUSTRY] }]));
107118
await use();
108119
await kernel.bootstrap();
109-
const manifest: any = kernel.getService('manifest');
120+
const manifest = kernel.getService<ManifestService>('manifest');
110121
await manifest.register({ id: 'com.test.late', name: 'late', objects: [ACCOUNT] });
111122
await manifest.register({
112123
id: 'com.test.late2', name: 'late2',
113124
picklists: [{ name: 'tier', label: 'Tier', options: [{ label: 'Gold', value: 'gold' }] }],
114125
objects: [{ name: 'pb_member', fields: { tier: { name: 'tier', type: 'select', picklist: 'tier' } } }],
115126
});
116-
const ql: any = kernel.getService('objectql');
117-
expect(ql.registry.getObject('pb_account').fields.industry.options.map((o: any) => o.value)).toEqual(['technology']);
118-
expect(ql.registry.getObject('pb_member').fields.tier.options.map((o: any) => o.value)).toEqual(['gold']);
127+
const ql = kernel.getService<ObjectQL>('objectql');
128+
expect(servedValues(ql, 'pb_account', 'industry')).toEqual(['technology']);
129+
expect(servedValues(ql, 'pb_member', 'tier')).toEqual(['gold']);
119130
});
120131
});

‎packages/objectql/src/protocol-picklist-served-roundtrip.test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ function makeStubDriver() {
9393
async checkHealth() { return true; },
9494
async execute() { return null; },
9595
async find(object: string, ast: any) {
96-
return Array.from(storeFor(object).values()).filter((r) => matchesWhere(r, ast?.where));
96+
const rows = Array.from(storeFor(object).values()).filter((r) => matchesWhere(r, ast?.where));
97+
return typeof ast?.limit === 'number' ? rows.slice(0, ast.limit) : rows;
9798
},
9899
async findOne(object: string, ast: any) {
99100
for (const r of storeFor(object).values()) if (matchesWhere(r, ast?.where)) return r;

0 commit comments

Comments
 (0)