import { describe, it, expect } from 'vitest' import { isPlainObject, defaultStructure, cloneStructure, computeStructureStats, formatStructurePreview, } from '~/shared/model/componentStructure' import { defaultPieceStructure, defaultProductStructure, clonePieceStructure, cloneProductStructure, } from '~/shared/model/pieceProductStructure' describe('isPlainObject', () => { it('returns true for plain objects', () => { expect(isPlainObject({})).toBe(true) expect(isPlainObject({ key: 'value' })).toBe(true) }) it('returns false for arrays', () => { expect(isPlainObject([])).toBe(false) }) it('returns false for null', () => { expect(isPlainObject(null)).toBe(false) }) it('returns false for primitives', () => { expect(isPlainObject('string')).toBe(false) expect(isPlainObject(42)).toBe(false) expect(isPlainObject(undefined)).toBe(false) }) }) describe('defaultStructure', () => { it('returns a fresh empty structure each time', () => { const a = defaultStructure() const b = defaultStructure() expect(a).toEqual(b) expect(a).not.toBe(b) expect(a.customFields).toEqual([]) expect(a.pieces).toEqual([]) expect(a.products).toEqual([]) expect(a.subcomponents).toEqual([]) }) }) describe('cloneStructure', () => { it('deep clones a structure', () => { const original = defaultStructure() original.customFields.push({ name: 'test', type: 'text', required: false }) const cloned = cloneStructure(original) expect(cloned.customFields).toHaveLength(1) expect(cloned.customFields[0].name).toBe('test') // Ensure deep clone — mutating original doesn't affect clone original.customFields[0].name = 'mutated' expect(cloned.customFields[0].name).toBe('test') }) it('returns default structure for null input', () => { const result = cloneStructure(null) expect(result).toEqual(defaultStructure()) }) it('returns default structure for undefined input', () => { const result = cloneStructure(undefined) expect(result).toEqual(defaultStructure()) }) it('preserves typeComposantId and alias', () => { const input = { ...defaultStructure(), typeComposantId: 'abc-123', alias: 'Motor', } const result = cloneStructure(input) expect(result.typeComposantId).toBe('abc-123') expect(result.alias).toBe('Motor') }) }) describe('computeStructureStats', () => { it('counts elements in a structure', () => { const structure = { ...defaultStructure(), customFields: [ { name: 'A', type: 'text' as const, required: false }, { name: 'B', type: 'number' as const, required: true }, ], pieces: [{ typePieceId: 'p1' }], products: [{ typeProductId: 'pr1' }], subcomponents: [{ subcomponents: [] }], } const stats = computeStructureStats(structure) expect(stats.customFields).toBe(2) expect(stats.pieces).toBe(1) expect(stats.products).toBe(1) expect(stats.subcomponents).toBe(1) }) it('returns zeros for empty structure', () => { const stats = computeStructureStats(defaultStructure()) expect(stats).toEqual({ customFields: 0, pieces: 0, products: 0, subcomponents: 0, }) }) }) describe('formatStructurePreview', () => { it('returns "Structure vide" for empty structure', () => { const result = formatStructurePreview(defaultStructure()) expect(result).toBe('Structure vide') }) it('formats a non-empty structure', () => { const structure = { ...defaultStructure(), customFields: [{ name: 'A', type: 'text' as const, required: false }], pieces: [{ typePieceId: 'p1' }, { typePieceId: 'p2' }], } const result = formatStructurePreview(structure) expect(result).toContain('1 champ') expect(result).toContain('2 pièce') }) }) describe('defaultPieceStructure', () => { it('returns a valid empty piece structure', () => { const result = defaultPieceStructure() expect(result.customFields).toEqual([]) expect(result.products).toEqual([]) }) }) describe('defaultProductStructure', () => { it('returns a valid empty product structure', () => { const result = defaultProductStructure() expect(result.customFields).toEqual([]) }) }) describe('clonePieceStructure', () => { it('deep clones a piece structure', () => { const original = defaultPieceStructure() original.customFields.push({ name: 'Weight', type: 'number', required: true }) const cloned = clonePieceStructure(original) expect(cloned.customFields).toHaveLength(1) original.customFields[0].name = 'mutated' expect(cloned.customFields[0].name).toBe('Weight') }) it('returns default for null', () => { expect(clonePieceStructure(null)).toEqual(defaultPieceStructure()) }) }) describe('cloneProductStructure', () => { it('deep clones a product structure', () => { const original = defaultProductStructure() original.customFields.push({ name: 'Color', type: 'text', required: false }) const cloned = cloneProductStructure(original) expect(cloned.customFields).toHaveLength(1) }) })