///////////////////////////////////////////////////////////// // // pgAdmin 4 - PostgreSQL Tools // // Copyright (C) 2013 - 2021, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////// import jasmineEnzyme from 'jasmine-enzyme'; import React from 'react'; import '../helper/enzyme.helper'; import { withTheme } from '../fake_theme'; import { createMount } from '@material-ui/core/test-utils'; import { OutlinedInput, FormHelperText, IconButton, FormControlLabel, Switch, Checkbox, Button, InputLabel } from '@material-ui/core'; import Select from 'react-select'; import CreatableSelect from 'react-select/creatable'; import CheckRoundedIcon from '@material-ui/icons/CheckRounded'; import ReportProblemIcon from '@material-ui/icons/ReportProblemRounded'; import InfoIcon from '@material-ui/icons/InfoRounded'; import CloseIcon from '@material-ui/icons/CloseRounded'; import CheckIcon from '@material-ui/icons/CheckCircleOutlineRounded'; import {FormInputText, FormInputFileSelect, FormInputSQL, FormInputSwitch, FormInputCheckbox, FormInputToggle, FormInputSelect, FormInputColor, FormFooterMessage, MESSAGE_TYPE} from '../../../pgadmin/static/js/components/FormComponents'; import * as legacyConnector from '../../../pgadmin/static/js/helpers/legacyConnector'; import CodeMirror from '../../../pgadmin/static/js/components/CodeMirror'; import { ToggleButton } from '@material-ui/lab'; import { DefaultButton, PrimaryButton } from '../../../pgadmin/static/js/components/Buttons'; /* MUI Components need to be wrapped in Theme for theme vars */ describe('FormComponents', ()=>{ let mount; /* Use createMount so that material ui components gets the required context */ /* https://material-ui.com/guides/testing/#api */ beforeAll(()=>{ mount = createMount(); }); afterAll(() => { mount.cleanUp(); }); beforeEach(()=>{ jasmineEnzyme(); }); describe('FormInputText', ()=>{ let ThemedFormInputText = withTheme(FormInputText), ctrl; beforeEach(()=>{ ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(OutlinedInput).prop('extraprop')).toEqual('test'); expect( ctrl.find(OutlinedInput).prop('inputProps')).toEqual(jasmine.objectContaining({ maxLength: 50, })); expect(ctrl.find(OutlinedInput).prop('readOnly')).toBe(false); expect(ctrl.find(OutlinedInput).prop('disabled')).toBe(false); expect(ctrl.find(OutlinedInput).prop('value')).toBe('thevalue'); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); it('props change', ()=>{ let onChange = ()=>{}; ctrl.setProps({ readonly: true, disabled: true, value: 'new value', onChange: onChange, }); expect(ctrl.find(OutlinedInput).prop('readOnly')).toBe(true); expect(ctrl.find(OutlinedInput).prop('disabled')).toBe(true); expect(ctrl.find(OutlinedInput).prop('value')).toBe('new value'); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); let inputProps = ctrl.find(OutlinedInput).prop('inputProps'); expect(inputProps).toEqual(jasmine.objectContaining({ id: 'inpCid', 'aria-describedby': 'hinpCid', })); }); }); describe('FormInputFileSelect', ()=>{ let ThemedFormInputFileSelect = withTheme(FormInputFileSelect), ctrl; beforeEach(()=>{ spyOn(legacyConnector, 'showFileDialog').and.callFake((controlProps, onFileSelect)=>{ onFileSelect('selected/file'); }); ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(OutlinedInput).prop('readOnly')).toBe(false); expect(ctrl.find(OutlinedInput).prop('disabled')).toBe(false); expect(ctrl.find(OutlinedInput).prop('value')).toBe('thevalue'); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); it('props change', ()=>{ ctrl.setProps({ readonly: true, disabled: true, value: 'new value', }); expect(ctrl.find(OutlinedInput).prop('readOnly')).toBe(true); expect(ctrl.find(OutlinedInput).prop('disabled')).toBe(true); expect(ctrl.find(OutlinedInput).prop('value')).toBe('new value'); expect(ctrl.find(IconButton).prop('disabled')).toBe(true); }); it('file select', (done)=>{ let onChange = jasmine.createSpy(); ctrl.setProps({ onChange: onChange, }); ctrl.find(IconButton).simulate('click'); setTimeout(()=>{ expect(onChange).toHaveBeenCalledWith('selected/file'); done(); }, 0); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); let inputProps = ctrl.find(OutlinedInput).prop('inputProps'); expect(inputProps).toEqual(jasmine.objectContaining({ id: 'inpCid', 'aria-describedby': 'hinpCid', })); }); }); describe('FormInputSQL', ()=>{ let ThemedFormInputSQL = withTheme(FormInputSQL), ctrl; beforeEach(()=>{ ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(CodeMirror).prop('value')).toEqual('thevalue'); expect(ctrl.find(CodeMirror).prop('options')).toEqual(jasmine.objectContaining({ op1: 'test' })); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); }); describe('FormInputSwitch', ()=>{ let ThemedFormInputSwitch = withTheme(FormInputSwitch), ctrl, onChange=()=>{return 1;}; beforeEach(()=>{ ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(Switch).prop('checked')).toBe(false); expect(ctrl.find(Switch).prop('onChange')).toBe(onChange); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); it('props change', ()=>{ ctrl.setProps({ readonly: true, value: true, }); expect(ctrl.find(Switch).prop('checked')).toBe(true); expect(ctrl.find(Switch).prop('onChange')).not.toBe(onChange); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); expect(ctrl.find(Switch).prop('id')).toBe('inpCid'); let inputProps = ctrl.find(Switch).prop('inputProps'); expect(inputProps).toEqual(jasmine.objectContaining({ 'aria-describedby': 'hinpCid', })); }); }); describe('FormInputCheckbox', ()=>{ let ThemedFormInputCheckbox = withTheme(FormInputCheckbox), ctrl, onChange=()=>{return 1;}; beforeEach(()=>{ ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(FormControlLabel).prop('label')).toBe('Second'); expect(ctrl.find(Checkbox).prop('checked')).toBe(false); expect(ctrl.find(Checkbox).prop('onChange')).toBe(onChange); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); it('props change', ()=>{ ctrl.setProps({ readonly: true, value: true, }); expect(ctrl.find(Checkbox).prop('checked')).toBe(true); expect(ctrl.find(Checkbox).prop('onChange')).not.toBe(onChange); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); expect(ctrl.find(Checkbox).prop('id')).toBe('inpCid'); let inputProps = ctrl.find(Checkbox).prop('inputProps'); expect(inputProps).toEqual(jasmine.objectContaining({ 'aria-describedby': 'hinpCid', })); }); }); describe('FormInputToggle', ()=>{ let ThemedFormInputToggle = withTheme(FormInputToggle), ctrl, onChange=()=>{return 1;}; beforeEach(()=>{ ctrl = mount( ); }); it('init', ()=>{ expect(ctrl.find(InputLabel).text()).toBe('First'); expect(ctrl.find(ToggleButton).length).toBe(3); expect(ctrl.find(PrimaryButton).length).toBe(1); expect(ctrl.find(DefaultButton).length).toBe(2); expect(ctrl.find(ToggleButton).at(1).prop('component')).toBe(PrimaryButton); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); }); it('props change', ()=>{ ctrl.setProps({ value: 1, }); expect(ctrl.find(ToggleButton).at(0).prop('component')).toBe(PrimaryButton); expect(ctrl.find(ToggleButton).at(0) .find(CheckRoundedIcon) .prop('style')).toEqual(jasmine.objectContaining({ visibility: 'visible' })); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); }); }); describe('FormInputSelect', ()=>{ let ThemedFormInputSelect = withTheme(FormInputSelect), ctrl, onChange=jasmine.createSpy('onChange'), ctrlMount = (props)=>{ ctrl?.unmount(); ctrl = mount( ); }; beforeEach(()=>{ ctrlMount(); }); it('init', (done)=>{ expect(ctrl.find(Select).exists()).toBe(true); expect(ctrl.find(CreatableSelect).exists()).toBe(false); expect(ctrl.find(FormHelperText).text()).toBe('some help message'); setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Select).props()).toEqual(jasmine.objectContaining({ isMulti: false, value: {label: 'Op1', value: 1}, inputId: 'inpCid', isSearchable: true, isClearable: true, isDisabled: false, })); done(); }, 0); }); it('readonly disabled', (done)=>{ ctrl.setProps({ readonly: true, disabled: true, }); setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Select).props()).toEqual(jasmine.objectContaining({ isSearchable: false, isClearable: false, isDisabled: true, openMenuOnClick: false, })); done(); }, 0); }); it('no-clear with multi', (done)=>{ ctrl.setProps({ controlProps: { allowClear: false, multiple: true, }, value: [2, 3], }); setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Select).props()).toEqual(jasmine.objectContaining({ isMulti: true, isClearable: false, value: [{label: 'Op2', value: 2}, {label: 'Op3', value: 3}] })); done(); }, 0); }); it('creatable with multi', (done)=>{ ctrl.setProps({ controlProps: { creatable: true, multiple: true, }, value: ['val1', 'val2'], }); setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Select).exists()).toBe(false); expect(ctrl.find(CreatableSelect).exists()).toBe(true); expect(ctrl.find(CreatableSelect).props()).toEqual(jasmine.objectContaining({ isMulti: true, value: [{label: 'val1', value: 'val1'}, {label: 'val2', value: 'val2'}] })); done(); }, 0); }); it('promise options', (done)=>{ let optionsLoaded = jasmine.createSpy(); let res = [ {label: 'PrOp1', value: 1}, {label: 'PrOp2', value: 2}, {label: 'PrOp3', value: 3}, ]; /* For options change, remount needed */ ctrlMount({ options: ()=>Promise.resolve(res), value: 3, optionsLoaded: optionsLoaded, }); setTimeout(()=>{ ctrl.update(); expect(optionsLoaded).toHaveBeenCalledWith(res, 3); expect(ctrl.find(Select).props()).toEqual(jasmine.objectContaining({ value: {label: 'PrOp3', value: 3}, })); done(); }, 0); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); }); }); describe('FormInputColor', ()=>{ let pickrObj = React.createRef(); let ThemedFormInputColor = withTheme(FormInputColor), ctrl, onChange=jasmine.createSpy('onChange'); beforeEach(()=>{ ctrl = mount( pickrObj.current=obj} />); }); afterEach(()=>{ ctrl.unmount(); }); it('init', (done)=>{ setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Button).prop('style')).toEqual(jasmine.objectContaining({ backgroundColor: '#f0f', })); done(); }, 0); }); it('no color', (done)=>{ ctrl.setProps({ value: null, }); setTimeout(()=>{ ctrl.update(); expect(ctrl.find(Button).prop('style')).toEqual(jasmine.objectContaining({ backgroundColor: null, })); expect(ctrl.find(Button).find(CloseIcon).exists()).toBe(true); done(); }, 0); }); it('other events', (done)=>{ pickrObj.current.applyColor(false); setTimeout(()=>{ expect(onChange).toHaveBeenCalled(); done(); }, 0); }); it('accessibility', ()=>{ expect(ctrl.find(InputLabel)).toHaveProp('htmlFor', 'inpCid'); expect(ctrl.find(FormHelperText)).toHaveProp('id', 'hinpCid'); }); }); describe('FormFooterMessage', ()=>{ let ThemedFormFooterMessage = withTheme(FormFooterMessage), ctrl, onClose=jasmine.createSpy('onClose'); beforeEach(()=>{ ctrl = mount( ); }); // if(close) { // TheIcon = CloseIcon; // } else if(type === MESSAGE_TYPE.SUCCESS) { // TheIcon = CheckIcon; // } else if(type === MESSAGE_TYPE.ERROR) { // TheIcon = ReportProblemIcon; // } else if(type === MESSAGE_TYPE.INFO) { // TheIcon = InfoIcon; // } it('init', ()=>{ expect(ctrl.find(CheckIcon).exists()).toBeTrue(); expect(ctrl.text()).toBe('Some message'); }); it('change types', ()=>{ ctrl.setProps({ type: MESSAGE_TYPE.ERROR, }); expect(ctrl.find(ReportProblemIcon).exists()).toBeTrue(); ctrl.setProps({ type: MESSAGE_TYPE.INFO, }); expect(ctrl.find(InfoIcon).exists()).toBeTrue(); }); it('closable', ()=>{ ctrl.setProps({ closable: true, }); expect(ctrl.find(CloseIcon).exists()).toBeTrue(); ctrl.find(IconButton).simulate('click'); expect(onClose).toHaveBeenCalled(); }); it('no message', ()=>{ ctrl.setProps({ message: '', }); expect(ctrl.isEmptyRender()).toBeTrue(); }); }); });