mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-17 16:37:43 +00:00
test(e2e): harden section reorder drag against bounding-box races
boundingBox() is a one-shot snapshot that returns null when the element has no layout box — which happens after every CDK drop, since the section task-list re-renders (@for track reorders nodes) and freshly-dropped tasks run the expandInOnly enter animation at height:0. Add a stableBoundingBox() helper that waits for visibility then polls for a real, non-null box before driving the pointer gesture, and exclude .ng-animating nodes when picking the reorder source/target (matching the existing 'before' capture). Test-only change; reorder behavior itself is covered by section.reducer unit tests.
This commit is contained in:
parent
2baf5fc512
commit
bab8af264e
1 changed files with 38 additions and 6 deletions
|
|
@ -69,6 +69,37 @@ test.describe('Sections', () => {
|
|||
): ReturnType<import('@playwright/test').Page['locator']> =>
|
||||
page.locator('.section-container').filter({ hasText: title });
|
||||
|
||||
/**
|
||||
* Read a locator's bounding box defensively. `boundingBox()` takes a
|
||||
* one-shot snapshot and returns `null` whenever the element has no
|
||||
* layout box at that instant — which happens constantly here because
|
||||
* the section task-list re-renders after every CDK drop (Angular's
|
||||
* `@for track` reorders nodes) and freshly-dropped tasks run an
|
||||
* `expandInOnly` enter animation that holds them at `height: 0`. Wait
|
||||
* for the element to be visible, then poll until it reports a real box
|
||||
* so the read can't race the re-render. This is the failure the two
|
||||
* `test.fixme`s below hit; keeping the guard here lets the active tests
|
||||
* stay reliable instead of throwing "no bounding box".
|
||||
*/
|
||||
const stableBoundingBox = async (
|
||||
locator: import('@playwright/test').Locator,
|
||||
): Promise<{ x: number; y: number; width: number; height: number }> => {
|
||||
await locator.waitFor({ state: 'visible', timeout: 10000 });
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
const b = await locator.boundingBox();
|
||||
return !!b && b.width > 0 && b.height > 0;
|
||||
},
|
||||
{ timeout: 10000 },
|
||||
)
|
||||
.toBe(true);
|
||||
// The poll guarantees a real box exists; re-read it for the gesture.
|
||||
const box = await locator.boundingBox();
|
||||
if (!box) throw new Error('drag source/target has no bounding box');
|
||||
return box;
|
||||
};
|
||||
|
||||
/**
|
||||
* CDK drag-drop is event-driven via Angular CDK's own pointer-event
|
||||
* handling. Playwright's `dragTo` uses HTML5 drag-and-drop events,
|
||||
|
|
@ -80,9 +111,8 @@ test.describe('Sections', () => {
|
|||
source: import('@playwright/test').Locator,
|
||||
target: import('@playwright/test').Locator,
|
||||
): Promise<void> => {
|
||||
const sBox = await source.boundingBox();
|
||||
const tBox = await target.boundingBox();
|
||||
if (!sBox || !tBox) throw new Error('drag source/target has no bounding box');
|
||||
const sBox = await stableBoundingBox(source);
|
||||
const tBox = await stableBoundingBox(target);
|
||||
/* eslint-disable no-mixed-operators */
|
||||
const sx = sBox.x + sBox.width / 2;
|
||||
const sy = sBox.y + sBox.height / 2;
|
||||
|
|
@ -293,9 +323,11 @@ test.describe('Sections', () => {
|
|||
expect(before.length).toBe(3);
|
||||
|
||||
// Drag the first task onto the last task. After the drop, the first
|
||||
// task should no longer be at index 0.
|
||||
const firstTask = section.locator('task').nth(0);
|
||||
const lastTask = section.locator('task').nth(2);
|
||||
// task should no longer be at index 0. Exclude `.ng-animating` nodes
|
||||
// (matching the `before` capture) so we never target a task that's
|
||||
// still running its enter animation at `height: 0`.
|
||||
const firstTask = section.locator('task:not(.ng-animating)').nth(0);
|
||||
const lastTask = section.locator('task:not(.ng-animating)').nth(2);
|
||||
await cdkDragTo(page, firstTask.locator('done-toggle').first(), lastTask);
|
||||
|
||||
await expect
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue