32 lines
1.6 KiB
TypeScript
32 lines
1.6 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
describe('web landing demo scroll containment (same-origin patch)', () => {
|
|
const stateBuilder = readFileSync('web/scripts/state-builder.js', 'utf8');
|
|
const html = readFileSync('web/index.html', 'utf8');
|
|
|
|
it('redirects scrollIntoView to the nearest iframe-internal scrollable ancestor', () => {
|
|
// 改写 iframe 内 Element.prototype.scrollIntoView,把滚动钳在 iframe 内最近的可滚祖先;
|
|
// 走到 documentElement 就直接 return,不让浏览器再向父页冒泡。
|
|
expect(stateBuilder).toContain('function patchSimulatorScrollPropagation');
|
|
expect(stateBuilder).toContain('ElementCtor.prototype.scrollIntoView = function patchedScrollIntoView');
|
|
expect(stateBuilder).toContain('if (!target || target === ownerDoc.documentElement) return;');
|
|
expect(stateBuilder).toContain('target.scrollTo({');
|
|
});
|
|
|
|
it('forces preventScroll on focus so input focus does not scroll parent', () => {
|
|
expect(stateBuilder).toContain('HTMLElementCtor.prototype.focus = function patchedFocus');
|
|
expect(stateBuilder).toContain('preventScroll: true');
|
|
});
|
|
|
|
it('applies the patch on iframe load', () => {
|
|
expect(stateBuilder).toContain("iframe.addEventListener('load', () => patchSimulatorScrollPropagation(iframe));");
|
|
});
|
|
|
|
it('does not install a body-fixed parent scroll lock', () => {
|
|
// 同源是部署约定;不再保留跨域 fallback,以免 demo 期间 paper 不能滚(包括失去 scroll chaining)。
|
|
expect(html).not.toContain('installPageScrollLock');
|
|
expect(html).not.toContain("body.style.position = 'fixed';");
|
|
});
|
|
});
|