Skip to content

Commit

Permalink
fix(filters): changing Slider value should update tooltip value (#788)
Browse files Browse the repository at this point in the history
* fix(filters): changing Slider value should update tooltip value
- when using SlickCustomTooltip addon and changing slider value, it should update the tooltip value without having to leave the cell and rehovering to see the updated value, it turns out that calling `onHeaderRowMouseEnter` will have that effect as long as we add a small `setTimeout` delay

* tests: add missing slider unit tests
  • Loading branch information
ghiscoding committed Nov 3, 2022
1 parent ef0ea73 commit 509a31d
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 106 deletions.
34 changes: 20 additions & 14 deletions packages/common/src/filters/__tests__/compoundSliderFilter.spec.ts
Expand Up @@ -6,6 +6,7 @@ import { TranslateServiceStub } from '../../../../../test/translateServiceStub';

const containerId = 'demo-container';
declare const Slick: SlickNamespace;
jest.useFakeTimers();

// define a <div> container to simulate the grid container
const template = `<div id="${containerId}"></div>`;
Expand All @@ -25,6 +26,7 @@ const gridStub = {
getHeaderRowColumn: jest.fn(),
render: jest.fn(),
onHeaderMouseLeave: new Slick.Event(),
onHeaderRowMouseEnter: new Slick.Event(),
} as unknown as SlickGrid;

describe('CompoundSliderFilter', () => {
Expand Down Expand Up @@ -77,19 +79,23 @@ describe('CompoundSliderFilter', () => {
});

it('should call "setValues" with "operator" set in the filter arguments and expect that value to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');
const filterArgs = { ...filterArguments, operator: '>', grid: gridStub } as FilterArguments;

filter.init(filterArgs);
filter.setValues(['2']);
const filterElm = divContainer.querySelector('.input-group.search-filter.filter-duration input') as HTMLInputElement;
filterElm.dispatchEvent(new CustomEvent('change'));

expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: ['2'], shouldTriggerQuery: true });
jest.runAllTimers(); // fast-forward timer

expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: ['2'], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
});

it('should call "setValues" with "operator" set in the filter arguments and expect that value, converted as a string, to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const filterArgs = { ...filterArguments, operator: '<=', grid: gridStub } as FilterArguments;

filter.init(filterArgs);
Expand All @@ -99,11 +105,11 @@ describe('CompoundSliderFilter', () => {
const filterFilledElms = divContainer.querySelectorAll('.slider-container.search-filter.filter-duration.filled');

expect(filterFilledElms.length).toBe(1);
expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['3'], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['3'], shouldTriggerQuery: true });
});

it('should trigger an operator change event and expect the callback to be called with the searchTerms and operator defined', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.setValues(9);
Expand All @@ -112,19 +118,19 @@ describe('CompoundSliderFilter', () => {
filterSelectElm.value = '<=';
filterSelectElm.dispatchEvent(new CustomEvent('change'));

expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['9'], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '<=', searchTerms: ['9'], shouldTriggerQuery: true });
});

it('should be able to call "setValues" with a value and an extra operator and expect it to be set as new operator', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.setValues(['9'], OperatorType.greaterThanOrEqual);

const filterSelectElm = divContainer.querySelector('.search-filter.filter-duration select') as HTMLInputElement;
filterSelectElm.dispatchEvent(new CustomEvent('change'));

expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>=', searchTerms: ['9'], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>=', searchTerms: ['9'], shouldTriggerQuery: true });
});

