From d0e92ca09b009d501b9e7f810dd0651c5bc8d221 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:14:42 +0000 Subject: [PATCH 1/5] Initial plan From 0f28a674d7f51515bc6dd5f748e7f68ba063e385 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 20:20:02 +0000 Subject: [PATCH 2/5] Optimize sync endpoint and fix accessibility issues - Replace unused existingFixtures variable with in-memory Map lookup - Add batch database operations (batchUpdateFixture, batchCreateFixtureWithAvailability) - Use batch operations instead of multiple sequential DB calls for better performance - Remove role="button" from dialog backdrop (accessibility fix) - Fix dialog keydown handler to allow Escape key propagation - Replace arbitrary timeouts with proper Playwright waiting mechanisms in tests - Remove unused syncingButton variable in tests - Update test expectations to verify batch operations Co-authored-by: chamika <754909+chamika@users.noreply.github.com> --- frontend/e2e/availability-validation.test.ts | 31 +++---- .../routes/availability/[teamId]/+page.svelte | 4 +- worker/src/database.ts | 83 +++++++++++++++++++ worker/src/index.test.ts | 71 ++++++++-------- worker/src/index.ts | 38 ++++----- 5 files changed, 152 insertions(+), 75 deletions(-) diff --git a/frontend/e2e/availability-validation.test.ts b/frontend/e2e/availability-validation.test.ts index 913c633..c0300be 100644 --- a/frontend/e2e/availability-validation.test.ts +++ b/frontend/e2e/availability-validation.test.ts @@ -262,13 +262,14 @@ test.describe('Player Summary Statistics', () => { test('should show confirmation dialog when sync button clicked', async ({ page }) => { // Navigate to Management tab await page.waitForSelector('nav[aria-label="Tabs"]', { timeout: 10000 }); - await page.locator('button:has-text("Management")').click(); - await page.waitForTimeout(500); + const managementTab = page.locator('button:has-text("Management")'); + await managementTab.click(); + await managementTab.waitFor({ state: 'visible' }); // Click sync button const syncButton = page.locator('button:has-text("Sync Fixtures")'); + await syncButton.waitFor({ state: 'visible' }); await syncButton.click(); - await page.waitForTimeout(300); // Check for confirmation dialog const dialogHeading = page.locator('h3:has-text("Confirm Fixture Sync")'); @@ -282,7 +283,6 @@ test.describe('Player Summary Statistics', () => { // Cancel the dialog await cancelButton.click(); - await page.waitForTimeout(300); // Dialog should be hidden await expect(dialogHeading).not.toBeVisible(); @@ -291,25 +291,28 @@ test.describe('Player Summary Statistics', () => { test('should show loading state during sync', async ({ page }) => { // Navigate to Management tab await page.waitForSelector('nav[aria-label="Tabs"]', { timeout: 10000 }); - await page.locator('button:has-text("Management")').click(); - await page.waitForTimeout(500); + const managementTab = page.locator('button:has-text("Management")'); + await managementTab.click(); + await managementTab.waitFor({ state: 'visible' }); // Click sync button const syncButton = page.locator('button:has-text("Sync Fixtures")'); + await syncButton.waitFor({ state: 'visible' }); await syncButton.click(); - await page.waitForTimeout(300); // Click Sync Now const syncNowButton = page.locator('button:has-text("Sync Now")'); + await syncNowButton.waitFor({ state: 'visible' }); await syncNowButton.click(); - // Should show loading state (briefly) - // Note: This might be too fast to catch in real scenarios - const syncingButton = page.locator('button:has-text("Syncing...")'); - // We don't assert visibility because sync might complete too quickly - - // Wait for sync to complete - look for success notification or completion - await page.waitForTimeout(2000); + // Wait for sync operation to complete by checking button state + // The button should either show "Syncing..." or go back to normal + await page.waitForFunction(() => { + const btn = document.querySelector('button:has-text("Sync Fixtures")'); + return btn && !btn.textContent?.includes('Syncing'); + }, { timeout: 5000 }).catch(() => { + // Sync might complete too quickly, which is fine + }); // After sync, button should be back to normal state await expect(syncButton).toBeVisible(); diff --git a/frontend/src/routes/availability/[teamId]/+page.svelte b/frontend/src/routes/availability/[teamId]/+page.svelte index 7548855..3c02ccf 100644 --- a/frontend/src/routes/availability/[teamId]/+page.svelte +++ b/frontend/src/routes/availability/[teamId]/+page.svelte @@ -435,8 +435,8 @@ {#if showSyncConfirm} -
showSyncConfirm = false} onkeydown={(e) => e.key === 'Escape' && (showSyncConfirm = false)}> -