AlgorithmEditor.spec.jsx 22.2 KB
Newer Older
1 2 3 4 5
// @flow
import React from 'react';
import { expect } from 'chai';
import { mount } from 'enzyme';
import sinon from 'sinon';
6
import { spies } from '@test';
7

8
import { AlgorithmEditor as C } from '.';
9
import {  getValidAlgorithmObj as getValidObj } from '@helpers/beat';
10 11

import testAlgs from '@test/test_algs.json';
12 13
import testDfs from '@test/test_dfs.json';
import testLibs from '@test/test_libs.json';
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

const libs = [];
const dfs = [];

describe('<AlgorithmEditor />', () => {
	let wrapper;

	afterEach(() => {
		if(wrapper && wrapper.unmount)
			wrapper.unmount();
	});

	describe('accepts', () => {
		const algs = [
			{
				name: 'test/non-analyzer-alg/1',
				contents: {
					language: 'python',
					description: 'A basic algorithm as a sanity test for the AlgorithmEditor',
					groups: [
						{
							name: 'group_1',
							inputs: {
37
								'input_1': { type: 'test/df/1' },
38 39
							},
							outputs: {
40
								'output_1': { type: 'test/df/2' },
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
							},
						}
					],
					uses: {
						'library_1': 'a/lib/1',
					},
					parameters: {
						'parameter_1': {
							type: 'string',
							choice: [
								'choice_1',
								'choice_2',
								'choice_3',
							],
							default: 'choice_1',
						}
					},
					// non-analyzer
					splittable: false,
				}
61

62
			}
63
		].concat(testAlgs.map(a => getValidObj(a)));
64 65 66

		algs.forEach(function(alg){
			const saveFunc = () => {};
67
			const updateFunc = () => {};
68 69 70
			it(`${ alg.name }`, () => {
				wrapper = mount(
					<C
71
						data={getValidObj(alg)}
72 73 74 75
						algorithms={algs}
						dataformats={dfs}
						libraries={libs}
						saveFunc={saveFunc}
76
						updateFunc={updateFunc}
77 78 79 80
					/>
				);

				expect(wrapper).to.have.props(
81
					['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
82
				).deep.equal(
83
					[alg, algs, dfs, libs, saveFunc, updateFunc]
84 85 86 87 88
				);
			});
		});
	});

Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
89
	describe('creates', () => {
90 91
		it('user/integers_echo/1', () => {
			const saveFunc = sinon.spy();
92 93 94 95
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
96
			const algName = 'user/integers_echo/1';
97 98
			wrapper = mount(
				<C
99
					data={getValidObj({name: algName, contents: {}})}
100 101 102 103
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
104
					updateFunc={updateFunc}
105 106 107 108
				/>
			);

			expect(wrapper).to.have.props(
109
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
110 111
			);

112
			expect(wrapper.props().data).to.have.property('name', algName);
113

114
			wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }});
115
			expect(updateFunc.callCount).to.equal(1);
116
			expect(wrapper.props().data.contents).to.have.property('splittable', true);
117

118
			expect(updateFunc.callCount).to.equal(1);
119 120 121
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs');
122

123
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
124

125
			wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
126
			expect(updateFunc.callCount).to.equal(2);
127
			wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }});
128
			expect(updateFunc.callCount).to.equal(3);
129 130

			const ioType = 'system/integer/1';
131
			wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }});
132
			expect(updateFunc.callCount).to.equal(4);
133
			wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }});
134
			expect(updateFunc.callCount).to.equal(5);
135

136 137
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
			expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType });
138

