Skip to content

Commit 7fff05b

Browse files
committed
test(combobox): update snapshots and add e2e for menu positioning
1 parent afa680b commit 7fff05b

4 files changed

Lines changed: 70 additions & 5 deletions

File tree

packages/pluggableWidgets/combobox-web/e2e/Combobox.spec.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,71 @@ test.describe("combobox-web", () => {
172172
await expect(getOptions(comboBox)).toHaveText(["Antartica", "Australia"]);
173173
});
174174
});
175+
176+
test.describe("menu positioning (floating-ui)", () => {
177+
// Regression for WC-3406: the menu used to flip between above/below the input
178+
// and jump when its content height changed. It must now settle in one place and,
179+
// when space is tight, shrink + scroll within the viewport instead of overflowing.
180+
181+
test("menu does not jump (top stays stable) while open", async ({ page }) => {
182+
const comboBox = page.locator(".mx-name-comboBox2");
183+
await expect(comboBox).toBeVisible({ timeout: 10000 });
184+
185+
await comboBox.click();
186+
const menu = page.locator(".mx-name-comboBox2 .widget-combobox-menu").first();
187+
await expect(menu).toBeVisible();
188+
189+
// Let floating-ui position it, then sample the top across several frames.
190+
const readTop = () => menu.evaluate(el => el.getBoundingClientRect().top);
191+
const first = await readTop();
192+
const samples = [];
193+
for (let i = 0; i < 5; i++) {
194+
await page.waitForTimeout(60);
195+
samples.push(await readTop());
196+
}
197+
198+
// No oscillation: every later sample equals the first (sub-pixel tolerance).
199+
for (const top of samples) {
200+
expect(Math.abs(top - first)).toBeLessThanOrEqual(1);
201+
}
202+
});
203+
204+
test("menu shrinks and stays within the viewport when space is tight", async ({ page }) => {
205+
const comboBox = page.locator(".mx-name-comboBox2");
206+
await expect(comboBox).toBeVisible({ timeout: 10000 });
207+
208+
// Shrink the viewport so there is little room below the input, forcing the
209+
// size() middleware to cap the menu height.
210+
await page.setViewportSize({ width: 1024, height: 360 });
211+
212+
await comboBox.click();
213+
const menu = page.locator(".mx-name-comboBox2 .widget-combobox-menu").first();
214+
await expect(menu).toBeVisible();
215+
216+
const box = await menu.boundingBox();
217+
const viewport = page.viewportSize();
218+
219+
// Menu bottom stays on screen (respecting the 8px viewport padding).
220+
expect(box.y + box.height).toBeLessThanOrEqual(viewport.height);
221+
// Menu height is capped below the 320px default because space is limited.
222+
expect(box.height).toBeLessThan(320);
223+
});
224+
225+
test("menu width matches the input width", async ({ page }) => {
226+
const comboBox = page.locator(".mx-name-comboBox2");
227+
await expect(comboBox).toBeVisible({ timeout: 10000 });
228+
229+
const inputContainer = comboBox.locator(".widget-combobox-input-container").first();
230+
await comboBox.click();
231+
const menu = page.locator(".mx-name-comboBox2 .widget-combobox-menu").first();
232+
await expect(menu).toBeVisible();
233+
234+
const inputBox = await inputContainer.boundingBox();
235+
const menuBox = await menu.boundingBox();
236+
237+
expect(Math.abs(menuBox.width - inputBox.width)).toBeLessThanOrEqual(1);
238+
});
239+
});
175240
});
176241

177242
function getOptions(combobox) {

packages/pluggableWidgets/combobox-web/src/__tests__/__snapshots__/MultiSelection.spec.tsx.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ exports[`Combo box (Association) renders combobox widget 1`] = `
7676
</div>
7777
<div
7878
class="widget-combobox-menu widget-combobox-menu-hidden"
79-
style="visibility: hidden; position: fixed;"
79+
style="--this-is-mocked-from-unit-tests: true;"
8080
>
8181
<div
8282
class="widget-combobox-menu-header widget-combobox-item"
@@ -186,7 +186,7 @@ exports[`Combo box (Association) toggles combobox menu on: input CLICK(focus) /
186186
</div>
187187
<div
188188
class="widget-combobox-menu widget-combobox-menu-hidden"
189-
style="visibility: visible; position: fixed; width: 0px; top: 0px; left: 0px;"
189+
style="--this-is-mocked-from-unit-tests: true;"
190190
>
191191
<div
192192
class="widget-combobox-menu-header widget-combobox-item"
@@ -296,7 +296,7 @@ exports[`Combo box (Association) toggles combobox menu on: input TOGGLE BUTTON 1
296296
</div>
297297
<div
298298
class="widget-combobox-menu widget-combobox-menu-hidden"
299-
style="visibility: hidden; position: fixed;"
299+
style="--this-is-mocked-from-unit-tests: true;"
300300
>
301301
<div
302302
class="widget-combobox-menu-header widget-combobox-item"

packages/pluggableWidgets/combobox-web/src/__tests__/__snapshots__/SingleSelection.spec.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ exports[`Combo box (Association) renders combobox widget 1`] = `
8282
</div>
8383
<div
8484
class="widget-combobox-menu widget-combobox-menu-hidden"
85-
style="visibility: hidden; position: fixed;"
85+
style="--this-is-mocked-from-unit-tests: true;"
8686
>
8787
<ul
8888
aria-labelledby="comboBox1-label"

packages/pluggableWidgets/combobox-web/src/__tests__/__snapshots__/StaticSelection.spec.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ exports[`Combo box (Static values) renders combobox widget 1`] = `
8282
</div>
8383
<div
8484
class="widget-combobox-menu widget-combobox-menu-hidden"
85-
style="visibility: hidden; position: fixed;"
85+
style="position: fixed; left: 0px; top: 0px; visibility: hidden; transform: translate(0px, 0px);"
8686
>
8787
<ul
8888
aria-labelledby="comboBox1-label"

0 commit comments

Comments
 (0)