/** * 488-2 — 선 특성 메뉴 = 고른 것의 값(다르면 빈 칸) · 바꾸면 고른 것만 · 폴리선 자식까지 · Ctrl+Z 한 번에 옛 값. * 짝: `src/helpers/selection-style.ts`(리본 특성 · 특성 판 · COLOR · LWEIGHT 등 명령 같이 씀). * 실행: cd B07_DesignDetail/openwebcad && npx vitest run --dir ../../resources/tester/cad selection-style */ // 앱과 같은 flatten 사본(시험 쪽 사본 점은 앱 Segment 가 못 받음) import { Point } from "../../../B07_DesignDetail/openwebcad/node_modules/@flatten-js/core"; import { beforeEach, describe, expect, it } from "vitest"; import type { Entity } from "../../../B07_DesignDetail/openwebcad/src/entities/Entity"; import { LineEntity } from "../../../B07_DesignDetail/openwebcad/src/entities/LineEntity"; import { PolyLineEntity } from "../../../B07_DesignDetail/openwebcad/src/entities/PolyLineEntity"; import { TextEntity } from "../../../B07_DesignDetail/openwebcad/src/entities/TextEntity"; import { dashToLineType, restyle, selectionLineStyle, styleTargets, } from "../../../B07_DesignDetail/openwebcad/src/helpers/selection-style"; import { getActiveLineWidth, getEntities, getSelectedEntities, resetUndoBaseline, setActiveLineWidth, setEntities, setLayers, setSelectedEntityIds, undo, } from "../../../B07_DesignDetail/openwebcad/src/state"; const line = (color: string, width = 1, dash?: number[]) => { const entity = new LineEntity("L", new Point(0, 0), new Point(10, 0)); entity.lineColor = color; entity.lineWidth = width; entity.lineDash = dash; return entity; }; /** 엔진 꼴 — 부모 값과 자식 선 값이 따로 */ const poly = (childColor: string) => { const kids = [line(childColor), line(childColor)]; const entity = new PolyLineEntity("L", kids); entity.lineColor = "#ffffff"; return entity; }; const leafWidths = (entity: Entity) => entity instanceof PolyLineEntity ? entity.getEntities().map((kid) => kid.lineWidth) : [entity.lineWidth]; const byId = (id: string) => getEntities().find((entity) => entity.id === id) as Entity; /** 실은 도면 = 선 a(빨강) · 폴리선 b(자식 파랑) · 글 · 방금 그린 선 d */ let a: LineEntity; let b: PolyLineEntity; let d: LineEntity; beforeEach(() => { setLayers([{ id: "L", name: "L", isVisible: true, isLocked: false }]); a = line("#ff0000"); b = poly("#0000ff"); const text = new TextEntity("L", "글", new Point(0, 0)); setEntities([a, b, text], false); resetUndoBaseline(); d = line("#00ff00"); setEntities([...getEntities(), d], true); // 방금 그린 선 setSelectedEntityIds([a.id, b.id, text.id]); setActiveLineWidth(1); }); describe("selectionLineStyle", () => { it("다른 색 = 빈 칸 · 같은 두께 · 선종류 = 그 값 · 글은 안 봄", () => { expect(styleTargets(getSelectedEntities())).toHaveLength(2); expect(selectionLineStyle()).toEqual({ color: "", width: "1", lineType: "solid" }); }); it("폴리선은 자식 값을 봄 · 목록 밖 두께 · 점선 = 빈 칸", () => { setSelectedEntityIds([b.id]); expect(selectionLineStyle().color).toBe("#0000ff"); a.lineWidth = 0.5; a.lineDash = [6, 4]; // 엔진 점선(목록 밖) setSelectedEntityIds([a.id]); expect(selectionLineStyle()).toEqual({ color: "#ff0000", width: "", lineType: "" }); expect([dashToLineType([]), dashToLineType(undefined), dashToLineType([10, 5])]).toEqual([ "solid", "solid", "dashed", ]); }); it("고른 선 없으면 그리기 기본값", () => { setSelectedEntityIds([]); setActiveLineWidth(4); expect(selectionLineStyle().width).toBe("4"); }); }); describe("restyle", () => { it("고른 것만 · 폴리선 자식까지 · 고름 · id 그대로 · 기본값 그대로", () => { restyle(styleTargets(getSelectedEntities()), (entity) => { entity.lineWidth = 3; }); expect(leafWidths(byId(a.id))).toEqual([3]); expect(leafWidths(byId(b.id))).toEqual([3, 3]); expect(byId(d.id).lineWidth).toBe(1); expect(getSelectedEntities()).toHaveLength(3); expect(selectionLineStyle().width).toBe("3"); expect(getActiveLineWidth()).toBe(1); }); it("Ctrl+Z 한 번 = 옛 값 · 방금 그린 선 남음", () => { restyle(styleTargets(getSelectedEntities()), (entity) => { entity.lineWidth = 3; }); undo(); expect(leafWidths(byId(a.id))).toEqual([1]); expect(leafWidths(byId(b.id))).toEqual([1, 1]); expect(getEntities().map((entity) => entity.id)).toContain(d.id); }); it("고른 것 없으면 아무것도 안 바뀜 · 되돌리기 칸 안 쌓임", () => { expect(restyle([], () => {})).toEqual([]); undo(); expect(getEntities().map((entity) => entity.id)).not.toContain(d.id); // 한 칸 전 = 그리기 전 }); });