mock: スイッチ・スタビの十字をトグルで出し、スタビ候補を選べるようにする(T-30 単位8)
スタビ候補はキーの長辺の長さで引き、キーごとに複数選べる。選択は ProjectFile.ui.phy.stabilizers に持つ。 プロパティ欄に switchOffset の入力欄を置く。異形キーは候補なし。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yoUu9Xd8dhwyQdCfKfaXG
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
defaultStabilizerSelection,
|
||||
stabilizerCandidates,
|
||||
stabilizerPoints,
|
||||
switchPoint,
|
||||
} from "../src/domain/stabilizers";
|
||||
import { mountMarks, selectedStabilizers, stabilizerSelections, withStabilizers } from "../src/ui/phy/logic";
|
||||
import type { KeyNode } from "../src/domain/phy";
|
||||
import type { ProjectFile } from "../src/domain/project";
|
||||
|
||||
const key = (id: string, w: number, h = 1, extra: Partial<KeyNode> = {}): KeyNode => ({
|
||||
type: "key",
|
||||
id,
|
||||
profile: "p",
|
||||
transform: { x: 0, y: 0, rotation: 0 },
|
||||
size: { w, h },
|
||||
...extra,
|
||||
});
|
||||
const ids = (w: number, h = 1) => stabilizerCandidates({ w, h }).map((c) => c.id);
|
||||
|
||||
describe("stabilizer candidates", () => {
|
||||
it("looks up candidates by the long side", () => {
|
||||
expect(ids(1)).toEqual([]);
|
||||
expect(ids(1.75)).toEqual([]);
|
||||
expect(ids(2.25)).toEqual(["11.938mm"]);
|
||||
expect(ids(1, 2)).toEqual(["11.938mm"]);
|
||||
expect(ids(6)).toEqual(["2.5u", "2u"]);
|
||||
expect(ids(6.25)).toEqual(["50mm", "40mm", "42.5mm"]);
|
||||
expect(ids(10)).toEqual(["3.5u"]);
|
||||
expect(ids(6.75)).toEqual([]);
|
||||
});
|
||||
it("gives no candidates to non-rectangular keys", () => {
|
||||
expect(stabilizerCandidates({ w: 1.25, h: 2, w2: 1.5, h2: 1, x2: -0.25 })).toEqual([]);
|
||||
expect(stabilizerCandidates({ w: 2, h: 1, w2: 2.25 })).toEqual([]);
|
||||
});
|
||||
it("selects a lone candidate by default and nothing when there are several", () => {
|
||||
expect(defaultStabilizerSelection({ w: 2, h: 1 })).toEqual(["11.938mm"]);
|
||||
expect(defaultStabilizerSelection({ w: 6.25, h: 1 })).toEqual([]);
|
||||
});
|
||||
it("places mounts around the rectangle center along the long axis", () => {
|
||||
expect(stabilizerPoints({ w: 7, h: 1 }, ["3u"])).toEqual([
|
||||
{ x: 0.5, y: 0.5 },
|
||||
{ x: 6.5, y: 0.5 },
|
||||
]);
|
||||
const [top, bottom] = stabilizerPoints({ w: 1, h: 2 }, ["11.938mm"]);
|
||||
expect(top!.x).toBe(0.5);
|
||||
expect(bottom!.y - top!.y).toBeCloseTo(23.876 / 19.05, 12);
|
||||
expect(stabilizerPoints({ w: 6, h: 1 }, ["2.5u", "2u"])).toHaveLength(4);
|
||||
});
|
||||
it("keeps stabilizers on the key center when the switch is offset", () => {
|
||||
const k = key("k", 6, 1, { switchOffset: { x: 0.5, y: 0 } });
|
||||
expect(switchPoint(k)).toEqual({ x: 3.5, y: 0.5 });
|
||||
expect(stabilizerPoints(k.size, ["2.5u"]).map((p) => p.x)).toEqual([0.5, 5.5]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("stabilizer selections in ProjectFile.ui", () => {
|
||||
const project = { ui: { other: 1 } } as unknown as ProjectFile;
|
||||
it("falls back to the size default and drops ids the size no longer offers", () => {
|
||||
expect(selectedStabilizers({}, key("a", 2))).toEqual(["11.938mm"]);
|
||||
expect(selectedStabilizers({ a: [] }, key("a", 2))).toEqual([]);
|
||||
expect(selectedStabilizers({ a: ["2.5u", "3u"] }, key("a", 6))).toEqual(["2.5u"]);
|
||||
});
|
||||
it("writes per key without touching other ui state", () => {
|
||||
const next = withStabilizers(withStabilizers(project, "a", ["50mm"]), "b", []);
|
||||
expect(stabilizerSelections(next)).toEqual({ a: ["50mm"], b: [] });
|
||||
expect((next.ui as { other: number }).other).toBe(1);
|
||||
expect(stabilizerSelections(project)).toEqual({});
|
||||
});
|
||||
it("lists marks for visible keys only, skipping decals", () => {
|
||||
const marks = mountMarks(
|
||||
[
|
||||
key("a", 2),
|
||||
key("d", 2, 1, { decal: true }),
|
||||
{
|
||||
type: "variantGroup",
|
||||
id: "g",
|
||||
name: "g",
|
||||
default: "v1",
|
||||
transform: { x: 0, y: 1, rotation: 0 },
|
||||
children: [
|
||||
{ type: "variant", id: "v1", name: "1", children: [key("b", 1)] },
|
||||
{ type: "variant", id: "v2", name: "2", children: [key("c", 1)] },
|
||||
],
|
||||
},
|
||||
],
|
||||
{ g: "v2" },
|
||||
{},
|
||||
);
|
||||
expect(marks.map((m) => m.id)).toEqual(["a", "c"]);
|
||||
expect(marks[1]!.transform.f).toBe(1);
|
||||
expect(marks[0]!.stabs).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user