mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
test(server): cover the env mapping of every registered setting and the packing write paths the ratchet counts
This commit is contained in:
@@ -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 ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user