mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-07 09:53:17 +00:00
fix(settings): harden audited state synchronization
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import * as ipc from '../ipc';
|
||||
import { updateDockBadge } from './dockBadge';
|
||||
|
||||
vi.mock('../ipc', () => ({
|
||||
invokeCommand: vi.fn()
|
||||
}));
|
||||
|
||||
describe('dock badge synchronization', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.mocked(ipc.invokeCommand).mockImplementation(async command => (
|
||||
command === 'begin_dock_badge_session' ? 1 : undefined
|
||||
));
|
||||
});
|
||||
|
||||
it('attaches increasing generations to concurrent updates', async () => {
|
||||
await Promise.all([updateDockBadge(3), updateDockBadge(0)]);
|
||||
|
||||
const calls = vi.mocked(ipc.invokeCommand).mock.calls;
|
||||
expect(calls).toHaveLength(3);
|
||||
expect(calls[0]).toEqual(['begin_dock_badge_session']);
|
||||
const badgeCalls = calls.slice(1);
|
||||
expect(badgeCalls[0]).toEqual([
|
||||
'update_dock_badge',
|
||||
{ count: 3, generation: expect.any(Number), session: 1 }
|
||||
]);
|
||||
expect(badgeCalls[1]).toEqual([
|
||||
'update_dock_badge',
|
||||
{ count: 0, generation: expect.any(Number), session: 1 }
|
||||
]);
|
||||
const firstBadgeArgs = badgeCalls[0][1] as { generation: number };
|
||||
const secondBadgeArgs = badgeCalls[1][1] as { generation: number };
|
||||
expect(secondBadgeArgs.generation).toBe(firstBadgeArgs.generation + 1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import { invokeCommand } from '../ipc';
|
||||
|
||||
let dockBadgeGeneration = 0;
|
||||
let dockBadgeSessionRequest: Promise<number> | null = null;
|
||||
|
||||
const getDockBadgeSession = (): Promise<number> => {
|
||||
if (!dockBadgeSessionRequest) {
|
||||
const request = invokeCommand('begin_dock_badge_session');
|
||||
dockBadgeSessionRequest = request.catch(error => {
|
||||
dockBadgeSessionRequest = null;
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
return dockBadgeSessionRequest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attach the backend session and a per-session generation to every badge
|
||||
* update so stale main-thread callbacks cannot overwrite a newer session.
|
||||
*/
|
||||
export const updateDockBadge = async (count: number): Promise<void> => {
|
||||
const session = await getDockBadgeSession();
|
||||
const generation = ++dockBadgeGeneration;
|
||||
await invokeCommand('update_dock_badge', { count, generation, session });
|
||||
};
|
||||
Reference in New Issue
Block a user