From ffa5b59a5ceb48bde78b6020733fa9cfee124625 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 1 Apr 2026 05:08:30 +0000 Subject: [PATCH] fix(e2e): fix category-management filter scoping and recent grid pagination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - category-management: replace filter({ has: dialog.locator(...) }) with filter({ hasText }) on the .category-item row. Playwright cannot scope an absolute locator (created via dialog.locator()) to each candidate element when used inside filter({ has: }), so the query always returned empty. Using hasText on the whole row correctly retries until Angular's @for loop re-renders filteredCategories() after the search field is populated. - recent.e2e.ts Xtream test: same pagination fix as favorites — derive movieTitle and seriesTitle from waitForFirstGridListCardTitle() instead of pickDistinctTitles(fixture.items)[0], which may be on page 2 of the date-sorted grid and never visible. https://claude.ai/code/session_01VU6ZZTG7YrhKhKBQvBfmpp --- .../src/category-management.e2e.ts | 12 +++++------- apps/electron-backend-e2e/src/recent.e2e.ts | 7 +++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/electron-backend-e2e/src/category-management.e2e.ts b/apps/electron-backend-e2e/src/category-management.e2e.ts index b50f0b92a..ab43ee62e 100644 --- a/apps/electron-backend-e2e/src/category-management.e2e.ts +++ b/apps/electron-backend-e2e/src/category-management.e2e.ts @@ -158,15 +158,13 @@ async function toggleManagedCategory( name: string; } ): Promise { - // Use Playwright's built-in filter so it retries until Angular re-renders - // the filtered list after the search field is populated. + // Use hasText on the whole row so Playwright's retry loop waits for Angular + // to re-render filteredCategories() after the search field is populated. + // Avoid nesting dialog.locator() inside filter({ has: }) — Playwright + // cannot scope an absolute locator to each candidate element. const categoryRow = dialog .locator('.category-item') - .filter({ - has: dialog.locator('.category-name', { - hasText: targetCategory.name, - }), - }) + .filter({ hasText: targetCategory.name }) .first(); await expect(categoryRow).toBeVisible({ timeout: 5000 }); diff --git a/apps/electron-backend-e2e/src/recent.e2e.ts b/apps/electron-backend-e2e/src/recent.e2e.ts index 77127fbb4..4257ad69c 100644 --- a/apps/electron-backend-e2e/src/recent.e2e.ts +++ b/apps/electron-backend-e2e/src/recent.e2e.ts @@ -23,6 +23,7 @@ import { switchUnifiedCollectionContent, switchUnifiedCollectionScope, test, + waitForFirstGridListCardTitle, waitForM3uCatalog, waitForStalkerCatalog, waitForXtreamWorkspaceReady, @@ -115,8 +116,6 @@ test.describe('Electron Recently Viewed', () => { xtreamCredentials ); const [liveTitle] = pickDistinctTitles(liveFixture.items, getXtreamTitle); - const [movieTitle] = pickDistinctTitles(vodFixture.items, getXtreamTitle); - const [seriesTitle] = pickDistinctTitles(seriesFixture.items, getXtreamTitle); const portalTitle = 'Xtream Recent Source'; const app = await launchElectronApp(dataDir); @@ -141,6 +140,9 @@ test.describe('Electron Recently Viewed', () => { app.mainWindow, vodFixture.categoryName ); + // Pick from the displayed grid: fixture order ≠ display order (date-desc + // sort + pagination), so the first fixture item may not be on page 1. + const movieTitle = await waitForFirstGridListCardTitle(app.mainWindow); await clickGridListCardByTitle(app.mainWindow, movieTitle); await playCurrentDetail(app.mainWindow); await goBackFromDetail(app.mainWindow); @@ -150,6 +152,7 @@ test.describe('Electron Recently Viewed', () => { app.mainWindow, seriesFixture.categoryName ); + const seriesTitle = await waitForFirstGridListCardTitle(app.mainWindow); await clickGridListCardByTitle(app.mainWindow, seriesTitle); await playFirstSeriesEpisode(app.mainWindow);