Files
webmail/lib/__tests__/mark-as-read-delay.test.ts
T
Peterka35 bbc3c2123e fix: follow markAsReadDelay when expanding a conversation or opening a Pro folder row
Expanding a conversation in the message list (row click, expand chevron,
or the `x` shortcut) and clicking a row in a Pro folder tab marked the
messages read straight away. They ignored "Mark as read: Never" and any
delay, which the reading pane and the conversation view follow.

Route them through one helper, scheduleAutoMarkAsRead: -1 never marks,
0 marks at once, any other value marks after that many milliseconds and
returns a cancel function.

- New store action autoMarkExpandedThreadAsRead keeps one pending timer
  per thread key. Collapsing the thread, or collapsing all threads, drops
  it. Both expansion paths (EmailList and the `x` handler in MailApp) use
  it.
- MailApp's handleEmailSelect drops the pending mark of every expanded
  thread other than the one the newly opened message belongs to, through
  cancelAutoMarkThreadAsRead. Moving on with `j`/`k` or a click no longer
  lets the delayed mark land on a conversation the user has left. The
  thread stays expanded.
- ProFolderTabBody schedules the row mark through the helper and drops a
  pending one when another row is opened or the tab unmounts.
2026-10-17 21:01:34 +02:00

44 lines
1.2 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { scheduleAutoMarkAsRead } from '../mark-as-read-delay';
describe('scheduleAutoMarkAsRead', () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
it('never marks with "Never" (-1)', () => {
const mark = vi.fn();
scheduleAutoMarkAsRead(-1, mark);
vi.advanceTimersByTime(60_000);
expect(mark).not.toHaveBeenCalled();
});
it('marks synchronously with "Instantly" (0)', () => {
const mark = vi.fn();
scheduleAutoMarkAsRead(0, mark);
expect(mark).toHaveBeenCalledTimes(1);
});
it('marks once the delay has passed', () => {
const mark = vi.fn();
scheduleAutoMarkAsRead(3000, mark);
vi.advanceTimersByTime(2999);
expect(mark).not.toHaveBeenCalled();
vi.advanceTimersByTime(1);
expect(mark).toHaveBeenCalledTimes(1);
});
it('drops a pending delayed mark when cancelled', () => {
const mark = vi.fn();
const cancel = scheduleAutoMarkAsRead(3000, mark);
vi.advanceTimersByTime(1000);
cancel();
vi.advanceTimersByTime(10_000);
expect(mark).not.toHaveBeenCalled();
});
});