test(FN-4307): add failed-notification grace window coverage
Fusion-Task-Id: FN-4307 Fusion-Task-Lineage: 00140a5a-af93-4905-8570-32d7ecb8a874
This commit is contained in:
@@ -12,10 +12,12 @@ type Listener = (...args: any[]) => void | Promise<void>;
|
||||
|
||||
function createStore(settings: Partial<Settings> = {}) {
|
||||
const listeners = new Map<string, Set<Listener>>();
|
||||
const tasks = new Map<string, Task>();
|
||||
const getBucket = (event: string) => listeners.get(event) ?? new Set<Listener>();
|
||||
|
||||
return {
|
||||
getSettings: vi.fn(async () => ({ ntfyEnabled: false, ...settings }) as Settings),
|
||||
getTask: vi.fn(async (id: string) => tasks.get(id)),
|
||||
on: vi.fn((event: string, listener: Listener) => {
|
||||
const bucket = getBucket(event);
|
||||
bucket.add(listener);
|
||||
@@ -29,6 +31,9 @@ function createStore(settings: Partial<Settings> = {}) {
|
||||
void listener(payload);
|
||||
}
|
||||
},
|
||||
setTask(task: Task) {
|
||||
tasks.set(task.id, task);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -579,4 +584,42 @@ describe("NotificationService", () => {
|
||||
await first.stop();
|
||||
await second.stop();
|
||||
});
|
||||
|
||||
it("suppresses transient failed notification after Auto-recovered status clear", async () => {
|
||||
vi.useFakeTimers();
|
||||
const store = createStore({ ntfyEnabled: true, ntfyTopic: "topic", failureNotificationMode: "sticky-only", failureNotificationDelayMs: 50 });
|
||||
const sendNotification = vi.fn(async () => ({ success: true, providerId: "mock" }));
|
||||
const service = new NotificationService(store as any);
|
||||
service.registerProvider({ getProviderId: () => "mock", isEventSupported: () => true, sendNotification });
|
||||
await service.start();
|
||||
|
||||
store.setTask(task({ id: "FN-1", status: "failed", column: "in-review" }));
|
||||
store.emit("task:updated", task({ id: "FN-1", status: "failed", column: "in-review" }));
|
||||
store.setTask(task({ id: "FN-1", status: "in-review", column: "in-review", log: [{ timestamp: new Date().toISOString(), action: "Auto-recovered: merge deadlock resolved" }] }));
|
||||
store.emit("task:updated", task({ id: "FN-1", status: "in-review" }));
|
||||
|
||||
await vi.advanceTimersByTimeAsync(60);
|
||||
expect(sendNotification).not.toHaveBeenCalledWith("failed", expect.anything());
|
||||
await service.stop();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("dispatches failed once when failure persists beyond grace window", async () => {
|
||||
vi.useFakeTimers();
|
||||
const store = createStore({ ntfyEnabled: true, ntfyTopic: "topic", failureNotificationMode: "sticky-only", failureNotificationDelayMs: 50 });
|
||||
const sendNotification = vi.fn(async () => ({ success: true, providerId: "mock" }));
|
||||
const service = new NotificationService(store as any);
|
||||
service.registerProvider({ getProviderId: () => "mock", isEventSupported: () => true, sendNotification });
|
||||
await service.start();
|
||||
|
||||
const failed = task({ id: "FN-1", status: "failed" });
|
||||
store.setTask(failed);
|
||||
store.emit("task:updated", failed);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(60);
|
||||
expect(sendNotification).toHaveBeenCalledTimes(1);
|
||||
expect(sendNotification).toHaveBeenCalledWith("failed", expect.objectContaining({ taskId: "FN-1" }));
|
||||
await service.stop();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user