fix: tests

This commit is contained in:
Stan
2026-03-29 17:28:51 +01:00
parent da207ed3f7
commit 18f2ebd040
6 changed files with 145 additions and 291 deletions

View File

@@ -272,11 +272,11 @@ describe('useHistory', () => {
const useModelStore = require('../../stores/modelStore').useModelStore;
const useSceneStore = require('../../stores/sceneStore').useSceneStore;
useModelStore.mockImplementation((selector) => {
useModelStore.mockImplementation((selector: (state: { actions: undefined }) => unknown) => {
const state = { actions: undefined };
return selector ? selector(state) : state;
});
useSceneStore.mockImplementation((selector) => {
useSceneStore.mockImplementation((selector: (state: { actions: undefined }) => unknown) => {
const state = { actions: undefined };
return selector ? selector(state) : state;
});
@@ -297,11 +297,11 @@ describe('useHistory', () => {
});
// Restore mocks for other tests
useModelStore.mockImplementation((selector) => {
useModelStore.mockImplementation((selector: (state: { actions: typeof mockModelStore }) => unknown) => {
const state = { actions: mockModelStore };
return selector ? selector(state) : state;
});
useSceneStore.mockImplementation((selector) => {
useSceneStore.mockImplementation((selector: (state: { actions: typeof mockSceneStore }) => unknown) => {
const state = { actions: mockSceneStore };
return selector ? selector(state) : state;
});

View File

@@ -107,22 +107,22 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'item1' }, face: 'right' },
{ id: 'anchor2', ref: { item: 'item2' }, face: 'left' }
{ id: 'anchor1', ref: { item: 'item1' } },
{ id: 'anchor2', ref: { item: 'item2' } }
]
},
{
id: 'connector2',
anchors: [
{ id: 'anchor3', ref: { item: 'item1' }, face: 'top' },
{ id: 'anchor4', ref: { item: 'nonexistent' }, face: 'bottom' } // Invalid reference
{ id: 'anchor3', ref: { item: 'item1' } },
{ id: 'anchor4', ref: { item: 'nonexistent' } } // Invalid reference
]
},
{
id: 'connector3',
anchors: [
{ id: 'anchor5', ref: { item: 'nonexistent1' }, face: 'right' }, // Invalid reference
{ id: 'anchor6', ref: { item: 'nonexistent2' }, face: 'left' } // Invalid reference
{ id: 'anchor5', ref: { item: 'nonexistent1' } }, // Invalid reference
{ id: 'anchor6', ref: { item: 'nonexistent2' } } // Invalid reference
]
}
],
@@ -167,8 +167,8 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'item1' }, face: 'right' },
{ id: 'anchor2', ref: { anchor: 'anchor3' }, face: 'left' } // References another anchor
{ id: 'anchor1', ref: { item: 'item1' } },
{ id: 'anchor2', ref: { anchor: 'anchor3' } } // References another anchor
]
}
],
@@ -237,15 +237,15 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'nonexistent1' }, face: 'right' },
{ id: 'anchor2', ref: { item: 'nonexistent2' }, face: 'left' }
{ id: 'anchor1', ref: { item: 'nonexistent1' } },
{ id: 'anchor2', ref: { item: 'nonexistent2' } }
]
},
{
id: 'connector2',
anchors: [
{ id: 'anchor3', ref: { item: 'deleted1' }, face: 'top' },
{ id: 'anchor4', ref: { item: 'deleted2' }, face: 'bottom' }
{ id: 'anchor3', ref: { item: 'deleted1' } },
{ id: 'anchor4', ref: { item: 'deleted2' } }
]
}
],
@@ -287,9 +287,9 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'item1' }, face: 'right' }, // Valid
{ id: 'anchor2', ref: { item: 'item2' }, face: 'left' }, // Valid
{ id: 'anchor3', ref: { item: 'nonexistent' }, face: 'top' } // Invalid
{ id: 'anchor1', ref: { item: 'item1' } }, // Valid
{ id: 'anchor2', ref: { item: 'item2' } }, // Valid
{ id: 'anchor3', ref: { item: 'nonexistent' } } // Invalid
]
}
],
@@ -328,8 +328,8 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'nonexistent' }, face: 'right' },
{ id: 'anchor2', ref: { item: 'item1' }, face: 'left' }
{ id: 'anchor1', ref: { item: 'nonexistent' } },
{ id: 'anchor2', ref: { item: 'item1' } }
]
}
],
@@ -401,15 +401,15 @@ describe('useInitialDataManager - Orphaned Connector Handling', () => {
{
id: 'connector1',
anchors: [
{ id: 'anchor1', ref: { item: 'item1' }, face: 'right' },
{ id: 'anchor2', ref: { item: 'item2' }, face: 'left' }
{ id: 'anchor1', ref: { item: 'item1' } },
{ id: 'anchor2', ref: { item: 'item2' } }
]
},
{
id: 'connector2',
anchors: [
{ id: 'anchor3', ref: { item: 'item2' }, face: 'right' },
{ id: 'anchor4', ref: { item: 'item3' }, face: 'left' }
{ id: 'anchor3', ref: { item: 'item2' } },
{ id: 'anchor4', ref: { item: 'item3' } }
]
}
],

View File

@@ -21,8 +21,8 @@ jest.mock('src/utils', () => ({
getConnectorPath: jest.fn(({ anchors }) => ({
tiles: [{ x: 0, y: 0 }, { x: 1, y: 1 }],
rectangle: {
from: { x: anchors.from.x || 0, y: anchors.from.y || 0 },
to: { x: anchors.to.x || 1, y: anchors.to.y || 1 }
from: { x: 0, y: 0 },
to: { x: 1, y: 1 }
}
}))
}));
@@ -38,12 +38,12 @@ describe('connector reducer', () => {
mockConnector = {
id: 'connector1',
anchors: {
from: { id: 'item1', face: 'right', x: 0, y: 0 },
to: { id: 'item2', face: 'left', x: 2, y: 0 }
},
label: 'Test Connection',
lineType: 'solid',
anchors: [
{ id: 'anchor1', ref: { item: 'item1' } },
{ id: 'anchor2', ref: { item: 'item2' } }
],
description: 'Test Connection',
style: 'SOLID',
color: 'color1'
};
@@ -67,9 +67,6 @@ describe('connector reducer', () => {
views: [mockView]
},
scene: {
viewId: 'view1',
viewport: { x: 0, y: 0, zoom: 1 },
grid: { enabled: true, size: 10, style: 'dots' },
connectors: {
'connector1': {
path: {
@@ -78,8 +75,6 @@ describe('connector reducer', () => {
}
}
},
viewItems: {},
rectangles: {},
textBoxes: {}
}
};
@@ -126,10 +121,10 @@ describe('connector reducer', () => {
it('should not affect other connectors when deleting one', () => {
const connector2: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item3', face: 'top' },
to: { id: 'item4', face: 'bottom' }
}
anchors: [
{ id: 'anchor3', ref: { item: 'item3' } },
{ id: 'anchor4', ref: { item: 'item4' } }
]
};
mockState.model.views[0].connectors = [mockConnector, connector2];
@@ -198,10 +193,10 @@ describe('connector reducer', () => {
});
it('should handle connectors with partial anchor data', () => {
mockConnector.anchors = {
from: { id: 'item1', face: 'right' },
to: { id: 'item2', face: 'left' }
};
mockConnector.anchors = [
{ id: 'anchor1', ref: { item: 'item1' } },
{ id: 'anchor2', ref: { item: 'item2' } }
];
const result = syncConnector('connector1', mockContext);
@@ -213,25 +208,25 @@ describe('connector reducer', () => {
it('should update connector properties', () => {
const updates = {
id: 'connector1',
label: 'Updated Connection',
description: 'Updated Connection',
color: 'color2',
lineType: 'dashed' as const
style: 'DASHED' as const
};
const result = updateConnector(updates, mockContext);
expect(result.model.views[0].connectors![0].label).toBe('Updated Connection');
expect(result.model.views[0].connectors![0].description).toBe('Updated Connection');
expect(result.model.views[0].connectors![0].color).toBe('color2');
expect(result.model.views[0].connectors![0].lineType).toBe('dashed');
expect(result.model.views[0].connectors![0].style).toBe('DASHED');
});
it('should sync connector when anchors are updated', () => {
const updates = {
id: 'connector1',
anchors: {
from: { id: 'item3', face: 'bottom' as const },
to: { id: 'item4', face: 'top' as const }
}
anchors: [
{ id: 'anchor3', ref: { item: 'item3' } },
{ id: 'anchor4', ref: { item: 'item4' } }
]
};
const result = updateConnector(updates, mockContext);
@@ -247,7 +242,7 @@ describe('connector reducer', () => {
const updates = {
id: 'connector1',
label: 'Just a label update'
description: 'Just a description update'
};
updateConnector(updates, mockContext);
@@ -258,14 +253,14 @@ describe('connector reducer', () => {
it('should throw error when connector does not exist', () => {
expect(() => {
updateConnector({ id: 'nonexistent', label: 'test' }, mockContext);
updateConnector({ id: 'nonexistent', description: 'test' }, mockContext);
}).toThrow('Item with id nonexistent not found');
});
it('should handle empty connectors array', () => {
mockState.model.views[0].connectors = undefined;
const result = updateConnector({ id: 'connector1', label: 'test' }, mockContext);
const result = updateConnector({ id: 'connector1', description: 'test' }, mockContext);
// Should return state unchanged when connectors is undefined
expect(result).toEqual(mockState);
@@ -274,7 +269,7 @@ describe('connector reducer', () => {
it('should preserve other connector properties when partially updating', () => {
const updates = {
id: 'connector1',
label: 'Partial Update'
description: 'Partial Update'
};
const result = updateConnector(updates, mockContext);
@@ -282,9 +277,9 @@ describe('connector reducer', () => {
// Original properties should be preserved
expect(result.model.views[0].connectors![0].anchors).toEqual(mockConnector.anchors);
expect(result.model.views[0].connectors![0].color).toBe(mockConnector.color);
expect(result.model.views[0].connectors![0].lineType).toBe(mockConnector.lineType);
expect(result.model.views[0].connectors![0].style).toBe(mockConnector.style);
// Updated property
expect(result.model.views[0].connectors![0].label).toBe('Partial Update');
expect(result.model.views[0].connectors![0].description).toBe('Partial Update');
});
});
@@ -292,11 +287,11 @@ describe('connector reducer', () => {
it('should create a new connector', () => {
const newConnector: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item5', face: 'right' },
to: { id: 'item6', face: 'left' }
},
label: 'New Connection'
anchors: [
{ id: 'anchor5', ref: { item: 'item5' } },
{ id: 'anchor6', ref: { item: 'item6' } }
],
description: 'New Connection'
};
const result = createConnector(newConnector, mockContext);
@@ -316,10 +311,10 @@ describe('connector reducer', () => {
const newConnector: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item5', face: 'right' },
to: { id: 'item6', face: 'left' }
}
anchors: [
{ id: 'anchor5', ref: { item: 'item5' } },
{ id: 'anchor6', ref: { item: 'item6' } }
]
};
const result = createConnector(newConnector, mockContext);
@@ -336,10 +331,10 @@ describe('connector reducer', () => {
const newConnector: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item5', face: 'right' },
to: { id: 'item6', face: 'left' }
}
anchors: [
{ id: 'anchor5', ref: { item: 'item5' } },
{ id: 'anchor6', ref: { item: 'item6' } }
]
};
const result = createConnector(newConnector, mockContext);
@@ -362,10 +357,10 @@ describe('connector reducer', () => {
const newConnector: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item5', face: 'right' },
to: { id: 'item6', face: 'left' }
}
anchors: [
{ id: 'anchor5', ref: { item: 'item5' } },
{ id: 'anchor6', ref: { item: 'item6' } }
]
};
expect(() => {
@@ -376,23 +371,21 @@ describe('connector reducer', () => {
it('should create connector with all optional properties', () => {
const newConnector: Connector = {
id: 'connector2',
anchors: {
from: { id: 'item5', face: 'right' },
to: { id: 'item6', face: 'left' }
},
label: 'Full Connector',
lineType: 'dotted',
color: 'color3',
labels: ['Label1', 'Label2']
anchors: [
{ id: 'anchor5', ref: { item: 'item5' } },
{ id: 'anchor6', ref: { item: 'item6' } }
],
description: 'Full Connector',
style: 'DOTTED',
color: 'color3'
};
const result = createConnector(newConnector, mockContext);
const created = result.model.views[0].connectors![0];
expect(created.label).toBe('Full Connector');
expect(created.lineType).toBe('dotted');
expect(created.description).toBe('Full Connector');
expect(created.style).toBe('DOTTED');
expect(created.color).toBe('color3');
expect(created.labels).toEqual(['Label1', 'Label2']);
});
});
@@ -409,16 +402,16 @@ describe('connector reducer', () => {
// Create
let result = createConnector({
id: 'connector2',
anchors: {
from: { id: 'item3', face: 'top' },
to: { id: 'item4', face: 'bottom' }
}
anchors: [
{ id: 'anchor3', ref: { item: 'item3' } },
{ id: 'anchor4', ref: { item: 'item4' } }
]
}, { ...mockContext, state: mockState });
// Update
result = updateConnector({
id: 'connector2',
label: 'Updated'
description: 'Updated'
}, { ...mockContext, state: result });
// Delete original
@@ -426,16 +419,16 @@ describe('connector reducer', () => {
expect(result.model.views[0].connectors).toHaveLength(1);
expect(result.model.views[0].connectors![0].id).toBe('connector2');
expect(result.model.views[0].connectors![0].label).toBe('Updated');
expect(result.model.views[0].connectors![0].description).toBe('Updated');
});
it('should handle view with multiple connectors', () => {
const connectors: Connector[] = Array.from({ length: 5 }, (_, i) => ({
id: `connector${i}`,
anchors: {
from: { id: `item${i}`, face: 'right' },
to: { id: `item${i + 1}`, face: 'left' }
}
anchors: [
{ id: `anchor${i * 2}`, ref: { item: `item${i}` } },
{ id: `anchor${i * 2 + 1}`, ref: { item: `item${i + 1}` } }
]
}));
mockState.model.views[0].connectors = connectors;

View File

@@ -30,14 +30,9 @@ describe('rectangle reducer', () => {
mockRectangle = {
id: 'rect1',
position: { x: 0, y: 0 },
size: { width: 100, height: 50 },
color: 'color1',
borderColor: 'color2',
borderWidth: 2,
borderStyle: 'solid',
opacity: 1,
cornerRadius: 5
from: { x: 0, y: 0 },
to: { x: 100, y: 50 },
color: 'color1'
};
mockView = {
@@ -60,11 +55,7 @@ describe('rectangle reducer', () => {
views: [mockView]
},
scene: {
viewId: 'view1',
viewport: { x: 0, y: 0, zoom: 1 },
grid: { enabled: true, size: 10, style: 'dots' },
connectors: {},
viewItems: {},
textBoxes: {}
}
};
@@ -79,16 +70,14 @@ describe('rectangle reducer', () => {
it('should update rectangle properties', () => {
const updates = {
id: 'rect1',
size: { width: 200, height: 100 },
color: 'color3',
opacity: 0.5
to: { x: 200, y: 100 },
color: 'color3'
};
const result = updateRectangle(updates, mockContext);
expect(result.model.views[0].rectangles![0].size).toEqual({ width: 200, height: 100 });
expect(result.model.views[0].rectangles![0].to).toEqual({ x: 200, y: 100 });
expect(result.model.views[0].rectangles![0].color).toBe('color3');
expect(result.model.views[0].rectangles![0].opacity).toBe(0.5);
});
it('should preserve other properties when partially updating', () => {
@@ -100,10 +89,8 @@ describe('rectangle reducer', () => {
const result = updateRectangle(updates, mockContext);
// Original properties should be preserved
expect(result.model.views[0].rectangles![0].position).toEqual(mockRectangle.position);
expect(result.model.views[0].rectangles![0].size).toEqual(mockRectangle.size);
expect(result.model.views[0].rectangles![0].borderColor).toBe(mockRectangle.borderColor);
expect(result.model.views[0].rectangles![0].cornerRadius).toBe(mockRectangle.cornerRadius);
expect(result.model.views[0].rectangles![0].from).toEqual(mockRectangle.from);
expect(result.model.views[0].rectangles![0].to).toEqual(mockRectangle.to);
// Updated property
expect(result.model.views[0].rectangles![0].color).toBe('color4');
});
@@ -130,29 +117,14 @@ describe('rectangle reducer', () => {
updateRectangle({ id: 'rect1', color: 'test' }, mockContext);
}).toThrow('Item with id nonexistent not found');
});
it('should update border properties', () => {
const updates = {
id: 'rect1',
borderColor: 'color5',
borderWidth: 4,
borderStyle: 'dashed' as const
};
const result = updateRectangle(updates, mockContext);
expect(result.model.views[0].rectangles![0].borderColor).toBe('color5');
expect(result.model.views[0].rectangles![0].borderWidth).toBe(4);
expect(result.model.views[0].rectangles![0].borderStyle).toBe('dashed');
});
});
describe('createRectangle', () => {
it('should create a new rectangle', () => {
const newRectangle: Rectangle = {
id: 'rect2',
position: { x: 50, y: 50 },
size: { width: 150, height: 75 },
from: { x: 50, y: 50 },
to: { x: 200, y: 125 },
color: 'color3'
};
@@ -169,8 +141,8 @@ describe('rectangle reducer', () => {
const newRectangle: Rectangle = {
id: 'rect2',
position: { x: 50, y: 50 },
size: { width: 150, height: 75 }
from: { x: 50, y: 50 },
to: { x: 200, y: 125 }
};
const result = createRectangle(newRectangle, mockContext);
@@ -182,37 +154,17 @@ describe('rectangle reducer', () => {
it('should create rectangle with all properties', () => {
const newRectangle: Rectangle = {
id: 'rect2',
position: { x: 50, y: 50 },
size: { width: 150, height: 75 },
from: { x: 50, y: 50 },
to: { x: 200, y: 125 },
color: 'color6',
borderColor: 'color7',
borderWidth: 3,
borderStyle: 'dotted',
opacity: 0.8,
cornerRadius: 10,
shadow: {
offsetX: 2,
offsetY: 2,
blur: 4,
color: 'color8'
}
customColor: '#FF5733'
};
const result = createRectangle(newRectangle, mockContext);
const created = result.model.views[0].rectangles![0];
expect(created.color).toBe('color6');
expect(created.borderColor).toBe('color7');
expect(created.borderWidth).toBe(3);
expect(created.borderStyle).toBe('dotted');
expect(created.opacity).toBe(0.8);
expect(created.cornerRadius).toBe(10);
expect(created.shadow).toEqual({
offsetX: 2,
offsetY: 2,
blur: 4,
color: 'color8'
});
expect(created.customColor).toBe('#FF5733');
});
it('should throw error when view does not exist', () => {
@@ -220,8 +172,8 @@ describe('rectangle reducer', () => {
const newRectangle: Rectangle = {
id: 'rect2',
position: { x: 50, y: 50 },
size: { width: 150, height: 75 }
from: { x: 50, y: 50 },
to: { x: 200, y: 125 }
};
expect(() => {
@@ -234,8 +186,8 @@ describe('rectangle reducer', () => {
// which ensures any necessary syncing happens
const newRectangle: Rectangle = {
id: 'rect2',
position: { x: 50, y: 50 },
size: { width: 150, height: 75 }
from: { x: 50, y: 50 },
to: { x: 200, y: 125 }
};
const result = createRectangle(newRectangle, mockContext);
@@ -280,8 +232,8 @@ describe('rectangle reducer', () => {
it('should not affect other rectangles when deleting one', () => {
const rect2: Rectangle = {
id: 'rect2',
position: { x: 100, y: 100 },
size: { width: 80, height: 40 }
from: { x: 100, y: 100 },
to: { x: 180, y: 140 }
};
mockState.model.views[0].rectangles = [mockRectangle, rect2];
@@ -308,15 +260,14 @@ describe('rectangle reducer', () => {
// Create
let result = createRectangle({
id: 'rect2',
position: { x: 200, y: 200 },
size: { width: 50, height: 50 }
from: { x: 200, y: 200 },
to: { x: 250, y: 250 }
}, { ...mockContext, state: mockState });
// Update
result = updateRectangle({
id: 'rect2',
color: 'updatedColor',
opacity: 0.7
color: 'updatedColor'
}, { ...mockContext, state: result });
// Delete original
@@ -325,14 +276,13 @@ describe('rectangle reducer', () => {
expect(result.model.views[0].rectangles).toHaveLength(1);
expect(result.model.views[0].rectangles![0].id).toBe('rect2');
expect(result.model.views[0].rectangles![0].color).toBe('updatedColor');
expect(result.model.views[0].rectangles![0].opacity).toBe(0.7);
});
it('should handle view with multiple rectangles', () => {
const rectangles: Rectangle[] = Array.from({ length: 5 }, (_, i) => ({
id: `rect${i}`,
position: { x: i * 20, y: i * 20 },
size: { width: 100, height: 50 }
from: { x: i * 20, y: i * 20 },
to: { x: i * 20 + 100, y: i * 20 + 50 }
}));
mockState.model.views[0].rectangles = rectangles;
@@ -342,33 +292,5 @@ describe('rectangle reducer', () => {
expect(result.model.views[0].rectangles).toHaveLength(4);
expect(result.model.views[0].rectangles!.find(r => r.id === 'rect2')).toBeUndefined();
});
it('should handle rectangles with complex nested properties', () => {
const complexRect: Rectangle = {
id: 'rect2',
position: { x: 0, y: 0 },
size: { width: 100, height: 100 },
shadow: {
offsetX: 5,
offsetY: 5,
blur: 10,
color: 'shadowColor'
},
gradient: {
type: 'linear',
angle: 45,
stops: [
{ offset: 0, color: 'color1' },
{ offset: 1, color: 'color2' }
]
}
};
const result = createRectangle(complexRect, mockContext);
const created = result.model.views[0].rectangles![0];
expect(created.shadow).toEqual(complexRect.shadow);
expect(created.gradient).toEqual(complexRect.gradient);
});
});
});

View File

@@ -35,13 +35,9 @@ describe('textBox reducer', () => {
mockTextBox = {
id: 'textbox1',
position: { x: 10, y: 20 },
tile: { x: 10, y: 20 },
content: 'Test Content',
fontSize: 14,
color: 'color1',
backgroundColor: 'color2',
borderColor: 'color3',
alignment: 'left'
fontSize: 14
};
mockView = {
@@ -64,12 +60,7 @@ describe('textBox reducer', () => {
views: [mockView]
},
scene: {
viewId: 'view1',
viewport: { x: 0, y: 0, zoom: 1 },
grid: { enabled: true, size: 10, style: 'dots' },
connectors: {},
viewItems: {},
rectangles: {},
textBoxes: {
'textbox1': {
size: { width: 120, height: 14 }
@@ -128,15 +119,13 @@ describe('textBox reducer', () => {
const updates = {
id: 'textbox1',
content: 'Updated Content',
fontSize: 18,
color: 'color4'
fontSize: 18
};
const result = updateTextBox(updates, mockContext);
expect(result.model.views[0].textBoxes![0].content).toBe('Updated Content');
expect(result.model.views[0].textBoxes![0].fontSize).toBe(18);
expect(result.model.views[0].textBoxes![0].color).toBe('color4');
});
it('should sync when content is updated', () => {
@@ -169,22 +158,6 @@ describe('textBox reducer', () => {
expect(getTextBoxDimensions).toHaveBeenCalled();
});
it('should not sync when other properties are updated', () => {
const getTextBoxDimensions = require('src/utils').getTextBoxDimensions;
getTextBoxDimensions.mockClear();
const updates = {
id: 'textbox1',
color: 'color5',
backgroundColor: 'color6'
};
updateTextBox(updates, mockContext);
// Should NOT trigger sync for non-size-affecting properties
expect(getTextBoxDimensions).not.toHaveBeenCalled();
});
it('should handle undefined textBoxes array', () => {
mockState.model.views[0].textBoxes = undefined;
@@ -204,8 +177,7 @@ describe('textBox reducer', () => {
// Original properties should be preserved
expect(result.model.views[0].textBoxes![0].fontSize).toBe(mockTextBox.fontSize);
expect(result.model.views[0].textBoxes![0].color).toBe(mockTextBox.color);
expect(result.model.views[0].textBoxes![0].position).toEqual(mockTextBox.position);
expect(result.model.views[0].textBoxes![0].tile).toEqual(mockTextBox.tile);
// Updated property
expect(result.model.views[0].textBoxes![0].content).toBe('Partial Update');
});
@@ -221,7 +193,7 @@ describe('textBox reducer', () => {
it('should create a new text box', () => {
const newTextBox: TextBox = {
id: 'textbox2',
position: { x: 30, y: 40 },
tile: { x: 30, y: 40 },
content: 'New Text Box',
fontSize: 16
};
@@ -243,7 +215,7 @@ describe('textBox reducer', () => {
const newTextBox: TextBox = {
id: 'textbox2',
position: { x: 30, y: 40 },
tile: { x: 30, y: 40 },
content: 'New Text Box'
};
@@ -256,15 +228,9 @@ describe('textBox reducer', () => {
it('should create text box with all properties', () => {
const newTextBox: TextBox = {
id: 'textbox2',
position: { x: 30, y: 40 },
tile: { x: 30, y: 40 },
content: 'Full Text Box',
fontSize: 20,
color: 'color7',
backgroundColor: 'color8',
borderColor: 'color9',
alignment: 'center',
bold: true,
italic: true
fontSize: 20
};
const result = createTextBox(newTextBox, mockContext);
@@ -272,12 +238,6 @@ describe('textBox reducer', () => {
const created = result.model.views[0].textBoxes![0];
expect(created.content).toBe('Full Text Box');
expect(created.fontSize).toBe(20);
expect(created.color).toBe('color7');
expect(created.backgroundColor).toBe('color8');
expect(created.borderColor).toBe('color9');
expect(created.alignment).toBe('center');
expect(created.bold).toBe(true);
expect(created.italic).toBe(true);
});
it('should throw error when view does not exist', () => {
@@ -285,7 +245,7 @@ describe('textBox reducer', () => {
const newTextBox: TextBox = {
id: 'textbox2',
position: { x: 30, y: 40 },
tile: { x: 30, y: 40 },
content: 'New Text Box'
};
@@ -331,7 +291,7 @@ describe('textBox reducer', () => {
it('should not affect other text boxes when deleting one', () => {
const textBox2: TextBox = {
id: 'textbox2',
position: { x: 50, y: 60 },
tile: { x: 50, y: 60 },
content: 'Second Text Box'
};
@@ -364,7 +324,7 @@ describe('textBox reducer', () => {
// Create
let result = createTextBox({
id: 'textbox2',
position: { x: 100, y: 100 },
tile: { x: 100, y: 100 },
content: 'New Box'
}, { ...mockContext, state: mockState });
@@ -387,7 +347,7 @@ describe('textBox reducer', () => {
it('should handle view with multiple text boxes', () => {
const textBoxes: TextBox[] = Array.from({ length: 5 }, (_, i) => ({
id: `textbox${i}`,
position: { x: i * 10, y: i * 10 },
tile: { x: i * 10, y: i * 10 },
content: `Text ${i}`
}));

View File

@@ -46,8 +46,7 @@ describe('viewItem reducer', () => {
mockViewItem = {
id: 'item1',
tile: { x: 0, y: 0 },
size: { width: 100, height: 100 }
tile: { x: 0, y: 0 }
};
mockConnector = {
@@ -55,15 +54,11 @@ describe('viewItem reducer', () => {
anchors: [
{
id: 'anchor1',
ref: { item: 'item1' },
face: 'right',
offset: 0
ref: { item: 'item1' }
},
{
id: 'anchor2',
ref: { item: 'item2' },
face: 'left',
offset: 0
ref: { item: 'item2' }
}
]
};
@@ -88,9 +83,6 @@ describe('viewItem reducer', () => {
views: [mockView]
},
scene: {
viewId: 'view1',
viewport: { x: 0, y: 0, zoom: 1 },
grid: { enabled: true, size: 10, style: 'dots' },
connectors: {
'connector1': {
path: {
@@ -99,8 +91,6 @@ describe('viewItem reducer', () => {
}
}
},
viewItems: {},
rectangles: {},
textBoxes: {}
}
};
@@ -130,13 +120,11 @@ describe('viewItem reducer', () => {
anchors: [
{
id: 'anchor3',
ref: { item: 'item2' },
face: 'top'
ref: { item: 'item2' }
},
{
id: 'anchor4',
ref: { item: 'item3' },
face: 'bottom'
ref: { item: 'item3' }
}
]
};
@@ -162,13 +150,11 @@ describe('viewItem reducer', () => {
anchors: [
{
id: 'anchor3',
ref: { item: 'item2' },
face: 'top'
ref: { item: 'item2' }
},
{
id: 'anchor4',
ref: { item: 'item3' },
face: 'bottom'
ref: { item: 'item3' }
}
]
}];
@@ -208,18 +194,15 @@ describe('viewItem reducer', () => {
anchors: [
{
id: 'anchor5',
ref: { item: 'item1' },
face: 'top'
ref: { item: 'item1' }
},
{
id: 'anchor6',
ref: { item: 'item1' },
face: 'bottom'
ref: { item: 'item1' }
},
{
id: 'anchor7',
ref: { item: 'item2' },
face: 'left'
ref: { item: 'item2' }
}
]
};
@@ -237,15 +220,13 @@ describe('viewItem reducer', () => {
it('should update view item properties', () => {
const updates = {
id: 'item1',
tile: { x: 2, y: 2 },
size: { width: 200, height: 200 }
tile: { x: 2, y: 2 }
};
const result = updateViewItem(updates, mockContext);
const updatedItem = result.model.views[0].items.find(item => item.id === 'item1');
expect(updatedItem?.tile).toEqual({ x: 2, y: 2 });
expect(updatedItem?.size).toEqual({ width: 200, height: 200 });
});
it('should update connectors when item tile position changes', () => {
@@ -280,8 +261,7 @@ describe('viewItem reducer', () => {
view.mockClear();
const updates = {
id: 'item1',
size: { width: 150, height: 150 }
id: 'item1'
};
updateViewItem(updates, mockContext);
@@ -301,8 +281,7 @@ describe('viewItem reducer', () => {
it('should create a new view item', () => {
const newItem: ViewItem = {
id: 'item3',
tile: { x: 3, y: 3 },
size: { width: 100, height: 100 }
tile: { x: 3, y: 3 }
};
const result = createViewItem(newItem, mockContext);
@@ -359,14 +338,14 @@ describe('viewItem reducer', () => {
// Update
result = updateViewItem({
id: 'item3',
size: { width: 150, height: 150 }
tile: { x: 5, y: 5 }
}, { ...mockContext, state: result });
// Delete original
result = deleteViewItem('item1', { ...mockContext, state: result });
expect(result.model.views[0].items.find(item => item.id === 'item3')).toBeDefined();
expect(result.model.views[0].items.find(item => item.id === 'item3')?.size).toEqual({ width: 150, height: 150 });
expect(result.model.views[0].items.find(item => item.id === 'item3')?.tile).toEqual({ x: 5, y: 5 });
expect(result.model.views[0].items.find(item => item.id === 'item1')).toBeUndefined();
// Connector referencing item1 should be removed