139
			expect(wrapper.props().data.contents).to.deep.equal({
140 141 142 143 144 145 146 147
				description: '',
				'groups': [
					{
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						},
148
						'name': 'group',
149 150 151 152 153 154 155 156 157 158 159 160 161 162
						'outputs': {
							'out_data': {
								'type': 'system/integer/1'
							}
						}
					}
				],
				parameters: {},
				uses: {},
				'splittable': true,
				'language': 'python'
			});
		});

Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
163
		it('user/integers_add/1', () => {
164
			const saveFunc = sinon.spy();
165 166 167 168
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
169
			const algName = 'user/integers_add/1';
170 171
			wrapper = mount(
				<C
172
					data={getValidObj({name: algName, contents: {}})}
173 174 175 176
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
177
					updateFunc={updateFunc}
178 179
				/>
			);
180

181
			expect(wrapper).to.have.props(
182
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
183 184
			);

185
			expect(wrapper.props().data).to.have.property('name', algName);
186

187
			wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }});
188
			expect(wrapper.props().data.contents).to.have.property('splittable', true);
189

190 191 192
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs');
193

194
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
195

196 197
			wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
			wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }});
198 199

			const ioType = 'system/integer/1';
200 201
			wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }});
			wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }});
202

203 204
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
			expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType });
205 206 207 208 209

			wrapper.find('a')
			.findWhere(w => {
				const html = w.html();
				return html && html.includes('Parameters');
210 211 212
			})
			.at(0)
			.simulate('click');
213 214 215

			wrapper.find('button#newParameterBtn').simulate('click');

216 217
			wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'offset' }});
			wrapper.find('[tabId="1"] select').prop('onChange')( { target: { value: 'int32' }});
218 219
			wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '1' }});

220
			expect(wrapper.props().data.contents.parameters).to.have.deep.property('offset', {
221 222 223 224 225 226 227 228 229
				'default': '1',
				'type': 'int32',
				'description': '',
			});

			wrapper.find('a')
			.findWhere(w => {
				const html = w.html();
				return html && html.includes('Libraries');
230 231 232
			})
			.at(0)
			.simulate('click');
233 234 235

			wrapper.find('button#newLibraryBtn').simulate('click');

236 237
			wrapper.find('[tabId="2"] CacheInput[type="text"]').prop('onChange')( { target: { value: 'lib' }});
			wrapper.find('[tabId="2"] select').prop('onChange')( { target: { value: 'user/thelib/1' }});
238

239
			expect(wrapper.props().data.contents.uses).to.have.property('lib', 'user/thelib/1');
240

241
			expect(wrapper.props().data.contents).to.deep.equal({
242 243 244 245 246 247 248 249
				description: '',
				'groups': [
					{
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						},
250
						'name': 'group',
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
						'outputs': {
							'out_data': {
								'type': 'system/integer/1'
							}
						}
					}
				],
				'parameters': {
					'offset': {
						'default': '1',
						'type': 'int32',
						description: '',
					}
				},
				'uses': {
					'lib': 'user/thelib/1'
				},
				'splittable': true,
				'language': 'python'
			});
271
		});
272 273 274

		it('user/integers_echo_analyzer/1', () => {
			const saveFunc = sinon.spy();
275 276 277 278
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
279
			const algName = 'user/integer_echo_analyzer/1';
280 281
			wrapper = mount(
				<C
282
					data={getValidObj({name: algName, contents: {}})}
283 284 285 286
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
287
					updateFunc={updateFunc}
288 289 290 291
				/>
			);

			expect(wrapper).to.have.props(
292
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
293 294
			);

295
			expect(wrapper.props().data).to.have.property('name', algName);
296

297
			wrapper.find('#algAnalyzer input').prop('onChange')( { target: { checked: true }});
298
			expect(wrapper.props().data.contents).to.have.property('results');
299

300 301 302
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.not.have.property('outputs');
303

304
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
305

306
			wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
307 308

			const ioType = 'system/integer/1';
309
			wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }});
310

311
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
312 313 314 315 316

			wrapper.find('a')
			.findWhere(w => {
				const html = w.html();
				return html && html.includes('Results');
317 318 319
			})
			.at(0)
			.simulate('click');
