fix(tests): correct mock types to satisfy tsgo strict checking

Vitest infers mock return types from the initial factory function, causing
tsgo to reject mockReturnValueOnce/mockResolvedValueOnce calls that pass
types incompatible with the inferred return. Fix by:

- Widening resolveGatewayTarget mock to () => 'local' | 'remote' | undefined
- Widening extractDeliveryInfo mock threadId/accountId to string | undefined
- Using 'as never' on mockReturnValueOnce/mockResolvedValueOnce overrides
  that pass edge-case values (null sentinel, undefined merge results,
  partial payload objects) that intentionally don't match the strict type

All 71 tests still pass.
This commit is contained in:
Bryan Marty 2026-03-10 02:59:07 +00:00
parent 874b906b3d
commit f7132aeb79
No known key found for this signature in database
2 changed files with 26 additions and 22 deletions

View File

@ -4,15 +4,19 @@ const mocks = vi.hoisted(() => ({
isRestartEnabled: vi.fn(() => true),
resolveConfigSnapshotHash: vi.fn(() => undefined),
extractDeliveryInfo: vi.fn(() => ({
deliveryContext: { channel: "telegram", to: "+19995550001", accountId: undefined },
threadId: undefined,
deliveryContext: {
channel: "telegram",
to: "+19995550001",
accountId: undefined as string | undefined,
},
threadId: undefined as string | undefined,
})),
writeRestartSentinel: vi.fn(async () => undefined),
scheduleGatewaySigusr1Restart: vi.fn(() => ({ ok: true })),
formatDoctorNonInteractiveHint: vi.fn(() => ""),
callGatewayTool: vi.fn(async () => ({})),
readGatewayCallOptions: vi.fn(() => ({})),
resolveGatewayTarget: vi.fn(() => undefined),
resolveGatewayTarget: vi.fn((): "local" | "remote" | undefined => undefined),
}));
vi.mock("../../config/commands.js", () => ({ isRestartEnabled: mocks.isRestartEnabled }));

View File

@ -151,7 +151,7 @@ describe("scheduleRestartSentinelWake two-step delivery + resume", () => {
});
it("no-ops when there is no sentinel file", async () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce(null);
mocks.consumeRestartSentinel.mockResolvedValueOnce(null as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -198,8 +198,8 @@ describe("scheduleRestartSentinelWake fallback to enqueueSystemEvent", () =>
it("falls back to enqueueSystemEvent when channel is missing from merged delivery context", async () => {
// mergeDeliveryContext is called twice (inner + outer merge); mock the outer to drop channel
mocks.mergeDeliveryContext
.mockReturnValueOnce(undefined) // inner: sessionDeliveryContext merge
.mockReturnValueOnce({ to: "+15550002" }); // outer: sentinelContext wins, no channel
.mockReturnValueOnce(undefined as never) // inner: sessionDeliveryContext merge
.mockReturnValueOnce({ to: "+15550002" } as never); // outer: sentinelContext wins, no channel
await scheduleRestartSentinelWake({ deps: {} as never });
@ -212,8 +212,8 @@ describe("scheduleRestartSentinelWake fallback to enqueueSystemEvent", () =>
it("falls back to enqueueSystemEvent when to is missing from merged delivery context", async () => {
// Mock outer merge to return a context with no `to`
mocks.mergeDeliveryContext
.mockReturnValueOnce(undefined)
.mockReturnValueOnce({ channel: "whatsapp" });
.mockReturnValueOnce(undefined as never)
.mockReturnValueOnce({ channel: "whatsapp" } as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -260,10 +260,10 @@ describe("scheduleRestartSentinelWake thread routing", () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce({
payload: {
sessionKey: "agent:main:main",
deliveryContext: { channel: "slack", to: "C012AB3CD", accountId: undefined },
deliveryContext: { channel: "slack", to: "C012AB3CD", accountId: "acct-2" },
threadId: "1234567890.123456",
},
});
} as never);
mocks.normalizeChannelId.mockReturnValueOnce("slack");
await scheduleRestartSentinelWake({ deps: {} as never });
@ -277,10 +277,10 @@ describe("scheduleRestartSentinelWake thread routing", () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce({
payload: {
sessionKey: "agent:main:main",
deliveryContext: { channel: "discord", to: "123456789", accountId: undefined },
deliveryContext: { channel: "discord", to: "123456789", accountId: "acct-2" },
threadId: "discord-thread-id",
},
});
} as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -293,10 +293,10 @@ describe("scheduleRestartSentinelWake thread routing", () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce({
payload: {
sessionKey: "agent:main:main",
deliveryContext: { channel: "discord", to: "123456789", accountId: undefined },
deliveryContext: { channel: "discord", to: "123456789", accountId: "acct-2" },
threadId: "discord-thread-id",
},
});
} as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -308,15 +308,15 @@ describe("scheduleRestartSentinelWake thread routing", () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce({
payload: {
sessionKey: "agent:main:main",
deliveryContext: { channel: "whatsapp", to: "+15550002" },
deliveryContext: { channel: "whatsapp", to: "+15550002", accountId: "acct-2" },
threadId: "sentinel-thread",
},
});
} as never);
// parseSessionThreadInfo would derive a different threadId from the session key
mocks.parseSessionThreadInfo.mockReturnValueOnce({
baseSessionKey: null,
threadId: "session-thread",
});
} as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -339,7 +339,7 @@ describe("scheduleRestartSentinelWake delivery context priority", () => {
mocks.deliveryContextFromSession.mockReturnValueOnce({
channel: "webchat",
to: "heartbeat",
});
} as never);
await scheduleRestartSentinelWake({ deps: {} as never });
@ -352,15 +352,15 @@ describe("scheduleRestartSentinelWake delivery context priority", () => {
it("falls back to session store when sentinel has no deliveryContext", async () => {
mocks.consumeRestartSentinel.mockResolvedValueOnce({
payload: { sessionKey: "agent:main:main" }, // no deliveryContext
});
} as never);
mocks.deliveryContextFromSession.mockReturnValueOnce({
channel: "telegram",
to: "+19990001",
});
} as never);
// Mock both merge calls: inner produces session ctx; outer passes it through
mocks.mergeDeliveryContext
.mockReturnValueOnce({ channel: "telegram", to: "+19990001" }) // inner
.mockReturnValueOnce({ channel: "telegram", to: "+19990001" }); // outer
.mockReturnValueOnce({ channel: "telegram", to: "+19990001" } as never) // inner
.mockReturnValueOnce({ channel: "telegram", to: "+19990001" } as never); // outer
// resolveOutboundTarget must reflect the session-store to value
mocks.resolveOutboundTarget.mockReturnValueOnce({ ok: true as const, to: "+19990001" });