From e54f39cb3bf70e575126764d66dbd064d3d65734 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Thu, 15 Jan 2026 19:23:25 +0100 Subject: [PATCH] fix(e2e): resolve race conditions in sync tests - WebDAV sub-task sync: Add explicit waits for sub-task list visibility after sync instead of immediately asserting count - SuperSync setup: Wait for formly wrapper element before checking textarea visibility to handle async model updates --- e2e/pages/supersync.page.ts | 15 +++++++++++---- e2e/tests/sync/webdav-sync-advanced.spec.ts | 9 ++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/e2e/pages/supersync.page.ts b/e2e/pages/supersync.page.ts index 4dd77e2bb..2226d2f54 100644 --- a/e2e/pages/supersync.page.ts +++ b/e2e/pages/supersync.page.ts @@ -260,16 +260,23 @@ export class SuperSyncPage extends BasePage { // Wait for formly to re-render SuperSync-specific fields after provider selection // The hideExpression on these fields triggers a re-render that needs time to complete + // NOTE: The mat-select UI updates immediately, but the formly model update is async. + // We must wait for the actual DOM elements to appear, not just the UI selection. await this.page.waitForLoadState('networkidle').catch(() => {}); - await this.page.waitForTimeout(500); // Fill Access Token first (it's outside the collapsible) - // Use toPass() to handle slow formly rendering of the textarea + // Use toPass() to handle slow formly model updates and hideExpression re-evaluation + // First wait for the wrapper element to exist (formly has processed the model change) + // Then wait for the textarea inside to be visible await expect(async () => { + // Check if the wrapper element exists (formly hideExpression has evaluated) + const wrapper = this.page.locator('.e2e-accessToken'); + await wrapper.waitFor({ state: 'attached', timeout: 3000 }); + // Then check if the textarea is visible await this.accessTokenInput.waitFor({ state: 'visible', timeout: 3000 }); }).toPass({ - timeout: 15000, - intervals: [500, 1000, 1500, 2000], + timeout: 30000, + intervals: [500, 1000, 1500, 2000, 3000], }); await this.accessTokenInput.fill(config.accessToken); diff --git a/e2e/tests/sync/webdav-sync-advanced.spec.ts b/e2e/tests/sync/webdav-sync-advanced.spec.ts index e69c5ac0d..68398e781 100644 --- a/e2e/tests/sync/webdav-sync-advanced.spec.ts +++ b/e2e/tests/sync/webdav-sync-advanced.spec.ts @@ -75,12 +75,11 @@ test.describe('WebDAV Sync Advanced Features', () => { const parentTaskB = pageB.locator('task', { hasText: parentTaskName }).first(); await expect(parentTaskB).toBeVisible(); - // Check for subtask count - expand first - await parentTaskB.click(); // Ensure focus/expanded? Usually auto-expanded. - - // Use more specific locator for subtasks + // Wait for sub-task list to be rendered with correct count + // Sub-tasks are visible by default (no click needed to expand) const subTaskList = pageB.locator(`task-list[listid="SUB"]`); - await expect(subTaskList.locator('task')).toHaveCount(2); + await expect(subTaskList).toBeVisible({ timeout: 10000 }); + await expect(subTaskList.locator('task')).toHaveCount(2, { timeout: 10000 }); await expect(subTaskList.locator('task', { hasText: 'Sub Task 1' })).toBeVisible(); await expect(subTaskList.locator('task', { hasText: 'Sub Task 2' })).toBeVisible();