Files
TREK/server/tests/unit/nest/system-notices.service.test.ts
T
jubnl e1162c1c07 docs: bring the bridge docs in line
Roadmap census 14 -> 8 (5 seam-pinned, 3 verified-permanent), resources.ts DoD line closed, README in-container list and counts corrected. Includes the SystemNoticesService unit test the src/nest coverage ratchet demanded after the addonEnabled threading.
2026-08-11 17:00:05 +02:00

61 lines
2.7 KiB
TypeScript

/**
* SystemNoticesService — the DI wrapper over the plain systemNotices service.
* What's under test is the threading added when conditions.ts lost its
* addons.bridge import: getActiveFor must hand the evaluator a live
* addonEnabled callback over the INJECTED AddonsService. The upstream plain
* service is mocked; its own behavior is pinned in tests/unit/systemNotices/
* and the integration suite.
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
const { mockGetActive, mockDismiss } = vi.hoisted(() => ({ mockGetActive: vi.fn(), mockDismiss: vi.fn() }));
vi.mock('../../../src/systemNotices/service', () => ({
getActiveNoticesFor: mockGetActive,
dismissNotice: mockDismiss,
}));
import { SystemNoticesService } from '../../../src/nest/system-notices/system-notices.service';
import type { AddonsService } from '../../../src/nest/addons/addons.service';
const isAddonEnabled = vi.fn((id: string) => id === 'journey');
const svc = new SystemNoticesService({ isAddonEnabled } as unknown as AddonsService);
beforeEach(() => {
mockGetActive.mockReset();
mockDismiss.mockReset();
isAddonEnabled.mockClear();
});
describe('SystemNoticesService', () => {
it('getActiveFor threads a live addonEnabled check over the injected AddonsService', () => {
mockGetActive.mockReturnValue([]);
svc.getActiveFor(7);
expect(mockGetActive).toHaveBeenCalledWith(7, expect.any(Function));
const addonEnabled = mockGetActive.mock.calls[0][1] as (id: string) => boolean;
expect(addonEnabled('journey')).toBe(true);
expect(addonEnabled('vacay')).toBe(false);
expect(isAddonEnabled).toHaveBeenLastCalledWith('vacay');
});
it('dismiss passes through to the upstream service', () => {
mockDismiss.mockReturnValue(true);
expect(svc.dismiss(7, 'welcome')).toBe(true);
expect(mockDismiss).toHaveBeenCalledWith(7, 'welcome');
});
it('still loads and works when the AddonsService binding is unresolved (import-cycle fallback)', async () => {
// The emitted design:paramtypes metadata guards an unresolved class binding
// with `typeof AddonsService === 'undefined' ? Object : AddonsService`.
// Simulate that mid-cycle state: the module must still evaluate and the
// instance must still thread the callback.
vi.resetModules();
vi.doMock('../../../src/nest/addons/addons.service', () => ({ AddonsService: undefined }));
const { SystemNoticesService: Reloaded } = await import('../../../src/nest/system-notices/system-notices.service');
const inst = new Reloaded({ isAddonEnabled } as unknown as AddonsService);
mockGetActive.mockReturnValue([]);
inst.getActiveFor(1);
expect(mockGetActive).toHaveBeenCalledWith(1, expect.any(Function));
vi.doUnmock('../../../src/nest/addons/addons.service');
});
});