mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
1118 lines
50 KiB
JavaScript
1118 lines
50 KiB
JavaScript
/* global define, QUnit, module, test, ok, equal, deepEqual, notEqual */
|
|
define([
|
|
"jquery",
|
|
"libs/jquery/jstorage",
|
|
"libs/bootstrap",
|
|
"sinon-qunit",
|
|
"mvc/workflow/workflow-view",
|
|
"mvc/workflow/workflow-node",
|
|
"mvc/workflow/workflow-view-node",
|
|
"mvc/workflow/workflow-terminals",
|
|
"mvc/workflow/workflow-view-terminals",
|
|
"mvc/workflow/workflow-connector"
|
|
], function(
|
|
$,
|
|
jstorage,
|
|
bootstrap,
|
|
sinon,
|
|
App,
|
|
Node,
|
|
NodeView,
|
|
Terminals,
|
|
TerminalsView,
|
|
Connector
|
|
){
|
|
"use strict";
|
|
window.show_modal = function(a, b, c) {}
|
|
window.hide_modal = function() {}
|
|
|
|
// create body and app
|
|
var create_app = function() {
|
|
// build body
|
|
$('body').append( '<div id="canvas-viewport">' +
|
|
'<div id="canvas-container"/>' +
|
|
'</div>' +
|
|
'<div id="overview">' +
|
|
'<canvas id="overview-canvas"/>' +
|
|
'<div id="overview-viewport"/>' +
|
|
'</div>');
|
|
|
|
// build app
|
|
return new App({
|
|
id : null,
|
|
urls : { get_datatypes : galaxy_config.root + 'api/datatypes/mapping' }
|
|
});
|
|
};
|
|
|
|
// create server (fake)
|
|
var create_server = function() {
|
|
var server = sinon.fakeServer.create();
|
|
server.respondWith('GET', galaxy_config.root + 'api/datatypes/mapping', [200, { 'Content-Type': 'application/json' },
|
|
'{"ext_to_class_name" : {"txt" : "Text", "data":"Data","tabular":"Tabular", "binary": "Binary", "bam": "Bam" }, "class_to_classes": { "Data": { "Data": true }, "Text": { "Text": true, "Data": true }, "Tabular": { "Tabular": true, "Text": true, "Data": true }, "Binary": { "Data": true, "Binary": true }, "Bam": { "Data": true, "Binary": true, "Bam": true }}}']);
|
|
server.respondWith('GET', galaxy_config.root + 'api/datatypes', [200, { 'Content-Type': 'application/json' },
|
|
'["RData", "ab1", "affybatch", "txt"]']);
|
|
return server;
|
|
};
|
|
|
|
module( "Input terminal model test", {
|
|
setup: function( ) {
|
|
this.server = create_server();
|
|
this.node = new Node( create_app(), { } );
|
|
this.input = { extensions: [ "txt" ], multiple: false };
|
|
this.input_terminal = new Terminals.InputTerminal( { input: this.input } );
|
|
this.input_terminal.node = this.node;
|
|
},
|
|
teardown: function() {
|
|
this.server.restore();
|
|
delete this.server;
|
|
},
|
|
multiple: function( ) {
|
|
this.input.multiple = true;
|
|
this.input_terminal.update( this.input );
|
|
},
|
|
test_connector: function( ) {
|
|
var outputTerminal = new Terminals.OutputTerminal( { datatypes: [ 'input' ] } );
|
|
var inputTerminal = this.input_terminal;
|
|
var connector = new Connector( outputTerminal, inputTerminal );
|
|
return connector;
|
|
},
|
|
with_test_connector: function( f ) {
|
|
this.test_connector( );
|
|
f();
|
|
this.reset_connectors();
|
|
},
|
|
reset_connectors: function( ) {
|
|
this.input_terminal.connectors = [];
|
|
},
|
|
test_accept: function( other ) {
|
|
other = other || { node: {}, datatypes: [ "txt" ] };
|
|
if( ! other.mapOver ) {
|
|
other.mapOver = function() { return Terminals.NULL_COLLECTION_TYPE_DESCRIPTION; };
|
|
}
|
|
return this.input_terminal.canAccept( other );
|
|
},
|
|
pja_change_datatype_node: function( output_name, newtype ) {
|
|
var pja = { action_type: "ChangeDatatypeAction", output_name: output_name, action_arguments: { newtype: newtype } };
|
|
var otherNode = { post_job_actions: [ pja ] };
|
|
return otherNode;
|
|
}
|
|
} );
|
|
|
|
test( "test update", function() {
|
|
deepEqual( this.input_terminal.datatypes, [ 'txt' ] );
|
|
equal( this.input_terminal.multiple, false );
|
|
this.input_terminal.update( { extensions: [ 'bam' ], multiple: true } );
|
|
deepEqual( this.input_terminal.datatypes, [ 'bam' ] );
|
|
equal( this.input_terminal.multiple, true );
|
|
} );
|
|
|
|
test( "test connect", function() {
|
|
this.node.markChanged = sinon.spy();
|
|
var connector = {};
|
|
this.input_terminal.connect( connector );
|
|
// Assert node markChanged called
|
|
ok( this.node.markChanged.called );
|
|
// Assert connectors updated
|
|
ok( this.input_terminal.connectors[ 0 ] === connector );
|
|
} );
|
|
|
|
test( "test disconnect", function() {
|
|
this.node.markChanged = sinon.spy();
|
|
var connector = this.test_connector( );
|
|
this.input_terminal.disconnect( connector );
|
|
// Assert node markChanged called
|
|
ok( this.node.markChanged.called );
|
|
// Assert connectors updated
|
|
equal( this.input_terminal.connectors.length, 0 );
|
|
} );
|
|
|
|
test( "test redraw", function() {
|
|
var connector = this.test_connector( );
|
|
connector.redraw = sinon.spy();
|
|
this.input_terminal.redraw();
|
|
// Assert connectors were redrawn
|
|
ok( connector.redraw.called );
|
|
} );
|
|
|
|
test( "test destroy", function() {
|
|
var connector = this.test_connector();
|
|
connector.destroy = sinon.spy();
|
|
this.input_terminal.destroy();
|
|
// Assert connectors were destroyed
|
|
ok( connector.destroy.called );
|
|
} );
|
|
|
|
test( "can accept exact datatype", function() {
|
|
var other = { node: {}, datatypes: [ "txt" ] }; // input also txt
|
|
ok( this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "can accept subclass datatype", function() {
|
|
var other = { node: {}, datatypes: [ "tabular" ] }; // tabular subclass of input txt
|
|
ok( this.test_accept( other ) ) ;
|
|
} );
|
|
|
|
test( "cannot accept incorrect datatype", function() {
|
|
var other = { node: {}, datatypes: [ "binary" ] }; // binary is not txt
|
|
ok( ! this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "can accept incorrect datatype if converted with PJA", function() {
|
|
var otherNode = this.pja_change_datatype_node( "out1", "txt" );
|
|
var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" }; // Was binary but converted to txt
|
|
ok( this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "cannot accept incorrect datatype if converted with PJA to incompatible type", function() {
|
|
var otherNode = this.pja_change_datatype_node( "out1", "bam" ); // bam's are not txt
|
|
var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" };
|
|
ok( ! this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "cannot accept incorrect datatype if some other output converted with PJA to compatible type", function() {
|
|
var otherNode = this.pja_change_datatype_node( "out2", "txt" );
|
|
var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" };
|
|
ok( ! this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "can accept inputs", function() {
|
|
// Other is data input module - always accept (currently - could be
|
|
// more intelligent by looking at what else input is connected to.
|
|
var other = { node: {}, datatypes: [ "input" ] };
|
|
ok( this.test_accept( other ) );
|
|
} );
|
|
|
|
test( "cannot accept when already connected", function() {
|
|
var self = this;
|
|
// If other is subtype but already connected, cannot accept
|
|
this.with_test_connector( function() {
|
|
ok( ! self.test_accept() );
|
|
} );
|
|
} );
|
|
|
|
test( "can accept already connected inputs if input is multiple", function() {
|
|
var self = this;
|
|
this.multiple();
|
|
this.with_test_connector( function() {
|
|
ok( self.test_accept() );
|
|
} );
|
|
} );
|
|
|
|
test( "cannot accept already connected inputs if input is multiple but datatypes don't match", function() {
|
|
var other = { node: {}, datatypes: [ "binary" ] }; // binary is not txt
|
|
|
|
var self = this;
|
|
this.multiple();
|
|
this.with_test_connector( function() {
|
|
ok( ! self.test_accept( other ) );
|
|
} );
|
|
} );
|
|
|
|
test( "can accept list collection for multiple input parameters if datatypes match", function() {
|
|
var self = this;
|
|
this.multiple();
|
|
ok( self.test_accept() );
|
|
} );
|
|
|
|
test( "can accept list collection for empty multiple inputs", function() {
|
|
var other = { node: {}, datatypes: [ "tabular" ], mapOver: function() { return new Terminals.CollectionTypeDescription( "list" ) } };
|
|
var self = this;
|
|
this.multiple();
|
|
ok( self.test_accept( other ) );
|
|
} );
|
|
|
|
test( "cannot accept list collection for multiple input if collection already connected", function() {
|
|
var other = { node: {}, datatypes: [ "tabular" ], mapOver: function() { return new Terminals.CollectionTypeDescription( "list" ) } };
|
|
var self = this;
|
|
this.multiple();
|
|
this.with_test_connector( function() {
|
|
ok( ! self.test_accept( other ) );
|
|
} );
|
|
} );
|
|
|
|
module( "Connector test", {});
|
|
|
|
test( "connects only if both valid handles", function() {
|
|
var input = { connect: sinon.spy() };
|
|
var output = { connect: sinon.spy() };
|
|
new Connector( input, null );
|
|
new Connector( null, output );
|
|
// Not attempts to connect...
|
|
ok( ! input.connect.called );
|
|
ok( ! output.connect.called );
|
|
new Connector( input, output );
|
|
ok( input.connect.called );
|
|
ok( output.connect.called );
|
|
});
|
|
|
|
test( "default attributes", function() {
|
|
var input = { connect: sinon.spy() };
|
|
var output = { connect: sinon.spy() };
|
|
var connector = new Connector( input, output );
|
|
equal( connector.dragging, false );
|
|
equal( connector.canvas, null );
|
|
equal( connector.inner_color, "#FFFFFF" );
|
|
equal( connector.outer_color, "#D8B365" );
|
|
} );
|
|
|
|
test( "destroy", function() {
|
|
var input = { connect: sinon.spy(), disconnect: sinon.spy() };
|
|
var output = { connect: sinon.spy(), disconnect: sinon.spy() };
|
|
var connector = new Connector( input, output );
|
|
connector.destroy();
|
|
ok( input.disconnect.called );
|
|
ok( output.disconnect.called );
|
|
} );
|
|
|
|
test( "initial redraw", function() {
|
|
var input = { connect: sinon.spy(), element: $("<div>"), isMappedOver: function() { return false; } };
|
|
var output = { connect: sinon.spy(), element: $("<div>"), isMappedOver: function() { return false; } };
|
|
var connector = new Connector( input, output );
|
|
var n = $('#canvas-container').find('canvas').length;
|
|
connector.redraw();
|
|
// Ensure canvas gets set
|
|
ok( connector.canvas );
|
|
// Ensure it got added to canvas container
|
|
equal (n + 1, $('#canvas-container').find('canvas').length);
|
|
} );
|
|
|
|
module( "Input collection terminal model test", {
|
|
setup: function( ) {
|
|
this.node = new Node( create_app(), { } );
|
|
this.input = { extensions: [ "txt" ], collection_type: "list" };
|
|
this.input_terminal = new Terminals.InputCollectionTerminal( { input: this.input } );
|
|
this.input_terminal.node = this.node;
|
|
}
|
|
} );
|
|
|
|
test( "Collection output can connect to same collection input type", function() {
|
|
var self = this;
|
|
var inputTerminal = self.input_terminal;
|
|
var outputTerminal = new Terminals.OutputCollectionTerminal( {
|
|
datatypes: 'txt',
|
|
collection_type: 'list'
|
|
} );
|
|
outputTerminal.node = {};
|
|
ok( this.input_terminal.canAccept( outputTerminal ) );
|
|
} );
|
|
|
|
test( "Collection output cannot connect to different collection input type", function() {
|
|
var self = this;
|
|
var inputTerminal = self.input_terminal;
|
|
var outputTerminal = new Terminals.OutputCollectionTerminal( {
|
|
datatypes: 'txt',
|
|
collection_type: 'paired'
|
|
} );
|
|
outputTerminal.node = {};
|
|
ok( ! this.input_terminal.canAccept( outputTerminal ) );
|
|
} );
|
|
|
|
module( "Node unit test", {
|
|
setup: function() {
|
|
this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
|
|
this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
|
|
this.element = $("<div><div class='toolFormBody'></div></div>");
|
|
this.app = create_app();
|
|
this.node = new Node( this.app, { element: this.element } );
|
|
this.node.input_terminals.i1 = this.input_terminal;
|
|
this.node.output_terminals.o1 = this.output_terminal;
|
|
},
|
|
$: function( selector ) {
|
|
return $( this.node.element.find( selector ) );
|
|
},
|
|
expect_workflow_node_changed: function( f ) {
|
|
var node = this.node;
|
|
var node_changed_spy = sinon.spy( this.app.workflow, "node_changed" );
|
|
f();
|
|
ok( node_changed_spy.calledWith( node ) );
|
|
},
|
|
init_field_data_simple: function() {
|
|
var data = {
|
|
data_inputs: [ {name: "input1", extensions: [ "data" ] } ],
|
|
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
|
};
|
|
this.node.init_field_data( data );
|
|
},
|
|
update_field_data_with_new_input: function() {
|
|
var new_data = {
|
|
data_inputs: [
|
|
{ name: "input1", extensions: [ "data" ] },
|
|
{ name: "extra_0|input1", extensions: [ "data" ] },
|
|
],
|
|
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
|
post_job_actions: "{}"
|
|
};
|
|
this.node.update_field_data( new_data );
|
|
}
|
|
} );
|
|
|
|
test( "make active", function() {
|
|
ok( ! this.element.hasClass( "toolForm-active" ) );
|
|
this.node.make_active();
|
|
ok( this.element.hasClass( "toolForm-active" ) );
|
|
} );
|
|
|
|
test( "destroy", function() {
|
|
var remove_node_spy = sinon.spy( this.app.workflow, "remove_node" );
|
|
this.node.destroy();
|
|
ok( this.input_terminal.destroy.called );
|
|
ok( this.output_terminal.destroy.called );
|
|
ok( remove_node_spy.calledWith( this.node ) );
|
|
} );
|
|
|
|
test( "error", function() {
|
|
// Test body of toolFormBody div updated and workflow notified of change.
|
|
var test = this;
|
|
this.expect_workflow_node_changed( function() {
|
|
test.node.error( "TOOL ERROR" );
|
|
equal( $( test.$(".toolFormBody").children()[ 0 ] ).html(), "TOOL ERROR" );
|
|
} );
|
|
} );
|
|
|
|
test( "init_field_data properties", function() {
|
|
var node = this.node;
|
|
this.expect_workflow_node_changed( function( ) {
|
|
var data = {
|
|
data_inputs: [],
|
|
data_outputs: [],
|
|
type: "tool",
|
|
name: "cat1",
|
|
form_html: "<form>",
|
|
tool_state: "ok",
|
|
tool_errors: false,
|
|
tooltip: "tool tooltip",
|
|
annotation: "tool annotation",
|
|
workflow_outputs: [ "out1" ],
|
|
};
|
|
node.init_field_data( data );
|
|
equal( node.type, "tool" );
|
|
equal( node.name, "cat1" );
|
|
equal( node.form_html, "<form>" );
|
|
equal( node.tool_state, "ok" );
|
|
equal( node.tooltip, "tool tooltip" );
|
|
equal( node.annotation, "tool annotation" );
|
|
deepEqual( node.post_job_actions, {} );
|
|
deepEqual( node.workflow_outputs, [ "out1" ] );
|
|
} );
|
|
} );
|
|
|
|
test( "init_field_data data", function() {
|
|
var test = this;
|
|
this.expect_workflow_node_changed( function( ) {
|
|
// pre-init not tool form body...
|
|
equal( test.$( ".output-terminal" ).length, 0 );
|
|
equal( test.$( ".input-terminal" ).length, 0 );
|
|
equal( test.$( ".rule" ).length, 0 );
|
|
test.init_field_data_simple();
|
|
// After init tool form should have three "rows"/divs - , inputs div, one output, and rule...
|
|
equal( test.$( ".output-terminal" ).length, 1 );
|
|
equal( test.$( ".input-terminal" ).length, 1 );
|
|
equal( test.$( ".rule" ).length, 1 );
|
|
equal( test.$( ".toolFormBody" ).children().length, 3 );
|
|
} );
|
|
} );
|
|
|
|
test( "update_field_data updated data inputs and outputs", function() {
|
|
var test = this;
|
|
this.expect_workflow_node_changed( function( ) {
|
|
// Call init with one input and output.
|
|
test.init_field_data_simple();
|
|
|
|
test.update_field_data_with_new_input();
|
|
|
|
// Now there are 2 inputs...
|
|
equal( test.$( ".input-terminal" ).length, 2 );
|
|
equal( test.$( ".output-terminal" ).length, 1 );
|
|
equal( test.$( ".rule" ).length, 1 );
|
|
} );
|
|
} );
|
|
|
|
test( "update_field_data preserves connectors", function() {
|
|
var test = this;
|
|
var node = this.node;
|
|
this.expect_workflow_node_changed( function( ) {
|
|
// Call init with one input and output.
|
|
test.init_field_data_simple();
|
|
|
|
var connector = new Connector();
|
|
var old_input_terminal = node.input_terminals.input1;
|
|
old_input_terminal.connectors.push( connector );
|
|
|
|
// Update node, make sure connector still the same...
|
|
test.update_field_data_with_new_input();
|
|
var new_input_terminal = node.input_terminals.input1;
|
|
equal( connector, new_input_terminal.connectors[ 0 ] );
|
|
|
|
// Update a second time, make sure connector still the same...
|
|
test.update_field_data_with_new_input();
|
|
new_input_terminal = node.input_terminals.input1;
|
|
equal( connector, new_input_terminal.connectors[ 0 ] );
|
|
} );
|
|
} );
|
|
|
|
test( "update_field_data destroys old terminals", function() {
|
|
var test = this;
|
|
var node = this.node;
|
|
this.expect_workflow_node_changed( function( ) {
|
|
var data = {
|
|
data_inputs: [ { name: "input1", extensions: [ "data" ] },
|
|
{ name: "willDisappear", extensions: [ "data" ] } ],
|
|
data_outputs: [ {name: "output1", extensions: [ "data" ] } ],
|
|
};
|
|
node.init_field_data( data );
|
|
var old_input_terminal = node.input_terminals.willDisappear;
|
|
var destroy_spy = sinon.spy( old_input_terminal, "destroy" );
|
|
// Update
|
|
test.update_field_data_with_new_input();
|
|
ok( destroy_spy.called );
|
|
} );
|
|
} );
|
|
|
|
module( "create_node", {
|
|
setup: function() {
|
|
this.app = create_app();
|
|
}
|
|
});
|
|
|
|
test( "node added to workflow", function() {
|
|
var add_node_spy = sinon.spy( this.app.workflow, "add_node" );
|
|
var node = this.app.workflow.create_node( "tool", "Cat Files", "cat1" );
|
|
ok( add_node_spy.calledWith( node ) );
|
|
} );
|
|
|
|
// global NodeView
|
|
module( "Node view ", {
|
|
setup: function() {
|
|
this.set_for_node( { input_terminals: {}, output_terminals: {}, markChanged: function() {}, terminalMapping: { disableMapOver: function() {} } } );
|
|
},
|
|
set_for_node: function( node ) {
|
|
var element = $("<div><div class='toolFormBody'></div></div>");
|
|
this.view = new NodeView( { node: node, el: element[ 0 ] } );
|
|
},
|
|
connectAttachedTerminal: function( inputType, outputType ) {
|
|
this.view.addDataInput( { name: "TestName", extensions: [ inputType ] } );
|
|
var terminal = this.view.node.input_terminals[ "TestName" ];
|
|
|
|
var outputTerminal = new Terminals.OutputTerminal( { name: "TestOuptut", datatypes: [ outputType ] } );
|
|
outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
|
|
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: Terminals.NULL_COLLECTION_TYPE_DESCRIPTION };
|
|
var c = new Connector( outputTerminal, terminal );
|
|
|
|
return c;
|
|
},
|
|
connectAttachedMultiInputTerminal: function( inputType, outputType ) {
|
|
this.view.addDataInput( { name: "TestName", extensions: [ inputType ], multiple: true } );
|
|
var terminal = this.view.node.input_terminals[ "TestName" ];
|
|
|
|
var outputTerminal = new Terminals.OutputTerminal( { name: "TestOuptut", datatypes: [ "txt" ] } );
|
|
outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
|
|
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: new Terminals.CollectionTypeDescription( "list" ) };
|
|
var c = new Connector( outputTerminal, terminal );
|
|
|
|
return c;
|
|
},
|
|
connectAttachedMappedOutput: function( ) {
|
|
this.view.addDataInput( { name: "TestName", extensions: [ "txt" ], input_type: "dataset_collection" } );
|
|
var terminal = this.view.node.input_terminals[ "TestName" ];
|
|
|
|
var outputTerminal = new Terminals.OutputTerminal( { name: "TestOuptut", datatypes: [ "txt" ] } );
|
|
outputTerminal.node = { markChanged: function() {}, post_job_actions: [], hasMappedOverInputTerminals: function() { return false; }, hasConnectedOutputTerminals: function() { return true; } };
|
|
outputTerminal.terminalMapping = { disableMapOver: function() {}, mapOver: new Terminals.CollectionTypeDescription( "list" ) };
|
|
var c = new Connector( outputTerminal, terminal );
|
|
|
|
return c;
|
|
}
|
|
} );
|
|
|
|
test( "tool error styling", function() {
|
|
this.set_for_node( { tool_errors: false } );
|
|
this.view.render();
|
|
ok( ! this.view.$el.hasClass( "tool-node-error" ) );
|
|
this.set_for_node( { tool_errors: true } );
|
|
this.view.render();
|
|
ok( this.view.$el.hasClass( "tool-node-error" ) );
|
|
} );
|
|
|
|
test( "rendering correct width", function() {
|
|
// Default width is 150
|
|
this.view.render();
|
|
equal( this.view.$el.width(), 150 );
|
|
|
|
// If any data rows are greater, it will update
|
|
this.view.updateMaxWidth( 200 );
|
|
this.view.render();
|
|
equal( this.view.$el.width(), 200 );
|
|
|
|
// However 250 is the maximum width of node
|
|
this.view.updateMaxWidth( 300 );
|
|
this.view.render();
|
|
equal( this.view.$el.width(), 250 );
|
|
|
|
} );
|
|
|
|
test( "replacing terminal on data input update preserves connections", function() {
|
|
var connector = this.connectAttachedTerminal( "txt", "txt" );
|
|
var newElement = $("<div class='inputs'></div>");
|
|
this.view.addDataInput( { name: "TestName", extensions: ["txt"] }, newElement );
|
|
var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
|
|
ok( connector.handle2 === terminal );
|
|
} );
|
|
|
|
test( "replacing terminal on data multiple input update preserves collection connections", function() {
|
|
var connector = this.connectAttachedMultiInputTerminal( "txt", "txt" );
|
|
var connector_destroy_spy = sinon.spy( connector, "destroy" );
|
|
var newElement = $("<div class='inputs'></div>");
|
|
this.view.addDataInput( { name: "TestName", extensions: ["txt"], multiple: true }, newElement );
|
|
ok( ! connector_destroy_spy.called );
|
|
} );
|
|
|
|
test( "replacing mapped terminal on data collection input update preserves connections", function() {
|
|
var connector = this.connectAttachedMappedOutput();
|
|
var newElement = $("<div class='inputs'></div>");
|
|
this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
|
|
var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
|
|
ok( connector.handle2 === terminal );
|
|
} );
|
|
|
|
test( "replacing terminal on data input destroys invalid connections", function() {
|
|
var connector = this.connectAttachedTerminal( "txt", "txt" );
|
|
var newElement = $("<div class='inputs'></div>");
|
|
var connector_destroy_spy = sinon.spy( connector, "destroy" );
|
|
// Replacing input with same name - but now of type bam should destroy connection.
|
|
this.view.addDataInput( { name: "TestName", extensions: ["bam"] }, newElement );
|
|
var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
|
|
ok( connector_destroy_spy.called );
|
|
} );
|
|
|
|
test( "replacing terminal on data input with collection changes mapping view type", function() {
|
|
var connector = this.connectAttachedTerminal( "txt", "txt" );
|
|
var newElement = $("<div class='inputs'></div>");
|
|
var connector_destroy_spy = sinon.spy( connector, "destroy" );
|
|
this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset_collection" }, newElement );
|
|
// Input type changed to dataset_collection - old connections are reset.
|
|
// Would be nice to preserve these connections and make them map over.
|
|
var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
|
|
ok( connector_destroy_spy.called );
|
|
} );
|
|
|
|
test( "replacing terminal on data collection input with simple input changes mapping view type", function() {
|
|
var connector = this.connectAttachedMappedOutput();
|
|
var newElement = $("<div class='inputs'></div>");
|
|
var connector_destroy_spy = sinon.spy( connector, "destroy" );
|
|
this.view.addDataInput( { name: "TestName", extensions: ["txt"], input_type: "dataset" }, newElement );
|
|
var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
|
|
ok( connector_destroy_spy.called );
|
|
} );
|
|
|
|
// global InputTerminalView
|
|
module( "Input terminal view", {
|
|
setup: function() {
|
|
this.node = { input_terminals: [] };
|
|
this.input = { name: "i1", extensions: "txt", multiple: false };
|
|
this.view = new TerminalsView.InputTerminalView( {
|
|
node: this.node,
|
|
input: this.input,
|
|
});
|
|
}
|
|
} );
|
|
|
|
test( "terminal added to node", function() {
|
|
ok( this.node.input_terminals.i1 );
|
|
equal( this.node.input_terminals.i1.datatypes, [ "txt" ] );
|
|
equal( this.node.input_terminals.i1.multiple, false );
|
|
} );
|
|
|
|
test( "terminal element", function() {
|
|
var el = this.view.el;
|
|
equal( el.tagName, "DIV" );
|
|
equal( el.className, "terminal input-terminal");
|
|
} );
|
|
|
|
// global OutputTerminalView
|
|
module( "Output terminal view", {
|
|
setup: function() {
|
|
this.node = { output_terminals: [] };
|
|
this.output = { name: "o1", extensions: "txt" };
|
|
this.view = new TerminalsView.OutputTerminalView( {
|
|
node: this.node,
|
|
output: this.output,
|
|
});
|
|
}
|
|
} );
|
|
|
|
test( "terminal added to node", function() {
|
|
ok( this.node.output_terminals.o1 );
|
|
equal( this.node.output_terminals.o1.datatypes, [ "txt" ] );
|
|
} );
|
|
|
|
test( "terminal element", function() {
|
|
var el = this.view.el;
|
|
equal( el.tagName, "DIV" );
|
|
equal( el.className, "terminal output-terminal");
|
|
} );
|
|
|
|
module( "CollectionTypeDescription", {
|
|
listType: function() {
|
|
return new Terminals.CollectionTypeDescription( "list" );
|
|
},
|
|
pairedType: function() {
|
|
return new Terminals.CollectionTypeDescription( "paired" );
|
|
},
|
|
pairedListType: function() {
|
|
return new Terminals.CollectionTypeDescription( "list:paired" );
|
|
}
|
|
} );
|
|
|
|
test( "canMatch", function() {
|
|
ok( this.listType().canMatch( this.listType() ) );
|
|
ok( ! this.listType().canMatch( this.pairedType() ) );
|
|
ok( ! this.listType().canMatch( this.pairedListType() ) );
|
|
} );
|
|
|
|
test( "canMatch special types", function() {
|
|
ok( this.listType().canMatch( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.canMatch( this.pairedListType() ) );
|
|
|
|
ok( ! this.listType().canMatch( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.canMatch( this.pairedListType() ) );
|
|
} );
|
|
|
|
test( "canMapOver", function() {
|
|
ok( ! this.listType().canMapOver( this.listType() ) );
|
|
ok( ! this.listType().canMapOver( this.pairedType() ) );
|
|
ok( this.pairedListType().canMapOver( this.pairedType() ) );
|
|
ok( ! this.listType().canMapOver( this.pairedListType() ) );
|
|
} );
|
|
|
|
test( "canMapOver special types", function() {
|
|
ok( ! this.listType().canMapOver( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.canMapOver( this.pairedListType() ) );
|
|
|
|
// Following two should be able to be relaxed someday maybe - but the
|
|
// tracking gets tricky I think. For now mapping only works for explicitly
|
|
// defined collection types.
|
|
ok( ! this.listType().canMapOver( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.canMapOver( this.pairedListType() ) );
|
|
} );
|
|
|
|
test( "append", function( other ) {
|
|
var appendedType = this.listType().append( this.pairedType() );
|
|
equal( appendedType.collectionType, "list:paired" );
|
|
} );
|
|
|
|
test( "isCollection", function() {
|
|
ok( this.listType().isCollection );
|
|
ok( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.isCollection );
|
|
ok( ! Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.isCollection );
|
|
} );
|
|
|
|
test( "equal", function() {
|
|
ok( ! this.listType().equal( this.pairedType() ) );
|
|
ok( this.listType().equal( this.listType() ) );
|
|
|
|
ok( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.equal( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.equal( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.ANY_COLLECTION_TYPE_DESCRIPTION.equal( this.pairedType() ) );
|
|
ok( ! this.pairedType().equal( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION ) );
|
|
|
|
ok( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.equal( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.equal( Terminals.ANY_COLLECTION_TYPE_DESCRIPTION ) );
|
|
ok( ! Terminals.NULL_COLLECTION_TYPE_DESCRIPTION.equal( this.listType() ) );
|
|
ok( ! this.listType().equal( Terminals.NULL_COLLECTION_TYPE_DESCRIPTION ) );
|
|
|
|
} );
|
|
|
|
module( "TerminalMapping", {
|
|
} );
|
|
|
|
test( "default constructor", function() {
|
|
var terminal = {};
|
|
var mapping = new Terminals.TerminalMapping( { terminal: terminal } );
|
|
ok( terminal.terminalMapping === mapping );
|
|
ok( mapping.mapOver === Terminals.NULL_COLLECTION_TYPE_DESCRIPTION );
|
|
} );
|
|
|
|
test( "constructing with mapOver", function() {
|
|
var terminal = {};
|
|
var mapping = new Terminals.TerminalMapping( { terminal: terminal, mapOver: new Terminals.CollectionTypeDescription( "list" ) } );
|
|
ok( mapping.mapOver.collectionType == "list" );
|
|
} );
|
|
|
|
test( "disableMapOver", function() {
|
|
var terminal = {};
|
|
var mapping = new Terminals.TerminalMapping( { terminal: terminal, mapOver: new Terminals.CollectionTypeDescription( "list" ) } );
|
|
var changeSpy = sinon.spy();
|
|
mapping.bind( "change", changeSpy );
|
|
mapping.disableMapOver();
|
|
ok( mapping.mapOver === Terminals.NULL_COLLECTION_TYPE_DESCRIPTION );
|
|
ok( changeSpy.called );
|
|
} );
|
|
|
|
module( "terminal mapping logic", {
|
|
newInputTerminal: function( mapOver, input, node ) {
|
|
input = input || {};
|
|
node = node || this.newNode();
|
|
if( ! ( 'extensions' in input ) ) {
|
|
input[ 'extensions'] = [ 'data' ];
|
|
}
|
|
var inputEl = $("<div>")[ 0 ];
|
|
var inputTerminal = new Terminals.InputTerminal( { element: inputEl, input: input } );
|
|
var inputTerminalMapping = new Terminals.TerminalMapping( { terminal: inputTerminal } );
|
|
inputTerminal.node = node;
|
|
if( mapOver ) {
|
|
inputTerminal.setMapOver( new Terminals.CollectionTypeDescription( mapOver ) );
|
|
}
|
|
return inputTerminal;
|
|
},
|
|
newInputCollectionTerminal: function( input, node ) {
|
|
input = input || {};
|
|
node = node || this.newNode();
|
|
if( ! ( 'extensions' in input ) ) {
|
|
input[ 'extensions'] = [ 'data' ];
|
|
}
|
|
var inputEl = $("<div>")[ 0 ];
|
|
var inputTerminal = new Terminals.InputCollectionTerminal( { element: inputEl, input: input } );
|
|
var inputTerminalMapping = new Terminals.TerminalMapping( { terminal: inputTerminal } );
|
|
inputTerminal.node = node;
|
|
return inputTerminal;
|
|
},
|
|
newOutputTerminal: function( mapOver, output, node ) {
|
|
output = output || {};
|
|
node = node || this.newNode();
|
|
if( ! ( 'extensions' in output ) ) {
|
|
output[ 'extensions'] = [ 'data' ];
|
|
}
|
|
var outputEl = $("<div>")[ 0 ];
|
|
var outputTerminal = new Terminals.OutputTerminal( { element: outputEl, datatypes: output.extensions } );
|
|
var outputTerminalMapping = new Terminals.TerminalMapping( { terminal: outputTerminal } );
|
|
outputTerminal.node = node;
|
|
if( mapOver ) {
|
|
outputTerminal.setMapOver( new Terminals.CollectionTypeDescription( mapOver ) );
|
|
}
|
|
return outputTerminal;
|
|
},
|
|
newOutputCollectionTerminal: function( collectionType, output, node, mapOver ) {
|
|
collectionType = collectionType || "list";
|
|
output = output || {};
|
|
node = node || this.newNode();
|
|
if( ! ( 'extensions' in output ) ) {
|
|
output[ 'extensions'] = [ 'data' ];
|
|
}
|
|
var outputEl = $("<div>")[ 0 ];
|
|
var outputTerminal = new Terminals.OutputCollectionTerminal( { element: outputEl, datatypes: output.extensions, collection_type: collectionType } );
|
|
var outputTerminalMapping = new Terminals.TerminalMapping( { terminal: outputTerminal } );
|
|
outputTerminal.node = node;
|
|
if( mapOver ) {
|
|
outputTerminal.setMapOver( new Terminals.CollectionTypeDescription( mapOver ) );
|
|
}
|
|
return outputTerminal;
|
|
},
|
|
newNode: function( ) {
|
|
var nodeEl = $("<div>")[ 0 ];
|
|
var node = new Node( create_app(), { element: nodeEl } );
|
|
return node;
|
|
},
|
|
_addExistingOutput: function( terminal, output, connected ) {
|
|
var self = this;
|
|
var node = terminal.node;
|
|
if( connected ) {
|
|
var inputTerminal = self.newInputTerminal();
|
|
new Connector( inputTerminal, output );
|
|
}
|
|
this._addTerminalTo( output, node.output_terminals );
|
|
return output;
|
|
},
|
|
addOutput: function( terminal, connected ) {
|
|
var connectedOutput = this.newOutputTerminal();
|
|
return this._addExistingOutput( terminal, connectedOutput, connected );
|
|
},
|
|
addCollectionOutput: function( terminal, connected ) {
|
|
var collectionOutput = this.newOutputCollectionTerminal();
|
|
return this._addExistingOutput( terminal, collectionOutput, connected );
|
|
},
|
|
addConnectedOutput: function( terminal ) {
|
|
return this.addOutput( terminal, true );
|
|
},
|
|
addConnectedCollectionOutput: function( terminal ) {
|
|
var connectedOutput = this.newOutputCollectionTerminal();
|
|
return this._addExistingOutput( terminal, connectedOutput, true );
|
|
},
|
|
addConnectedInput: function( terminal ) {
|
|
var self = this;
|
|
var connectedInput = this.newInputTerminal();
|
|
var node = terminal.node;
|
|
var outputTerminal = self.newOutputTerminal();
|
|
new Connector( connectedInput, outputTerminal );
|
|
this._addTerminalTo( connectedInput, node.input_terminals );
|
|
return connectedInput;
|
|
},
|
|
_addTerminalTo: function( terminal, terminals ) {
|
|
var name = "other";
|
|
while( name in terminals ) {
|
|
name += "_";
|
|
}
|
|
terminals[ name ] = terminal;
|
|
},
|
|
verifyNotAttachable: function( inputTerminal, output ) {
|
|
var outputTerminal;
|
|
var outputTerminal;
|
|
if( typeof( output ) == "string" ) {
|
|
// Just given a collection type... create terminal out of it.
|
|
outputTerminal = this.newOutputTerminal( output );
|
|
} else {
|
|
outputTerminal = output;
|
|
}
|
|
|
|
ok( ! inputTerminal.attachable( outputTerminal ) );
|
|
},
|
|
verifyAttachable: function( inputTerminal, output ) {
|
|
var outputTerminal;
|
|
if( typeof( output ) == "string" ) {
|
|
// Just given a collection type... create terminal out of it.
|
|
outputTerminal = this.newOutputTerminal( output );
|
|
} else {
|
|
outputTerminal = output;
|
|
}
|
|
|
|
ok( inputTerminal.attachable( outputTerminal ) );
|
|
|
|
// Go further... make sure datatypes are being enforced
|
|
inputTerminal.datatypes = [ "bam" ];
|
|
outputTerminal.datatypes = [ "txt" ];
|
|
ok( ! inputTerminal.attachable( outputTerminal ) );
|
|
},
|
|
verifyMappedOver: function( terminal ) {
|
|
ok( terminal.terminalMapping.mapOver.isCollection );
|
|
},
|
|
verifyNotMappedOver: function( terminal ) {
|
|
ok( ! terminal.terminalMapping.mapOver.isCollection );
|
|
},
|
|
} );
|
|
|
|
test( "unconstrained input can be mapped over", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unmapped input can be mapped over if matching connected input terminals map type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list") );
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unmapped input cannot be mapped over if not matching connected input terminals map type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput.setMapOver( new Terminals.CollectionTypeDescription( "paired" ) );
|
|
this.verifyNotAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unmapped input can be attached to by output collection if matching connected input terminals map type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list") );
|
|
var outputTerminal = this.newOutputCollectionTerminal( "list" );
|
|
this.verifyAttachable( inputTerminal1, outputTerminal );
|
|
} );
|
|
|
|
test( "unmapped input cannot be attached to by output collection if matching connected input terminals don't match map type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list") );
|
|
var outputTerminal = this.newOutputCollectionTerminal( "paired" );
|
|
this.verifyNotAttachable( inputTerminal1, outputTerminal );
|
|
} );
|
|
|
|
test( "unmapped input can be attached to by output collection if effective output type (output+mapover) is same as mapped over input", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list:paired") );
|
|
var outputTerminal = this.newOutputCollectionTerminal( "paired" );
|
|
outputTerminal.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
this.verifyAttachable( inputTerminal1, outputTerminal );
|
|
} );
|
|
|
|
test( "unmapped input cannot be attached to by output collection if effective output type (output+mapover) is not same as mapped over input (1)", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list:paired") );
|
|
var outputTerminal = this.newOutputCollectionTerminal( "list" );
|
|
outputTerminal.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
this.verifyNotAttachable( inputTerminal1, outputTerminal );
|
|
} );
|
|
|
|
test( "unmapped input cannot be attached to by output collection if effective output type (output+mapover) is not same as mapped over input (2)", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
var connectedInput2 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput2.setMapOver( new Terminals.CollectionTypeDescription( "list:paired") );
|
|
var outputTerminal = this.newOutputCollectionTerminal( "list" );
|
|
outputTerminal.setMapOver( new Terminals.CollectionTypeDescription( "paired" ) );
|
|
this.verifyNotAttachable( inputTerminal1, outputTerminal );
|
|
} );
|
|
|
|
test( "unmapped input with unmapped, connected outputs cannot be mapped over", function() {
|
|
// It would invalidate the connections - someday maybe we could try to
|
|
// recursively map over everything down the DAG - it would be expensive
|
|
// to check that though.
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
this.addConnectedOutput( inputTerminal1 );
|
|
this.verifyNotAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unmapped input with connected mapped outputs can be mapped over if matching", function() {
|
|
// It would invalidate the connections - someday maybe we could try to
|
|
// recursively map over everything down the DAG - it would be expensive
|
|
// to check that though.
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedOutput = this.addConnectedOutput( inputTerminal1 );
|
|
connectedOutput.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unmapped input with connected mapped outputs cannot be mapped over if mapover not matching", function() {
|
|
// It would invalidate the connections - someday maybe we could try to
|
|
// recursively map over everything down the DAG - it would be expensive
|
|
// to check that though.
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedOutput = this.addConnectedOutput( inputTerminal1 );
|
|
connectedOutput.setMapOver( new Terminals.CollectionTypeDescription( "paired" ) );
|
|
this.verifyNotAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "explicitly constrained input can not be mapped over by incompatible collection type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
inputTerminal1.setMapOver( new Terminals.CollectionTypeDescription( "paired" ) );
|
|
this.verifyNotAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "explicitly constrained input can be mapped over by compatible collection type", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
inputTerminal1.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unconstrained collection input can be mapped over", function() {
|
|
var inputTerminal1 = this.newInputCollectionTerminal( { collection_type: "paired" } );
|
|
this.verifyAttachable( inputTerminal1, "list:paired" );
|
|
} );
|
|
|
|
test( "unconstrained collection input cannot be mapped over by incompatible type", function() {
|
|
var inputTerminal1 = this.newInputCollectionTerminal( { collection_type: "list" } ); // Would need to be paired...
|
|
this.verifyNotAttachable( inputTerminal1, "list:paired" );
|
|
} );
|
|
|
|
test( "explicitly mapped over collection input can be attached by explicit mapping", function() {
|
|
var inputTerminal1 = this.newInputCollectionTerminal( { collection_type: "paired" } );
|
|
inputTerminal1.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
this.verifyAttachable( inputTerminal1, "list:paired" );
|
|
} );
|
|
|
|
test( "explicitly mapped over collection input can be attached by explicit mapping", function() {
|
|
var inputTerminal1 = this.newInputCollectionTerminal( { collection_type: "list:paired" } );
|
|
inputTerminal1.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
// effectively input is list:list:paired so shouldn't be able to attach
|
|
this.verifyNotAttachable( inputTerminal1, "list:paired" );
|
|
} );
|
|
|
|
test( "unconnected multiple inputs can be connected to rank 1 collections", function() {
|
|
var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "multiple input attachable by collections", function() {
|
|
var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
this.addConnectedOutput( connectedInput1 );
|
|
this.verifyAttachable( inputTerminal1, "list" );
|
|
} );
|
|
|
|
test( "unconnected multiple inputs cannot be connected to rank > 1 collections (yet...)", function() {
|
|
var inputTerminal1 = this.newInputTerminal( null, { multiple: true } );
|
|
this.verifyNotAttachable( inputTerminal1, "list:paired" );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded does nothing if not mapped", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyNotMappedOver( inputTerminal1 );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded resets unconstrained input", function() {
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
this.verifyMappedOver( inputTerminal1 );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyNotMappedOver( inputTerminal1 );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded does not reset if connected output depends on being mapped", function() {
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
var connectedOutput = this.addConnectedOutput( inputTerminal1 );
|
|
connectedOutput.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyMappedOver( inputTerminal1 );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded resets if node outputs are not connected to anything", function() {
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
var output = this.addOutput( inputTerminal1 );
|
|
output.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyNotMappedOver( inputTerminal1 );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded an input resets node outputs if they not connected to anything", function() {
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
var output = this.addOutput( inputTerminal1 );
|
|
output.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyNotMappedOver( output );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded an input resets node collection outputs if they not connected to anything", function() {
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
var output = this.addCollectionOutput( inputTerminal1 );
|
|
output.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
this.verifyNotMappedOver( output );
|
|
} );
|
|
|
|
test( "resetMappingIfNeeded resets if not last mapped over input", function() {
|
|
// Idea here is that other nodes are forcing output to still be mapped
|
|
// over so don't need to disconnect output nodes.
|
|
var inputTerminal1 = this.newInputTerminal( "list" );
|
|
var connectedInput1 = this.addConnectedInput( inputTerminal1 );
|
|
connectedInput1.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
var connectedOutput = this.addConnectedOutput( inputTerminal1 );
|
|
connectedOutput.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
inputTerminal1.resetMappingIfNeeded();
|
|
// inputTerminal1 can be reset because connectedInput1
|
|
// is still forcing connectedOutput to be mapped over,
|
|
// so verify inputTerminal1 is rest and connectedInput1
|
|
// and connectedOutput are untouched.
|
|
this.verifyNotMappedOver( inputTerminal1 );
|
|
this.verifyMappedOver( connectedInput1 );
|
|
this.verifyMappedOver( connectedOutput );
|
|
} );
|
|
|
|
test( "simple mapping over collection outputs works correctly", function() {
|
|
var inputTerminal1 = this.newInputTerminal();
|
|
var connectedOutput = this.addConnectedCollectionOutput( inputTerminal1 );
|
|
inputTerminal1.setMapOver( new Terminals.CollectionTypeDescription( "list" ) );
|
|
|
|
// Can attach list output of collection type list that is being mapped
|
|
// over another list to a list:list (because this is what it is) but not
|
|
// to a list:list:list.
|
|
var testTerminal2 = this.newInputTerminal( "list:list" );
|
|
this.verifyAttachable( testTerminal2, connectedOutput );
|
|
|
|
var testTerminal1 = this.newInputTerminal( "list:list:list" );
|
|
this.verifyNotAttachable( testTerminal1, connectedOutput );
|
|
} );
|
|
}); |