test(server): cover the env mapping of every registered setting and the packing write paths the ratchet counts

This commit is contained in:
Maurice
2026-10-10 23:37:19 +02:00
parent 0b8ddd7dcb
commit 7c56c74077
4 changed files with 69 additions and 0 deletions
@@ -85,6 +85,13 @@ describe('AdminPackingTemplatesController', () => {
);
});
it('PACKTPL-004b a rename hands the body to the service and answers its { template } as it stands, unaudited', async () => {
const { c, packing } = controller();
expect(await c.update('1', { name: 'Mountains' })).toEqual({ template: { id: 1 } });
expect(packing.updatePackingTemplate).toHaveBeenCalledWith('1', { name: 'Mountains' });
expect(writeAudit).not.toHaveBeenCalled();
});
it('PACKTPL-005 delete audits the removed name and answers { success: true }', async () => {
const { c } = controller();
expect(await c.remove(user, '1', req)).toEqual({ success: true });
@@ -115,6 +115,36 @@ describe('reading', () => {
// A key without an environment variable reads the row.
expect(await resolveAppSetting(repoOf({ require_mfa: 'true' }), 'require_mfa')).toBe('true');
});
it('APPSET-012: every env-backed key reads its own variable, the secrets included', async () => {
// The two secrets are read past the register by their callers (they are stored
// encrypted), so this is the one place their mapping is pinned.
const variables: Record<string, [string, string]> = {
smtp_host: ['SMTP_HOST', 'smtp.env.example'],
smtp_port: ['SMTP_PORT', '2525'],
smtp_user: ['SMTP_USER', 'mailer'],
smtp_pass: ['SMTP_PASS', 'env-secret'],
smtp_from: ['SMTP_FROM', 'trek@env.example'],
oidc_issuer: ['OIDC_ISSUER', 'https://idp.env.example'],
oidc_client_id: ['OIDC_CLIENT_ID', 'trek-env'],
oidc_client_secret: ['OIDC_CLIENT_SECRET', 'oidc-env-secret'],
oidc_display_name: ['OIDC_DISPLAY_NAME', 'Company SSO'],
oidc_discovery_url: ['OIDC_DISCOVERY_URL', 'https://idp.env.example/.well-known/openid-configuration'],
};
const withEnv = (Object.entries(APP_SETTINGS) as Array<[string, AppSettingDef]>)
.filter(([, def]) => def.env)
.map(([key]) => key);
expect(withEnv.sort()).toEqual(Object.keys(variables).sort());
const keys = Object.keys(variables) as Array<keyof typeof APP_SETTINGS>;
const stored = Object.fromEntries(keys.map((key) => [key, `stored-${key}`]));
const resolveAll = () => Promise.all(keys.map((key) => resolveAppSetting(repoOf(stored), key)));
for (const [name] of Object.values(variables)) vi.stubEnv(name, '');
expect(await resolveAll()).toEqual(keys.map((key) => `stored-${key}`));
for (const [name, value] of Object.values(variables)) vi.stubEnv(name, value);
expect(await resolveAll()).toEqual(keys.map((key) => variables[key][1]));
});
});
describe('isOidcConfigured', () => {
@@ -130,6 +130,28 @@ describe('packing item events: REST == MCP', () => {
});
});
describe("REST writer: PackingService's broadcasts", () => {
it('PACK-REST-001: carries the user and the socket, and emit skips the sender for the room or names each viewer', () => {
const s = setup();
const writer = s.writes.restWriter('5', user, 'sock');
expect(writer).toMatchObject({ userId: 1, role: 'user', socketId: 'sock', surface: 'rest' });
writer.events.emit('packing:deleted', { itemId: 3 });
writer.events.emit('packing:deleted', { itemId: 4 }, [1, 2]);
expect(s.realtime.broadcast.mock.calls).toEqual([
['5', 'packing:deleted', { itemId: 3 }, 'sock'],
['5', 'packing:deleted', { itemId: 4 }, 'sock', 1],
['5', 'packing:deleted', { itemId: 4 }, 'sock', 2],
]);
});
it('PACK-REST-002: emitAll reaches every socket in the room, the sender included', () => {
const s = setup();
s.writes.restWriter('5', user, 'sock').events.emitAll('packing:bag-totals', {});
expect(s.realtime.broadcast.mock.calls).toEqual([['5', 'packing:bag-totals', {}, undefined]]);
});
});
describe('packing item use cases: refusals', () => {
const mcpText = (err: unknown) => (err as DomainError).mcpMessage ?? (err as DomainError).publicMessage;
@@ -1110,6 +1110,16 @@ describe('notifyTagged', () => {
expect.objectContaining({ params: expect.objectContaining({ trip: 'Untitled' }) }),
);
});
it('swallows a failed send: tagging stays fire-and-forget and never rejects the write', async () => {
send.mockRejectedValueOnce(new Error('smtp down'));
await expect(
svc.notifyTagged('999999', { id: 1, email: 'a@b.c' } as never, 'Clothes', [2]),
).resolves.toBeUndefined();
// Let the rejected send settle; an unhandled rejection would fail the run here.
await new Promise((resolve) => setTimeout(resolve, 0));
expect(send).toHaveBeenCalledTimes(1);
});
});
// ── Bridge delegation ─────────────────────────────────────────────────────────