mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-17 16:37:43 +00:00
test(sections): de-flake intra-section drag reorder e2e
The "reorders tasks within a section via drag and drop" test
intermittently failed with "drag source/target has no bounding box"
(e.g. CI run 26681989260). Each CDK drop re-creates the moved task as a
fresh @for :enter, replaying the expandInOnly animation (height: 0 -> *),
so its layout box collapses to zero height mid-gesture and boundingBox()
returns null.
Disable animations for this test via the app's own isDisableAnimations
config (toggles @HostBinding('@.disabled')), which removes the height:0
window. Verified 5/5 green locally.
Scoped to the reorder test only; the cross-list "drops a task into a
section" test keeps animations on, since disabling them makes the empty
drop target reflow instantly and miss.
This commit is contained in:
parent
24725c9360
commit
59a7bd03b2
1 changed files with 55 additions and 0 deletions
|
|
@ -129,6 +129,60 @@ test.describe('Sections', () => {
|
|||
await page.mouse.up();
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable Angular animations for the current session before driving CDK
|
||||
* drag gestures that reorder tasks *already inside* a section. Each drop
|
||||
* re-creates the moved task as a fresh `@for` `:enter`, so it replays the
|
||||
* `expandInOnly` animation (`height: 0 -> *`, expand.ani.ts) and has a
|
||||
* zero-height layout box mid-animation. `boundingBox()` returns `null` for
|
||||
* that, which is the root cause of the "drag source/target has no bounding
|
||||
* box" flake (and why the cross-section tests below are fixme'd).
|
||||
*
|
||||
* Flipping the app's own `isDisableAnimations` config toggles the
|
||||
* `@HostBinding('@.disabled')` on the root component (app.component.ts),
|
||||
* which disables every `@trigger` including `expandInOnly` — so dropped
|
||||
* tasks render at full height instantly and their box never collapses.
|
||||
*
|
||||
* NOTE: only the intra-section reorder test uses this. The "drops a task
|
||||
* into a section" test intentionally keeps animations on: it drags out of
|
||||
* the no-section list into an *empty* section, and with animations off the
|
||||
* source-removal reflow is instant, so the empty drop target can jump out
|
||||
* from under the in-flight pointer and the drop misses.
|
||||
*/
|
||||
const disableAnimations = async (
|
||||
page: import('@playwright/test').Page,
|
||||
): Promise<void> => {
|
||||
await expect
|
||||
.poll(
|
||||
() =>
|
||||
page.evaluate(() => {
|
||||
const store = (
|
||||
window as unknown as {
|
||||
__e2eTestHelpers?: { store?: { dispatch: (a: unknown) => void } };
|
||||
}
|
||||
).__e2eTestHelpers?.store;
|
||||
if (!store) return false;
|
||||
store.dispatch({
|
||||
// updateGlobalConfigSection
|
||||
// (src/app/features/config/store/global-config.actions.ts)
|
||||
type: '[Global Config] Update Global Config Section',
|
||||
sectionKey: 'misc',
|
||||
sectionCfg: { isDisableAnimations: true },
|
||||
isSkipSnack: true,
|
||||
});
|
||||
return true;
|
||||
}),
|
||||
{ timeout: 10000 },
|
||||
)
|
||||
.toBe(true);
|
||||
// `global-theme.service` mirrors the config onto a body class via an
|
||||
// `effect()`. Waiting for it confirms the `@.disabled` binding has flipped
|
||||
// before the first gesture reads layout.
|
||||
await page
|
||||
.locator('body.isDisableAnimations')
|
||||
.waitFor({ state: 'attached', timeout: 5000 });
|
||||
};
|
||||
|
||||
test('creates a section via the project context menu', async ({
|
||||
page,
|
||||
workViewPage,
|
||||
|
|
@ -286,6 +340,7 @@ test.describe('Sections', () => {
|
|||
projectPage,
|
||||
}) => {
|
||||
await setupTestProject(workViewPage, projectPage);
|
||||
await disableAnimations(page);
|
||||
|
||||
await openProjectContextMenu(page);
|
||||
await clickAddSection(page);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue