task(CAD-14): phase 3 - V2 select tool on v2 doc (click via bridge hitTest, shift-additive, box-select by center-in-bbox, onChange app channel via ref), bridge onChange wired
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* CAD-14 Phase 3: selectTool V2 — Auswahl direkt auf dem V2-Dokument.
|
||||
* Klick = hitTest via SelectionBridge, Leerklick leert, Shift additiv,
|
||||
* Drag = Box-Select (Elemente mit Zentrum in BBox).
|
||||
*/
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { selectTool } from '../src/plugins/builtin/core-drawing';
|
||||
import { CADDocument } from '../src/kernel/document/CADDocument';
|
||||
import { YjsDocument } from '../src/crdt/YjsDocument';
|
||||
import type { CADElement, Pt } from '../src/types/cad.types';
|
||||
|
||||
function pe(x: number, y: number, shift = false): { world: Pt; shift: boolean } {
|
||||
return { world: { x, y }, shift } as never;
|
||||
}
|
||||
|
||||
function makeCtx(ids: string[], hit: CADElement | null) {
|
||||
const selected: string[][] = [];
|
||||
const onChangeCalls: string[][] = [];
|
||||
const realDoc = new CADDocument(new YjsDocument());
|
||||
let currentIds = [...ids];
|
||||
const ctx: any = {
|
||||
options: {},
|
||||
selection: {
|
||||
getIds: () => currentIds,
|
||||
setIds: (next: string[], additive?: boolean) => {
|
||||
currentIds = additive ? [...currentIds, ...next] : next;
|
||||
selected.push(currentIds);
|
||||
},
|
||||
hitTest: (_x: number, _y: number, _tol: number) => hit,
|
||||
onChange: (ids2: string[]) => onChangeCalls.push(ids2),
|
||||
},
|
||||
doc: realDoc,
|
||||
setStatus: () => {},
|
||||
setPreview: () => {},
|
||||
};
|
||||
return { ctx, selected, onChangeCalls, realDoc, getCurrentIds: () => currentIds };
|
||||
}
|
||||
|
||||
function lineEl(id: string, x1: number, y1: number, x2: number, y2: number): CADElement {
|
||||
return {
|
||||
id, type: 'line', layerId: 'l', x: (x1 + x2) / 2, y: (y1 + y2) / 2,
|
||||
width: Math.abs(x2 - x1), height: Math.abs(y2 - y1),
|
||||
properties: { x1, y1, x2, y2 },
|
||||
} as unknown as CADElement;
|
||||
}
|
||||
|
||||
describe('CAD-14 Phase 3: selectTool V2', () => {
|
||||
beforeEach(() => {
|
||||
selectTool.handlers.cancel?.({ setStatus: () => {}, setPreview: () => {} } as never);
|
||||
});
|
||||
|
||||
it('Manifest: id=select, basic-tag (immer sichtbar)', () => {
|
||||
expect(selectTool.manifest.id).toBe('select');
|
||||
expect((selectTool.manifest.tags ?? []).includes('basic')).toBe(true);
|
||||
});
|
||||
|
||||
it('Klick auf Element: hitTest-Treffer wird selektiert (setIds mit ID)', () => {
|
||||
const el = lineEl('e1', 0, 0, 100, 100);
|
||||
const { ctx, selected } = makeCtx([], el);
|
||||
selectTool.handlers.down!(pe(50, 50), ctx);
|
||||
expect(selected.length).toBe(1);
|
||||
expect(selected[0]).toEqual(['e1']);
|
||||
});
|
||||
|
||||
it('Leerklick (hitTest null): Auswahl geleert (setIds mit [])', () => {
|
||||
const { ctx, selected } = makeCtx(['e9'], null);
|
||||
selectTool.handlers.down!(pe(500, 500), ctx);
|
||||
expect(selected.length).toBe(1);
|
||||
expect(selected[0]).toEqual([]);
|
||||
});
|
||||
|
||||
it('Shift-Klick additiv: setIds mit additive=true', () => {
|
||||
const el = lineEl('e1', 0, 0, 100, 100);
|
||||
const { ctx, selected } = makeCtx(['e9'], el);
|
||||
selectTool.handlers.down!(pe(50, 50, true), ctx);
|
||||
expect(selected.length).toBe(1);
|
||||
// additive-Variante: bestaehige IDs + neue ID
|
||||
expect(selected[0]).toEqual(['e9', 'e1']);
|
||||
});
|
||||
|
||||
it('Box-Select: Element mit Zentrum in BBox wird selektiert', () => {
|
||||
const { ctx, realDoc, getCurrentIds } = makeCtx([], null);
|
||||
const el = lineEl('e1', 0, 0, 100, 100);
|
||||
realDoc.addElement(el);
|
||||
// down in leerer Gegend startet Box (Leerklick leert zuerst — korrekt),
|
||||
// move zeigt Vorschau, up schliesst BBox um Element.
|
||||
selectTool.handlers.down!(pe(-10, -10), ctx);
|
||||
selectTool.handlers.move!(pe(200, 200), ctx);
|
||||
selectTool.handlers.up!(pe(200, 200), ctx);
|
||||
expect(getCurrentIds()).toEqual(['e1']);
|
||||
});
|
||||
|
||||
it('onChange feuert nach Klick-Auswahl (App-Kanal)', () => {
|
||||
const el = lineEl('e1', 0, 0, 100, 100);
|
||||
const { ctx, onChangeCalls } = makeCtx([], el);
|
||||
selectTool.handlers.down!(pe(50, 50), ctx);
|
||||
expect(onChangeCalls.length).toBe(1);
|
||||
expect(onChangeCalls[0]).toEqual(['e1']);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user