229 lines
7.2 KiB
HTML
229 lines
7.2 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<meta charset="utf-8" />
|
|
<title>档案导航文字与刻度过渡检查</title>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
background: #eae5e1;
|
|
font: 13px monospace;
|
|
}
|
|
iframe {
|
|
width: 1100px;
|
|
height: 620px;
|
|
border: 0;
|
|
}
|
|
pre {
|
|
padding: 16px;
|
|
white-space: pre-wrap;
|
|
}
|
|
</style>
|
|
<iframe src="/?scene=archive" title="真实交互场景"></iframe>
|
|
<pre id="result">正在检查…</pre>
|
|
<script type="module">
|
|
import { records, columnFiles, archiveColumns } from "/src/data.ts";
|
|
const frame = document.querySelector("iframe"),
|
|
result = document.querySelector("#result"),
|
|
checks = [];
|
|
const pause = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
function check(ok, label) {
|
|
if (!ok) throw new Error(label);
|
|
checks.push(label);
|
|
}
|
|
async function until(fn) {
|
|
const start = performance.now();
|
|
while (!fn()) {
|
|
if (performance.now() - start > 12000) throw new Error("等待状态超时");
|
|
await pause(25);
|
|
}
|
|
}
|
|
try {
|
|
await until(
|
|
() =>
|
|
frame.contentWindow.rhine?.stats().loaded &&
|
|
!frame.contentDocument.querySelector("#loading"),
|
|
);
|
|
const win = frame.contentWindow,
|
|
doc = frame.contentDocument,
|
|
app = win.rhine;
|
|
const q = (s) => doc.querySelector(s),
|
|
value = (s) => q(s).querySelector(".rn-value")?.textContent;
|
|
const moving = (s) =>
|
|
q(s)
|
|
.getAnimations({ subtree: true })
|
|
.some((a) => a.playState === "running");
|
|
const height = (b) =>
|
|
parseFloat(win.getComputedStyle(b, "::before").height);
|
|
const button = (a) => q(`[data-action="${a}"]`);
|
|
app.archive();
|
|
await pause(800);
|
|
const ticks = [...q("#file-ticks").children],
|
|
a = columnFiles(0),
|
|
b = columnFiles(1);
|
|
app.select(a[1]);
|
|
await pause(600);
|
|
app.select(b[5]);
|
|
await pause(600);
|
|
button("column-prev").click();
|
|
await pause(90);
|
|
check(
|
|
moving("#column-name") && moving("#archive-category"),
|
|
"切列时底部列名与顶部分类同时滚动",
|
|
);
|
|
check(
|
|
value("#column-name") === archiveColumns[0] &&
|
|
value("#archive-category") === archiveColumns[0],
|
|
"分类语义文字立即对应当前列",
|
|
);
|
|
check(
|
|
ticks.every((node, i) => q("#file-ticks").children[i] === node),
|
|
"切列复用原有八个刻度节点",
|
|
);
|
|
check(
|
|
height(ticks[1]) > 12 &&
|
|
height(ticks[1]) < 33 &&
|
|
height(ticks[5]) > 12 &&
|
|
height(ticks[5]) < 33,
|
|
"跨列选中刻度在新旧位置间连续伸缩",
|
|
);
|
|
check(
|
|
app.stats().selected === records[a[1]].id,
|
|
"切列保留各自档案位置记忆",
|
|
);
|
|
button("column-next").click();
|
|
await pause(55);
|
|
button("column-prev").click();
|
|
await pause(650);
|
|
check(
|
|
ticks[1].getAttribute("aria-pressed") === "true" &&
|
|
Math.abs(height(ticks[1]) - 33) < 0.1,
|
|
"快速反向切列最终刻度正确",
|
|
);
|
|
ticks[3].click();
|
|
check(
|
|
app.stats().selected === records[a[3]].id,
|
|
"复用刻度按钮正确映射当前列档案",
|
|
);
|
|
button("column-next").click();
|
|
await pause(650);
|
|
check(
|
|
app.stats().selected === records[b[5]].id &&
|
|
ticks[5].getAttribute("aria-pressed") === "true",
|
|
"另一列的选择记忆与刻度一致",
|
|
);
|
|
check(
|
|
parseFloat(
|
|
win.getComputedStyle(q("#column-name .rn-face")).fontSize,
|
|
) === parseFloat(win.getComputedStyle(q("#column-name")).fontSize),
|
|
"列名内部文字保持原字号",
|
|
);
|
|
check(
|
|
parseFloat(
|
|
win.getComputedStyle(q("#archive-category .rn-face")).marginLeft,
|
|
) === 0,
|
|
"分类内部字形没有继承分隔符外边距",
|
|
);
|
|
for (let i = 0; i < 7; i++) {
|
|
button("column-next").click();
|
|
await pause(35);
|
|
}
|
|
await pause(700);
|
|
check(
|
|
value("#column-name") === archiveColumns[3] &&
|
|
value("#archive-category") === archiveColumns[3],
|
|
"跨首尾连续切列收敛到最终分类",
|
|
);
|
|
check(!moving("#selected-clearance"), "内容不变的权限标签不重复滚动");
|
|
app.select(a[0]);
|
|
await pause(2200);
|
|
const canvas = q("#three-scene canvas"),
|
|
label = q("#hover-label"),
|
|
rect = canvas.getBoundingClientRect(),
|
|
hits = [];
|
|
function hover(p) {
|
|
canvas.dispatchEvent(
|
|
new win.PointerEvent("pointermove", {
|
|
clientX: rect.left + p.x,
|
|
clientY: rect.top + p.y,
|
|
bubbles: true,
|
|
}),
|
|
);
|
|
}
|
|
for (
|
|
let y = rect.height * 0.2;
|
|
y < rect.height * 0.8 && hits.length < 3;
|
|
y += 22
|
|
) {
|
|
for (
|
|
let x = rect.width * 0.35;
|
|
x < rect.width * 0.93 && hits.length < 3;
|
|
x += 22
|
|
) {
|
|
hover({ x, y });
|
|
const text = value("#hover-title");
|
|
if (!label.hidden && !hits.some((p) => p.text === text))
|
|
hits.push({ x, y, text });
|
|
}
|
|
}
|
|
check(hits.length >= 2, "实际场景射线可命中至少两份不同档案");
|
|
canvas.dispatchEvent(new win.PointerEvent("pointerleave"));
|
|
hover(hits[0]);
|
|
check(
|
|
!label.hidden &&
|
|
!moving("#hover-title") &&
|
|
value("#hover-title") === hits[0].text,
|
|
"首次悬停直接显示当前标题",
|
|
);
|
|
await pause(100);
|
|
hover(hits[1]);
|
|
await pause(70);
|
|
check(
|
|
moving("#hover-title") && value("#hover-title") === hits[1].text,
|
|
"悬停从第一份切到第二份即开始文字滚动",
|
|
);
|
|
hover(hits[0]);
|
|
hover(hits[1]);
|
|
await pause(650);
|
|
check(
|
|
value("#hover-title") === hits[1].text && !moving("#hover-title"),
|
|
"快速悬停切换显示最终标题",
|
|
);
|
|
canvas.dispatchEvent(new win.PointerEvent("pointerleave"));
|
|
check(
|
|
label.hidden && !moving("#hover-title"),
|
|
"离开阵列结束隐藏标签的动画",
|
|
);
|
|
button("column-next").click();
|
|
await pause(60);
|
|
app.detail();
|
|
check(
|
|
!moving("#column-name") && !moving("#archive-category") && label.hidden,
|
|
"进入详情结束导航文字动画并隐藏悬停",
|
|
);
|
|
app.archive();
|
|
await pause(500);
|
|
button("settings").click();
|
|
await pause(350);
|
|
const reduced = q('[data-pref="reduced"]'),
|
|
before = reduced.checked;
|
|
if (!before) reduced.click();
|
|
app.select(b[2]);
|
|
await pause(40);
|
|
const reducedSettled =
|
|
!moving("#column-name") &&
|
|
!moving("#archive-category") &&
|
|
!moving("#selected-title");
|
|
if (!before) reduced.click();
|
|
check(reducedSettled, "减少动态效果立即更新全部档案文字");
|
|
result.textContent = JSON.stringify({ passed: true, checks }, null, 2);
|
|
} catch (error) {
|
|
result.textContent = JSON.stringify(
|
|
{ passed: false, checks, error: error.message },
|
|
null,
|
|
2,
|
|
);
|
|
console.error(error);
|
|
}
|
|
</script>
|
|
</html>
|