Commit 89b211ad authored by Jaden DIEFENBAUGH's avatar Jaden DIEFENBAUGH
Browse files

[js][db] refactored db editor & tests, reenabled creation test

parent ac831105
......@@ -35,6 +35,7 @@ import type { BeatObject } from '@helpers/beat';
import * as Selectors from '@store/selectors.js';
import * as Actions from '@store/actions.js';
import ValidSchemaBadge from '../ValidSchemaBadge.jsx';
import CacheInput from '../CacheInput.jsx';
import DeleteInputBtn from '../DeleteInputBtn.jsx';
......@@ -48,10 +49,10 @@ type Props = {
saveFunc: (BeatObject) => any,
databases: BeatObject[],
dataformats: BeatObject[],
updateFunc: (BeatObject) => any,
};
type State = {
cache: any,
activeProtocol: number,
};
......@@ -80,24 +81,15 @@ export class DatabaseEditor extends React.Component<Props, State> {
}
state = {
cache: getValidObj(this.props.data),
activeProtocol: 0,
}
componentWillReceiveProps (nextProps: Props) {
this.setState({
cache: getValidObj(nextProps.data),
});
}
setContents = (newContents: any) => {
this.setState({
cache: {
...this.state.cache,
contents: {
'description': this.state.cache.contents['description'],
...newContents,
}
this.props.updateFunc({
...this.props.data,
contents: {
'description': this.props.data.contents['description'],
...newContents,
}
});
}
......@@ -108,13 +100,13 @@ export class DatabaseEditor extends React.Component<Props, State> {
updateProtocol = (index: number, obj: Protocol) => {
this.setContents({
...this.state.cache.contents,
protocols: this.state.cache.contents.protocols.map((o, i) => i === index ? obj : o)
...this.props.data.contents,
protocols: this.props.data.contents.protocols.map((o, i) => i === index ? obj : o)
});
}
updateSet = (idxProtocol: number, idxSet: number, obj: Set) => {
const protocol = this.state.cache.contents.protocols[idxProtocol];
const protocol = this.props.data.contents.protocols[idxProtocol];
this.updateProtocol(
idxProtocol,
{
......@@ -507,7 +499,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
render = () => {
const protocolIdx = this.state.activeProtocol;
const protocol = protocolIdx > -1 ? this.state.cache.contents.protocols[protocolIdx] || undefined : undefined;
const protocol = protocolIdx > -1 ? this.props.data.contents.protocols[protocolIdx] || undefined : undefined;
return (
<div className='databaseEditor'>
......@@ -516,12 +508,12 @@ export class DatabaseEditor extends React.Component<Props, State> {
className='mx-auto'
outline
color='secondary'
onClick={() => this.props.saveFunc(this.state.cache)}
onClick={() => this.props.saveFunc(this.props.data)}
>
Save Changes (Changes are <ValidSchemaBadge entity='database' obj={this.state.cache} />)
Save Changes (Changes are <ValidSchemaBadge entity='database' obj={this.props.data} />)
</Button>
<TemplateButton
data={this.state.cache}
data={this.props.data}
entity={'database'}
/>
</div>
......@@ -533,8 +525,8 @@ export class DatabaseEditor extends React.Component<Props, State> {
type='text'
name='description'
placeholder='Database description...'
value={this.state.cache.contents['description']}
onChange={e => this.setContents({ ...this.state.cache.contents, 'description': e.target.value})}
value={this.props.data.contents['description']}
onChange={e => this.setContents({ ...this.props.data.contents, 'description': e.target.value})}
/>
</FormGroup>
<FormGroup>
......@@ -543,8 +535,8 @@ export class DatabaseEditor extends React.Component<Props, State> {
type='text'
name='rootFolder'
placeholder='Valid system path...'
value={this.state.cache.contents['root_folder']}
onChange={e => this.setContents({ ...this.state.cache.contents, 'root_folder': e.target.value})}
value={this.props.data.contents['root_folder']}
onChange={e => this.setContents({ ...this.props.data.contents, 'root_folder': e.target.value})}
/>
</FormGroup>
</FormGroup>
......@@ -563,15 +555,15 @@ export class DatabaseEditor extends React.Component<Props, State> {
</DropdownToggle>
<DropdownMenu>
{
this.state.cache.contents.protocols
this.props.data.contents.protocols
.map((p, i) =>
<DropdownItem
id={`protocolChoice${ i }`}
key={i}
onClick={() => this.activateProtocol(i)}
>
{ this.state.cache.contents.protocols[i].name }{' '}
({ this.state.cache.contents.protocols[i].template })
{ this.props.data.contents.protocols[i].name }{' '}
({ this.props.data.contents.protocols[i].template })
</DropdownItem>
)
}
......@@ -580,11 +572,11 @@ export class DatabaseEditor extends React.Component<Props, State> {
<ButtonGroup>
<Button outline color='danger'
onClick={e => {
const protocols = this.state.cache.contents.protocols
const protocols = this.props.data.contents.protocols
.filter((p, i) => i !== protocolIdx);
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -595,7 +587,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
</Button>
<Button outline color='secondary'
onClick={e => {
const protocols = [...this.state.cache.contents.protocols];
const protocols = [...this.props.data.contents.protocols];
protocols.splice(
protocolIdx + 1,
0,
......@@ -603,7 +595,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
);
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -618,14 +610,14 @@ export class DatabaseEditor extends React.Component<Props, State> {
color='success'
id='newProtocol'
onClick={e => {
const protocols = [...this.state.cache.contents.protocols, {
const protocols = [...this.props.data.contents.protocols, {
name: '',
template: '',
sets: [],
}];
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -644,7 +636,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
<h4>Quick Jump:</h4>
<ListGroup>
{
this.state.cache.contents.protocols.map((p, i) => {
this.props.data.contents.protocols.map((p, i) => {
const setList = (
<ListGroup className='mt-1'>
{
......@@ -744,11 +736,11 @@ export class DatabaseEditor extends React.Component<Props, State> {
<ButtonGroup className='float-right'>
<Button size='sm' outline color='danger'
onClick={e => {
const protocols = this.state.cache.contents.protocols
const protocols = this.props.data.contents.protocols
.filter((p, i) => i !== protocolIdx);
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -759,7 +751,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
</Button>
<Button size='sm' outline color='secondary'
onClick={e => {
const protocols = [...this.state.cache.contents.protocols];
const protocols = [...this.props.data.contents.protocols];
protocols.splice(
protocolIdx + 1,
0,
......@@ -767,7 +759,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
);
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -785,14 +777,14 @@ export class DatabaseEditor extends React.Component<Props, State> {
}
<ListGroupItem tag='button' action className='text-primary'
onClick={e => {
const protocols = [...this.state.cache.contents.protocols, {
const protocols = [...this.props.data.contents.protocols, {
name: '',
template: '',
sets: [],
}];
this.setContents({
...this.state.cache.contents,
...this.props.data.contents,
protocols
});
......@@ -809,11 +801,21 @@ export class DatabaseEditor extends React.Component<Props, State> {
}
const mapStateToProps = (state, ownProps) => {
const dbs = Selectors.databaseGet(state);
const obj = {
databases: Selectors.databaseGet(state),
databases: dbs,
dataformats: Selectors.dataformatGet(state),
data: dbs[ownProps.index] || getValidObj()
};
return obj;
};
export default connect(mapStateToProps)(DatabaseEditor);
const mapDispatchToProps = (dispatch, ownProps) => ({
// replace the obj in the Redux store with the new object
updateFunc: (obj) => {
console.log(`dispatching for ${ obj.name }`);
dispatch(Actions[`databaseUpdate`](obj.name, obj));
},
});
export default connect(mapStateToProps, mapDispatchToProps)(DatabaseEditor);
......@@ -5,6 +5,7 @@ import { mount } from 'enzyme';
import sinon from 'sinon';
import { spies } from '@test';
import { getValidDatabaseObj as getValidObj } from '@helpers/beat';
import { DatabaseEditor as C } from '.';
import testDbs from '@test/test_dbs.json';
......@@ -48,10 +49,11 @@ describe('<DatabaseEditor />', () => {
]
}
}
].concat(testDbs);
].concat(testDbs.map(db => getValidObj(db)));
dbs.forEach(function(db){
const saveFunc = () => {};
const updateFunc = () => {};
it(`${ db.name }`, () => {
wrapper = mount(
<C
......@@ -59,28 +61,34 @@ describe('<DatabaseEditor />', () => {
databases={dbs}
dataformats={dfs}
saveFunc={saveFunc}
updateFunc={updateFunc}
/>
);
expect(wrapper).to.have.props(
['data', 'databases', 'dataformats', 'saveFunc']
['data', 'databases', 'dataformats', 'saveFunc', 'updateFunc']
).deep.equal(
[db, dbs, dfs, saveFunc]
[db, dbs, dfs, saveFunc, updateFunc]
);
});
});
});
describe.skip('creates', () => {
describe('creates', () => {
it('simple/1', () => {
const dbName = 'simple/1';
const saveFunc = sinon.spy();
const _updateFunc = (obj) => {
wrapper.setProps && wrapper.setProps({ data: obj });
};
const updateFunc = sinon.spy(_updateFunc);
wrapper = mount(
<C
data={{name: dbName, contents: {}}}
databases={testDbs.filter(d => d.name !== dbName)}
data={getValidObj({name: dbName, contents: {}})}
databases={testDbs.filter(d => d.name !== dbName).map(d => getValidObj(d))}
dataformats={testDfs}
saveFunc={saveFunc}
updateFunc={updateFunc}
/>
);
......@@ -89,101 +97,136 @@ describe('<DatabaseEditor />', () => {
);
// general db
expect(wrapper.state('cache')).to.have.property('name', dbName);
expect(wrapper.props().data).to.have.property('name', dbName);
wrapper.find('input[name="description"]').simulate('change', { target: { value: 'A test database that emits integers' }});
expect(wrapper.state('cache').contents).to.have.property('description', 'A test database that emits integers');
expect(updateFunc.callCount).to.equal(1);
expect(wrapper.props().data.contents).to.have.property('description', 'A test database that emits integers');
wrapper.find('input[name="rootFolder"]').simulate('change', { target: { value: '/this/database/does/not/require/a/path' }});
expect(wrapper.state('cache').contents).to.have.property('root_folder', '/this/database/does/not/require/a/path');
expect(updateFunc.callCount).to.equal(2);
expect(wrapper.props().data.contents).to.have.property('root_folder', '/this/database/does/not/require/a/path');
// create protocols
wrapper.find('button#newProtocol').simulate('click');
expect(updateFunc.callCount).to.equal(3);
wrapper.find('button#newProtocol').simulate('click');
expect(updateFunc.callCount).to.equal(4);
expect(wrapper.state('cache').contents).to.have.property('protocols').with.lengthOf(2);
expect(wrapper.props().data.contents).to.have.property('protocols').with.lengthOf(2);
// protocol 1
wrapper.find('button#protocolChoice0').simulate('click');
wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol' }});
expect(wrapper.state('cache').contents.protocols[0]).to.have.property('name', 'protocol');
expect(updateFunc.callCount).to.equal(5);
expect(wrapper.props().data.contents.protocols[0]).to.have.property('name', 'protocol');
wrapper.find('CacheInput[name="protocolTemplate"]').prop('onChange')( { target: { value: 'test_integers' }});
expect(wrapper.state('cache').contents.protocols[0]).to.have.property('template', 'test_integers');
expect(updateFunc.callCount).to.equal(6);
expect(wrapper.props().data.contents.protocols[0]).to.have.property('template', 'test_integers');
// protocol 1 sets
wrapper.find('button#newSet').simulate('click');
expect(updateFunc.callCount).to.equal(7);
wrapper.find('button#newSet').simulate('click');
expect(wrapper.state('cache').contents.protocols[0]).to.have.property('sets').with.lengthOf(2);
expect(updateFunc.callCount).to.equal(8);
expect(wrapper.props().data.contents.protocols[0]).to.have.property('sets').with.lengthOf(2);
// protocol 1 set 1
wrapper.find('CacheInput[name="setName0"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[0].sets[0]).to.have.property('name', 'set');
expect(updateFunc.callCount).to.equal(9);
expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('name', 'set');
wrapper.find('CacheInput[name="setTemplate0"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[0].sets[0]).to.have.property('template', 'set');
expect(updateFunc.callCount).to.equal(10);
expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('template', 'set');
wrapper.find('CacheInput[name="setView0"]').prop('onChange')( { target: { value: 'View' }});
expect(wrapper.state('cache').contents.protocols[0].sets[0]).to.have.property('view', 'View');
expect(updateFunc.callCount).to.equal(11);
expect(wrapper.props().data.contents.protocols[0].sets[0]).to.have.property('view', 'View');
wrapper.find('.set0 button.newOutput').simulate('click');
expect(updateFunc.callCount).to.equal(12);
wrapper.find('.set0 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }});
expect(updateFunc.callCount).to.equal(13);
wrapper.find('.set0 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }});
expect(wrapper.state('cache').contents.protocols[0].sets[0].outputs).to.have.property('out', 'system/integer/1');
expect(updateFunc.callCount).to.equal(14);
expect(wrapper.props().data.contents.protocols[0].sets[0].outputs).to.have.property('out', 'system/integer/1');
// protocol 1 set 2
wrapper.find('CacheInput[name="setName1"]').prop('onChange')( { target: { value: 'set2' }});
expect(wrapper.state('cache').contents.protocols[0].sets[1]).to.have.property('name', 'set2');
expect(updateFunc.callCount).to.equal(15);
expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('name', 'set2');
wrapper.find('CacheInput[name="setTemplate1"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[0].sets[1]).to.have.property('template', 'set');
expect(updateFunc.callCount).to.equal(16);
expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('template', 'set');
wrapper.find('CacheInput[name="setView1"]').prop('onChange')( { target: { value: 'View2' }});
expect(wrapper.state('cache').contents.protocols[0].sets[1]).to.have.property('view', 'View2');
expect(updateFunc.callCount).to.equal(17);
expect(wrapper.props().data.contents.protocols[0].sets[1]).to.have.property('view', 'View2');
wrapper.find('.set1 button.newOutput').simulate('click');
expect(updateFunc.callCount).to.equal(18);
wrapper.find('.set1 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }});
expect(updateFunc.callCount).to.equal(19);
wrapper.find('.set1 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }});
expect(wrapper.state('cache').contents.protocols[0].sets[1].outputs).to.have.property('out', 'system/integer/1');
expect(updateFunc.callCount).to.equal(20);
expect(wrapper.props().data.contents.protocols[0].sets[1].outputs).to.have.property('out', 'system/integer/1');
// protocol 2
wrapper.find('button#protocolChoice1').simulate('click');
wrapper.find('CacheInput[name="protocolName"]').prop('onChange')( { target: { value: 'protocol2' }});
expect(wrapper.state('cache').contents.protocols[1]).to.have.property('name', 'protocol2');
expect(updateFunc.callCount).to.equal(21);
expect(wrapper.props().data.contents.protocols[1]).to.have.property('name', 'protocol2');
wrapper.find('CacheInput[name="protocolTemplate"]').prop('onChange')( { target: { value: 'test_integers' }});
expect(wrapper.state('cache').contents.protocols[1]).to.have.property('template', 'test_integers');
expect(updateFunc.callCount).to.equal(22);
expect(wrapper.props().data.contents.protocols[1]).to.have.property('template', 'test_integers');
// protocol 2 sets
wrapper.find('button#newSet').simulate('click');
expect(updateFunc.callCount).to.equal(23);
wrapper.find('button#newSet').simulate('click');
expect(wrapper.state('cache').contents.protocols[1]).to.have.property('sets').with.lengthOf(2);
expect(updateFunc.callCount).to.equal(24);
expect(wrapper.props().data.contents.protocols[1]).to.have.property('sets').with.lengthOf(2);
// protocol 1 set 1
// protocol 2 set 1
wrapper.find('CacheInput[name="setName0"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[1].sets[0]).to.have.property('name', 'set');
expect(updateFunc.callCount).to.equal(25);
expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('name', 'set');
wrapper.find('CacheInput[name="setTemplate0"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[1].sets[0]).to.have.property('template', 'set');
expect(updateFunc.callCount).to.equal(26);
expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('template', 'set');
wrapper.find('CacheInput[name="setView0"]').prop('onChange')( { target: { value: 'LargeView' }});
expect(wrapper.state('cache').contents.protocols[1].sets[0]).to.have.property('view', 'LargeView');
expect(updateFunc.callCount).to.equal(27);
expect(wrapper.props().data.contents.protocols[1].sets[0]).to.have.property('view', 'LargeView');
wrapper.find('.set0 button.newOutput').simulate('click');
expect(updateFunc.callCount).to.equal(28);
wrapper.find('.set0 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }});
expect(updateFunc.callCount).to.equal(29);
wrapper.find('.set0 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }});
expect(wrapper.state('cache').contents.protocols[1].sets[0].outputs).to.have.property('out', 'system/integer/1');
expect(updateFunc.callCount).to.equal(30);
expect(wrapper.props().data.contents.protocols[1].sets[0].outputs).to.have.property('out', 'system/integer/1');
// protocol 1 set 2
// protocol 2 set 2
wrapper.find('CacheInput[name="setName1"]').prop('onChange')( { target: { value: 'set2' }});
expect(wrapper.state('cache').contents.protocols[1].sets[1]).to.have.property('name', 'set2');
expect(updateFunc.callCount).to.equal(31);
expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('name', 'set2');
wrapper.find('CacheInput[name="setTemplate1"]').prop('onChange')( { target: { value: 'set' }});
expect(wrapper.state('cache').contents.protocols[1].sets[1]).to.have.property('template', 'set');
expect(updateFunc.callCount).to.equal(32);
expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('template', 'set');
wrapper.find('CacheInput[name="setView1"]').prop('onChange')( { target: { value: 'View2' }});
expect(wrapper.state('cache').contents.protocols[1].sets[1]).to.have.property('view', 'View2');
expect(updateFunc.callCount).to.equal(33);
expect(wrapper.props().data.contents.protocols[1].sets[1]).to.have.property('view', 'View2');
wrapper.find('.set1 button.newOutput').simulate('click');
expect(updateFunc.callCount).to.equal(34);
wrapper.find('.set1 .setOutput CacheInput[type="text"]').prop('onChange')( { target: { value: 'out' }});
expect(updateFunc.callCount).to.equal(35);
wrapper.find('.set1 .setOutput select').simulate('change', { target: { value: 'system/integer/1' }});
expect(wrapper.state('cache').contents.protocols[1].sets[1].outputs).to.have.property('out', 'system/integer/1');
expect(updateFunc.callCount).to.equal(36);
expect(wrapper.props().data.contents.protocols[1].sets[1].outputs).to.have.property('out', 'system/integer/1');
console.log(JSON.stringify(wrapper.state('cache').contents));
expect(wrapper.state('cache').contents).to.deep.equal({
expect(wrapper.props().data.contents).to.deep.equal({
'root_folder': '/this/database/does/not/require/a/path',
'description': 'A test database that emits integers',
'protocols': [
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment