import { describe, it, expect, beforeEach } from 'vitest';
import {
Scene,
cubeScad, sphereScad, cylinderScad, coneScad, torusScad,
translateScad, rotateScad, scaleScad, mirrorScad,
booleanScad,
text3dScad,
linearExtrudeScad, circleScad, squareScad, polygonScad,
} from '../src/scene.js';
describe('Scene', () => {
let scene: Scene;
beforeEach(() => {
scene = new Scene();
});
it('should start empty', () => {
expect(scene.objectCount).toBe(0);
expect(scene.rootCount).toBe(0);
});
it('should add objects', () => {
const obj = scene.addObject({
name: 'test-cube',
type: 'primitive',
scadCode: cubeScad([10, 10, 10]),
children: [],
metadata: {},
});
expect(obj.id).toBeDefined();
expect(scene.objectCount).toBe(1);
expect(scene.rootCount).toBe(1);
});
it('should remove objects', () => {
const obj = scene.addObject({
name: 'cube',
type: 'primitive',
scadCode: cubeScad([5, 5, 5]),
children: [],
metadata: {},
});
expect(scene.removeObject(obj.id)).toBe(true);
expect(scene.objectCount).toBe(0);
});
it('should clear all objects', () => {
scene.addObject({ name: 'a', type: 'primitive', scadCode: '', children: [], metadata: {} });
scene.addObject({ name: 'b', type: 'primitive', scadCode: '', children: [], metadata: {} });
expect(scene.objectCount).toBe(2);
scene.clear();
expect(scene.objectCount).toBe(0);
});
it('should generate SCAD code', () => {
scene.addObject({
name: 'cube',
type: 'primitive',
scadCode: cubeScad([20, 20, 10]),
children: [],
metadata: {},
});
const scad = scene.toScad();
expect(scad).toContain('cube([20, 20, 10]');
});
it('should handle boolean children correctly in root list', () => {
const a = scene.addObject({
name: 'a',
type: 'primitive',
scadCode: cubeScad([10, 10, 10]),
children: [],
metadata: {},
});
const b = scene.addObject({
name: 'b',
type: 'primitive',
scadCode: sphereScad(5),
children: [],
metadata: {},
});
expect(scene.rootCount).toBe(2);
scene.addObject({
name: 'union',
type: 'boolean',
scadCode: booleanScad('union', [a.scadCode, b.scadCode]),
children: [a.id, b.id],
metadata: {},
});
// a and b should no longer be root
expect(scene.rootCount).toBe(1);
});
});
describe('SCAD Generators', () => {
it('cube', () => {
expect(cubeScad([10, 20, 30])).toBe('cube([10, 20, 30], center = true);');
expect(cubeScad([5, 5, 5], false)).toBe('cube([5, 5, 5], center = false);');
});
it('sphere', () => {
expect(sphereScad(15)).toBe('sphere(r = 15, $fn = 32);');
expect(sphereScad(10, 64)).toBe('sphere(r = 10, $fn = 64);');
});
it('cylinder', () => {
expect(cylinderScad(20, 5)).toContain('cylinder(h = 20, r = 5');
});
it('cone', () => {
const code = coneScad(10, 5);
expect(code).toContain('r1 = 5');
expect(code).toContain('r2 = 0');
});
it('torus', () => {
const code = torusScad(10, 3);
expect(code).toContain('rotate_extrude');
expect(code).toContain('translate([10, 0, 0])');
});
it('text3d', () => {
const code = text3dScad('Hello', 12, 3);
expect(code).toContain('linear_extrude');
expect(code).toContain('"Hello"');
expect(code).toContain('size = 12');
});
it('translate', () => {
const code = translateScad([5, 10, 15], 'cube([1,1,1]);');
expect(code).toContain('translate([5, 10, 15])');
expect(code).toContain('cube([1,1,1]);');
});
it('rotate', () => {
const code = rotateScad([0, 0, 45], 'cube([1,1,1]);');
expect(code).toContain('rotate([0, 0, 45])');
});
it('scale', () => {
const code = scaleScad([2, 2, 1], 'sphere(r=5);');
expect(code).toContain('scale([2, 2, 1])');
});
it('mirror', () => {
const code = mirrorScad([1, 0, 0], 'cube([1,1,1]);');
expect(code).toContain('mirror([1, 0, 0])');
});
it('boolean union', () => {
const code = booleanScad('union', ['cube([1,1,1]);', 'sphere(r=1);']);
expect(code).toContain('union()');
expect(code).toContain('cube');
expect(code).toContain('sphere');
});
it('boolean difference', () => {
const code = booleanScad('difference', ['cube([10,10,10]);', 'cylinder(h=12,r=3);']);
expect(code).toContain('difference()');
});
it('linear extrude circle', () => {
const code = linearExtrudeScad(10, 90, 0.5, 32, circleScad(5));
expect(code).toContain('linear_extrude');
expect(code).toContain('twist = 90');
expect(code).toContain('circle(r = 5');
});
it('square', () => {
expect(squareScad([10, 20])).toBe('square([10, 20], center = true);');
});
it('polygon', () => {
const code = polygonScad([[0, 0], [10, 0], [5, 10]]);
expect(code).toContain('polygon');
expect(code).toContain('[0, 0]');
});
});