diff --git a/src/app/modules/angular-slickgrid/filter-conditions/__tests__/numberFilterCondition.spec.ts b/src/app/modules/angular-slickgrid/filter-conditions/__tests__/numberFilterCondition.spec.ts index dd4f4fd54..646a3d61b 100644 --- a/src/app/modules/angular-slickgrid/filter-conditions/__tests__/numberFilterCondition.spec.ts +++ b/src/app/modules/angular-slickgrid/filter-conditions/__tests__/numberFilterCondition.spec.ts @@ -69,27 +69,51 @@ describe('numberFilterCondition method', () => { expect(output).toBe(false); }); - it('should return True when input value is in the range of search terms', () => { + it('should return True when input value is in the range of search terms using 2 dots (..) notation', () => { const options = { dataKey: '', operator: 'EQ', cellValue: '3', fieldType: FieldType.number, searchTerms: ['1..5'] } as FilterConditionOption; const output = numberFilterCondition(options); expect(output).toBe(true); }); - it('should return False when input value is not in the range of search terms', () => { + it('should return False when input value is not in the range of search terms using 2 dots (..) notation', () => { const options = { dataKey: '', operator: 'EQ', cellValue: '15', fieldType: FieldType.number, searchTerms: ['1..5'] } as FilterConditionOption; const output = numberFilterCondition(options); expect(output).toBe(false); }); - it('should return True when input value equals the search terms min inclusive value and operator is set to "rangeInclusive"', () => { + it('should return True when input value equals the search terms min inclusive value and operator is set to "rangeInclusive" using 2 dots (..) notation', () => { const options = { dataKey: '', operator: 'RangeInclusive', cellValue: '1', fieldType: FieldType.number, searchTerms: ['1..5'] } as FilterConditionOption; const output = numberFilterCondition(options); expect(output).toBe(true); }); - it('should return False when input value equals the search terms min inclusive value and operator is set to "RangeExclusive"', () => { + it('should return False when input value equals the search terms min inclusive value and operator is set to "RangeExclusive" using 2 dots (..) notation', () => { const options = { dataKey: '', operator: 'RangeExclusive', cellValue: '1', fieldType: FieldType.number, searchTerms: ['1..5'] } as FilterConditionOption; const output = numberFilterCondition(options); expect(output).toBe(false); }); + + it('should return True when input value is in the range of search terms array', () => { + const options = { dataKey: '', operator: 'EQ', cellValue: '3', fieldType: FieldType.number, searchTerms: [1, 5] } as FilterConditionOption; + const output = numberFilterCondition(options); + expect(output).toBe(true); + }); + + it('should return False when input value is not in the range of search terms array', () => { + const options = { dataKey: '', operator: 'EQ', cellValue: '15', fieldType: FieldType.number, searchTerms: [1, 5] } as FilterConditionOption; + const output = numberFilterCondition(options); + expect(output).toBe(false); + }); + + it('should return True when input value equals the search terms min (first array term) inclusive value and operator is set to "rangeInclusive"', () => { + const options = { dataKey: '', operator: 'RangeInclusive', cellValue: '1', fieldType: FieldType.number, searchTerms: [1, 5] } as FilterConditionOption; + const output = numberFilterCondition(options); + expect(output).toBe(true); + }); + + it('should return False when input value equals the search terms min (first array term) inclusive value and operator is set to "RangeExclusive"', () => { + const options = { dataKey: '', operator: 'RangeExclusive', cellValue: '1', fieldType: FieldType.number, searchTerms: [1, 5] } as FilterConditionOption; + const output = numberFilterCondition(options); + expect(output).toBe(false); + }); }); diff --git a/src/app/modules/angular-slickgrid/filter-conditions/numberFilterCondition.ts b/src/app/modules/angular-slickgrid/filter-conditions/numberFilterCondition.ts index 4da863d34..9c51dbd9d 100644 --- a/src/app/modules/angular-slickgrid/filter-conditions/numberFilterCondition.ts +++ b/src/app/modules/angular-slickgrid/filter-conditions/numberFilterCondition.ts @@ -3,26 +3,22 @@ import { testFilterCondition } from './filterUtilities'; export const numberFilterCondition: FilterCondition = (options: FilterConditionOption) => { const cellValue = parseFloat(options.cellValue); - const searchTerm = (Array.isArray(options.searchTerms) && options.searchTerms[0]) || 0; + const searchTerms = Array.isArray(options.searchTerms) && options.searchTerms || [0]; let isRangeSearch = false; let searchValue1; let searchValue2; - if (typeof searchTerm === 'string') { - if (searchTerm.indexOf('..') >= 0) { - isRangeSearch = true; - const searchValues = searchTerm.split('..'); - searchValue1 = parseFloat(Array.isArray(searchValues) && searchValues[0]); - searchValue2 = parseFloat(Array.isArray(searchValues) && searchValues[1]); - } else { - searchValue1 = parseFloat(searchTerm); - } + if (searchTerms.length === 2 || (typeof searchTerms[0] === 'string' && (searchTerms[0] as string).indexOf('..') > 0)) { + isRangeSearch = true; + const searchValues = (searchTerms.length === 2) ? searchTerms : (searchTerms[0] as string).split('..'); + searchValue1 = parseFloat(Array.isArray(searchValues) && searchValues[0] + ''); + searchValue2 = parseFloat(Array.isArray(searchValues) && searchValues[1] + ''); } else { - searchValue1 = searchTerm; + searchValue1 = searchTerms[0]; } - if (!searchTerm && !options.operator) { + if (!searchValue1 && !options.operator) { return true; } diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts index af962e925..f29604fa2 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputFilter.spec.ts @@ -7,8 +7,7 @@ import { CompoundInputFilter } from '../compoundInputFilter'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, @@ -100,11 +99,7 @@ describe('CompoundInputFilter', () => { const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); filterInputElm.focus(); - filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); const filterFilledElms = divContainer.querySelectorAll('.search-filter.filter-duration.filled'); expect(filterFilledElms.length).toBe(1); @@ -121,11 +116,7 @@ describe('CompoundInputFilter', () => { const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); filterInputElm.focus(); - filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: ['9'], shouldTriggerQuery: true }); }); @@ -155,11 +146,7 @@ describe('CompoundInputFilter', () => { const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); filterInputElm.focus(); - filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: ['987'], shouldTriggerQuery: true }); }); @@ -176,11 +163,7 @@ describe('CompoundInputFilter', () => { const filterInputElm = divContainer.querySelector('.search-filter.filter-duration input'); filterInputElm.focus(); - filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '>', searchTerms: ['987'], shouldTriggerQuery: true }); }); @@ -193,11 +176,7 @@ describe('CompoundInputFilter', () => { filterInputElm.focus(); filterInputElm.value = 'a'; - filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterInputElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: '', searchTerms: ['a'], shouldTriggerQuery: true }); }); diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputNumberFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputNumberFilter.spec.ts index dca5e6ad6..d6bd9815d 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputNumberFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputNumberFilter.spec.ts @@ -7,8 +7,7 @@ import { CompoundInputNumberFilter } from '../compoundInputNumberFilter'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputPasswordFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputPasswordFilter.spec.ts index 19521f30d..ae0a8bf8b 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputPasswordFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/compoundInputPasswordFilter.spec.ts @@ -7,8 +7,7 @@ import { CompoundInputPasswordFilter } from '../compoundInputPasswordFilter'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/inputFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/inputFilter.spec.ts index 069583bd4..f4bcdd8a9 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/inputFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/inputFilter.spec.ts @@ -5,8 +5,7 @@ import { Filters } from '..'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, @@ -78,11 +77,7 @@ describe('InputFilter', () => { const filterElm = divContainer.querySelector('input.filter-duration'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); const filterFilledElms = divContainer.querySelectorAll('input.filter-duration.filled'); expect(filterFilledElms.length).toBe(1); @@ -98,11 +93,7 @@ describe('InputFilter', () => { const filterElm = divContainer.querySelector('input.filter-duration'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); const filterFilledElms = divContainer.querySelectorAll('input.filter-duration.filled'); expect(filterFilledElms.length).toBe(1); @@ -119,11 +110,7 @@ describe('InputFilter', () => { const filterElm = divContainer.querySelector('input.filter-duration'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); const filterFilledElms = divContainer.querySelectorAll('input.filter-duration.filled'); expect(filterFilledElms.length).toBe(1); @@ -138,11 +125,7 @@ describe('InputFilter', () => { filterElm.focus(); filterElm.value = 'a'; - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['a'], shouldTriggerQuery: true }); }); diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/inputMaskFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/inputMaskFilter.spec.ts index cc22b6aba..43fd24eb6 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/inputMaskFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/inputMaskFilter.spec.ts @@ -5,8 +5,7 @@ import { Filters } from '..'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, @@ -84,11 +83,7 @@ describe('InputMaskFilter', () => { filter.setValues('1234567890'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); }); @@ -101,11 +96,7 @@ describe('InputMaskFilter', () => { filter.setValues('1234567890'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('(123) 456-7890'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); @@ -119,11 +110,7 @@ describe('InputMaskFilter', () => { filter.setValues('1234567890abc'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('(123) 456-7890'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); @@ -137,11 +124,7 @@ describe('InputMaskFilter', () => { filter.setValues('1234567890'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('(123) 456-7890'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); @@ -155,11 +138,7 @@ describe('InputMaskFilter', () => { filter.setValues('H1H1H1'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('H1H 1H1'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['H1H1H1'], shouldTriggerQuery: true }); @@ -174,11 +153,7 @@ describe('InputMaskFilter', () => { filter.setValues(' 1234567890 '); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('(123) 456-7890'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); @@ -194,11 +169,7 @@ describe('InputMaskFilter', () => { filter.setValues(' 1234567890 '); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('(123) 456-7890'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1234567890'], shouldTriggerQuery: true }); @@ -212,11 +183,7 @@ describe('InputMaskFilter', () => { filter.setValues('abc'); const filterElm = divContainer.querySelector('input.filter-mask'); filterElm.focus(); - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(filterElm.value).toBe('() -'); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: [''], shouldTriggerQuery: true }); @@ -231,11 +198,7 @@ describe('InputMaskFilter', () => { filterElm.focus(); filterElm.value = '1'; - filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { - keyCode: 97, - bubbles: true, - cancelable: true - })); + filterElm.dispatchEvent(new (window.window as any).KeyboardEvent('keyup', { keyCode: 97, bubbles: true, cancelable: true })); expect(spyCallback).toHaveBeenCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'EQ', searchTerms: ['1'], shouldTriggerQuery: true }); }); diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/inputNumberFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/inputNumberFilter.spec.ts index 301eda5bf..5cbff3fbd 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/inputNumberFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/inputNumberFilter.spec.ts @@ -5,8 +5,7 @@ import { Filters } from '..'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/inputPasswordFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/inputPasswordFilter.spec.ts index e93508663..5b2f33a85 100644 --- a/src/app/modules/angular-slickgrid/filters/__tests__/inputPasswordFilter.spec.ts +++ b/src/app/modules/angular-slickgrid/filters/__tests__/inputPasswordFilter.spec.ts @@ -5,8 +5,7 @@ import { Filters } from '..'; const containerId = 'demo-container'; // define a
container to simulate the grid container -const template = - `
`; +const template = `
`; const gridOptionMock = { enableFiltering: true, diff --git a/src/app/modules/angular-slickgrid/filters/__tests__/sliderRangeFilter.spec.ts b/src/app/modules/angular-slickgrid/filters/__tests__/sliderRangeFilter.spec.ts new file mode 100644 index 000000000..a9a2cbae6 --- /dev/null +++ b/src/app/modules/angular-slickgrid/filters/__tests__/sliderRangeFilter.spec.ts @@ -0,0 +1,229 @@ +import { JQueryUiSliderOption } from './../../models/jQueryUiSliderOption.interface'; +import { GridOption, FilterArguments, Column } from '../../models'; +import { Filters } from '..'; +import { SliderRangeFilter } from '../sliderRangeFilter'; + +const containerId = 'demo-container'; + +// define a
container to simulate the grid container +const template = `
`; + +const gridOptionMock = { + enableFiltering: true, + enableFilterTrimWhiteSpace: true, +} as GridOption; + +const gridStub = { + getOptions: () => gridOptionMock, + getColumns: jest.fn(), + getHeaderRowColumn: jest.fn(), + render: jest.fn(), +}; + +describe('SliderRangeFilter', () => { + let divContainer: HTMLDivElement; + let filter: SliderRangeFilter; + let filterArguments: FilterArguments; + let spyGetHeaderRow; + let mockColumn: Column; + + beforeEach(() => { + divContainer = document.createElement('div'); + divContainer.innerHTML = template; + document.body.appendChild(divContainer); + spyGetHeaderRow = jest.spyOn(gridStub, 'getHeaderRowColumn').mockReturnValue(divContainer); + + mockColumn = { id: 'duration', field: 'duration', filterable: true, filter: { model: Filters.sliderRange } }; + filterArguments = { + grid: gridStub, + columnDef: mockColumn, + callback: jest.fn() + }; + + filter = new SliderRangeFilter(); + }); + + afterEach(() => { + filter.destroy(); + }); + + it('should throw an error when trying to call init without any arguments', () => { + expect(() => filter.init(null)).toThrowError('[Angular-SlickGrid] A filter must always have an "init()" with valid arguments.'); + }); + + it('should throw an error when trying override the slider "change" method', () => { + try { + mockColumn.filter.filterOptions = { change: () => { } } as JQueryUiSliderOption; + filter.init(filterArguments); + } catch (e) { + expect(e.toString()).toContain(`[Angular-Slickgrid] You cannot override the "change" and/or the "slide" callback methods`); + } + }); + + it('should throw an error when trying override the slider "slide" method', () => { + try { + mockColumn.filter.filterOptions = { slide: () => { } } as JQueryUiSliderOption; + filter.init(filterArguments); + } catch (e) { + expect(e.toString()).toContain(`[Angular-Slickgrid] You cannot override the "change" and/or the "slide" callback methods`); + } + }); + + it('should initialize the filter', () => { + filter.init(filterArguments); + const filterCount = divContainer.querySelectorAll('.search-filter.slider-range-container.filter-duration').length; + + expect(spyGetHeaderRow).toHaveBeenCalled(); + expect(filterCount).toBe(1); + }); + + it('should be able to retrieve default slider options through the Getter', () => { + filter.init(filterArguments); + + expect(filter.sliderOptions).toEqual({ + change: expect.anything(), + max: 100, + min: 0, + range: true, + slide: expect.anything(), + step: 1, + values: [0, 100], + }); + }); + + it('should be able to retrieve slider options defined through the Getter when passing different filterOptions', () => { + mockColumn.filter = { + minValue: 4, + maxValue: 69, + valueStep: 5, + }; + filter.init(filterArguments); + + expect(filter.sliderOptions).toEqual({ + change: expect.anything(), + max: 69, + min: 4, + range: true, + slide: expect.anything(), + step: 5, + values: [4, 69], + }); + }); + + it('should call "setValues" and expect that value to be in the callback when triggered', () => { + const spyCallback = jest.spyOn(filterArguments, 'callback'); + + filter.init(filterArguments); + filter.setValues(['2..80']); + + expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeExclusive', searchTerms: [2, 80], shouldTriggerQuery: true }); + }); + + it('should call "setValues" and expect that value to be in the callback when triggered', () => { + const spyCallback = jest.spyOn(filterArguments, 'callback'); + + filter.init(filterArguments); + filter.setValues([3, 84]); + + expect(spyCallback).toHaveBeenLastCalledWith(expect.anything(), { columnDef: mockColumn, operator: 'RangeExclusive', searchTerms: [3, 84], shouldTriggerQuery: true }); + }); + + it('should create the input filter with default search terms range when passed as a filter argument', () => { + filterArguments.searchTerms = [3, 80]; + + filter.init(filterArguments); + + const filterLowestElm = divContainer.querySelector('.lowest-range-duration'); + const filterHighestElm = divContainer.querySelector('.highest-range-duration'); + + expect(filterLowestElm.textContent).toBe('3'); + expect(filterHighestElm.textContent).toBe('80'); + expect(filter.currentValues).toEqual([3, 80]); + }); + + it('should create the input filter with min/max slider values being set by filter "minValue" and "maxValue"', () => { + mockColumn.filter = { + minValue: 4, + maxValue: 69, + }; + + filter.init(filterArguments); + + const filterLowestElm = divContainer.querySelector('.lowest-range-duration'); + const filterHighestElm = divContainer.querySelector('.highest-range-duration'); + + expect(filterLowestElm.textContent).toBe('4'); + expect(filterHighestElm.textContent).toBe('69'); + expect(filter.currentValues).toEqual([4, 69]); + }); + + it('should create the input filter with min/max slider values being set by filter "sliderStartValue" and "sliderEndValue" through the filter params', () => { + mockColumn.filter = { + params: { + sliderStartValue: 4, + sliderEndValue: 69, + } + }; + + filter.init(filterArguments); + + const filterLowestElm = divContainer.querySelector('.lowest-range-duration'); + const filterHighestElm = divContainer.querySelector('.highest-range-duration'); + + expect(filterLowestElm.textContent).toBe('4'); + expect(filterHighestElm.textContent).toBe('69'); + expect(filter.currentValues).toEqual([4, 69]); + }); + + it('should create the input filter with default search terms range but without showing side numbers when "hideSliderNumbers" is set in params', () => { + filterArguments.searchTerms = [3, 80]; + mockColumn.filter.params = { hideSliderNumbers: true }; + + filter.init(filterArguments); + + const filterLowestElms = divContainer.querySelectorAll('.lowest-range-duration'); + const filterHighestElms = divContainer.querySelectorAll('.highest-range-duration'); + + expect(filterLowestElms.length).toBe(0); + expect(filterHighestElms.length).toBe(0); + expect(filter.currentValues).toEqual([3, 80]); + }); + + 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'); + + filter.init(filterArguments); + filter.clear(); + + expect(filter.currentValues).toEqual([0, 100]); + expect(spyCallback).toHaveBeenLastCalledWith(null, { 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'); + + filter.init(filterArguments); + filter.clear(false); + + expect(filter.currentValues).toEqual([0, 100]); + expect(spyCallback).toHaveBeenLastCalledWith(null, { 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 filter params', () => { + const spyCallback = jest.spyOn(filterArguments, 'callback'); + mockColumn.filter = { + params: { + sliderStartValue: 4, + sliderEndValue: 69, + } + }; + + filter.init(filterArguments); + filter.clear(false); + + expect(filter.currentValues).toEqual([4, 69]); + expect(spyCallback).toHaveBeenLastCalledWith(null, { columnDef: mockColumn, clearFilterTriggered: true, shouldTriggerQuery: false }); + }); +}); diff --git a/src/app/modules/angular-slickgrid/filters/sliderRangeFilter.ts b/src/app/modules/angular-slickgrid/filters/sliderRangeFilter.ts index 3ff519dcc..5ee63e570 100644 --- a/src/app/modules/angular-slickgrid/filters/sliderRangeFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/sliderRangeFilter.ts @@ -22,6 +22,7 @@ const DEFAULT_STEP = 1; /** A Slider Range Filter which uses jQuery UI, this is only meant to be used as a range filter (with 2 handles lowest & highest values) */ export class SliderRangeFilter implements Filter { private _clearFilterTriggered = false; + private _currentValues: number[]; private _shouldTriggerQuery = true; private _sliderOptions: JQueryUiSliderOption; private $filterElm: any; @@ -46,6 +47,11 @@ export class SliderRangeFilter implements Filter { return this.columnDef && this.columnDef.filter || {}; } + /** Getter for the Current Slider Values */ + get currentValues(): number[] { + return this._currentValues; + } + /** Getter for the Grid Options pulled through the Grid Object */ get gridOptions(): GridOption { return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {}; @@ -86,6 +92,7 @@ export class SliderRangeFilter implements Filter { this.searchTerms = []; const lowestValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : DEFAULT_MIN_VALUE; const highestValue = this.filterParams.hasOwnProperty('sliderEndValue') ? this.filterParams.sliderEndValue : DEFAULT_MAX_VALUE; + this._currentValues = [lowestValue, highestValue]; this.$filterElm.slider('values', [lowestValue, highestValue]); if (!this.filterParams.hideSliderNumbers) { this.renderSliderValues(lowestValue, highestValue); @@ -120,12 +127,10 @@ export class SliderRangeFilter implements Filter { } if (Array.isArray(sliderValues) && sliderValues.length === 2) { - this.$filterElm.slider('values', [sliderValues[0], sliderValues[1]]); + this.$filterElm.slider('values', sliderValues); if (!this.filterParams.hideSliderNumbers) { this.renderSliderValues(sliderValues[0], sliderValues[1]); } - } else { - this.clear(true); } } } @@ -139,7 +144,7 @@ export class SliderRangeFilter implements Filter { * @param searchTerm optional preset search terms */ private createDomElement(searchTerms?: SearchTerm | SearchTerm[]) { - if (this.columnFilter.filterOptions && this.columnFilter.filterOptions.change || this.columnFilter.filterOptions.slide) { + if (this.columnFilter && this.columnFilter.filterOptions && (this.columnFilter.filterOptions.change || this.columnFilter.filterOptions.slide)) { throw new Error(`[Angular-Slickgrid] You cannot override the "change" and/or the "slide" callback methods since they are used in SliderRange Filter itself, however any other methods can be used for example the "create", "start", "stop" methods.`); } @@ -149,14 +154,14 @@ export class SliderRangeFilter implements Filter { const maxValue = this.filterProperties.hasOwnProperty('maxValue') ? this.filterProperties.maxValue : DEFAULT_MAX_VALUE; const step = this.filterProperties.hasOwnProperty('valueStep') ? this.filterProperties.valueStep : DEFAULT_STEP; - let defaultStartValue; - let defaultEndValue; + let defaultStartValue: number = DEFAULT_MIN_VALUE; + let defaultEndValue: number = DEFAULT_MAX_VALUE; if (Array.isArray(searchTerms) && searchTerms.length > 1) { - defaultStartValue = searchTerms[0]; - defaultEndValue = searchTerms[1]; + defaultStartValue = +searchTerms[0]; + defaultEndValue = +searchTerms[1]; } else { - defaultStartValue = this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue; - defaultEndValue = this.filterParams.hasOwnProperty('sliderEndValue') ? this.filterParams.sliderEndValue : maxValue; + defaultStartValue = +(this.filterParams.hasOwnProperty('sliderStartValue') ? this.filterParams.sliderStartValue : minValue); + defaultEndValue = +(this.filterParams.hasOwnProperty('sliderEndValue') ? this.filterParams.sliderEndValue : maxValue); } $($headerElm).empty(); @@ -170,8 +175,8 @@ export class SliderRangeFilter implements Filter {
${defaultEndValue}
`); - this.$filterElm = $(`
`); - this.$filterContainerElm = $(`
`); + this.$filterElm = $(`
`); + this.$filterContainerElm = $(`
`); if (this.filterParams.hideSliderNumbers) { this.$filterContainerElm.append(this.$filterElm); @@ -181,6 +186,9 @@ export class SliderRangeFilter implements Filter { this.$filterContainerElm.append($highestSliderValueElm); } + // if we are preloading searchTerms, we'll keep them for reference + this._currentValues = [defaultStartValue, defaultEndValue]; + const definedOptions: JQueryUiSliderOption = { range: true, min: +minValue, @@ -215,7 +223,7 @@ export class SliderRangeFilter implements Filter { /** On a value change event triggered */ private onValueChanged(e: Event, ui: JQueryUiSliderResponse) { - const values = ui.values; + const values = ui && Array.isArray(ui.values) ? ui.values : []; const value = values.join('..'); if (this._clearFilterTriggered) { @@ -223,7 +231,7 @@ export class SliderRangeFilter implements Filter { this.$filterContainerElm.removeClass('filled'); } else { value === '' ? this.$filterContainerElm.removeClass('filled') : this.$filterContainerElm.addClass('filled'); - this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: [value], shouldTriggerQuery: this._shouldTriggerQuery }); + this.callback(e, { columnDef: this.columnDef, operator: this.operator, searchTerms: values, shouldTriggerQuery: this._shouldTriggerQuery }); } // reset both flags for next use this._clearFilterTriggered = false;