Skip to content

Commit 9581fc9

Browse files
richlundeenCopilot
andauthored
FIX: converter adding bug on certain screen sizes (#2850)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 39366f9 commit 9581fc9

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

‎frontend/e2e/registry.spec.ts‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,70 @@ test.describe("Converter Registry", () => {
363363
const bounds = await listbox.boundingBox();
364364
expect(bounds?.height).toBeGreaterThan(300);
365365
});
366+
367+
for (const { name, viewport, deviceScaleFactor } of [
368+
{ name: "wide short screen", viewport: { width: 1920, height: 600 }, deviceScaleFactor: 1 },
369+
{ name: "scaled laptop", viewport: { width: 1280, height: 640 }, deviceScaleFactor: 1.5 },
370+
{ name: "narrow screen", viewport: { width: 390, height: 640 }, deviceScaleFactor: 2 },
371+
]) {
372+
test.describe(name, () => {
373+
test.use({ viewport, deviceScaleFactor });
374+
375+
test("keeps a long converter list vertical, stable, and scrollable", async ({ page }) => {
376+
await page.getByRole("button", { name: "New Converter" }).click();
377+
const trigger = page.getByRole("combobox", { name: "Converter type" });
378+
await trigger.click();
379+
380+
const listbox = page.getByRole("listbox");
381+
await expect(listbox).toBeVisible();
382+
const anchor = await trigger.evaluate((button) => {
383+
const { x, y, width, height } = button.parentElement!.getBoundingClientRect();
384+
return { x, y, width, height };
385+
});
386+
await expect.poll(async () => {
387+
const box = (await listbox.boundingBox())!;
388+
return Math.abs(box.x - anchor.x);
389+
}).toBeLessThanOrEqual(1);
390+
391+
// Sample successive frames: a single bounding box can miss position oscillation.
392+
const samples = await listbox.evaluate(async (element) => {
393+
const bounds = [];
394+
for (let frame = 0; frame < 60; frame++) {
395+
await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));
396+
const { x, y, width, height } = element.getBoundingClientRect();
397+
bounds.push({ x, y, width, height });
398+
}
399+
return bounds;
400+
});
401+
402+
for (const box of samples) {
403+
expect(Math.abs(box.x - anchor.x)).toBeLessThanOrEqual(1);
404+
expect(Math.abs(box.width - anchor.width)).toBeLessThanOrEqual(1);
405+
expect(box.height).toBeGreaterThan(0);
406+
expect(box.x).toBeGreaterThanOrEqual(-1);
407+
expect(box.y).toBeGreaterThanOrEqual(-1);
408+
expect(box.x + box.width).toBeLessThanOrEqual(viewport.width + 1);
409+
expect(box.y + box.height).toBeLessThanOrEqual(viewport.height + 1);
410+
expect(
411+
box.y >= anchor.y + anchor.height - 1
412+
|| box.y + box.height <= anchor.y + 1,
413+
).toBe(true);
414+
expect(Math.abs(box.y - samples[0].y)).toBeLessThanOrEqual(1);
415+
expect(Math.abs(box.height - samples[0].height)).toBeLessThanOrEqual(1);
416+
}
417+
418+
const scroll = await listbox.evaluate((element) => ({
419+
height: element.clientHeight,
420+
contentHeight: element.scrollHeight,
421+
}));
422+
expect(scroll.contentHeight).toBeGreaterThan(scroll.height);
423+
const lastOption = listbox.getByRole("option").last();
424+
await lastOption.scrollIntoViewIfNeeded();
425+
await expect(lastOption).toBeInViewport();
426+
await lastOption.click();
427+
await expect(listbox).toBeHidden();
428+
await expect(trigger).toHaveText("ViewportConverter9");
429+
});
430+
});
431+
}
366432
});

‎frontend/src/components/Registry/CreateConverterDialog.tsx‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,10 @@ export default function CreateConverterDialog({
498498
placeholder="Select a converter type"
499499
positioning={{
500500
align: 'start',
501+
autoSize: 'height',
502+
fallbackPositions: ['above-start'],
501503
matchTargetSize: 'width',
504+
overflowBoundary: 'window',
502505
position: 'below',
503506
}}
504507
selectedOptions={selectedType ? [selectedType] : []}

0 commit comments

Comments
 (0)