it('should be able to call "setValues" and set empty values and the input to not have the "filled" css class', () => {
Expand Down Expand Up @@ -208,29 +214,29 @@ describe('CompoundSliderFilter', () => {

it('should trigger a callback with the clear filter set when calling the "clear" method', () => {
const filterArgs = { ...filterArguments, operator: '<=', searchTerms: [3], grid: gridStub } as FilterArguments;
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArgs);
filter.clear();

expect(filter.getValues()).toBe(0);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
});

it('should trigger a callback with the clear filter but without querying when when calling the "clear" method with False as argument', () => {
const filterArgs = { ...filterArguments, operator: '<=', searchTerms: [3], grid: gridStub } as FilterArguments;
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArgs);
filter.clear(false);

expect(filter.getValues()).toBe(0);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});

it('should trigger a callback with the clear filter set when calling the "clear" method and expect min slider values being with values of "sliderStartValue" when defined through the filter params', () => {
const filterArgs = { ...filterArguments, operator: '<=', searchTerms: [3], grid: gridStub, } as FilterArguments;
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
mockColumn.filter = {
params: {
sliderStartValue: 4,
Expand All @@ -242,7 +248,7 @@ describe('CompoundSliderFilter', () => {
filter.clear(false);

expect(filter.getValues()).toEqual(4);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});

it('should create the input filter with all available operators in a select dropdown options as a prepend element', () => {
Expand Down
26 changes: 16 additions & 10 deletions packages/common/src/filters/__tests__/sliderFilter.spec.ts
Expand Up @@ -4,6 +4,7 @@ import { SliderFilter } from '../sliderFilter';

const containerId = 'demo-container';
declare const Slick: SlickNamespace;
jest.useFakeTimers();

// define a <div> container to simulate the grid container
const template = `<div id="${containerId}"></div>`;
Expand All @@ -19,6 +20,7 @@ const gridStub = {
getHeaderRowColumn: jest.fn(),
render: jest.fn(),
onHeaderMouseLeave: new Slick.Event(),
onHeaderRowMouseEnter: new Slick.Event(),
} as unknown as SlickGrid;

describe('SliderFilter', () => {
Expand Down Expand Up @@ -69,18 +71,22 @@ describe('SliderFilter', () => {
});

it('should call "setValues" and expect that value to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArgs, 'callback');
const callbackSpy = jest.spyOn(filterArgs, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');

filter.init(filterArgs);
filter.setValues(['2']);
const filterElm = divContainer.querySelector('.search-filter.slider-container.filter-duration input') as HTMLInputElement;
filterElm.dispatchEvent(new CustomEvent('change'));

expect(spyCallback).toHaveBeenLastCalledWith(new CustomEvent('change'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['2'], shouldTriggerQuery: true });
jest.runAllTimers(); // fast-forward timer

expect(callbackSpy).toHaveBeenLastCalledWith(new CustomEvent('change'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['2'], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
});

it('should call "setValues" and expect that value, converted as a string, to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArgs, 'callback');
const callbackSpy = jest.spyOn(filterArgs, 'callback');

filter.init(filterArgs);
filter.setValues(3);
Expand All @@ -92,7 +98,7 @@ describe('SliderFilter', () => {
const filterFilledElms = divContainer.querySelectorAll('.search-filter.slider-container.filter-duration.filled');

expect(filterFilledElms.length).toBe(1);
expect(spyCallback).toHaveBeenLastCalledWith(new CustomEvent('change'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['13'], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(new CustomEvent('change'), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['13'], shouldTriggerQuery: true });
});

it('should be able to call "setValues" and set empty values and the input to not have the "filled" css class', () => {
Expand Down Expand Up @@ -176,28 +182,28 @@ describe('SliderFilter', () => {

it('should trigger a callback with the clear filter set when calling the "clear" method', () => {
filterArgs.searchTerms = [3];
const spyCallback = jest.spyOn(filterArgs, 'callback');
const callbackSpy = jest.spyOn(filterArgs, 'callback');

filter.init(filterArgs);
filter.clear();

expect(filter.getValues()).toBe(0);
expect(spyCallback).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: true });
});

it('should trigger a callback with the clear filter but without querying when when calling the "clear" method with False as argument', () => {
filterArgs.searchTerms = [3];
const spyCallback = jest.spyOn(filterArgs, 'callback');
const callbackSpy = jest.spyOn(filterArgs, 'callback');

filter.init(filterArgs);
filter.clear(false);

expect(filter.getValues()).toBe(0);
expect(spyCallback).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: false });
});

it('should trigger a callback with the clear filter set when calling the "clear" method and expect min slider values being with values of "sliderStartValue" when defined through the filter params', () => {
const spyCallback = jest.spyOn(filterArgs, 'callback');
const callbackSpy = jest.spyOn(filterArgs, 'callback');
mockColumn.filter = {
params: {
sliderStartValue: 4,
Expand All @@ -209,6 +215,6 @@ describe('SliderFilter', () => {
filter.clear(false);

expect(filter.getValues()).toEqual(4);
expect(spyCallback).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(new Event('change'), { columnDef: mockColumn, clearFilterTriggered: true, searchTerms: [], shouldTriggerQuery: false });
});
});
38 changes: 22 additions & 16 deletions packages/common/src/filters/__tests__/sliderRangeFilter.spec.ts
Expand Up @@ -4,6 +4,7 @@ import { SliderRangeFilter } from '../sliderRangeFilter';

const containerId = 'demo-container';
declare const Slick: SlickNamespace;
jest.useFakeTimers();

// define a <div> container to simulate the grid container
const template = `<div id="${containerId}"></div>`;
Expand All @@ -19,6 +20,7 @@ const gridStub = {
getHeaderRowColumn: jest.fn(),
render: jest.fn(),
onHeaderMouseLeave: new Slick.Event(),
onHeaderRowMouseEnter: new Slick.Event(),
} as unknown as SlickGrid;

describe('SliderRangeFilter', () => {
Expand Down Expand Up @@ -89,18 +91,22 @@ describe('SliderRangeFilter', () => {
});

it('should call "setValues" and expect that value to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const rowMouseEnterSpy = jest.spyOn(gridStub.onHeaderRowMouseEnter, 'notify');

filter.init(filterArguments);
filter.setValues(['2..80']);
const filterElms = divContainer.querySelectorAll<HTMLInputElement>('.search-filter.slider-container.filter-duration input');
filterElms[0].dispatchEvent(new CustomEvent('change'));

expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [2, 80], shouldTriggerQuery: true });
jest.runAllTimers(); // fast-forward timer

expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [2, 80], shouldTriggerQuery: true });
expect(rowMouseEnterSpy).toHaveBeenCalledWith({ column: mockColumn, grid: gridStub }, expect.anything());
});

it('should call "setValues" and expect that value to be in the callback when triggered', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.setValues([3, 84]);
Expand All @@ -110,11 +116,11 @@ describe('SliderRangeFilter', () => {

expect(sliderInputs[0].style.zIndex).toBe('0');
expect(sliderInputs[1].style.zIndex).toBe('1');
expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [3, 84], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [3, 84], shouldTriggerQuery: true });
});

it('should change z-index on left handle when it is by 20px near right handle so it shows over the right handle not below', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.setValues([50, 63]);
Expand All @@ -124,11 +130,11 @@ describe('SliderRangeFilter', () => {

expect(sliderInputs[0].style.zIndex).toBe('1');
expect(sliderInputs[1].style.zIndex).toBe('0');
expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [50, 63], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [50, 63], shouldTriggerQuery: true });
});

it('should change minValue to a lower value when it is to close to maxValue and "stopGapBetweenSliderHandles" is enabled so it will auto-change minValue to a lower value plus gap', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const minVal = 56;
const maxVal = 58;

Expand All @@ -143,11 +149,11 @@ describe('SliderRangeFilter', () => {

expect(sliderInputs[0].value).toBe(`${minVal - 5}`);
expect(sliderInputs[1].value).toBe('58');
expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [51, 58], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [51, 58], shouldTriggerQuery: true });
});

it('should change maxValue to a lower value when it is to close to minValue and "stopGapBetweenSliderHandles" is enabled so it will auto-change maxValue to a lower value plus gap', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
const minVal = 56;
const maxVal = 58;

Expand All @@ -162,7 +168,7 @@ describe('SliderRangeFilter', () => {

expect(sliderInputs[0].value).toBe('56');
expect(sliderInputs[1].value).toBe(`${minVal + 5}`);
expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [56, 61], shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeInclusive', searchTerms: [56, 61], shouldTriggerQuery: true });
});

it('should be able to call "setValues" and set empty values and the input to not have the "filled" css class', () => {
Expand Down Expand Up @@ -259,28 +265,28 @@ describe('SliderRangeFilter', () => {

it('should trigger a callback with the clear filter set when calling the "clear" method', () => {
filterArguments.searchTerms = [3, 80];
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.clear();

expect(filter.currentValues).toEqual([0, 100]);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: true });
});

it('should trigger a callback with the clear filter but without querying when when calling the "clear" method with False as argument', () => {
filterArguments.searchTerms = [3, 80];
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');

filter.init(filterArguments);
filter.clear(false);

expect(filter.currentValues).toEqual([0, 100]);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});

it('should trigger a callback with the clear filter set when calling the "clear" method and expect min/max slider values being with values of "sliderStartValue" and "sliderEndValue" when defined through the filterOptions', () => {
const spyCallback = jest.spyOn(filterArguments, 'callback');
const callbackSpy = jest.spyOn(filterArguments, 'callback');
mockColumn.filter = {
filterOptions: {
sliderStartValue: 4,
Expand All @@ -292,7 +298,7 @@ describe('SliderRangeFilter', () => {
filter.clear(false);

expect(filter.currentValues).toEqual([4, 69]);
expect(spyCallback).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
expect(callbackSpy).toHaveBeenLastCalledWith(undefined, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false });
});

it('should enableSliderTrackColoring and trigger a change event and expect slider track to have background color', () => {
Expand Down

0 comments on commit 509a31d

Please sign in to comment.