mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
ResizableDirective started a drag from offsetWidth, which includes padding and border, but writes the result to style.width. The hosts are content-box, so the first move widened a padded host by its padding plus border: 23px on the workspace categories panel, 1px on the Favorites sidebar. Each drag also saved a width that much larger. A drag now starts from the computed CSS width (the box style.width sizes), falling back to the directive's own width when that is not a length. Border-box hosts (live-layout and groups rails) are unchanged. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
import { Locator, Page } from '@playwright/test';
|
|
import {
|
|
addXtreamPortal,
|
|
closeElectronApp,
|
|
expect,
|
|
launchElectronApp,
|
|
openSettings,
|
|
openWorkspaceSection,
|
|
resetMockServers,
|
|
test,
|
|
waitForXtreamWorkspaceReady,
|
|
} from './electron-test-fixtures';
|
|
|
|
/**
|
|
* The workspace context panels share one stored width but clamp it to their
|
|
* own limits. Opening a narrower panel used to save its clamped width, so a
|
|
* categories panel widened past Settings' 400px maximum came back at 400.
|
|
* The drag also lands on 520 only if the padded panel does not jump wider
|
|
* when the drag starts.
|
|
*/
|
|
|
|
const SHARED_WIDTH_KEY = 'sidebar-width';
|
|
|
|
/** The CSS width the directive sets; the panels are content-box. */
|
|
function renderedWidth(panel: Locator): Promise<number> {
|
|
return panel.evaluate((el) => parseFloat(getComputedStyle(el).width));
|
|
}
|
|
|
|
function storedWidth(page: Page): Promise<string | null> {
|
|
return page.evaluate((key) => localStorage.getItem(key), SHARED_WIDTH_KEY);
|
|
}
|
|
|
|
async function dragPanelTo(
|
|
page: Page,
|
|
panel: Locator,
|
|
width: number
|
|
): Promise<void> {
|
|
const handle = panel.locator(':scope > .resize-handle');
|
|
const box = await handle.boundingBox();
|
|
if (!box) throw new Error('The panel has no resize handle');
|
|
const startX = Math.round(box.x + box.width / 2);
|
|
const y = Math.round(box.y + box.height / 2);
|
|
// A drag starts from the CSS width, so the panel's padding and border
|
|
// must not count toward the distance.
|
|
const delta = width - (await renderedWidth(panel));
|
|
|
|
await page.mouse.move(startX, y);
|
|
await page.mouse.down();
|
|
await page.mouse.move(startX + delta, y, { steps: 10 });
|
|
await page.mouse.up();
|
|
}
|
|
|
|
test.describe('Electron shared sidebar width', () => {
|
|
test('@persistence @electron keeps a widened categories panel after Settings clamps it', async ({
|
|
dataDir,
|
|
request,
|
|
}) => {
|
|
await resetMockServers(request, ['xtream']);
|
|
const app = await launchElectronApp(dataDir);
|
|
try {
|
|
const page = app.mainWindow;
|
|
await page.setViewportSize({ width: 1440, height: 900 });
|
|
await addXtreamPortal(page);
|
|
await openWorkspaceSection(page, 'Movies');
|
|
await waitForXtreamWorkspaceReady(page);
|
|
const categories = page.locator('aside.context-panel--route');
|
|
await expect(categories).toBeVisible();
|
|
const categoriesUrl = page.url();
|
|
|
|
await dragPanelTo(page, categories, 520);
|
|
await expect.poll(() => renderedWidth(categories)).toBe(520);
|
|
await expect.poll(() => storedWidth(page)).toBe('520');
|
|
|
|
await openSettings(page);
|
|
const settings = page.locator('aside.context-panel--settings');
|
|
await expect(settings).toBeVisible();
|
|
await expect.poll(() => renderedWidth(settings)).toBe(400);
|
|
expect(await storedWidth(page)).toBe('520');
|
|
|
|
await page.goBack();
|
|
await page.waitForURL(categoriesUrl);
|
|
await expect(categories).toBeVisible();
|
|
await expect.poll(() => renderedWidth(categories)).toBe(520);
|
|
expect(await storedWidth(page)).toBe('520');
|
|
} finally {
|
|
await closeElectronApp(app);
|
|
}
|
|
});
|
|
});
|