Commit da592232 authored by Jaden DIEFENBAUGH's avatar Jaden DIEFENBAUGH
Browse files

add skeleton ToolchainEditor & save more test data

parent 16b98e19
......@@ -32,6 +32,7 @@ import AlgorithmEditorContainer from './AlgorithmEditor.jsx';
import LibraryEditorContainer from './LibraryEditor.jsx';
import DatabaseEditorContainer from './DatabaseEditor.jsx';
import ExperimentEditorContainer from './ExperimentEditor.jsx';
import ToolchainEditorContainer from './ToolchainEditor.jsx';
type Props = {
match: any,
......@@ -147,6 +148,13 @@ export class EntityDetail extends React.Component<Props, State> {
saveFunc={this.saveChanges}
/>
}
{
this.props.match.params.entity === 'toolchain' &&
<ToolchainEditorContainer
data={this.props.getEntityObject()}
saveFunc={this.saveChanges}
/>
}
</TabPane>
<TabPane tabId='1'>
<Row>
......
// @flow
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { spies } from '@test';
import * as Selectors from '@store/selectors.js';
import { ExperimentEditor as C } from './ExperimentEditor.jsx';
import testAlgs from '@test/test_algs.json';
import testDbs from '@test/test_dbs.json';
import testExps from '@test/test_exps.json';
import testTcs from '@test/test_tcs.json';
describe.only('<ExperimentEditor />', () => {
let wrapper;
const normalBlocks = Selectors.normalBlocks({ algorithm: testAlgs });
const analyzerBlocks = Selectors.analyzerBlocks({ algorithm: testAlgs });
const datasets = Selectors.flattenedDatabases({ database: testDbs });
afterEach(() => {
if(wrapper && wrapper.unmount)
wrapper.unmount();
});
describe('accepts', () => {
const exps = [
].concat(testExps);
exps.forEach(function(exp){
const saveFunc = () => {};
const tc = testTcs.find(tc => exp.name.includes(tc.name));
it(`${ exp.name }`, () => {
wrapper = mount(
<C
data={exp}
experiments={exps}
normalBlocks={normalBlocks}
analyzerBlocks={analyzerBlocks}
datasets={datasets}
toolchain={tc}
saveFunc={saveFunc}
/>
);
expect(wrapper).to.have.props(
['data', 'experiments', 'normalBlocks', 'analyzerBlocks', 'datasets', 'toolchain', 'saveFunc']
);
});
});
});
describe('creates', () => {
it(`user/user/single/1/single_add`, () => {
const expName = 'user/user/single/1/single_add';
const saveFunc = sinon.spy();
const tc = testTcs.find(tc => expName.includes(tc.name));
wrapper = mount(
<C
data={{name: '', contents: {}}}
experiments={[]}
normalBlocks={normalBlocks}
analyzerBlocks={analyzerBlocks}
datasets={datasets}
toolchain={tc}
saveFunc={saveFunc}
/>
);
wrapper.find('.expName').find('input').simulate('change', { target: { value: expName }});
expect(wrapper.state('cache')).to.have.property('name', expName);
wrapper.find('div.dataset0 select').simulate('change', { target: { value: 'protocol/set (simple/1)'}});
expect(wrapper.state('cache').contents).to.have.deep.property('datasets', {
'set': {
'set': 'set',
'protocol': 'protocol',
'database': 'simple/1'
}
});
wrapper.find('div.block0 div.algorithm select').at(0).simulate('change', { target: { value: 'user/integers_add/1'}});
expect(wrapper.state('cache').contents).to.have.deep.property('blocks', {
'echo': {
'inputs': {
'in_data': 'in'
},
'algorithm': 'user/integers_add/1',
'outputs': {
'out_data': 'out'
},
parameters: {}
}
});
wrapper.find('div.block0 div.algorithm select').at(1).simulate('change', { target: { value: 'user/integers_echo_analyzer/1'}});
expect(wrapper.state('cache').contents).to.have.deep.property('analyzers', {
'analysis': {
'inputs': {
'in_data': 'in'
},
'algorithm': 'user/integers_echo_analyzer/1',
parameters: {},
}
});
wrapper.find('input.queue').simulate('change', { target: { value: 'queue'}});
wrapper.find('input.envName').simulate('change', { target: { value: 'Python 2.7'}});
wrapper.find('input.envVersion').simulate('change', { target: { value: '1.2.0'}});
console.log(JSON.stringify(wrapper.state('cache').contents.globals));
expect(wrapper.state('cache').contents).to.have.deep.property('globals', {
'queue': 'queue',
'environment': {
'version': '1.2.0',
'name': 'Python 2.7'
},
'user/integers_add/1': {
offset: 1
},
});
expect(wrapper.state('cache')).to.be.deep.equal({
'name': 'user/user/single/1/single_add',
'contents': {
description: '',
'analyzers': {
'analysis': {
'inputs': {
'in_data': 'in'
},
'algorithm': 'user/integers_echo_analyzer/1',
parameters: {},
}
},
'datasets': {
'set': {
'set': 'set',
'protocol': 'protocol',
'database': 'simple/1'
}
},
'blocks': {
'echo': {
'inputs': {
'in_data': 'in'
},
'algorithm': 'user/integers_add/1',
'outputs': {
'out_data': 'out'
},
parameters: {}
}
},
'globals': {
'queue': 'queue',
'environment': {
'version': '1.2.0',
'name': 'Python 2.7'
},
'user/integers_add/1': {
offset: 1
},
}
}
});
});
});
});
// @flow
import * as React from 'react';
import {
Container,
Row,
Col,
Button,
Form,
FormGroup,
Label,
Input,
InputGroup,
FormText,
Collapse,
Card,
CardHeader,
CardBody,
TabContent, TabPane, Nav, NavItem, NavLink, CardTitle, CardText,
FormFeedback,
Alert,
InputGroupAddon,
Badge,
} from 'reactstrap';
import { connect } from 'react-redux';
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
import cn from 'classnames';
import { nameValidator } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat';
import { changeObjFieldName } from '@helpers';
import * as Selectors from '@store/selectors.js';
import ValidSchemaBadge from './ValidSchemaBadge.jsx';
import CacheInput from './CacheInput.jsx';
import DeleteInputBtn from './DeleteInputBtn.jsx';
import TypedField from './TypedField.jsx';
type Props = {
data: BeatObject,
toolchains: BeatObject[],
saveFunc: (BeatObject) => any,
};
type State = {
cache: any,
};
const getValidObj = (data = {}) => {
const getObj = {
name: '',
contents: {},
...JSON.parse(JSON.stringify(data))
};
const obj = {
...getObj,
contents: {
'description': '',
...getObj.contents,
},
};
return obj;
};
export class ToolchainEditor extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
}
state = {
cache: getValidObj(this.props.data),
}
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,
}
}
});
}
validatorFunc = nameValidator('toolchain', this.props.toolchains.map(o => o.name));
nameIsValid = (str: string = this.state.cache.name): true | React.Node => {
const err =
<span>
Please provide a <strong>unique</strong> toolchain name
</span>
;
return str === this.props.data.name || this.validatorFunc(str) || err;
}
render = () => (
<div>
<div className='d-flex'>
<Button
className='mx-auto'
outline
color='secondary'
onClick={() => this.props.saveFunc(this.state.cache)}
>
Save Changes (Changes are <ValidSchemaBadge entity='toolchain' obj={this.state.cache} />)
</Button>
</div>
<Form onSubmit={(e) => e.preventDefault()}>
<FormGroup tag='fieldset'>
<FormGroup>
<Label>Name</Label>
<CacheInput
type='text'
className='tcName'
placeholder='New toolchain name...'
value={this.state.cache.name}
onChange={e => this.setState({ cache: {...this.state.cache, 'name': e.target.value}})}
validateFunc={str => this.nameIsValid(str)}
/>
</FormGroup>
<FormGroup>
<Label>Short Description</Label>
<Input
type='text'
className='tcDescription'
placeholder='Toolchain description...'
value={this.state.cache.contents['description']}
onChange={e => this.setContents({ ...this.state.cache.contents, 'description': e.target.value})}
/>
</FormGroup>
</FormGroup>
</Form>
</div>
);
}
const mapStateToProps: MapStateToProps<*,*,*> = (state, ownProps) => {
const obj = {
toolchains: Selectors.toolchainGet(state),
};
return obj;
};
export default connect(mapStateToProps)(ToolchainEditor);
This diff is collapsed.
This diff is collapsed.
Markdown is supported
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