Files
matrix-screen-controller/核桃派软件源代码/tests/test_media_import_ui.mjs
T

101 lines
4.4 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import test from "node:test";
import { clampCropCenter, cropCenterBounds, cropGeometry } from "../app/static/media-crop-geometry.js";
import { shouldReuseMediaJobCard } from "../app/static/media-import-ui-model.js";
const html = fs.readFileSync(new URL("../app/static/index.html", import.meta.url), "utf8");
const app = fs.readFileSync(new URL("../app/static/app.js", import.meta.url), "utf8");
const view = fs.readFileSync(new URL("../app/static/views/media-import.js", import.meta.url), "utf8");
const copyCatalog = JSON.parse(fs.readFileSync(new URL("../app/static/ui-copy.json", import.meta.url), "utf8"));
test("media import workspace exposes streaming upload, crop controls, and queue polling", () => {
assert.match(app, /views\/media-import\.js/);
assert.match(html, /id="workspace-media-import"/);
assert.match(html, /id="media-source-file"/);
assert.doesNotMatch(html, /id="media-output-name"/);
assert.match(html, /class="media-source-field"/);
assert.match(html, /id="media-upload-progress"/);
assert.match(view, /XMLHttpRequest/);
assert.match(view, /pointermove/);
assert.match(view, /transparency_color/);
assert.match(view, /padding_color/);
assert.match(view, /document\.hidden/);
assert.match(view, /setInterval\(refreshJobs, 2000\)/);
assert.match(view, /id: "media-import"/);
assert.doesNotMatch(view, /nameInput/);
assert.doesNotMatch(view, /&name=/);
assert.doesNotMatch(view, /裁切填满/);
assert.doesNotMatch(fs.readFileSync(new URL("../app/static/style.css", import.meta.url), "utf8"), /object-fit:\s*cover/);
});
test("free framing starts from the complete source and keeps one pixel visible", () => {
const centered = cropGeometry({
viewportWidth: 400, viewportHeight: 400,
sourceWidth: 800, sourceHeight: 400,
zoom: 1, centerX: 0.5, centerY: 0.5,
});
assert.deepEqual(centered, { width: 400, height: 200, left: 0, top: 100 });
const bounds = cropCenterBounds({
viewportWidth: 400, viewportHeight: 400,
sourceWidth: 800, sourceHeight: 400, zoom: 1,
});
const corner = cropGeometry({
viewportWidth: 400, viewportHeight: 400,
sourceWidth: 800, sourceHeight: 400, zoom: 1,
centerX: bounds.minX, centerY: bounds.minY,
});
assert.equal(corner.left, 393.75);
assert.equal(corner.top, 393.75);
assert.deepEqual(
clampCropCenter({ centerX: -100, centerY: 100 }, bounds),
{ centerX: bounds.minX, centerY: bounds.maxY },
);
});
test("free framing copy is stable and catalogued", () => {
assert.match(view, /copy\.dynamic\.media\.mode_crop", "自由取景"/);
assert.equal(copyCatalog.items["copy.dynamic.media.mode_crop"]?.text, "自由取景");
assert.equal(copyCatalog.items["copy.dynamic.media.crop_zoom"]?.text, "取景缩放");
});
test("upload action has visible ordinary-build copy", () => {
assert.match(html, /id="media-upload-button"[^>]*>上传文件<\/button>/);
const item = Object.values(copyCatalog.items).find(
(candidate) => candidate.render?.selector === "#media-upload-button",
);
assert.equal(item?.text, "上传文件");
assert.equal(Boolean(item?.render?.default_hidden), false);
});
test("media naming happens after analysis and conflicts keep the draft", () => {
assert.match(view, /copy\.dynamic\.media\.name_conflict", "保存名称已存在,请更换名称。"/);
assert.match(view, /error\.message === "output name already exists"/);
assert.match(view, /const file = fileInput\.files\[0\]/);
assert.doesNotMatch(html, />保存名称<\/span>[\s\S]*media-upload-button/);
assert.equal(copyCatalog.items["copy.dynamic.media.name_conflict"]?.text, "保存名称已存在,请更换名称。");
});
test("awaiting-settings cards survive polling without hiding server transitions", () => {
const rendered = {
id: "job-1", state: "awaiting_settings", updatedAt: "2026-08-15T10:00:00Z", dirty: false,
};
const unchanged = {
id: "job-1", state: "awaiting_settings", updated_at: "2026-08-15T10:00:00Z",
};
assert.equal(shouldReuseMediaJobCard(rendered, unchanged), true);
assert.equal(shouldReuseMediaJobCard(
{ ...rendered, dirty: true },
{ ...unchanged, updated_at: "2026-08-15T10:01:00Z" },
), true);
assert.equal(shouldReuseMediaJobCard(
rendered,
{ ...unchanged, updated_at: "2026-08-15T10:01:00Z" },
), false);
assert.equal(shouldReuseMediaJobCard(
rendered,
{ ...unchanged, state: "queued" },
), false);
});