Skip to content

Commit d4ab36e

Browse files
grypezclaude
andcommitted
test(kernel-utils): add getSection explicit-guard test coverage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 88d0e31 commit d4ab36e

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

packages/kernel-utils/src/sheaf/sheafify.test.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,3 +573,110 @@ describe('sheafify', () => {
573573
).toBeUndefined();
574574
});
575575
});
576+
577+
// ---------------------------------------------------------------------------
578+
// Unit: getSection with explicit guard
579+
// ---------------------------------------------------------------------------
580+
581+
describe('getSection with explicit guard', () => {
582+
it('dispatches calls that fall within the explicit guard', async () => {
583+
const sections: PresheafSection<Record<string, never>>[] = [
584+
{
585+
exo: makeSection(
586+
'Wallet:0',
587+
M.interface('Wallet:0', {
588+
getBalance: M.call(M.string()).returns(M.number()),
589+
transfer: M.call(M.string(), M.number()).returns(M.boolean()),
590+
}),
591+
{
592+
getBalance: (_acct: string) => 42,
593+
transfer: (_to: string, _amt: number) => true,
594+
},
595+
),
596+
},
597+
];
598+
599+
const readGuard = M.interface('ReadOnly', {
600+
getBalance: M.call(M.string()).returns(M.number()),
601+
});
602+
603+
const section = sheafify({ name: 'Wallet', sections }).getSection({
604+
guard: readGuard,
605+
async *lift(germs) {
606+
yield germs[0]!;
607+
},
608+
});
609+
610+
expect(await E(section).getBalance('alice')).toBe(42);
611+
});
612+
613+
it('rejects method calls outside the explicit guard', async () => {
614+
const sections: PresheafSection<Record<string, never>>[] = [
615+
{
616+
exo: makeSection(
617+
'Wallet:0',
618+
M.interface('Wallet:0', {
619+
getBalance: M.call(M.string()).returns(M.number()),
620+
transfer: M.call(M.string(), M.number()).returns(M.boolean()),
621+
}),
622+
{
623+
getBalance: (_acct: string) => 42,
624+
transfer: (_to: string, _amt: number) => true,
625+
},
626+
),
627+
},
628+
];
629+
630+
const readGuard = M.interface('ReadOnly', {
631+
getBalance: M.call(M.string()).returns(M.number()),
632+
});
633+
634+
const section = sheafify({ name: 'Wallet', sections }).getSection({
635+
guard: readGuard,
636+
async *lift(germs) {
637+
yield germs[0]!;
638+
},
639+
});
640+
641+
// makeExo only places methods from the guard on the object — transfer is absent
642+
expect((section as Record<string, unknown>).transfer).toBeUndefined();
643+
});
644+
645+
it('getDiscoverableSection exposes __getDescription__ and obeys explicit guard', async () => {
646+
const sections: PresheafSection<Record<string, never>>[] = [
647+
{
648+
exo: makeSection(
649+
'Wallet:0',
650+
M.interface('Wallet:0', {
651+
getBalance: M.call(M.string()).returns(M.number()),
652+
transfer: M.call(M.string(), M.number()).returns(M.boolean()),
653+
}),
654+
{
655+
getBalance: (_acct: string) => 42,
656+
transfer: (_to: string, _amt: number) => true,
657+
},
658+
),
659+
},
660+
];
661+
662+
const readGuard = M.interface('ReadOnly', {
663+
getBalance: M.call(M.string()).returns(M.number()),
664+
});
665+
666+
const schema = { getBalance: { description: 'Get account balance.' } };
667+
668+
const section = sheafify({
669+
name: 'Wallet',
670+
sections,
671+
}).getDiscoverableSection({
672+
guard: readGuard,
673+
async *lift(germs) {
674+
yield germs[0]!;
675+
},
676+
schema,
677+
});
678+
679+
expect(E(section)[GET_DESCRIPTION]()).toStrictEqual(schema);
680+
expect(await E(section).getBalance('alice')).toBe(42);
681+
});
682+
});

0 commit comments

Comments
 (0)