320 321 322 323 324 325

			wrapper.find('button#newResultBtn').simulate('click');
			wrapper.find('button#newResultBtn').simulate('click');
			wrapper.find('button#newResultBtn').simulate('click');
			wrapper.find('button#newResultBtn').simulate('click');

326 327
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(0).prop('onChange')( { target: { value: 'roc' }});
			wrapper.find('[tabId="3"] select').at(0).prop('onChange')( { target: { value: 'plot/isoroc/1' }});
328

329 330
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(1).prop('onChange')( { target: { value: 'plot' }});
			wrapper.find('[tabId="3"] select').at(1).prop('onChange')( { target: { value: 'plot/scatter/1' }});
331

332 333
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(2).prop('onChange')( { target: { value: 'out_data' }});
			wrapper.find('[tabId="3"] select').at(2).prop('onChange')( { target: { value: 'int32' }});
334

335 336
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(3).prop('onChange')( { target: { value: 'bar_plot' }});
			wrapper.find('[tabId="3"] select').at(3).prop('onChange')( { target: { value: 'plot/bar/1' }});
337

338
			expect(wrapper.props().data.contents.results).to.deep.equal({
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
				'roc': {
					'type': 'plot/isoroc/1',
					'display': false
				},
				'plot': {
					'type': 'plot/scatter/1',
					'display': false
				},
				'out_data': {
					'type': 'int32',
					'display': false
				},
				'bar_plot': {
					'type': 'plot/bar/1',
					'display': false
				}
			});
356

357
			expect(wrapper.props().data.contents).to.deep.equal({
358 359 360 361 362 363 364 365
				description: '',
				'groups': [
					{
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						},
366
						'name': 'group'
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
					}
				],
				parameters: {},
				uses: {},
				'language': 'python',
				'results': {
					'roc': {
						'type': 'plot/isoroc/1',
						'display': false
					},
					'plot': {
						'type': 'plot/scatter/1',
						'display': false
					},
					'out_data': {
						'type': 'int32',
						'display': false
					},
					'bar_plot': {
						'type': 'plot/bar/1',
						'display': false
					}
				}
			});
		});

		it('user/integers_echo_ignore/1', () => {
			const saveFunc = sinon.spy();
395 396 397 398
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
399
			const algName = 'user/integers_echo/1';
400 401
			wrapper = mount(
				<C
402
					data={getValidObj({name: algName, contents: {}})}
403 404 405 406
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
407
					updateFunc={updateFunc}
408 409 410 411
				/>
			);

			expect(wrapper).to.have.props(
412
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
413 414
			);

415
			expect(wrapper.props().data).to.have.property('name', algName);
416

417
			wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }});
418
			expect(wrapper.props().data.contents).to.have.property('splittable', true);
419 420 421

			wrapper.find('button#newGroupBtn').simulate('click');

422 423 424 425 426
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(2);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs');
			expect(wrapper.props().data.contents.groups[1]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[1]).to.not.have.property('outputs');
427 428

			// Group 1
429
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
430

431 432
			wrapper.find('#endpoint0 .algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
			wrapper.find('#endpoint0 .algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }});
433 434

			const ioType = 'system/integer/1';
435 436
			wrapper.find('#endpoint0 .algInput select').prop('onChange')( { target: { value: ioType }});
			wrapper.find('#endpoint0 .algOutput select').prop('onChange')( { target: { value: ioType }});
437

438 439
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
			expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType });
440 441

			// Group 2
442
			expect(wrapper.props().data.contents.groups[1]).to.have.property('name', 'group0');
443 444 445

			wrapper.find('#endpoint1 button#newInputBtn').simulate('click');

446 447
			wrapper.find('#endpoint1 .algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data2' }});
			wrapper.find('#endpoint1 .algInput select').prop('onChange')( { target: { value: ioType }});
448
			expect(wrapper.props().data.contents.groups[1].inputs).to.have.deep.property('in_data2', { type: ioType });
449

450
			expect(wrapper.props().data.contents).to.be.deep.equal({
451 452 453 454 455 456 457 458
				description: '',
				'groups': [
					{
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						},
459
						'name': 'group',
460 461 462 463 464 465 466 467 468 469 470 471
						'outputs': {
							'out_data': {
								'type': 'system/integer/1'
							}
						}
					},
					{
						'inputs': {
							'in_data2': {
								'type': 'system/integer/1'
							}
						},
472
						'name': 'group0'
473 474 475 476 477 478 479 480 481 482 483
					}
				],
				parameters: {},
				uses: {},
				'splittable': true,
				'language': 'python'
			});
		});

		it('system/integers_echo_sleep/1', () => {
			const saveFunc = sinon.spy();
484 485 486 487
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
488
			const algName = 'user/integers_echo_sleep/1';
489 490
			wrapper = mount(
				<C
491
					data={getValidObj({name: algName, contents: {}})}
492 493 494 495
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
496
					updateFunc={updateFunc}
497 498 499 500
				/>
			);

			expect(wrapper).to.have.props(
501
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
502 503
			);

504
			expect(wrapper.props().data).to.have.property('name', algName);
505

506
			wrapper.find('#algSplittable input').prop('onChange')( { target: { checked: true }});
507
			expect(wrapper.props().data.contents).to.have.property('splittable', true);
508

509 510 511
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs');
512

513
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
514

515 516
			wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
			wrapper.find('.algOutput').find('CacheInput').prop('onChange')( { target: { value: 'out_data' }});
517 518

			const ioType = 'system/integer/1';
519 520
			wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }});
			wrapper.find('.algOutput select').prop('onChange')( { target: { value: ioType }});
521

522 523
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
			expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('out_data', { type: ioType });
524 525 526 527 528

			wrapper.find('a')
			.findWhere(w => {
				const html = w.html();
				return html && html.includes('Parameters');
529 530 531
			})
			.at(0)
			.simulate('click');
532 533 534

			wrapper.find('button#newParameterBtn').simulate('click');

535 536
			wrapper.find('CacheInput[placeholder="Parameter name..."]').prop('onChange')( { target: { value: 'delay' }});
			wrapper.find('[tabId="1"] select').prop('onChange')( { target: { value: 'uint32' }});
537 538 539
			wrapper.find('input[placeholder="Default"]').simulate('change', { target: { value: '30' }});
			wrapper.find('input[placeholder="Description"]').simulate('change', { target: { value: 'Time to sleep in seconds' }});

540
			expect(wrapper.props().data.contents.parameters).to.have.deep.property('delay', {
541 542 543 544 545
				'default': '30',
				'type': 'uint32',
				'description': 'Time to sleep in seconds',
			});

