mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added React framework for the properties dialog and port Server Group, Server, and Database dialogs.
Following changes done for the framework: - Framework for creating React based dynamic form view out of a pre-defined UI schema. Previously, it was based on Backform/Backbone. - The new framework and components will use MaterialUI as the base. Previously, Bootstrap/Backform/jQuery components were used. - The new code uses JSS instead of CSS since material UI and most modern React libraries also use JSS. In the future, this will allow us to change the theme in real-time without refresh. - 90% code covered by 80-85 new jasmine test cases. - Server group node UI Schema migration to new, with schema test cases. - Server node UI Schema migration to new, with schema test cases. - Database node UI Schema migration to new, with schema test cases. - Few other UI changes. Fixes #6130
This commit is contained in:
committed by
Akshay Joshi
parent
a10b0c7786
commit
764677431f
56
web/regression/javascript/components/Buttons.spec.js
Normal file
56
web/regression/javascript/components/Buttons.spec.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 InfoIcon from '@material-ui/icons/InfoRounded';
|
||||
|
||||
import {PrimaryButton, DefaultButton, PgIconButton} from 'sources/components/Buttons';
|
||||
|
||||
/* MUI Components need to be wrapped in Theme for theme vars */
|
||||
describe('components Buttons', ()=>{
|
||||
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();
|
||||
});
|
||||
|
||||
it('PrimaryButton', ()=>{
|
||||
let ThemedBtn = withTheme(PrimaryButton);
|
||||
let btn = mount(<ThemedBtn>Test</ThemedBtn>);
|
||||
expect(btn.getDOMNode().classList.contains('MuiButton-containedPrimary')).toBe(true);
|
||||
});
|
||||
|
||||
it('DefaultButton', ()=>{
|
||||
let ThemedBtn = withTheme(DefaultButton);
|
||||
let btn = mount(<ThemedBtn className="testClass">Test</ThemedBtn>);
|
||||
expect(btn.getDOMNode().classList.contains('MuiButton-outlined')).toBe(true);
|
||||
expect(btn.getDOMNode().classList.contains('testClass')).toBe(true);
|
||||
});
|
||||
|
||||
it('PgIconButton', ()=>{
|
||||
let Icon = <InfoIcon />;
|
||||
let ThemedBtn = withTheme(PgIconButton);
|
||||
let btn = mount(<ThemedBtn title="The icon button" icon={Icon} className="testClass"></ThemedBtn>);
|
||||
expect(btn.find(InfoIcon)).not.toBe(null);
|
||||
});
|
||||
});
|
||||
46
web/regression/javascript/components/CodeMirror.spec.js
Normal file
46
web/regression/javascript/components/CodeMirror.spec.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 {default as OrigCodeMirror} from 'bundled_codemirror';
|
||||
|
||||
import CodeMirror from 'sources/components/CodeMirror';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
describe('CodeMirror', ()=>{
|
||||
let cmInstance, options={
|
||||
lineNumbers: true,
|
||||
mode: 'text/x-pgsql',
|
||||
}, cmObj = jasmine.createSpyObj('cmObj', {'setValue': ()=>{}, 'refresh': ()=>{}});
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
spyOn(OrigCodeMirror, 'fromTextArea').and.returnValue(cmObj);
|
||||
cmInstance = mount(
|
||||
<CodeMirror
|
||||
value={'Init text'}
|
||||
options={options}
|
||||
className="testClass"
|
||||
/>);
|
||||
});
|
||||
|
||||
it('init', ()=>{
|
||||
/* textarea ref passed to fromTextArea */
|
||||
expect(OrigCodeMirror.fromTextArea).toHaveBeenCalledWith(cmInstance.getDOMNode(), options);
|
||||
expect(cmObj.setValue).toHaveBeenCalledWith('Init text');
|
||||
expect(cmObj.refresh).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('change value', ()=>{
|
||||
cmInstance.setProps({value: 'the new text'});
|
||||
expect(cmObj.setValue).toHaveBeenCalledWith('the new text');
|
||||
expect(cmObj.refresh).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
606
web/regression/javascript/components/FormComponents.spec.js
Normal file
606
web/regression/javascript/components/FormComponents.spec.js
Normal file
@@ -0,0 +1,606 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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(
|
||||
<ThemedFormInputText
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputText */
|
||||
readonly={false}
|
||||
disabled={false}
|
||||
maxlength={50}
|
||||
value={'thevalue'}
|
||||
controlProps={{
|
||||
extraprop: 'test'
|
||||
}}
|
||||
/>);
|
||||
});
|
||||
|
||||
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');
|
||||
expect(ctrl.find(OutlinedInput).prop('onChange')).toBe(onChange);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputFileSelect
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputText */
|
||||
readonly={false}
|
||||
disabled={false}
|
||||
value={'thevalue'}
|
||||
controlProps={{
|
||||
dialogType: 'select_file', supportedTypes: ['*'],
|
||||
}}
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputSQL
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputSQL */
|
||||
value={'thevalue'}
|
||||
controlProps={{
|
||||
op1: 'test'
|
||||
}}
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputSwitch
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputSwitch */
|
||||
readonly={false}
|
||||
value={false}
|
||||
onChange={onChange}
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputCheckbox
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputCheckbox */
|
||||
disabled={false}
|
||||
value={false}
|
||||
onChange={onChange}
|
||||
controlProps={{
|
||||
label: 'Second'
|
||||
}}
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputToggle
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputToggle */
|
||||
disabled={false}
|
||||
options={[
|
||||
{label: 'Op1', value: 1},
|
||||
{label: 'Op2', value: 2},
|
||||
{label: 'Op3', value: 3},
|
||||
]}
|
||||
value={2}
|
||||
onChange={onChange}
|
||||
/>);
|
||||
});
|
||||
|
||||
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(
|
||||
<ThemedFormInputSelect
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputSelect */
|
||||
readonly={false}
|
||||
disabled={false}
|
||||
options={[
|
||||
{label: 'Op1', value: 1},
|
||||
{label: 'Op2', value: 2},
|
||||
{label: 'Op3', value: 3},
|
||||
]}
|
||||
value={1}
|
||||
onChange={onChange}
|
||||
{...props}
|
||||
/>);
|
||||
};
|
||||
|
||||
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(
|
||||
<ThemedFormInputColor
|
||||
label="First"
|
||||
className="someClass"
|
||||
testcid="inpCid"
|
||||
helpMessage="some help message"
|
||||
/* InputColor */
|
||||
disabled={false}
|
||||
value="#f0f"
|
||||
onChange={onChange}
|
||||
currObj={(obj)=>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(
|
||||
<ThemedFormFooterMessage
|
||||
type={MESSAGE_TYPE.SUCCESS}
|
||||
message="Some message"
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
/>);
|
||||
});
|
||||
|
||||
// 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
52
web/regression/javascript/components/Loader.spec.js
Normal file
52
web/regression/javascript/components/Loader.spec.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 { createMount } from '@material-ui/core/test-utils';
|
||||
import { withTheme } from '../fake_theme';
|
||||
import Loader from 'sources/components/Loader';
|
||||
|
||||
|
||||
/* MUI Components need to be wrapped in Theme for theme vars */
|
||||
describe('Loader', ()=>{
|
||||
let mount, loaderInst, ThemedLoader;
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
/* Loader need Mui Theme context as well */
|
||||
ThemedLoader = withTheme(Loader);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
loaderInst = mount(<ThemedLoader message={'loading'} />);
|
||||
});
|
||||
|
||||
it('init', ()=>{
|
||||
expect(loaderInst.find('.MuiTypography-root').text()).toBe('loading');
|
||||
});
|
||||
|
||||
it('no message', ()=>{
|
||||
loaderInst.setProps({message: ''});
|
||||
expect(loaderInst.isEmptyRender()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('change message', ()=>{
|
||||
loaderInst.setProps({message: 'test message'});
|
||||
expect(loaderInst.find('.MuiTypography-root').text()).toBe('test message');
|
||||
});
|
||||
});
|
||||
204
web/regression/javascript/components/Privilege.spec.js
Normal file
204
web/regression/javascript/components/Privilege.spec.js
Normal file
@@ -0,0 +1,204 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 Privilege from 'sources/components/Privilege';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
describe('Privilege', ()=>{
|
||||
let ctrl, onChange = jasmine.createSpy('onChange');
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
ctrl = mount(
|
||||
<Privilege
|
||||
value={[{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
}]}
|
||||
controlProps={{
|
||||
supportedPrivs: ['C', 'a', 'r']
|
||||
}}
|
||||
onChange={onChange}
|
||||
/>);
|
||||
});
|
||||
|
||||
it('init', ()=>{
|
||||
expect(ctrl.find('InputText').prop('value')).toBe('Ca*');
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(0).prop('value')).toBeTrue();
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(1).prop('value')).toBeFalse();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(0).prop('value')).toBeTrue();
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(1).prop('value')).toBeTrue();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(0).prop('value')).toBeFalse();
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(1).prop('value')).toBeFalse();
|
||||
});
|
||||
|
||||
it('change prop value', ()=>{
|
||||
ctrl.setProps({value: [{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'r',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
}]});
|
||||
|
||||
expect(ctrl.find('InputText').prop('value')).toBe('C*r');
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(0).prop('value')).toBeTrue();
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(1).prop('value')).toBeTrue();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(0).prop('value')).toBeFalse();
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(1).prop('value')).toBeFalse();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(0).prop('value')).toBeTrue();
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(1).prop('value')).toBeFalse();
|
||||
});
|
||||
|
||||
it('no prop value', ()=>{
|
||||
ctrl.setProps({value: null});
|
||||
|
||||
expect(ctrl.find('InputText').prop('value')).toBe('');
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(0).prop('value')).toBeFalse();
|
||||
expect(ctrl.find('InputCheckbox[name="C"]').at(1).prop('value')).toBeFalse();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(0).prop('value')).toBeFalse();
|
||||
expect(ctrl.find('InputCheckbox[name="a"]').at(1).prop('value')).toBeFalse();
|
||||
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(0).prop('value')).toBeFalse();
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(1).prop('value')).toBeFalse();
|
||||
});
|
||||
|
||||
it('with grant disabled', ()=>{
|
||||
expect(ctrl.find('InputCheckbox[name="all"]').at(1).prop('disabled')).toBeTrue();
|
||||
expect(ctrl.find('InputCheckbox[name="r"]').at(1).prop('disabled')).toBeTrue();
|
||||
});
|
||||
|
||||
it('on check click', (done)=>{
|
||||
onChange.calls.reset();
|
||||
ctrl.find('InputCheckbox[name="C"]').at(0).find('input').
|
||||
simulate('change', {target: {checked: false, name: 'C'}});
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(onChange).toHaveBeenCalledWith([{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
}]);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('on new check click', (done)=>{
|
||||
onChange.calls.reset();
|
||||
ctrl.find('InputCheckbox[name="r"]').at(0).find('input').
|
||||
simulate('change', {target: {checked: true, name: 'r'}});
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(onChange).toHaveBeenCalledWith([{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'r',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
}]);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('on check grant click', (done)=>{
|
||||
onChange.calls.reset();
|
||||
ctrl.find('InputCheckbox[name="C"]').at(1).find('input').
|
||||
simulate('change', {target: {checked: true, name: 'C'}});
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(onChange).toHaveBeenCalledWith([{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
}]);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('on all click', (done)=>{
|
||||
ctrl.find('InputCheckbox[name="all"]').at(0).find('input').simulate('change', {target: {checked: true}});
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(onChange).toHaveBeenCalledWith([{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'r',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
}]);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('on all with grant click', (done)=>{
|
||||
ctrl.setProps({
|
||||
value: [{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'r',
|
||||
privilege: true,
|
||||
with_grant: false,
|
||||
}]
|
||||
});
|
||||
ctrl.find('InputCheckbox[name="all"]').at(1).find('input').simulate('change', {target: {checked: true}});
|
||||
|
||||
setTimeout(()=>{
|
||||
expect(onChange).toHaveBeenCalledWith([{
|
||||
privilege_type: 'C',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'a',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
},{
|
||||
privilege_type: 'r',
|
||||
privilege: true,
|
||||
with_grant: true,
|
||||
}]);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
48
web/regression/javascript/components/TabPanel.spec.js
Normal file
48
web/regression/javascript/components/TabPanel.spec.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 { createMount } from '@material-ui/core/test-utils';
|
||||
import { withTheme } from '../fake_theme';
|
||||
import TabPanel from 'sources/components/TabPanel';
|
||||
|
||||
|
||||
/* MUI Components need to be wrapped in Theme for theme vars */
|
||||
describe('TabPanel', ()=>{
|
||||
let mount, panelInst, ThemedPanel;
|
||||
|
||||
/* Use createMount so that material ui components gets the required context */
|
||||
/* https://material-ui.com/guides/testing/#api */
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
/* Need Mui Theme context as well */
|
||||
ThemedPanel = withTheme(TabPanel);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
panelInst = mount(<ThemedPanel value={1} index={0}><h1>test</h1></ThemedPanel>);
|
||||
});
|
||||
|
||||
it('init', ()=>{
|
||||
expect(panelInst.getDOMNode().hidden).toBeTrue();
|
||||
expect(panelInst.find('h1')).not.toBe(null);
|
||||
});
|
||||
|
||||
it('tab select', ()=>{
|
||||
panelInst.setProps({value: 0});
|
||||
expect(panelInst.getDOMNode().hidden).toBeFalse();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user