mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-31 04:58:09 +00:00
fix(extension): harden chat and target tab lifecycle
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { CHAT_MESSAGE_RATE_LIMIT } from '../server/rate-limiter.js';
|
||||
import {
|
||||
CHAT_ECHO_TIMEOUT_MS,
|
||||
CHAT_SEND_LIMIT,
|
||||
createChatEchoTracker,
|
||||
createChatSendLimiter,
|
||||
createLatestTaskQueue,
|
||||
MAX_ROOM_ID_LENGTH,
|
||||
normalizeRoomId
|
||||
normalizeRoomId,
|
||||
shouldShowChatNotification
|
||||
} from './chat-session.js';
|
||||
|
||||
describe('chat session boundaries', () => {
|
||||
@@ -14,7 +18,8 @@ describe('chat session boundaries', () => {
|
||||
expect(normalizeRoomId(null)).toBe('');
|
||||
});
|
||||
|
||||
it('keeps client chat bursts below the relay disconnect threshold', () => {
|
||||
it('allows ten-message client bursts without exceeding the relay threshold', () => {
|
||||
expect(CHAT_SEND_LIMIT).toBe(CHAT_MESSAGE_RATE_LIMIT);
|
||||
let current = 1000;
|
||||
const limiter = createChatSendLimiter({ now: () => current });
|
||||
for (let index = 0; index < CHAT_SEND_LIMIT; index++) {
|
||||
@@ -27,6 +32,49 @@ describe('chat session boundaries', () => {
|
||||
expect(limiter.take()).toEqual({ allowed: true, retryAfterMs: 0 });
|
||||
});
|
||||
|
||||
it('waits for the matching relay echo and clears pending sends on reset or timeout', async () => {
|
||||
const timers = new Map();
|
||||
let nextTimerId = 1;
|
||||
const tracker = createChatEchoTracker({
|
||||
setTimer(callback, timeoutMs) {
|
||||
const id = nextTimerId++;
|
||||
timers.set(id, { callback, timeoutMs });
|
||||
return id;
|
||||
},
|
||||
clearTimer(id) {
|
||||
timers.delete(id);
|
||||
}
|
||||
});
|
||||
|
||||
const acknowledged = tracker.waitFor('ciphertext-1');
|
||||
expect(tracker.acknowledge('ciphertext-1')).toBe(true);
|
||||
await expect(acknowledged).resolves.toBe(true);
|
||||
|
||||
const reset = tracker.waitFor('ciphertext-2');
|
||||
tracker.reset();
|
||||
await expect(reset).resolves.toBe(false);
|
||||
|
||||
const timedOut = tracker.waitFor('ciphertext-3');
|
||||
const timeout = [...timers.values()][0];
|
||||
expect(timeout.timeoutMs).toBe(CHAT_ECHO_TIMEOUT_MS);
|
||||
timeout.callback();
|
||||
await expect(timedOut).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it('suppresses chat notifications only while the target tab and its window are focused', () => {
|
||||
const focused = {
|
||||
enabled: true,
|
||||
targetTabId: 7,
|
||||
tab: { id: 7, active: true, windowId: 3 },
|
||||
windowInfo: { id: 3, focused: true }
|
||||
};
|
||||
expect(shouldShowChatNotification(focused)).toBe(false);
|
||||
expect(shouldShowChatNotification({ ...focused, windowInfo: { id: 3, focused: false } })).toBe(true);
|
||||
expect(shouldShowChatNotification({ ...focused, tab: { id: 7, active: false, windowId: 3 } })).toBe(true);
|
||||
expect(shouldShowChatNotification({ ...focused, targetTabId: 8 })).toBe(true);
|
||||
expect(shouldShowChatNotification({ ...focused, enabled: false })).toBe(false);
|
||||
});
|
||||
|
||||
it('serializes join work and prevents an older request from winning storage races', async () => {
|
||||
const queue = createLatestTaskQueue();
|
||||
let releaseFirst;
|
||||
|
||||
Reference in New Issue
Block a user