test: add refresh overlay for Xtream source menu and improve visibility checks

Entire-Checkpoint: f957cd9849e0
This commit is contained in:
4gray committed 2026-05-04 00:52:04 +02:00
1 parent d0f590d8fe
commit 1a09e696b4
2 files changed
+135 -56

No files matched your search

@@ -231,6 +231,20 @@ async function refreshFromWorkspaceHeader(page: Page): Promise<void> {
const dialog = page.locator('mat-dialog-container');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: 'Yes', exact: true }).click();
const refreshOverlay = page.locator('app-workspace-shell-import-overlay');
await expect(refreshOverlay).toBeVisible({ timeout: 5000 });
await expect(
refreshOverlay.getByRole('heading', {
name: 'Refreshing playlist',
exact: true,
})
).toBeVisible();
await expect(refreshOverlay).toContainText(/Local library/);
await expect(refreshOverlay).toContainText(
/Preserving your library data|Removing cached streams|Removing cached categories/
);
await page.waitForSelector('mat-dialog-container', { state: 'detached' });
}
@@ -240,66 +254,60 @@ function sidebarCategoryById(page: Page, categoryId: string): Locator {
);
}
async function expectVisibleSidebarCategoryIds(
page: Page,
expectedIds: string[]
): Promise<void> {
const categories = page.locator(
'app-workspace-context-panel .category-item:visible'
);
const actualIds: string[] = [];
const count = await categories.count();
for (let index = 0; index < count; index += 1) {
const categoryId = await categories
.nth(index)
.getAttribute('data-category-id');
if (categoryId) {
actualIds.push(categoryId.trim());
}
}
expect(actualIds).toEqual(expectedIds);
}
async function expectVisibleSidebarCategoryNames(
page: Page,
expectedNames: string[]
): Promise<void> {
await expect
.poll(async () => {
const categories = page.locator(
'app-workspace-context-panel .category-item:visible'
);
const actualNames: string[] = [];
const count = await categories.count();
try {
await expect
.poll(() => readVisibleSidebarCategoryNames(page), {
timeout: 30000,
})
.toEqual(expectedNames);
} catch (error) {
const actualNames = await readVisibleSidebarCategoryNames(page);
throw new Error(
`Expected visible sidebar categories ${JSON.stringify(
expectedNames
)}, received ${JSON.stringify(actualNames)}`,
{ cause: error }
);
}
}
for (let index = 0; index < count; index += 1) {
const categoryName =
(
await categories
.nth(index)
.locator('.nav-item-label')
.textContent()
)?.trim() ?? '';
async function readVisibleSidebarCategoryNames(page: Page): Promise<string[]> {
const categories = page.locator(
'app-workspace-context-panel .category-item'
);
const actualNames: string[] = [];
const count = await categories.count();
if (categoryName) {
actualNames.push(categoryName);
}
}
for (let index = 0; index < count; index += 1) {
const category = categories.nth(index);
if (!(await category.isVisible())) {
continue;
}
return actualNames;
})
.toEqual(expectedNames);
const categoryName =
(await category.locator('.nav-item-label').textContent())?.trim() ??
'';
if (categoryName) {
actualNames.push(categoryName);
}
}
return actualNames;
}
async function pickSidebarCategory(
page: Page
): Promise<{ id: string; itemCount: number; name: string }> {
let preferredCandidate:
| { id: string; itemCount: number; name: string }
| null = null;
let preferredCandidate: {
id: string;
itemCount: number;
name: string;
} | null = null;
await expect
.poll(async () => {
+79 -8
View File
@@ -13,6 +13,7 @@ import {
resetMockServers,
stalkerMockServer,
test,
waitForXtreamImportToFinish,
waitForStalkerCatalog,
waitForXtreamCatalog,
} from './electron-test-fixtures';
@@ -65,23 +66,93 @@ test.describe('Electron Provider Smoke Tests', () => {
await closeElectronApp(app);
}
});
test('shows refresh overlay immediately from the dashboard Xtream source menu', async ({
dataDir,
request,
}) => {
await resetMockServers(request, ['xtream']);
const app = await launchElectronApp(dataDir);
try {
await addXtreamPortal(app.mainWindow);
await waitForXtreamCatalog(app.mainWindow);
await expectPortalDebugSuccess(app.mainWindow, 'xtream');
await goToDashboard(app.mainWindow);
await refreshRecentXtreamSourceFromDashboard(
app.mainWindow,
defaultXtreamPortalName
);
await waitForXtreamImportToFinish(app.mainWindow);
} finally {
await closeElectronApp(app);
}
});
});
async function expectRecentSourceCard(
page: Page,
title: string
): Promise<void> {
await expect(
page.getByTestId('dashboard-recent-sources-rail')
).toBeVisible({
timeout: 20000,
});
await expect(page.getByTestId('dashboard-recent-sources-rail')).toBeVisible(
{
timeout: 20000,
}
);
await expect(
page.getByTestId('dashboard-recent-sources-rail-card').filter({
hasText: title,
}).first()
page
.getByTestId('dashboard-recent-sources-rail-card')
.filter({
hasText: title,
})
.first()
).toBeVisible({
timeout: 20000,
});
}
async function refreshRecentXtreamSourceFromDashboard(
page: Page,
title: string
): Promise<void> {
const sourceCard = page
.getByTestId('dashboard-recent-sources-rail-card')
.filter({
hasText: title,
})
.first();
await expect(sourceCard).toBeVisible({ timeout: 20000 });
await sourceCard.hover();
await sourceCard
.getByTestId('dashboard-recent-sources-rail-card-actions')
.click();
await page
.getByRole('menuitem', {
name: 'Refresh Xtream playlist from remote',
exact: true,
})
.click();
const dialog = page.locator('mat-dialog-container');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: 'Yes', exact: true }).click();
const refreshOverlay = page.locator('app-workspace-shell-import-overlay');
await expect(refreshOverlay).toBeVisible({ timeout: 5000 });
await expect(
refreshOverlay.getByRole('heading', {
name: 'Refreshing playlist',
exact: true,
})
).toBeVisible();
await expect(refreshOverlay).toContainText(/Local library/);
await expect(refreshOverlay).toContainText(
/Preserving your library data|Removing cached streams|Removing cached categories/
);
await page.waitForSelector('mat-dialog-container', { state: 'detached' });
}