From 17555f24943cc880e35a8fe8bf29cc28417c253c Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Wed, 2 Jun 2021 13:20:32 -0400 Subject: [PATCH] fix(editors): select dropdown value is undefined it shouldn't call save --- .../__tests__/singleSelectEditor.spec.ts | 37 +++++++++++++------ .../angular-slickgrid/editors/selectEditor.ts | 4 +- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/app/modules/angular-slickgrid/editors/__tests__/singleSelectEditor.spec.ts b/src/app/modules/angular-slickgrid/editors/__tests__/singleSelectEditor.spec.ts index 9565a1bee..024a2a122 100644 --- a/src/app/modules/angular-slickgrid/editors/__tests__/singleSelectEditor.spec.ts +++ b/src/app/modules/angular-slickgrid/editors/__tests__/singleSelectEditor.spec.ts @@ -6,6 +6,7 @@ import { TranslateService, TranslateModule } from '@ngx-translate/core'; import { Editors } from '../index'; import { SingleSelectEditor } from '../singleSelectEditor'; import { Column, EditorArguments, GridOption } from '../../models'; +import { ColumnEditor } from 'dist/public_api'; const containerId = 'demo-container'; @@ -20,7 +21,7 @@ const gridOptionMock = { autoCommitEdit: false, editable: true, i18n: null, -} as GridOption; +} as unknown as GridOption; const getEditorLockMock = { commitCurrentEdit: jest.fn(), @@ -72,7 +73,7 @@ describe('SelectEditor', () => { grid: gridStub, column: mockColumn, item: mockItemData, - event: null, + event: null as any, cancelChanges: jest.fn(), commitChanges: jest.fn(), container: divContainer, @@ -87,7 +88,7 @@ describe('SelectEditor', () => { beforeEach(() => { mockItemData = { id: 1, gender: 'male', isActive: true }; mockColumn = { id: 'gender', field: 'gender', editable: true, editor: { model: Editors.multipleSelect }, internalColumnEditor: {} } as Column; - mockColumn.internalColumnEditor.collection = [{ value: '', label: '' }, { value: 'male', label: 'male' }, { value: 'female', label: 'female' }]; + (mockColumn.internalColumnEditor as ColumnEditor).collection = [{ value: '', label: '' }, { value: 'male', label: 'male' }, { value: 'female', label: 'female' }]; editorArguments.column = mockColumn; editorArguments.item = mockItemData; @@ -98,7 +99,7 @@ describe('SelectEditor', () => { }); it('should initialize the editor', () => { - mockColumn.internalColumnEditor.collection = [{ value: 'male', label: 'male' }, { value: 'female', label: 'female' }]; + (mockColumn.internalColumnEditor as ColumnEditor).collection = [{ value: 'male', label: 'male' }, { value: 'female', label: 'female' }]; gridOptionMock.i18n = translate; editor = new SingleSelectEditor(editorArguments); const editorCount = document.body.querySelectorAll('select.ms-filter.editor-gender').length; @@ -108,7 +109,7 @@ describe('SelectEditor', () => { it('should hide the DOM element div wrapper when the "hide" method is called', () => { editor = new SingleSelectEditor(editorArguments); - const editorElm = document.body.querySelector('[name=editor-gender].ms-drop'); + const editorElm = document.body.querySelector('[name=editor-gender].ms-drop') as HTMLDivElement; editor.show(); expect(editorElm.style.display).toBe(''); @@ -119,7 +120,7 @@ describe('SelectEditor', () => { it('should show the DOM element div wrapper when the "show" method is called', () => { editor = new SingleSelectEditor(editorArguments); - const editorElm = document.body.querySelector('[name=editor-gender].ms-drop'); + const editorElm = document.body.querySelector('[name=editor-gender].ms-drop') as HTMLDivElement; editor.hide(); expect(editorElm.style.display).toBe('none'); @@ -136,9 +137,21 @@ describe('SelectEditor', () => { }); describe('isValueChanged method', () => { + it('should return False if the value is undefined', () => { + editor = new SingleSelectEditor(editorArguments); + const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice') as HTMLButtonElement; + const editorListElm = divContainer.querySelectorAll(`[name=editor-gender].ms-drop ul>li input[type=radio]`); + editorBtnElm.click(); + + // we can use property "checked" or dispatch an event + editorListElm[0].checked = false; + + expect(editor.isValueChanged()).toBe(false); + }); + it('should return True after doing a check of an option', () => { editor = new SingleSelectEditor(editorArguments); - const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice'); + const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice') as HTMLButtonElement; const editorListElm = divContainer.querySelectorAll(`[name=editor-gender].ms-drop ul>li input[type=radio]`); editorBtnElm.click(); @@ -150,13 +163,13 @@ describe('SelectEditor', () => { }); it('should return False after re-selecting the same option as the one loaded', () => { - mockColumn.internalColumnEditor.collection = ['male', 'female']; + (mockColumn.internalColumnEditor as ColumnEditor).collection = ['male', 'female']; mockItemData = { id: 1, gender: 'male', isActive: true }; editor = new SingleSelectEditor(editorArguments); editor.loadValue(mockItemData); - const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice'); + const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice') as HTMLButtonElement; const editorListElm = divContainer.querySelectorAll(`[name=editor-gender].ms-drop ul>li input[type=radio]`); editorBtnElm.click(); @@ -213,7 +226,7 @@ describe('SelectEditor', () => { it('should return value as a string when using a dot (.) notation for complex object', () => { mockColumn.field = 'employee.gender'; - mockColumn.internalColumnEditor.collection = ['male', 'female']; + (mockColumn.internalColumnEditor as ColumnEditor).collection = ['male', 'female']; mockItemData = { id: 1, employee: { gender: 'male' }, isActive: true }; editor = new SingleSelectEditor(editorArguments); @@ -238,7 +251,7 @@ describe('SelectEditor', () => { editor = new SingleSelectEditor(editorArguments); editor.setValue(false); - const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice'); + const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice') as HTMLButtonElement; const editorListElm = divContainer.querySelectorAll(`[name=editor-gender].ms-drop ul>li span`); editorBtnElm.click(); @@ -265,7 +278,7 @@ describe('SelectEditor', () => { editor = new SingleSelectEditor(editorArguments); editor.loadValue(mockItemData); - const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice'); + const editorBtnElm = divContainer.querySelector('.ms-parent.ms-filter.editor-gender button.ms-choice') as HTMLButtonElement; const editorListElm = divContainer.querySelectorAll(`[name=editor-gender].ms-drop ul>li span`); editorBtnElm.click(); diff --git a/src/app/modules/angular-slickgrid/editors/selectEditor.ts b/src/app/modules/angular-slickgrid/editors/selectEditor.ts index a7937a4ff..95e8a718e 100644 --- a/src/app/modules/angular-slickgrid/editors/selectEditor.ts +++ b/src/app/modules/angular-slickgrid/editors/selectEditor.ts @@ -360,7 +360,7 @@ export class SelectEditor implements Editor { } destroy() { - // when autoCommitEdit is enabled, we might end up leave the editor without it being saved, if so do call a save before destroying + // when autoCommitEdit is enabled, we might end up leaving an editor without it being saved, if so do call a save before destroying // this mainly happens doing a blur or focusing on another cell in the grid (it won't come here if we click outside the grid, in the body) if (this.$editorElm && this.hasAutoCommitEdit && this.isValueChanged() && !this._isDisposing) { this._isDisposing = true; // change destroying flag to avoid infinite loop @@ -456,7 +456,7 @@ export class SelectEditor implements Editor { return !isEqual; } const value = Array.isArray(valueSelection) && valueSelection.length > 0 ? valueSelection[0] : undefined; - return value !== this.originalValue; + return value !== undefined && value !== this.originalValue; } validate(inputValue?: any): EditorValidatorOutput {