75 lines
5.1 KiB
TypeScript
75 lines
5.1 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { predictLayout } from "../adapters/prediction.ts";
|
|
|
|
test("prediction measures desktop and mobile geometry and restores closed disclosure", async () => {
|
|
const html = '<!doctype html><html><head><style>.panel { width: 400px; height: 180px; } @media(max-width:48rem) { .panel { width: 200px; height: 240px; } }</style></head><body><details><summary>Menu</summary><div class="panel" data-muddle-anchor="panel">Content</div></details></body></html>';
|
|
const result = await predictLayout(html, { selectors: [".panel"], strict: true });
|
|
expect(result.predictions.map((prediction) => prediction.width)).toEqual([400, 200]);
|
|
expect(result.predictions.map((prediction) => prediction.height)).toEqual([180, 240]);
|
|
expect(result.html).not.toContain("<details open");
|
|
expect(result.html).toContain('data-muddle-predicted="predict-0"');
|
|
expect(result.html).toContain("--muddle-predicted-desktop-width: 400px");
|
|
expect(result.html).toContain("--muddle-predicted-mobile-width: 200px");
|
|
expect(result.html).toContain("--muddle-relate-panel-desktop-width: 400px");
|
|
expect(result.html).toContain("--muddle-relate-panel-mobile-width: 200px");
|
|
expect(result.html).toContain("@media (max-width: 48rem)");
|
|
});
|
|
|
|
test("prediction resolves a target that is sized from an ahead-of-time relation", async () => {
|
|
const html = `<!doctype html><html><head><style>
|
|
.source { position: absolute; left: 100px; top: 20px; width: 240px; height: 32px; }
|
|
.target { position: absolute; left: var(--muddle-relate-source-x); top: 80px; width: var(--muddle-relate-source-width); height: 24px; }
|
|
@media (max-width: 48rem) {
|
|
.source { left: 24px; width: 160px; }
|
|
}
|
|
</style></head><body>
|
|
<div class="source" data-muddle-anchor="source"></div>
|
|
<div class="target"></div>
|
|
</body></html>`;
|
|
const result = await predictLayout(html, { selectors: [".target"], strict: true });
|
|
const target = result.predictions.filter((prediction) => prediction.selector === '[data-muddle-predicted="predict-0"]');
|
|
expect(target.map((prediction) => prediction.width)).toEqual([240, 160]);
|
|
expect(target.map((prediction) => prediction.x)).toEqual([100, 24]);
|
|
expect(result.html).toContain("--muddle-predicted-desktop-width: 240px");
|
|
expect(result.html).toContain("--muddle-predicted-mobile-width: 160px");
|
|
});
|
|
|
|
test("prediction settles chained relations before writing the static page", async () => {
|
|
const html = `<!doctype html><html><head><style>
|
|
.source { position: absolute; left: 72px; top: 20px; width: 216px; height: 24px; }
|
|
.middle { position: absolute; left: var(--muddle-relate-source-x); top: 60px; width: var(--muddle-relate-source-width); height: 24px; }
|
|
.target { position: absolute; left: var(--muddle-relate-middle-x); top: 100px; width: var(--muddle-relate-middle-width); height: 24px; }
|
|
</style></head><body>
|
|
<div class="source" data-muddle-anchor="source"></div>
|
|
<div class="middle" data-muddle-anchor="middle"></div>
|
|
<div class="target"></div>
|
|
</body></html>`;
|
|
const result = await predictLayout(html, { selectors: [".target"], strict: true });
|
|
const target = result.predictions.filter((prediction) => prediction.selector === '[data-muddle-predicted="predict-0"]');
|
|
expect(target.map((prediction) => prediction.width)).toEqual([216, 216]);
|
|
expect(target.map((prediction) => prediction.x)).toEqual([72, 72]);
|
|
});
|
|
|
|
test("prediction follows the page's widest mobile breakpoint", async () => {
|
|
const html = '<!doctype html><html><head><style>.panel { width: 500px; height: 24px; } @media (max-width: 40rem) { .panel { width: 280px; } }</style></head><body><div class="panel" data-muddle-anchor="panel"></div></body></html>';
|
|
const result = await predictLayout(html, { selectors: [".panel"], strict: true });
|
|
expect(result.predictions.map((prediction) => prediction.width)).toEqual([500, 280]);
|
|
expect(result.html).toContain("@media (max-width: 40rem)");
|
|
});
|
|
|
|
test("prediction emits each selected breakpointAcc relation layer", async () => {
|
|
const html = '<!doctype html><html><head><style>.panel { width: 600px; height: 24px; } @media (max-width: 64rem) { .panel { width: 420px; } } @media (max-width: 48rem) { .panel { width: 300px; } }</style></head><body><div class="panel" data-muddle-anchor="panel"></div></body></html>';
|
|
const result = await predictLayout(html, { selectors: [".panel"], breakpointAcc: ["LG", "MD"], strict: true });
|
|
expect(result.html).toContain("--muddle-relate-panel-lg-width: 420px");
|
|
expect(result.html).toContain("--muddle-relate-panel-md-width: 300px");
|
|
expect(result.html).toContain("@media (max-width: 64rem)");
|
|
expect(result.html).toContain("@media (max-width: 48rem)");
|
|
});
|
|
|
|
test("prediction discovers dotted anchor groups and emits reflective metadata", async () => {
|
|
const html = '<!doctype html><html><head><style>.item { width: 200px; }</style></head><body><a class="item" data-muddle-anchor="docs.intro"></a><a class="item" data-muddle-anchor="docs.api"></a></body></html>';
|
|
const result = await predictLayout(html, { strict: true });
|
|
expect(result.groups).toEqual([{ name: "docs", anchors: ["docs.intro", "docs.api"] }]);
|
|
expect(result.html).toContain('data-muddle-group="docs"');
|
|
expect(result.html).toContain('--muddle-reflect-docs-count: 2');
|
|
});
|