Skip to content

Commit f3ec760

Browse files
authored
fix: regression onSelectedRowsChanged not receiving correct caller (#1342)
* fix: regression `onSelectedRowsChanged` not receiving correct `caller` - a regression was introduced when dropping jQuery, the SlickEvent structure changed in the `notify` function. Previously a SlickEvent would accept a CustomEvent directly and the previous code was expecting that event to exists and override its CustomEvent `detail`, however the newer approach is to always use a SlickEventData and no longer use the CustomEvent directly and this caused the regression since the SlickEventData doesn't have a `detail` property but rather something like this `SlickEventData { event: { detail } }` - the fix is to simply create a CustomEvent with `{ detail: caller }` which we then pass to the `SlickEventData` constructor so that our `caller` isn't lost and rather reused later when triggered by `onSelectedRowsChanged`
1 parent 915ce0a commit f3ec760

8 files changed

Lines changed: 33 additions & 17 deletions

File tree

.github/workflows/cypress.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
push:
55
branches:
66
- master
7+
- next
8+
- version3
79
pull_request:
810
branches:
911
- '**'

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# CI Build & Jest Unit Tests (ship smaller name for CI badge)
22
name: Build & Tests
33
on:
4-
# Trigger the workflow on push or pull request,
5-
# but only for the master branch on Push and any branches on PR
64
push:
75
branches:
86
- master
7+
- next
8+
- version3
99
pull_request:
1010
branches:
1111
- '**'

packages/common/src/extensions/__tests__/slickCellSelectionModel.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const addVanillaEventPropagation = function (event, commandKeys: string[] = [],
2222
Object.defineProperty(event, 'key', { writable: true, configurable: true, value: keyName });
2323
}
2424
return event;
25-
}
25+
};
2626

2727
const mockGridOptions = {
2828
frozenColumn: 1,
@@ -44,7 +44,7 @@ const mockColumns = [
4444
{ id: 'firstName', field: 'firstName' },
4545
{ id: 'lastName', field: 'lastName' },
4646
{ id: 'age', field: 'age' },
47-
]
47+
];
4848

