f94552d452
92 файла одной пачкой. Исключены чужие зоны: CLAUDE.md, .claude/settings.json, docs/observer/.pii-counters.json. gitleaks staged: no leaks found. Не верифицировано тестами - сохранение труда в историю. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
import { repositionMenuAfterOpen } from '../../resources/js/utils/menuRepositionFix';
|
|
|
|
/**
|
|
* Unit-тесты воркэраунда Vuetify location-strategy (см. menuRepositionFix.ts).
|
|
* Реальный баг — гонка позиционирования в браузере под prefers-reduced-motion —
|
|
* в jsdom не воспроизводится (нет layout); он покрыт Playwright-пробой. Здесь
|
|
* проверяется контракт утилиты: при стабилизации overlay-меню шлётся один resize.
|
|
*/
|
|
function makeStableMenu(left: number): HTMLElement {
|
|
const overlay = document.createElement('div');
|
|
overlay.className = 'v-overlay v-menu';
|
|
const content = document.createElement('div');
|
|
content.className = 'v-overlay__content';
|
|
content.getBoundingClientRect = () =>
|
|
({
|
|
width: 400,
|
|
height: 300,
|
|
left,
|
|
top: 50,
|
|
right: left + 400,
|
|
bottom: 350,
|
|
x: left,
|
|
y: 50,
|
|
toJSON() {},
|
|
}) as DOMRect;
|
|
overlay.appendChild(content);
|
|
document.body.appendChild(overlay);
|
|
return overlay;
|
|
}
|
|
|
|
const wait = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
|
|
|
|
describe('repositionMenuAfterOpen', () => {
|
|
afterEach(() => {
|
|
document.querySelectorAll('.v-overlay').forEach((el) => el.remove());
|
|
});
|
|
|
|
it('does nothing when menu is closing (open=false)', async () => {
|
|
const spy = vi.fn();
|
|
window.addEventListener('resize', spy);
|
|
repositionMenuAfterOpen(false);
|
|
await wait(200);
|
|
window.removeEventListener('resize', spy);
|
|
expect(spy).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('dispatches a single resize once the overlay content is geometrically stable', async () => {
|
|
makeStableMenu(120);
|
|
const spy = vi.fn();
|
|
window.addEventListener('resize', spy);
|
|
repositionMenuAfterOpen(true);
|
|
await wait(400);
|
|
window.removeEventListener('resize', spy);
|
|
expect(spy).toHaveBeenCalled();
|
|
});
|
|
|
|
it('does not dispatch resize or throw when no overlay is present', async () => {
|
|
const spy = vi.fn();
|
|
window.addEventListener('resize', spy);
|
|
expect(() => repositionMenuAfterOpen(true)).not.toThrow();
|
|
await wait(300);
|
|
window.removeEventListener('resize', spy);
|
|
expect(spy).not.toHaveBeenCalled();
|
|
});
|
|
});
|