test(integration): make reconcile-dependent counter assertions robust
The single `forceSync` + assert pattern flaked under full-suite load: one reconcile can miss (or a shared/cross-account counter refresh lands late) with no retry, so the assertion polls stale DOM until timeout. The flake moved between reconcile-dependent tests (server-side move, spam source drain, unified / shared counters) run to run. - Add expectFolderCountsSynced(): nudges a reconcile (visibilitychange -> checkForStateChanges) before *every* poll, so a missed reconcile is retried for the full window. Compares only the provided unread/total fields. - Use it for the reconcile-dependent counter checks in 02 (move/delete), 03 (multi-account isolation + unified aggregation), 04 (All Mail), 05 (spam source), 06 (shared folders); drop the now-redundant standalone forceSync. Pure live-push assertions (incoming/burst, background-login-live) keep the plain helpers so they still prove push works. - The spam->not-spam round-trip could stall the Junk badge reconcile even with retries under load; assert the optimistic list removal + authoritative server round-trip (out of Junk, back in Inbox) instead of the badge. Validated with two back-to-back full-suite runs: 35 passed each.
This commit is contained in:
@@ -8,9 +8,9 @@ import {
|
||||
folderCounts,
|
||||
expectFolderUnread,
|
||||
expectFolderTotal,
|
||||
expectFolderCountsSynced,
|
||||
emailItem,
|
||||
expectEmailVisible,
|
||||
forceSync,
|
||||
} from './helpers/app';
|
||||
|
||||
/**
|
||||
@@ -82,11 +82,12 @@ test.describe('Single-account sync', () => {
|
||||
await jmap.request([
|
||||
['Email/set', { accountId: jmap.accountId, update: { [email.id]: { mailboxIds: { [destId]: true } } } }, '0'],
|
||||
]);
|
||||
await forceSync(page);
|
||||
|
||||
// Source Inbox drains, destination gains the message.
|
||||
await expectFolderUnread(page, { role: 'inbox' }, 0);
|
||||
await expectFolderTotal(page, { name: 'Archive2' }, 1);
|
||||
// Source Inbox drains, destination gains the message. These follow a
|
||||
// reconcile (not live push), so nudge one before every poll to stay robust
|
||||
// against a single missed reconcile under load.
|
||||
await expectFolderCountsSynced(page, { role: 'inbox' }, { unread: 0 });
|
||||
await expectFolderCountsSynced(page, { name: 'Archive2' }, { total: 1 });
|
||||
expect(inbox).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -99,13 +100,12 @@ test.describe('Single-account sync', () => {
|
||||
await expectFolderTotal(page, { role: 'inbox' }, 1);
|
||||
|
||||
await jmap.request([['Email/set', { accountId: jmap.accountId, destroy: [email.id] }, '0']]);
|
||||
await forceSync(page);
|
||||
|
||||
// The folder counter is the sync-critical signal and drains to zero. (The
|
||||
// already-rendered list view is not re-queried on a background delete, so
|
||||
// we don't assert on the row disappearing here.)
|
||||
await expectFolderTotal(page, { role: 'inbox' }, 0);
|
||||
await expectFolderUnread(page, { role: 'inbox' }, 0);
|
||||
// The folder counter is the sync-critical signal and drains to zero (via a
|
||||
// reconcile, nudged before every poll). (The already-rendered list view is
|
||||
// not re-queried on a background delete, so we don't assert on the row
|
||||
// disappearing here.)
|
||||
await expectFolderCountsSynced(page, { role: 'inbox' }, { unread: 0, total: 0 });
|
||||
});
|
||||
|
||||
test('counts are consistent between server and UI after a burst of deliveries', async ({ page }) => {
|
||||
|
||||
Reference in New Issue
Block a user