4949
const gridStub = {
5050
canCellBeSelected: jest.fn(),
@@ -330,7 +330,10 @@ describe('CellSelectionModel Plugin', () => {
330330
expect(setSelectRangeSpy).toHaveBeenCalledWith(expectedRangeCalled);
331331
expect(scrollCellSpy).toHaveBeenCalledWith(4, 2, false);
332332
expect(scrollRowSpy).toHaveBeenCalledWith(4);
333-
expect(onSelectedRangeSpy).toHaveBeenCalledWith(expectedRangeCalled, expect.objectContaining({ detail: { caller: 'SlickCellSelectionModel.setSelectedRanges' } }));
333+
expect(onSelectedRangeSpy).toHaveBeenCalledWith(
334+
expectedRangeCalled,
335+
expect.objectContaining({ event: expect.objectContaining({ detail: { caller: 'SlickCellSelectionModel.setSelectedRanges' } }) })
336+
);
334337
});
335338

336339
it('should call "setSelectedRanges" with Slick Range from current position to a calculated size of a page down when using Shift+PageDown key combo when triggered by "onKeyDown"', () => {

packages/common/src/extensions/__tests__/slickRowSelectionModel.spec.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const addVanillaEventPropagation = function (event, commandKey = '', keyName = '
1818
Object.defineProperty(event, 'key', { writable: true, configurable: true, value: keyName });
1919
}
2020
return event;
21-
}
21+
};
2222

2323
const mockGridOptions = {
2424
frozenColumn: 1,
@@ -192,9 +192,18 @@ describe('SlickRowSelectionModel Plugin', () => {
192192

193193
expect(onSelectedRangeSpy).toHaveBeenCalledWith(
194194
[{ fromCell: 0, fromRow: 0, toCell: 2, toRow: 0, }],
195-
expect.objectContaining({
196-
detail: { caller: 'SlickRowSelectionModel.setSelectedRanges' }
197-
}));
195+
expect.objectContaining({ event: expect.objectContaining({ detail: { caller: 'SlickRowSelectionModel.setSelectedRanges' } }) }));
196+
});
197+
198+
it('should call "setSelectedRanges" with valid ranges input with a "caller" defined and expect to "onSelectedRangesChanged" to be triggered', () => {
199+
const caller = 'click.toggle';
200+
const onSelectedRangeSpy = jest.spyOn(plugin.onSelectedRangesChanged, 'notify');
201+
202+
plugin.setSelectedRanges([{ fromCell: 0, fromRow: 0, toCell: 2, toRow: 0, }], caller);
203+
204+
expect(onSelectedRangeSpy).toHaveBeenCalledWith(
205+
[{ fromCell: 0, fromRow: 0, toCell: 2, toRow: 0, }],
206+
expect.objectContaining({ event: expect.objectContaining({ detail: { caller } }) }));
198207
});
199208

200209
it('should call "setSelectedRanges" with Slick Ranges when triggered by "onActiveCellChanged" and "selectActiveRow" is True', () => {

packages/common/src/extensions/slickCellSelectionModel.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,9 @@ export class SlickCellSelectionModel {
149149

150150
this._ranges = this.removeInvalidRanges(ranges);
151151
if (rangeHasChanged) {
152-
const eventData = new Slick.EventData();
153-
Object.defineProperty(eventData, 'detail', { writable: true, configurable: true, value: { caller } });
152+
// provide extra "caller" argument through SlickEventData event to avoid breaking the previous pubsub event structure
153+
// that only accepts an array of selected range `SlickRange[]`, the SlickEventData args will be merged and used later by `onSelectedRowsChanged`
154+
const eventData = new Slick.EventData(new CustomEvent('click', { detail: { caller } }), this._ranges);
154155
this.onSelectedRangesChanged.notify(this._ranges, eventData);
155156
}
156157
}

packages/common/src/extensions/slickRowSelectionModel.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,9 @@ export class SlickRowSelectionModel {
120120
return;
121121
}
122122
this._ranges = ranges;
123-
const eventData = new Slick.EventData();
124-
Object.defineProperty(eventData, 'detail', { writable: true, configurable: true, value: { caller } });
123+
// provide extra "caller" argument through SlickEventData event to avoid breaking the previous pubsub event structure
124+
// that only accepts an array of selected range `SlickRange[]`, the SlickEventData args will be merged and used later by `onSelectedRowsChanged`
125+
const eventData = new Slick.EventData(new CustomEvent('click', { detail: { caller } }), this._ranges);
125126
this.onSelectedRangesChanged.notify(this._ranges, eventData);
126127
}
127128

@@ -221,7 +222,7 @@ export class SlickRowSelectionModel {
221222
selectedRows = [activeRow.row];
222223
}
223224

224-
let active:number;
225+
let active: number;
225226
let top = selectedRows[0];
226227
let bottom = selectedRows[selectedRows.length - 1];
227228

packages/common/src/interfaces/slickNamespace.interface.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export interface SlickNamespace {
100100
* An event object for passing data to event handlers and letting them control propagation.
101101
* This is pretty much identical to how W3C implement events.
102102
*/
103-
EventData: new () => SlickEventData;
103+
EventData: new (e?: Event, args?: any) => SlickEventData;
104104

105105
/** EventHandler is a Pub/Sub SlickGrid Event Handler */
106106
EventHandler: new () => SlickEventHandler;
@@ -195,13 +195,13 @@ export interface SlickNamespace {
195195
innerSize: (elm: HTMLElement, type: 'height' | 'width') => number;
196196
height: (elm: HTMLElement, val?: number | string) => number | void;
197197
width: (elm: HTMLElement, val?: number | string) => number | void;
198-
offset: (elm: HTMLElement) => undefined | { top: number, left: number };
198+
offset: (elm: HTMLElement) => undefined | { top: number, left: number; };
199199
isEmptyObject: (obj: any) => boolean;
200200
parents: (elm: HTMLElement, selector: string) => HTMLElement[];
201201
setStyleSize: (elm: HTMLElement, style: string, val: string | (() => string)) => void;
202202
hide: (elm: HTMLElement, type?: string) => void;
203203
show: (elm: HTMLElement, type?: string) => void;
204204
toFloat: (val: number) => number;
205205
windowScrollPosition: () => { top: number; left: number; };
206-
}
206+
};
207207
}
Binary file not shown.

0 commit comments

Comments
 (0)