Files
web-cad/frontend/tests/GroupTool.test.ts
T

191 lines
6.2 KiB
TypeScript
Raw Normal View History

/**
* GroupTool Tests GroupManager: create, ungroup, nest, query
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { GroupManager } from '../src/tools/modification/GroupTool';
import type { ElementGroup } from '../src/tools/modification/GroupTool';
describe('GroupManager', () => {
let gm: GroupManager;
beforeEach(() => {
gm = new GroupManager();
});
describe('createGroup', () => {
it('should create a group with element IDs', () => {
const group = gm.createGroup(['el-1', 'el-2', 'el-3']);
expect(group.id).toBeDefined();
expect(group.elementIds).toEqual(['el-1', 'el-2', 'el-3']);
expect(group.parentGroupId).toBeNull();
});
it('should create a group with a custom name', () => {
const group = gm.createGroup(['el-1'], 'My Group');
expect(group.name).toBe('My Group');
});
it('should create a group with default name when no name provided', () => {
const group = gm.createGroup(['el-1']);
expect(group.name).toContain('Group');
});
it('should create multiple groups with unique IDs', () => {
const g1 = gm.createGroup(['el-1']);
const g2 = gm.createGroup(['el-2']);
expect(g1.id).not.toBe(g2.id);
});
});
describe('ungroup', () => {
it('should remove a group and return its element IDs', () => {
const group = gm.createGroup(['el-1', 'el-2']);
const ids = gm.ungroup(group.id);
expect(ids).toEqual(['el-1', 'el-2']);
expect(gm.getGroup(group.id)).toBeUndefined();
});
it('should return empty array for non-existent group', () => {
const ids = gm.ungroup('non-existent');
expect(ids).toEqual([]);
});
});
describe('getGroup', () => {
it('should retrieve a group by ID', () => {
const group = gm.createGroup(['el-1']);
const retrieved = gm.getGroup(group.id);
expect(retrieved).toBeDefined();
expect(retrieved!.id).toBe(group.id);
});
it('should return undefined for non-existent group', () => {
expect(gm.getGroup('non-existent')).toBeUndefined();
});
});
describe('getGroups', () => {
it('should return all groups', () => {
gm.createGroup(['el-1']);
gm.createGroup(['el-2']);
expect(gm.getGroups().length).toBe(2);
});
it('should return empty array when no groups', () => {
expect(gm.getGroups()).toEqual([]);
});
});
describe('getGroupedElements', () => {
it('should return set of all element IDs in all groups', () => {
gm.createGroup(['el-1', 'el-2']);
gm.createGroup(['el-3']);
const ids = gm.getGroupedElements();
expect(ids.size).toBe(3);
expect(ids.has('el-1')).toBe(true);
expect(ids.has('el-2')).toBe(true);
expect(ids.has('el-3')).toBe(true);
});
it('should return empty set when no groups', () => {
expect(gm.getGroupedElements().size).toBe(0);
});
});
describe('getGroupForElement', () => {
it('should return group ID for an element in a group', () => {
const group = gm.createGroup(['el-1', 'el-2']);
expect(gm.getGroupForElement('el-1')).toBe(group.id);
expect(gm.getGroupForElement('el-2')).toBe(group.id);
});
it('should return null for element not in any group', () => {
expect(gm.getGroupForElement('el-lonely')).toBeNull();
});
});
describe('moveGroup', () => {
it('should return element IDs that need to be moved', () => {
const group = gm.createGroup(['el-1', 'el-2']);
const ids = gm.moveGroup(group.id, 10, 20);
expect(ids).toEqual(['el-1', 'el-2']);
});
it('should return empty array for non-existent group', () => {
const ids = gm.moveGroup('non-existent', 10, 20);
expect(ids).toEqual([]);
});
});
describe('setParent (nested groups)', () => {
it('should set parent group for nesting', () => {
const parent = gm.createGroup(['el-1']);
const child = gm.createGroup(['el-2']);
gm.setParent(child.id, parent.id);
expect(gm.getGroup(child.id)!.parentGroupId).toBe(parent.id);
});
it('should prevent circular references', () => {
const g1 = gm.createGroup(['el-1']);
const g2 = gm.createGroup(['el-2']);
gm.setParent(g1.id, g2.id);
// Trying to set g2's parent to g1 would create a cycle: g1 -> g2 -> g1
gm.setParent(g2.id, g1.id);
expect(gm.getGroup(g2.id)!.parentGroupId).toBeNull();
});
it('should allow setting parent to null', () => {
const parent = gm.createGroup(['el-1']);
const child = gm.createGroup(['el-2']);
gm.setParent(child.id, parent.id);
gm.setParent(child.id, null);
expect(gm.getGroup(child.id)!.parentGroupId).toBeNull();
});
it('should do nothing for non-existent group', () => {
gm.setParent('non-existent', null);
expect(gm.getGroup('non-existent')).toBeUndefined();
});
});
describe('clear', () => {
it('should clear all groups', () => {
gm.createGroup(['el-1']);
gm.createGroup(['el-2']);
gm.clear();
expect(gm.getGroups().length).toBe(0);
});
});
describe('toJSON & fromJSON', () => {
it('should serialize groups to JSON', () => {
gm.createGroup(['el-1', 'el-2'], 'Group A');
gm.createGroup(['el-3'], 'Group B');
const json = gm.toJSON();
expect(json.length).toBe(2);
expect(json[0].name).toBe('Group A');
expect(json[1].name).toBe('Group B');
});
it('should restore groups from JSON', () => {
const groups: ElementGroup[] = [
{ id: 'grp-1', name: 'Restored A', elementIds: ['el-1'], parentGroupId: null },
{ id: 'grp-2', name: 'Restored B', elementIds: ['el-2', 'el-3'], parentGroupId: 'grp-1' },
];
gm.fromJSON(groups);
expect(gm.getGroups().length).toBe(2);
expect(gm.getGroup('grp-1')!.name).toBe('Restored A');
expect(gm.getGroup('grp-2')!.parentGroupId).toBe('grp-1');
});
it('should clear existing groups when restoring from JSON', () => {
gm.createGroup(['el-old']);
gm.fromJSON([
{ id: 'grp-new', name: 'New', elementIds: ['el-new'], parentGroupId: null },
]);
expect(gm.getGroups().length).toBe(1);
expect(gm.getGroup('grp-new')).toBeDefined();
});
});
});