@dragonworks/ngx-dashboard 20.0.5 → 20.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ng-package.json +7 -0
- package/package.json +34 -45
- package/src/lib/__tests__/dashboard-component-widget-state-integration.spec.ts +537 -0
- package/src/lib/cell/__tests__/cell-resize.component.spec.ts +442 -0
- package/src/lib/cell/__tests__/cell.component.spec.ts +541 -0
- package/src/lib/cell/cell-context-menu.component.ts +138 -0
- package/src/lib/cell/cell-context-menu.service.ts +36 -0
- package/src/lib/cell/cell.component.html +37 -0
- package/src/lib/cell/cell.component.scss +198 -0
- package/src/lib/cell/cell.component.ts +375 -0
- package/src/lib/dashboard/dashboard.component.html +18 -0
- package/src/lib/dashboard/dashboard.component.scss +17 -0
- package/src/lib/dashboard/dashboard.component.ts +187 -0
- package/src/lib/dashboard-editor/dashboard-editor.component.html +57 -0
- package/src/lib/dashboard-editor/dashboard-editor.component.scss +87 -0
- package/src/lib/dashboard-editor/dashboard-editor.component.ts +219 -0
- package/src/lib/dashboard-viewer/__tests__/dashboard-viewer.component.spec.ts +258 -0
- package/src/lib/dashboard-viewer/dashboard-viewer.component.html +20 -0
- package/src/lib/dashboard-viewer/dashboard-viewer.component.scss +50 -0
- package/src/lib/dashboard-viewer/dashboard-viewer.component.ts +70 -0
- package/src/lib/drop-zone/__tests__/drop-zone.component.spec.ts +465 -0
- package/src/lib/drop-zone/drop-zone.component.html +20 -0
- package/src/lib/drop-zone/drop-zone.component.scss +67 -0
- package/src/lib/drop-zone/drop-zone.component.ts +122 -0
- package/src/lib/internal-widgets/unknown-widget/unknown-widget.component.ts +72 -0
- package/src/lib/models/cell-data.ts +13 -0
- package/src/lib/models/cell-dialog.ts +7 -0
- package/src/lib/models/cell-id.ts +85 -0
- package/src/lib/models/cell-position.ts +15 -0
- package/src/lib/models/dashboard-data.dto.ts +44 -0
- package/src/lib/models/dashboard-data.utils.ts +49 -0
- package/src/lib/models/drag-data.ts +6 -0
- package/src/lib/models/index.ts +11 -0
- package/src/lib/models/reserved-space.ts +24 -0
- package/src/lib/models/widget-factory.ts +33 -0
- package/src/lib/models/widget-id.ts +70 -0
- package/src/lib/models/widget.ts +21 -0
- package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.component.ts +127 -0
- package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.provider.ts +15 -0
- package/src/lib/providers/cell-settings-dialog/cell-settings-dialog.tokens.ts +20 -0
- package/src/lib/providers/cell-settings-dialog/default-cell-settings-dialog.provider.ts +32 -0
- package/src/lib/providers/cell-settings-dialog/index.ts +3 -0
- package/src/lib/providers/index.ts +1 -0
- package/src/lib/services/__tests__/dashboard-bridge.service.spec.ts +220 -0
- package/src/lib/services/__tests__/dashboard-viewport.service.spec.ts +362 -0
- package/src/lib/services/dashboard-bridge.service.ts +155 -0
- package/src/lib/services/dashboard-viewport.service.ts +148 -0
- package/src/lib/services/dashboard.service.ts +62 -0
- package/src/lib/store/__tests__/dashboard-store-collision-detection.spec.ts +756 -0
- package/src/lib/store/__tests__/dashboard-store-computed-properties.spec.ts +974 -0
- package/src/lib/store/__tests__/dashboard-store-drag-drop.spec.ts +279 -0
- package/src/lib/store/__tests__/dashboard-store-export-import.spec.ts +780 -0
- package/src/lib/store/__tests__/dashboard-store-grid-config.spec.ts +128 -0
- package/src/lib/store/__tests__/dashboard-store-query-methods.spec.ts +229 -0
- package/src/lib/store/__tests__/dashboard-store-resize-operations.spec.ts +652 -0
- package/src/lib/store/__tests__/dashboard-store-widget-management.spec.ts +461 -0
- package/src/lib/store/__tests__/dashboard-store-widget-state-preservation.spec.ts +369 -0
- package/src/lib/store/dashboard-store.ts +239 -0
- package/src/lib/store/features/drag-drop.feature.ts +140 -0
- package/src/lib/store/features/grid-config.feature.ts +43 -0
- package/src/lib/store/features/resize.feature.ts +140 -0
- package/src/lib/store/features/utils/collision.utils.ts +89 -0
- package/src/lib/store/features/utils/grid-query-internal.utils.ts +37 -0
- package/src/lib/store/features/utils/resize.utils.ts +165 -0
- package/src/lib/store/features/widget-management.feature.ts +158 -0
- package/src/lib/styles/_dashboard-grid-vars.scss +11 -0
- package/src/lib/widget-list/__tests__/widget-list-bridge-integration.spec.ts +137 -0
- package/src/lib/widget-list/widget-list.component.html +22 -0
- package/src/lib/widget-list/widget-list.component.scss +154 -0
- package/src/lib/widget-list/widget-list.component.ts +106 -0
- package/src/public-api.ts +21 -0
- package/src/test-setup.ts +10 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +14 -0
- package/fesm2022/dragonworks-ngx-dashboard.mjs +0 -2178
- package/fesm2022/dragonworks-ngx-dashboard.mjs.map +0 -1
- package/index.d.ts +0 -678
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { ViewContainerRef, ElementRef, Renderer2 } from '@angular/core';
|
|
3
|
+
import { CellComponent } from '../cell.component';
|
|
4
|
+
import { DashboardStore } from '../../store/dashboard-store';
|
|
5
|
+
import { DashboardService } from '../../services/dashboard.service';
|
|
6
|
+
import { CellContextMenuService } from '../cell-context-menu.service';
|
|
7
|
+
import { CELL_SETTINGS_DIALOG_PROVIDER } from '../../providers/cell-settings-dialog';
|
|
8
|
+
import { CellId, CellIdUtils, WidgetId, WidgetIdUtils, WidgetFactory } from '../../models';
|
|
9
|
+
import { Component } from '@angular/core';
|
|
10
|
+
|
|
11
|
+
// Mock test widget component
|
|
12
|
+
@Component({
|
|
13
|
+
selector: 'lib-test-widget',
|
|
14
|
+
template: '<div>Test Widget</div>',
|
|
15
|
+
standalone: true,
|
|
16
|
+
})
|
|
17
|
+
class TestWidgetComponent {
|
|
18
|
+
dashboardGetState() {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
dashboardSetState(state: any) {}
|
|
22
|
+
dashboardEditState() {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('CellComponent - Resize Functionality', () => {
|
|
26
|
+
let component: CellComponent;
|
|
27
|
+
let fixture: ComponentFixture<CellComponent>;
|
|
28
|
+
let store: InstanceType<typeof DashboardStore>;
|
|
29
|
+
let realRenderer: Renderer2;
|
|
30
|
+
let mockDashboardService: jasmine.SpyObj<DashboardService>;
|
|
31
|
+
let mockContextMenuService: jasmine.SpyObj<CellContextMenuService>;
|
|
32
|
+
let mockDialogProvider: jasmine.SpyObj<any>;
|
|
33
|
+
|
|
34
|
+
const mockCellId: CellId = CellIdUtils.create(1, 1);
|
|
35
|
+
const mockWidgetId: WidgetId = WidgetIdUtils.generate();
|
|
36
|
+
const otherCellId: CellId = CellIdUtils.create(2, 2);
|
|
37
|
+
|
|
38
|
+
const mockWidgetFactory: WidgetFactory = {
|
|
39
|
+
widgetTypeid: 'test-widget',
|
|
40
|
+
name: 'Test Widget',
|
|
41
|
+
description: 'A test widget',
|
|
42
|
+
svgIcon: '<svg><rect width="10" height="10"/></svg>',
|
|
43
|
+
createInstance: jasmine
|
|
44
|
+
.createSpy('createInstance')
|
|
45
|
+
.and.callFake((container: ViewContainerRef, state?: unknown) => {
|
|
46
|
+
const componentRef = container.createComponent(TestWidgetComponent);
|
|
47
|
+
return componentRef;
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
beforeEach(async () => {
|
|
52
|
+
mockDashboardService = jasmine.createSpyObj('DashboardService', [
|
|
53
|
+
'getFactory',
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
mockContextMenuService = jasmine.createSpyObj('CellContextMenuService', [
|
|
57
|
+
'show',
|
|
58
|
+
'hide',
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
mockDialogProvider = jasmine.createSpyObj('CellSettingsDialogProvider', [
|
|
62
|
+
'openCellSettings',
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
await TestBed.configureTestingModule({
|
|
66
|
+
imports: [CellComponent, TestWidgetComponent],
|
|
67
|
+
providers: [
|
|
68
|
+
DashboardStore,
|
|
69
|
+
{ provide: DashboardService, useValue: mockDashboardService },
|
|
70
|
+
{ provide: CellContextMenuService, useValue: mockContextMenuService },
|
|
71
|
+
{
|
|
72
|
+
provide: CELL_SETTINGS_DIALOG_PROVIDER,
|
|
73
|
+
useValue: mockDialogProvider,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
}).compileComponents();
|
|
77
|
+
|
|
78
|
+
store = TestBed.inject(DashboardStore);
|
|
79
|
+
fixture = TestBed.createComponent(CellComponent);
|
|
80
|
+
component = fixture.componentInstance;
|
|
81
|
+
|
|
82
|
+
mockDashboardService.getFactory.and.returnValue(mockWidgetFactory);
|
|
83
|
+
|
|
84
|
+
// Setup component inputs
|
|
85
|
+
fixture.componentRef.setInput('widgetId', mockWidgetId);
|
|
86
|
+
fixture.componentRef.setInput('cellId', mockCellId);
|
|
87
|
+
fixture.componentRef.setInput('row', 2);
|
|
88
|
+
fixture.componentRef.setInput('column', 3);
|
|
89
|
+
fixture.detectChanges();
|
|
90
|
+
|
|
91
|
+
// Get the real renderer from the component's injector
|
|
92
|
+
realRenderer = fixture.debugElement.injector.get(Renderer2);
|
|
93
|
+
spyOn(realRenderer, 'listen').and.returnValue(() => {});
|
|
94
|
+
spyOn(realRenderer, 'addClass').and.callThrough();
|
|
95
|
+
spyOn(realRenderer, 'removeClass').and.callThrough();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('Resize Start - Public API Behavior', () => {
|
|
99
|
+
let mockMouseEvent: any;
|
|
100
|
+
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
mockMouseEvent = {
|
|
103
|
+
clientX: 150,
|
|
104
|
+
clientY: 200,
|
|
105
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
106
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
107
|
+
} as Partial<MouseEvent>;
|
|
108
|
+
|
|
109
|
+
store.setGridCellDimensions(100, 80);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should emit resize start event with correct data', () => {
|
|
113
|
+
spyOn(component.resizeStart, 'emit');
|
|
114
|
+
|
|
115
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
116
|
+
|
|
117
|
+
expect(component.resizeStart.emit).toHaveBeenCalledWith({
|
|
118
|
+
cellId: mockCellId,
|
|
119
|
+
direction: 'horizontal',
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should emit resize start event for vertical direction', () => {
|
|
124
|
+
spyOn(component.resizeStart, 'emit');
|
|
125
|
+
|
|
126
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'vertical');
|
|
127
|
+
|
|
128
|
+
expect(component.resizeStart.emit).toHaveBeenCalledWith({
|
|
129
|
+
cellId: mockCellId,
|
|
130
|
+
direction: 'vertical',
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should prevent default event behavior', () => {
|
|
135
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
136
|
+
|
|
137
|
+
expect(mockMouseEvent.preventDefault).toHaveBeenCalled();
|
|
138
|
+
expect(mockMouseEvent.stopPropagation).toHaveBeenCalled();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should add horizontal cursor class', () => {
|
|
142
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
143
|
+
|
|
144
|
+
expect(realRenderer.addClass).toHaveBeenCalledWith(
|
|
145
|
+
document.body,
|
|
146
|
+
'cursor-col-resize'
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should add vertical cursor class', () => {
|
|
151
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'vertical');
|
|
152
|
+
|
|
153
|
+
expect(realRenderer.addClass).toHaveBeenCalledWith(
|
|
154
|
+
document.body,
|
|
155
|
+
'cursor-row-resize'
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should setup document event listeners', () => {
|
|
160
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
161
|
+
|
|
162
|
+
expect(realRenderer.listen).toHaveBeenCalledWith(
|
|
163
|
+
'document',
|
|
164
|
+
'mousemove',
|
|
165
|
+
jasmine.any(Function)
|
|
166
|
+
);
|
|
167
|
+
expect(realRenderer.listen).toHaveBeenCalledWith(
|
|
168
|
+
'document',
|
|
169
|
+
'mouseup',
|
|
170
|
+
jasmine.any(Function)
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('Resize Move - Public API Behavior', () => {
|
|
176
|
+
beforeEach(() => {
|
|
177
|
+
store.setGridCellDimensions(100, 80);
|
|
178
|
+
|
|
179
|
+
// Setup initial resize state
|
|
180
|
+
const startEvent = {
|
|
181
|
+
clientX: 150,
|
|
182
|
+
clientY: 200,
|
|
183
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
184
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
185
|
+
} as Partial<MouseEvent>;
|
|
186
|
+
|
|
187
|
+
component.onResizeStart(startEvent as MouseEvent, 'horizontal');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should emit resize move event with correct horizontal delta', () => {
|
|
191
|
+
spyOn(component.resizeMove, 'emit');
|
|
192
|
+
|
|
193
|
+
// Simulate mouse move 100px right (1 cell width)
|
|
194
|
+
const moveEvent = { clientX: 250, clientY: 200 };
|
|
195
|
+
(component as any).handleResizeMove(moveEvent);
|
|
196
|
+
|
|
197
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
198
|
+
cellId: mockCellId,
|
|
199
|
+
direction: 'horizontal',
|
|
200
|
+
delta: 1,
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should emit resize move event with correct vertical delta', () => {
|
|
205
|
+
// Setup vertical resize
|
|
206
|
+
const startEvent = {
|
|
207
|
+
clientX: 150,
|
|
208
|
+
clientY: 200,
|
|
209
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
210
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
211
|
+
} as Partial<MouseEvent>;
|
|
212
|
+
|
|
213
|
+
component.onResizeStart(startEvent as MouseEvent, 'vertical');
|
|
214
|
+
spyOn(component.resizeMove, 'emit');
|
|
215
|
+
|
|
216
|
+
// Simulate mouse move 160px down (2 cell heights)
|
|
217
|
+
const moveEvent = { clientX: 150, clientY: 360 };
|
|
218
|
+
(component as any).handleResizeMove(moveEvent);
|
|
219
|
+
|
|
220
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
221
|
+
cellId: mockCellId,
|
|
222
|
+
direction: 'vertical',
|
|
223
|
+
delta: 2,
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should handle negative delta correctly', () => {
|
|
228
|
+
spyOn(component.resizeMove, 'emit');
|
|
229
|
+
|
|
230
|
+
// Simulate mouse move 100px left (-1 cell width)
|
|
231
|
+
const moveEvent = { clientX: 50, clientY: 200 };
|
|
232
|
+
(component as any).handleResizeMove(moveEvent);
|
|
233
|
+
|
|
234
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
235
|
+
cellId: mockCellId,
|
|
236
|
+
direction: 'horizontal',
|
|
237
|
+
delta: -1,
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('Resize End - Public API Behavior', () => {
|
|
243
|
+
beforeEach(() => {
|
|
244
|
+
const startEvent = {
|
|
245
|
+
clientX: 150,
|
|
246
|
+
clientY: 200,
|
|
247
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
248
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
249
|
+
} as Partial<MouseEvent>;
|
|
250
|
+
|
|
251
|
+
component.onResizeStart(startEvent as MouseEvent, 'horizontal');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should emit resize end event', () => {
|
|
255
|
+
spyOn(component.resizeEnd, 'emit');
|
|
256
|
+
|
|
257
|
+
(component as any).handleResizeEnd();
|
|
258
|
+
|
|
259
|
+
expect(component.resizeEnd.emit).toHaveBeenCalledWith({
|
|
260
|
+
cellId: mockCellId,
|
|
261
|
+
apply: true,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should remove cursor classes', () => {
|
|
266
|
+
(component as any).handleResizeEnd();
|
|
267
|
+
|
|
268
|
+
expect(realRenderer.removeClass).toHaveBeenCalledWith(
|
|
269
|
+
document.body,
|
|
270
|
+
'cursor-col-resize'
|
|
271
|
+
);
|
|
272
|
+
expect(realRenderer.removeClass).toHaveBeenCalledWith(
|
|
273
|
+
document.body,
|
|
274
|
+
'cursor-row-resize'
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe('Store Integration - Public Behavior', () => {
|
|
280
|
+
beforeEach(() => {
|
|
281
|
+
store.setGridCellDimensions(100, 80);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('should access grid cell dimensions from store', () => {
|
|
285
|
+
expect(component.gridCellDimensions).toBeDefined();
|
|
286
|
+
expect(typeof component.gridCellDimensions).toBe('function');
|
|
287
|
+
|
|
288
|
+
const dimensions = component.gridCellDimensions();
|
|
289
|
+
expect(dimensions).toEqual({ width: 100, height: 80 });
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe('Edge Cases - Public Behavior', () => {
|
|
294
|
+
let mockMouseEvent: any;
|
|
295
|
+
|
|
296
|
+
beforeEach(() => {
|
|
297
|
+
store.setGridCellDimensions(100, 80);
|
|
298
|
+
|
|
299
|
+
mockMouseEvent = {
|
|
300
|
+
clientX: 150,
|
|
301
|
+
clientY: 200,
|
|
302
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
303
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
304
|
+
} as Partial<MouseEvent>;
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should handle invalid direction gracefully', () => {
|
|
308
|
+
spyOn(component.resizeStart, 'emit');
|
|
309
|
+
|
|
310
|
+
expect(() => {
|
|
311
|
+
component.onResizeStart(mockMouseEvent, 'invalid' as any);
|
|
312
|
+
}).not.toThrow();
|
|
313
|
+
|
|
314
|
+
expect(component.resizeStart.emit).toHaveBeenCalledWith({
|
|
315
|
+
cellId: mockCellId,
|
|
316
|
+
direction: jasmine.any(String),
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should handle extreme coordinates', () => {
|
|
321
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
322
|
+
spyOn(component.resizeMove, 'emit');
|
|
323
|
+
|
|
324
|
+
// Test with very large coordinates
|
|
325
|
+
(component as any).handleResizeMove({ clientX: 999999, clientY: 999999 });
|
|
326
|
+
|
|
327
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
328
|
+
cellId: mockCellId,
|
|
329
|
+
direction: 'horizontal',
|
|
330
|
+
delta: jasmine.any(Number),
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should handle negative coordinates', () => {
|
|
335
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
336
|
+
spyOn(component.resizeMove, 'emit');
|
|
337
|
+
|
|
338
|
+
// Test with negative coordinates
|
|
339
|
+
(component as any).handleResizeMove({ clientX: -100, clientY: -100 });
|
|
340
|
+
|
|
341
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
342
|
+
cellId: mockCellId,
|
|
343
|
+
direction: 'horizontal',
|
|
344
|
+
delta: jasmine.any(Number),
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should handle zero cell dimensions', () => {
|
|
349
|
+
store.setGridCellDimensions(0, 0);
|
|
350
|
+
component.onResizeStart(mockMouseEvent as MouseEvent, 'horizontal');
|
|
351
|
+
spyOn(component.resizeMove, 'emit');
|
|
352
|
+
|
|
353
|
+
(component as any).handleResizeMove({ clientX: 200, clientY: 200 });
|
|
354
|
+
|
|
355
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
356
|
+
cellId: mockCellId,
|
|
357
|
+
direction: 'horizontal',
|
|
358
|
+
delta: jasmine.any(Number),
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe('User Scenarios - End-to-End Behavior', () => {
|
|
364
|
+
beforeEach(() => {
|
|
365
|
+
store.setGridCellDimensions(100, 80);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('should handle complete resize workflow', () => {
|
|
369
|
+
spyOn(component.resizeStart, 'emit');
|
|
370
|
+
spyOn(component.resizeMove, 'emit');
|
|
371
|
+
spyOn(component.resizeEnd, 'emit');
|
|
372
|
+
|
|
373
|
+
const startEvent = {
|
|
374
|
+
clientX: 150,
|
|
375
|
+
clientY: 200,
|
|
376
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
377
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
378
|
+
} as Partial<MouseEvent>;
|
|
379
|
+
|
|
380
|
+
// Start resize
|
|
381
|
+
component.onResizeStart(startEvent as MouseEvent, 'horizontal');
|
|
382
|
+
expect(component.resizeStart.emit).toHaveBeenCalledWith({
|
|
383
|
+
cellId: mockCellId,
|
|
384
|
+
direction: 'horizontal',
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Move resize
|
|
388
|
+
(component as any).handleResizeMove({ clientX: 250, clientY: 200 });
|
|
389
|
+
expect(component.resizeMove.emit).toHaveBeenCalledWith({
|
|
390
|
+
cellId: mockCellId,
|
|
391
|
+
direction: 'horizontal',
|
|
392
|
+
delta: 1,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// End resize
|
|
396
|
+
(component as any).handleResizeEnd();
|
|
397
|
+
expect(component.resizeEnd.emit).toHaveBeenCalledWith({
|
|
398
|
+
cellId: mockCellId,
|
|
399
|
+
apply: true,
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('should handle multiple sequential resize operations', () => {
|
|
404
|
+
spyOn(component.resizeStart, 'emit');
|
|
405
|
+
spyOn(component.resizeEnd, 'emit');
|
|
406
|
+
|
|
407
|
+
const startEvent = {
|
|
408
|
+
clientX: 150,
|
|
409
|
+
clientY: 200,
|
|
410
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
411
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
412
|
+
} as Partial<MouseEvent>;
|
|
413
|
+
|
|
414
|
+
// First resize cycle
|
|
415
|
+
component.onResizeStart(startEvent as MouseEvent, 'horizontal');
|
|
416
|
+
(component as any).handleResizeEnd();
|
|
417
|
+
|
|
418
|
+
// Second resize cycle
|
|
419
|
+
component.onResizeStart(startEvent as MouseEvent, 'vertical');
|
|
420
|
+
(component as any).handleResizeEnd();
|
|
421
|
+
|
|
422
|
+
expect(component.resizeStart.emit).toHaveBeenCalledTimes(2);
|
|
423
|
+
expect(component.resizeEnd.emit).toHaveBeenCalledTimes(2);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should cleanup on component destroy', () => {
|
|
427
|
+
const startEvent = {
|
|
428
|
+
clientX: 150,
|
|
429
|
+
clientY: 200,
|
|
430
|
+
preventDefault: jasmine.createSpy('preventDefault'),
|
|
431
|
+
stopPropagation: jasmine.createSpy('stopPropagation'),
|
|
432
|
+
} as Partial<MouseEvent>;
|
|
433
|
+
|
|
434
|
+
component.onResizeStart(startEvent as MouseEvent, 'horizontal');
|
|
435
|
+
|
|
436
|
+
// Component destruction should not throw
|
|
437
|
+
expect(() => {
|
|
438
|
+
fixture.destroy();
|
|
439
|
+
}).not.toThrow();
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
});
|