546
			expect(wrapper.props().data.contents).to.be.deep.equal({
547 548 549 550 551 552
				description: '',
				uses: {},
				'language': 'python',
				'splittable': true,
				'groups': [
					{
553
						'name': 'group',
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						},
						'outputs': {
							'out_data': {
								'type': 'system/integer/1'
							}
						}
					}
				],
				'parameters': {
					'delay': {
						'default': '30',
						'type': 'uint32',
						'description': 'Time to sleep in seconds'
					}
				}
			});
		});

		it('user/integers_mean_analyzer/1', () => {
			const saveFunc = sinon.spy();
578 579 580 581
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
582
			const algName = 'user/integers_mean_analyzer/1';
583 584
			wrapper = mount(
				<C
585
					data={getValidObj({name: algName, contents: {}})}
586 587 588 589
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
590
					updateFunc={updateFunc}
591 592 593 594
				/>
			);

			expect(wrapper).to.have.props(
595
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
596 597
			);

598
			expect(wrapper.props().data).to.have.property('name', algName);
599

600
			wrapper.find('#algAnalyzer input').prop('onChange')( { target: { checked: true }});
601
			expect(wrapper.props().data.contents).to.have.property('results');
602

603 604 605
			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.not.have.property('outputs');
606

607
			expect(wrapper.props().data.contents.groups[0]).to.have.property('name', 'group');
608

609
			wrapper.find('.algInput').find('CacheInput').prop('onChange')( { target: { value: 'in_data' }});
610 611

			const ioType = 'system/integer/1';
612
			wrapper.find('.algInput select').prop('onChange')( { target: { value: ioType }});
613

614
			expect(wrapper.props().data.contents.groups[0].inputs).to.have.deep.property('in_data', { type: ioType });
615 616 617 618 619

			wrapper.find('a')
			.findWhere(w => {
				const html = w.html();
				return html && html.includes('Results');
620 621 622
			})
			.at(0)
			.simulate('click');
623 624 625 626

			wrapper.find('button#newResultBtn').simulate('click');
			wrapper.find('button#newResultBtn').simulate('click');

627 628
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(0).prop('onChange')( { target: { value: 'plot' }});
			wrapper.find('[tabId="3"] select').at(0).prop('onChange')( { target: { value: 'plot/scatter/1' }});
629

630 631
			wrapper.find('[tabId="3"] CacheInput[type="text"]').at(1).prop('onChange')( { target: { value: 'out_data' }});
			wrapper.find('[tabId="3"] select').at(1).prop('onChange')( { target: { value: 'float32' }});
632

633
			expect(wrapper.props().data.contents.results).to.deep.equal({
634 635 636 637 638 639 640 641 642 643
				'plot': {
					'type': 'plot/scatter/1',
					'display': false,
				},
				'out_data': {
					'type': 'float32',
					'display': false
				},
			});

644
			expect(wrapper.props().data.contents).to.deep.equal({
645 646 647 648 649 650
				description: '',
				uses: {},
				parameters: {},
				'language': 'python',
				'groups': [
					{
651
						name: 'group',
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						}
					}
				],
				'results': {
					'out_data': {
						'type': 'float32',
						'display': false
					},
					'plot': {
						'type': 'plot/scatter/1',
						'display': false
					}
				}
			});
670
		});
671
	});
672

673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
	describe.only('regression', () => {
		it(`adds an output and removes results when toggling from analyzer to normal`, () => {
			const contents = {
				description: '',
				uses: {},
				parameters: {},
				'language': 'python',
				'groups': [
					{
						name: 'group',
						'inputs': {
							'in_data': {
								'type': 'system/integer/1'
							}
						}
					}
				],
				'results': {
					'out_data': {
						'type': 'float32',
						'display': false
					},
					'plot': {
						'type': 'plot/scatter/1',
						'display': false
					}
				}
			};
			const saveFunc = sinon.spy();
			const _updateFunc = (obj) => {
				wrapper.setProps && wrapper.setProps({ data: obj });
			};
			const updateFunc = sinon.spy(_updateFunc);
			const algName = 'user/integers_mean_analyzer/1';
			const obj = {
				name: algName,
				contents,
			};
			wrapper = mount(
				<C
					data={getValidObj(obj)}
					algorithms={[]}
					dataformats={testDfs}
					libraries={testLibs}
					saveFunc={saveFunc}
					updateFunc={updateFunc}
				/>
			);

			expect(wrapper).to.have.props(
				['data', 'algorithms', 'dataformats', 'libraries', 'saveFunc', 'updateFunc']
			);

			expect(wrapper.props().data).to.have.property('name', algName);

			wrapper.find('#algAnalyzer input').prop('onChange')( { target: { checked: false }});
			expect(wrapper.props().data.contents).to.not.have.property('results');

			expect(wrapper.props().data.contents).to.have.property('groups').with.lengthOf(1);
			expect(wrapper.props().data.contents.groups[0]).to.have.property('inputs');
			expect(wrapper.props().data.contents.groups[0]).to.have.property('outputs');
			expect(wrapper.props().data.contents.groups[0].outputs).to.have.deep.property('output', {
				type: ''
			});
		});
	});

740
});