mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
test(e2e): fix failing and flaky supersync archive conflict tests
Three separate root causes addressed: 1. markTaskDone/markSubtaskDone race with 200ms animation delay: toggleDoneWithAnimation uses window.setTimeout(200ms) before dispatching isDone:true. Tests proceeded before the state settled, causing subsequent assertions to fail. Fix: wait for isDone CSS class after clicking done-toggle. Also use .first() on the task locator to avoid Playwright strict-mode violations during CDK drag animation, where the same task briefly exists as two DOM elements. 2. Premature waitForURL resolution in supersync.spec.ts test 5.1: waitForURL(/tag\/TODAY/) matched the current /tag/TODAY/daily-summary URL immediately. Fix: add negative lookahead (?!\/daily-summary). 3. LWW worklog title nondeterminism in archive-conflict test: After archive-wins conflict resolution and multiple sync rounds, the archived task title on both clients depends on sync timing — it may be the original name or the renamed name. Fix: accept either title using hasTaskInWorklog OR, rather than asserting a specific title.
This commit is contained in:
parent
309670db3a
commit
c558bcab5e
3 changed files with 32 additions and 4 deletions
|
|
@ -9,6 +9,7 @@ import {
|
|||
renameTask,
|
||||
archiveDoneTasks,
|
||||
expectTaskInWorklog,
|
||||
hasTaskInWorklog,
|
||||
navigateToWorkView,
|
||||
type SimulatedE2EClient,
|
||||
} from '../../utils/supersync-helpers';
|
||||
|
|
@ -267,10 +268,30 @@ test.describe('@supersync Archive Conflict Resolution', () => {
|
|||
console.log('[BugB] Client B: task not visible in active list');
|
||||
|
||||
// ============ PHASE 7: Verify task IN worklog ============
|
||||
await expectTaskInWorklog(clientA, taskName);
|
||||
// After archive-wins conflict + sync rounds, the archived task may appear under
|
||||
// either the original title (if archive applied first) or the renamed title (if
|
||||
// the rename op was also synced). Accept either to avoid brittleness.
|
||||
const clientAFound =
|
||||
(await hasTaskInWorklog(clientA, taskName)) ||
|
||||
(await hasTaskInWorklog(clientA, taskRenamed));
|
||||
if (!clientAFound) {
|
||||
throw new Error(
|
||||
`[BugB] Client A: Expected task to be in worklog under "${taskName}" or "${taskRenamed}"`,
|
||||
);
|
||||
}
|
||||
console.log('[BugB] Client A: task found in worklog');
|
||||
|
||||
await expectTaskInWorklog(clientB, taskName);
|
||||
// Client B applied the rename locally before archive was received, so the task
|
||||
// is archived under the renamed title. But also accept the original in case the
|
||||
// archive was applied before the rename reached Client B.
|
||||
const clientBFound =
|
||||
(await hasTaskInWorklog(clientB, taskRenamed)) ||
|
||||
(await hasTaskInWorklog(clientB, taskName));
|
||||
if (!clientBFound) {
|
||||
throw new Error(
|
||||
`[BugB] Client B: Expected task to be in worklog under "${taskRenamed}" or "${taskName}"`,
|
||||
);
|
||||
}
|
||||
console.log('[BugB] Client B: task found in worklog');
|
||||
|
||||
console.log('[BugB] ✓ Test B passed: LWW Update did not resurrect archived task');
|
||||
|
|
|
|||
|
|
@ -672,8 +672,9 @@ test.describe('@supersync SuperSync E2E', () => {
|
|||
await saveAndGoHomeBtn.click();
|
||||
console.log('[Archive Test] Client B clicked Save and go home (archiving)');
|
||||
|
||||
// Wait for navigation back to work view
|
||||
await clientB.page.waitForURL(/tag\/TODAY/, { timeout: 10000 });
|
||||
// Wait for navigation back to work view.
|
||||
// Use negative lookahead to avoid matching /tag/TODAY/daily-summary prematurely.
|
||||
await clientB.page.waitForURL(/(tag\/TODAY(?!\/daily-summary))/, { timeout: 10000 });
|
||||
await clientB.page.waitForLoadState('networkidle');
|
||||
console.log('[Archive Test] Client B back on work view after archiving');
|
||||
|
||||
|
|
|
|||
|
|
@ -501,6 +501,10 @@ export const markTaskDone = async (
|
|||
const task = getTaskElement(client, taskName);
|
||||
await task.hover();
|
||||
await task.locator('done-toggle').click();
|
||||
// Wait for the 200ms animation delay in toggleDoneWithAnimation to complete.
|
||||
// During CDK drag animation the task may temporarily resolve to 2 elements;
|
||||
// use .first() to avoid strict-mode violations.
|
||||
await expect(task.first()).toHaveClass(/isDone/, { timeout: UI_VISIBLE_TIMEOUT });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -517,6 +521,8 @@ export const markSubtaskDone = async (
|
|||
const subtask = getSubtaskElement(client, subtaskName);
|
||||
await subtask.hover();
|
||||
await subtask.locator('done-toggle').click();
|
||||
// Wait for the 200ms animation delay in toggleDoneWithAnimation to complete
|
||||
await expect(subtask).toHaveClass(/isDone/, { timeout: UI_VISIBLE_TIMEOUT });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue