mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2026-04-24 00:53:44 -04:00
fix: tests
This commit is contained in:
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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' } }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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}`
|
||||
}));
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user