Skip to content

Commit

Permalink
feat(ui): ability to clone test (#357)
Browse files Browse the repository at this point in the history
* feat(ui): duplicate tests (#350)
* fix(ui): order columns in same order in tests and last reports view (#352)
  • Loading branch information
enudler authored Aug 23, 2020
1 parent ea06609 commit c839f97
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 317 deletions.
86 changes: 43 additions & 43 deletions package-lock.json

Large diffs are not rendered by default.

283 changes: 141 additions & 142 deletions ui/src/features/components/TestForm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class TestForm extends React.Component {
constructor(props) {
super(props);
if (props.data) {
this.state = createStateForEditTest(props.data);
this.state = createStateForEditTest(props.data, props.cloneMode);
} else {
this.state = {
scenarios: [],
Expand Down Expand Up @@ -92,7 +92,7 @@ export class TestForm extends React.Component {
componentDidMount() {
this.props.getProcessors({exclude: 'javascript'});
this.props.initForm();
if (this.state.editMode) {
if (this.state.editMode || this.props.cloneMode) {

if (this.props.data.csv_file_id) {
this.props.getFileMetadata(this.props.data.csv_file_id);
Expand All @@ -106,7 +106,6 @@ export class TestForm extends React.Component {
}
} else {
this.addScenarioHandler();

}
}

Expand All @@ -116,51 +115,51 @@ export class TestForm extends React.Component {
const error = createTestError || processorsError || maxSupportedScenariosUi;
return (
<Modal style={{paddingTop: '65px'}} height={'93%'} onExit={closeDialog}>
<FormWrapper title={`${editMode && 'Edit' || 'Create'} Test`}>
<div className={style['top']}>
<div className={style['top-inputs']}>
{/* left */}

<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Name'}>
<TextArea maxRows={5} value={name} onChange={(evt, value) => {
this.setState({name: evt.target.value})
}}/>
</TitleInput>
</div>
<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Description'}>
<TextArea maxRows={5} value={description} onChange={(evt, value) => {
this.setState({description: evt.target.value})
}}/>
</TitleInput>
</div>
<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Base url'}>
<TextArea maxRows={5} value={baseUrl} placeholder={'http://my.api.com/'}
onChange={(evt, value) => {
this.setState({baseUrl: evt.target.value})
}}/>
</TitleInput>
</div>

<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Processor'}>
<ProcessorsDropDown
onChange={this.onProcessorChosen} options={processorsList} value={processorId}
loading={processorsLoading}/>
</TitleInput>

</div>
</div>
</div>
{/* bottom */}

{this.generateScenarioDashBoard()}
{this.generateBottomBar()}
{error && <ErrorDialog closeDialog={this.onCloseErrorDialog} showMessage={error}/>}
</FormWrapper>
</Modal>
<FormWrapper title={`${editMode && 'Edit' || 'Create'} Test`}>
<div className={style['top']}>
<div className={style['top-inputs']}>
{/* left */}

<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Name'}>
<TextArea maxRows={5} value={name} onChange={(evt, value) => {
this.setState({name: evt.target.value})
}}/>
</TitleInput>
</div>
<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Description'}>
<TextArea maxRows={5} value={description} onChange={(evt, value) => {
this.setState({description: evt.target.value})
}}/>
</TitleInput>
</div>
<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Base url'}>
<TextArea maxRows={5} value={baseUrl} placeholder={'http://my.api.com/'}
onChange={(evt, value) => {
this.setState({baseUrl: evt.target.value})
}}/>
</TitleInput>
</div>

<div className={style['input-container']}>
<TitleInput style={{flex: '1', marginTop: '2px'}} title={'Processor'}>
<ProcessorsDropDown
onChange={this.onProcessorChosen} options={processorsList} value={processorId}
loading={processorsLoading}/>
</TitleInput>

</div>
</div>
</div>
{/* bottom */}

{this.generateScenarioDashBoard()}
{this.generateBottomBar()}
{error && <ErrorDialog closeDialog={this.onCloseErrorDialog} showMessage={error}/>}
</FormWrapper>
</Modal>
)
}

Expand All @@ -184,12 +183,12 @@ export class TestForm extends React.Component {
const {isLoading, closeDialog} = this.props;

return (<div style={{display: 'flex', justifyContent: 'flex-end', marginBottom: '10px'}}>
<div style={{display: 'flex', justifyContent: 'space-between', width: '230px'}}>
<Button inverted onClick={closeDialog}>Cancel</Button>
<Button spinner={isLoading} hover disabled={!this.state.name}
onClick={this.postTest}>Submit</Button>
<div style={{display: 'flex', justifyContent: 'space-between', width: '230px'}}>
<Button inverted onClick={closeDialog}>Cancel</Button>
<Button spinner={isLoading} hover disabled={!this.state.name}
onClick={this.postTest}>Submit</Button>
</div>
</div>)
</div>)
};
addScenarioHandler = () => {
const {scenarios} = this.state;
Expand Down Expand Up @@ -357,70 +356,70 @@ export class TestForm extends React.Component {
const activeTabKey = currentScenarioIndex === null ? before.id : scenarios[currentScenarioIndex] && scenarios[currentScenarioIndex].id;
return (
<div className={style['bottom']}>
{/* bottom */}
<div style={{
marginLeft: 'auto',
marginRight: '12px',
display: 'flex',
justifyContent: 'space-between',
// width: '313px'
}}>

<div className={style['actions-style']} onClick={this.addScenarioHandler}>+Add Scenario</div>
<div className={style['actions-style']} onClick={this.addStepHandler}>+Add Step</div>
<div className={style['actions-style']} onClick={() => this.addStepHandler(SLEEP)}>+Add Sleep</div>
<div className={style['actions-style']} onClick={this.addBeforeHandler}>+Add Before</div>
<div className={style['actions-style']}
onClick={() => this.setState({csvMode: true})}>{(csvFile || csvMetadata) ? 'Modify' : '+Add'} CSV
</div>
</div>
{csvMode &&
<DragAndDrop csvMetadata={csvMetadata} csvFile={currentCsvFile}
onDropFile={(file) => this.setState({csvFile: file})}/>}
<Tabs onTabChosen={(key) => this.onChooseScenario(key)} activeTabKey={activeTabKey}
className={style.tabs}>
{
tabsData.map((tabData, index) => {
return (
<Tabs.TabPane style={{
padding: '10px',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
flex: 1
}} tab={tabData.scenario_name || 'Scenario'}
key={tabData.id}>
{
!tabData.isBefore &&
<div style={{width: "80%"}}>

<CollapsibleScenarioConfig
allowedWeight={this.calcMaxAllowedWeight()}
scenario={tabData}
onChangeValueOfScenario={this.onChangeValueOfScenario}
processorsExportedFunctions={processorsExportedFunctions}
onDeleteScenario={scenarios.length === 1 ? undefined : this.onDeleteScenario}
onDuplicateScenario={this.onDuplicateScenario}
/>
</div>

{/* bottom */}
<div style={{
marginLeft: 'auto',
marginRight: '12px',
display: 'flex',
justifyContent: 'space-between',
// width: '313px'
}}>

<div className={style['actions-style']} onClick={this.addScenarioHandler}>+Add Scenario</div>
<div className={style['actions-style']} onClick={this.addStepHandler}>+Add Step</div>
<div className={style['actions-style']} onClick={() => this.addStepHandler(SLEEP)}>+Add Sleep</div>
<div className={style['actions-style']} onClick={this.addBeforeHandler}>+Add Before</div>
<div className={style['actions-style']}
onClick={() => this.setState({csvMode: true})}>{(csvFile || csvMetadata) ? 'Modify' : '+Add'} CSV
</div>
</div>
{csvMode &&
<DragAndDrop csvMetadata={csvMetadata} csvFile={currentCsvFile}
onDropFile={(file) => this.setState({csvFile: file})}/>}
<Tabs onTabChosen={(key) => this.onChooseScenario(key)} activeTabKey={activeTabKey}
className={style.tabs}>
{
tabsData.map((tabData, index) => {
return (
<Tabs.TabPane style={{
padding: '10px',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
flex: 1
}} tab={tabData.scenario_name || 'Scenario'}
key={tabData.id}>
{
!tabData.isBefore &&
<div style={{width: "80%"}}>

<CollapsibleScenarioConfig
allowedWeight={this.calcMaxAllowedWeight()}
scenario={tabData}
onChangeValueOfScenario={this.onChangeValueOfScenario}
processorsExportedFunctions={processorsExportedFunctions}
onDeleteScenario={scenarios.length === 1 ? undefined : this.onDeleteScenario}
onDuplicateScenario={this.onDuplicateScenario}
/>
</div>

}
<div style={{width: "70%"}}>
<StepsList steps={tabData.steps}
onChangeValueOfStep={this.onChangeValueOfStep}
processorsExportedFunctions={processorsExportedFunctions}
onDeleteStep={this.onDeleteStep}
onDuplicateStep={this.onDuplicateStep}
updateStepOrder={this.updateStepOrder}
/>
</div>

</Tabs.TabPane>
)
})
}
<div style={{width: "70%"}}>
<StepsList steps={tabData.steps}
onChangeValueOfStep={this.onChangeValueOfStep}
processorsExportedFunctions={processorsExportedFunctions}
onDeleteStep={this.onDeleteStep}
onDuplicateStep={this.onDuplicateStep}
updateStepOrder={this.updateStepOrder}
/>
</div>

</Tabs.TabPane>
)
})
}
</Tabs>
</div>
</div>
)
};

Expand Down Expand Up @@ -450,35 +449,35 @@ export const DragAndDrop = ({csvFile, onDropFile, csvMetadata}) => {
};
return (
<div style={styles}>
<FileDrop
targetClassName={style.fileDropTarget}
className={style.fileDrop}
// onFrameDragEnter={(event) => console.log('onFrameDragEnter', event)}
// onFrameDragLeave={(event) => console.log('onFrameDragLeave', event)}
// o nFrameDrop={(event) => console.log('onFrameDrop', event)}
// onDragOver={(event) => console.log('onDragOver', event)}
// onDragLeave={(event) => console.log('onDragLeave', event)}
onDrop={(files, event) => {
onDropFile(files[0])
}}
>

{
csvFile && csvFile.name
||
<span>Drop csv file here</span>
}
<FileDrop
targetClassName={style.fileDropTarget}
className={style.fileDrop}
// onFrameDragEnter={(event) => console.log('onFrameDragEnter', event)}
// onFrameDragLeave={(event) => console.log('onFrameDragLeave', event)}
// o nFrameDrop={(event) => console.log('onFrameDrop', event)}
// onDragOver={(event) => console.log('onDragOver', event)}
// onDragLeave={(event) => console.log('onDragLeave', event)}
onDrop={(files, event) => {
onDropFile(files[0])
}}
>

{csvMetadata &&
<div className={style['download-button']}
onClick={() => window.open(`${env.PREDATOR_URL}/files/${csvMetadata.id}`)}>
<FontAwesomeIcon icon={faDownload}/>
</div>
}
{
csvFile && csvFile.name
||
<span>Drop csv file here</span>
}

</FileDrop>
</div>
);
{csvMetadata &&
<div className={style['download-button']}
onClick={() => window.open(`${env.PREDATOR_URL}/files/${csvMetadata.id}`)}>
<FontAwesomeIcon icon={faDownload}/>
</div>
}

</FileDrop>
</div>
);
};

function mapStateToProps(state) {
Expand Down
4 changes: 2 additions & 2 deletions ui/src/features/components/TestForm/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const createTestRequest = (data) => {
}
};

export const createStateForEditTest = (test) => {
export const createStateForEditTest = (test, cloneMode) => {
test = cloneDeep(test);
const {artillery_test} = test;
const scenarios = testScenarioToTestScenario(artillery_test.scenarios);
Expand All @@ -43,7 +43,7 @@ export const createStateForEditTest = (test) => {
activeTabKey: scenarios[0] && scenarios[0].id,
type: test.type,
processorId: test.processor_id,
editMode: true,
editMode: !cloneMode,
processorsExportedFunctions: [],
csvFileId: test.csv_file_id
}
Expand Down
Loading

0 comments on commit c839f97

Please sign in to comment.