From 727ad08e23e5adc2467ce2e476fa59667eeb2c40 Mon Sep 17 00:00:00 2001
From: Jaden Diefenbaugh <jaden.diefenbaugh@idiap.ch>
Date: Fri, 21 Sep 2018 11:42:39 -0700
Subject: [PATCH] fix #130 & add tcmodal tests

---
 .../toolchain/ToolchainEditor.spec.jsx        |   2 +-
 .../components/toolchain/ToolchainModal.jsx   |  28 ++--
 .../toolchain/ToolchainModal.spec.jsx         | 122 ++++++++++++++++++
 3 files changed, 140 insertions(+), 12 deletions(-)
 create mode 100644 conda/js/src/components/toolchain/ToolchainModal.spec.jsx

diff --git a/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx b/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx
index 3c82fbc4..0abe32af 100644
--- a/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx
+++ b/conda/js/src/components/toolchain/ToolchainEditor.spec.jsx
@@ -158,7 +158,7 @@ const getIrisTc = (color1: string = '#008000', color2: string = '#FF0000') => {
 
 chai.use(deepEqualInAnyOrder);
 
-describe.only('<ToolchainEditor />', function() {
+describe('<ToolchainEditor />', function() {
 	// these tests might take a long time, comparatively
 	this.timeout(10000);
 
diff --git a/conda/js/src/components/toolchain/ToolchainModal.jsx b/conda/js/src/components/toolchain/ToolchainModal.jsx
index 0828e6a4..0d6bb84e 100644
--- a/conda/js/src/components/toolchain/ToolchainModal.jsx
+++ b/conda/js/src/components/toolchain/ToolchainModal.jsx
@@ -30,16 +30,19 @@ import {
 import CacheInput from '../CacheInput.jsx';
 import DeleteInputBtn from '../DeleteInputBtn.jsx';
 import { generateNewKey } from '@helpers';
+import type { BlockType } from '@helpers/toolchainTypes';
 
 type Props = {
-	// block data
-	data: any,
-	// func to close modal
-	toggle: () => any,
 	// is the modal active?
 	active: boolean,
+	// block data
+	data: BlockType,
 	// name of all blocks
 	blockNames: string[],
+	// possible channels the block can be sync'd to (an obj w keys as channel names & vals as colours)
+	possibleChannels: { [string]: string },
+	// func to close modal
+	toggle: () => any,
 	// change the block name
 	updateBlockName: (newName: string) => any,
 	// change the name of an input or output
@@ -50,8 +53,6 @@ type Props = {
 	deleteBlockIO: (ioType: 'input' | 'output', ioName: string) => any,
 	// delete the block
 	deleteBlock: () => any,
-	// possible channels the block can be sync'd to (an obj w keys as channel names & vals as colours)
-	possibleChannels: any,
 	// update sync'd channel
 	updateBlockChannel: (channel: string) => any,
 };
@@ -112,11 +113,16 @@ class ToolchainModal extends React.Component<Props, State> {
 									this.props.updateBlockName(e.target.value);
 								}}
 								validateFunc={(str) => {
-									return (
-										str === data.name ||
-										!this.props.blockNames.includes(str) ||
-										<span>This name is already taken by an existing block</span>
-									);
+									if(str === data.name){
+										return true;
+									}
+									if(this.props.blockNames.includes(str)){
+										return <span>This name is already taken by an existing block</span>;
+									}
+									if(str.includes('-')){
+										return <span>{`Cannot include the dash ("-") character`}</span>;
+									}
+									return true;
 								}}
 							/>
 						</FormGroup>
diff --git a/conda/js/src/components/toolchain/ToolchainModal.spec.jsx b/conda/js/src/components/toolchain/ToolchainModal.spec.jsx
new file mode 100644
index 00000000..7849ab9d
--- /dev/null
+++ b/conda/js/src/components/toolchain/ToolchainModal.spec.jsx
@@ -0,0 +1,122 @@
+// @flow
+import React from 'react';
+import { expect } from 'chai';
+import { mount } from 'enzyme';
+import sinon from 'sinon';
+import { spies } from '@test';
+
+import C from './ToolchainModal.jsx';
+
+// sleep for a bit, to wait for async things
+const sleep = (ms) => {
+	return new Promise(resolve => setTimeout(resolve, ms));
+};
+
+describe.only('<ToolchainModal />', () => {
+	let wrapper;
+
+	afterEach(() => {
+		if(wrapper && wrapper.unmount)
+			wrapper.unmount();
+	});
+
+	const testBlockData = {
+		name: 'block1',
+		inputs: [
+			'input1',
+		],
+		outputs: [
+			'output1',
+		],
+		synchronized_channel: 'dataset1',
+	};
+
+	const testChannels = { 'dataset1': '#880000' };
+
+	const testBlockNames = ['block1'];
+
+	it('accepts the test data with the right props', () => {
+		wrapper = mount(
+			<C
+				active={true}
+				data={testBlockData}
+				blockNames={testBlockNames}
+				possibleChannels={testChannels}
+				toggle={() => {}}
+				updateBlockName={() => {}}
+				updateBlockChannel={() => {}}
+				updateBlockIOName={() => {}}
+				addBlockIO={() => {}}
+				deleteBlockIO={() => {}}
+				deleteBlock={() => {}}
+			/>
+		);
+		expect(wrapper).to.have.props([
+			'active',
+			'data',
+			'blockNames',
+			'possibleChannels',
+			'toggle',
+			'updateBlockName',
+			'updateBlockChannel',
+			'updateBlockIOName',
+			'addBlockIO',
+			'deleteBlockIO',
+			'deleteBlock',
+		]);
+	});
+
+	it('lets you change the name to another valid name', async () => {
+		const newBlockName = 'block2';
+		const _updateBlockName = (str: string) => {
+			expect(str).to.equal(newBlockName);
+		};
+		wrapper = mount(
+			<C
+				active={true}
+				data={testBlockData}
+				blockNames={testBlockNames}
+				possibleChannels={testChannels}
+				toggle={() => {}}
+				updateBlockName={_updateBlockName}
+				updateBlockChannel={() => {}}
+				updateBlockIOName={() => {}}
+				addBlockIO={() => {}}
+				deleteBlockIO={() => {}}
+				deleteBlock={() => {}}
+			/>
+		);
+		wrapper.find('input#tcModalInitFocus').prop('onChange')( { target: { value: newBlockName }});
+		wrapper.update();
+		await sleep(300);
+		wrapper.update();
+		expect(wrapper.exists('.input-group-append .text-danger')).to.equal(false);
+	});
+
+	it('doesnt let you change the name to a valid name with a dash ("-") in it', async () => {
+		const newBlockName = 'block-2';
+		const _updateBlockName = (str: string) => {
+			expect(str).to.equal(newBlockName);
+		};
+		wrapper = mount(
+			<C
+				active={true}
+				data={testBlockData}
+				blockNames={testBlockNames}
+				possibleChannels={testChannels}
+				toggle={() => {}}
+				updateBlockName={_updateBlockName}
+				updateBlockChannel={() => {}}
+				updateBlockIOName={() => {}}
+				addBlockIO={() => {}}
+				deleteBlockIO={() => {}}
+				deleteBlock={() => {}}
+			/>
+		);
+		wrapper.find('input#tcModalInitFocus').prop('onChange')( { target: { value: newBlockName }});
+		wrapper.update();
+		await sleep(300);
+		wrapper.update();
+		expect(wrapper.exists('.input-group-append .text-danger')).to.equal(true);
+	});
+});
-- 
GitLab