mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
244 lines
12 KiB
JavaScript
244 lines
12 KiB
JavaScript
var require = patchRequire( require ),
|
|
spaceghost = require( 'spaceghost' ).fromCasper( casper ),
|
|
xpath = require( 'casper' ).selectXPath,
|
|
utils = require( 'utils' ),
|
|
format = utils.format;
|
|
|
|
spaceghost.test.begin( 'Test the workflows API', 0, function suite( test ){
|
|
spaceghost.start();
|
|
|
|
// =================================================================== SET UP
|
|
var email = spaceghost.user.getRandomEmail(),
|
|
password = '123456';
|
|
if( spaceghost.fixtureData.testUser ){
|
|
email = spaceghost.fixtureData.testUser.email;
|
|
password = spaceghost.fixtureData.testUser.password;
|
|
}
|
|
spaceghost.user.loginOrRegisterUser( email, password );
|
|
|
|
// =================================================================== TESTS
|
|
var workflowJSONFilepath = 'test-data/simple_test.ga',
|
|
workflowModelClass = 'StoredWorkflow',
|
|
workflowSummaryKeys = [
|
|
'id', 'model_class', 'name', 'published', 'tags', 'url'
|
|
],
|
|
workflowDetailKeys = workflowSummaryKeys.concat([
|
|
'inputs', 'steps'
|
|
]),
|
|
stepKeys = [
|
|
'id', 'input_steps', 'tool_id', 'type'
|
|
],
|
|
simpleBedFilepath = '../../test-data/2.bed',
|
|
uploadedId = null,
|
|
workflowCreateKeys = [ 'history', 'outputs' ];
|
|
|
|
spaceghost.openHomePage().then( function(){
|
|
|
|
// ------------------------------------------------------------------------------------------- UPLOAD
|
|
// upload first or we have no data to test
|
|
this.test.comment( 'upload should allow importing a new workflow given in JSON form' );
|
|
var workflowToUpload = this.loadJSONFile( workflowJSONFilepath );
|
|
//this.debug( this.jsonStr( workflowToUpload ) );
|
|
var returned = this.api.workflows.upload( workflowToUpload );
|
|
|
|
this.test.comment( 'upload should return a summary object of what we uploaded' );
|
|
//this.debug( this.jsonStr( returned ) );
|
|
this.test.assert( utils.isObject( returned ), "upload returned an object" );
|
|
this.test.assert( this.hasKeys( returned, workflowSummaryKeys ), "upload's return has the proper keys" );
|
|
this.test.assert( this.api.isEncodedId( returned.id ),
|
|
"id is of the proper form: " + returned.id );
|
|
this.test.assert( returned.model_class === workflowModelClass,
|
|
"has the proper model_class: " + returned.model_class );
|
|
this.test.assert( returned.name === workflowToUpload.name + ' ' + '(imported from API)',
|
|
"has the proper, modified name: " + returned.name );
|
|
this.test.assert( !returned.published,
|
|
"uploaded workflow defaults to un-published: " + returned.published );
|
|
this.test.assert( utils.isArray( returned.tags ) && returned.tags.length === 0,
|
|
"upload returned an empty tag array: " + this.jsonStr( returned.tags ) );
|
|
this.test.assert( returned.url === utils.format( this.api.workflows.urlTpls.show, returned.id ),
|
|
"url matches the show url: " + returned.url );
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------- INDEX
|
|
this.test.comment( 'index should get a list of workflows' );
|
|
var workflowIndex = this.api.workflows.index();
|
|
this.debug( this.jsonStr( workflowIndex ) );
|
|
this.test.assert( utils.isArray( workflowIndex ), "index returned an array: length " + workflowIndex.length );
|
|
this.test.assert( workflowIndex.length >= 1, "index returned at least one job" );
|
|
|
|
this.test.comment( 'index should have returned an object matching the workflow uploaded' );
|
|
var firstWorkflow = workflowIndex[0];
|
|
this.test.assert( this.hasKeys( firstWorkflow, workflowSummaryKeys ), "index has the proper keys" );
|
|
this.test.assert( this.api.isEncodedId( firstWorkflow.id ),
|
|
"id is of the proper form: " + firstWorkflow.id );
|
|
this.test.assert( firstWorkflow.model_class === workflowModelClass,
|
|
"has the proper model_class: " + firstWorkflow.model_class );
|
|
this.test.assert( firstWorkflow.name === workflowToUpload.name + ' ' + '(imported from API)',
|
|
"has the proper, modified name: " + firstWorkflow.name );
|
|
this.test.assert( !firstWorkflow.published,
|
|
"workflow is un-published: " + firstWorkflow.published );
|
|
this.test.assert( utils.isArray( firstWorkflow.tags ) && firstWorkflow.tags.length === 0,
|
|
"tag array is empty: " + this.jsonStr( firstWorkflow.tags ) );
|
|
this.test.assert( firstWorkflow.url === utils.format( this.api.workflows.urlTpls.show, firstWorkflow.id ),
|
|
"url matches the show url: " + firstWorkflow.url );
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------- SHOW
|
|
this.test.comment( 'show should get detailed data about the workflow with the given id' );
|
|
var workflowShow = this.api.workflows.show( firstWorkflow.id );
|
|
this.debug( this.jsonStr( workflowShow ) );
|
|
this.test.assert( utils.isObject( workflowShow ), "show returned an object" );
|
|
this.test.assert( this.hasKeys( workflowShow, workflowDetailKeys ), "show has the proper keys" );
|
|
this.test.assert( this.api.isEncodedId( workflowShow.id ),
|
|
"id is of the proper form: " + workflowShow.id );
|
|
this.test.assert( workflowShow.model_class === workflowModelClass,
|
|
"has the proper model_class: " + workflowShow.model_class );
|
|
this.test.assert( workflowShow.name === workflowToUpload.name + ' ' + '(imported from API)',
|
|
"has the proper, modified name: " + workflowShow.name );
|
|
this.test.assert( !workflowShow.published,
|
|
"workflow is un-published: " + workflowShow.published );
|
|
this.test.assert( utils.isArray( workflowShow.tags ) && workflowShow.tags.length === 0,
|
|
"tag array is empty: " + this.jsonStr( workflowShow.tags ) );
|
|
this.test.assert( workflowShow.url === utils.format( this.api.workflows.urlTpls.show, workflowShow.id ),
|
|
"url matches the show url: " + workflowShow.url );
|
|
|
|
this.test.comment( 'inputs from show should be an object (and, in this case, empty)' );
|
|
var inputs = workflowShow.inputs;
|
|
this.debug( 'inputs:\n' + this.jsonStr( inputs ) );
|
|
this.test.assert( utils.isObject( workflowShow.inputs ), "inputs is an object" );
|
|
this.test.assert( this.countKeys( workflowShow.inputs ) !== 0, "inputs has keys" );
|
|
|
|
this.test.comment( 'steps from show should be an object containing each tool defined as a step' );
|
|
var steps = workflowShow.steps;
|
|
//this.debug( 'steps:\n' + this.jsonStr( steps ) );
|
|
this.test.assert( utils.isObject( workflowShow.steps ), "steps is an object" );
|
|
//! ids for steps (and the keys used) are un-encoded (and in strings)
|
|
for( var stepKey in steps ){
|
|
if( steps.hasOwnProperty( stepKey ) ){
|
|
// any way to match this up with the workflowToUpload?
|
|
|
|
this.test.assert( utils.isString( stepKey ), "step key is a string: " + stepKey );
|
|
var step = steps[ stepKey ];
|
|
this.debug( 'step:\n' + this.jsonStr( step ) );
|
|
this.test.assert( this.hasKeys( step, stepKeys ), "step has the proper keys" );
|
|
|
|
this.test.assert( utils.isNumber( step.id ),
|
|
"step id is a number: " + step.id );
|
|
try {
|
|
this.test.assert( parseInt( stepKey, 10 ) === step.id,
|
|
"step id matches step key: " + step.id );
|
|
} catch( err ){
|
|
this.test.fail( 'couldnt parse stepKey: ' + stepKey + ',' + err );
|
|
}
|
|
|
|
this.test.assert( utils.isObject( step.input_steps ), "input_steps is an object" );
|
|
if( this.countKeys( step.input_steps ) !== 0 ){
|
|
this.test.assert( this.hasKeys( step.input_steps, [ 'input' ] ), "input_steps has the proper keys" );
|
|
}
|
|
|
|
if( step.type === 'tool' ){
|
|
// check for tools in this wf with the api
|
|
this.test.assert( utils.isString( step.tool_id ),
|
|
"step tool_id is a string: " + step.tool_id );
|
|
var tool_used = this.api.tools.show( step.tool_id.replace( / /g, '+' ) );
|
|
this.debug( this.jsonStr( tool_used ) );
|
|
this.test.assert( this.countKeys( tool_used ) !== 0, "found tool in api.tools for: " + step.tool_id );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------- MISC
|
|
});
|
|
|
|
// now run the uploaded workflow
|
|
spaceghost.api.tools.thenUploadToCurrent({ filepath: simpleBedFilepath }, function( id, json ){
|
|
uploadedId = id;
|
|
});
|
|
spaceghost.then( function(){
|
|
var currentHistory = this.api.histories.index()[0],
|
|
firstWorkflow = this.api.workflows.show( this.api.workflows.index()[0].id );
|
|
|
|
this.debug( this.jsonStr( uploadedId ) );
|
|
this.debug( this.jsonStr( this.api.hdas.show( currentHistory.id, uploadedId ) ) );
|
|
|
|
//this.debug( this.jsonStr( firstWorkflow ) );
|
|
// find the input step by looking for a step where input_steps == {}
|
|
var input_step = null;
|
|
for( var stepKey in firstWorkflow.steps ){
|
|
if( firstWorkflow.steps.hasOwnProperty( stepKey ) ){
|
|
var step = firstWorkflow.steps[ stepKey ];
|
|
if( this.countKeys( step.input_steps ) === 0 ){
|
|
input_step = stepKey;
|
|
this.debug( 'input step: ' + this.jsonStr( step ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------- CREATE
|
|
this.test.comment( 'create should allow running an existing workflow' );
|
|
// needs workflow_id, history, ds_map
|
|
var executionData = {
|
|
workflow_id : firstWorkflow.id,
|
|
history : 'hist_id=' + currentHistory.id,
|
|
ds_map : {}
|
|
};
|
|
executionData.ds_map[ input_step ] = {
|
|
src: 'hda',
|
|
id: uploadedId
|
|
};
|
|
var returned = this.api.workflows.create( executionData );
|
|
this.debug( this.jsonStr( returned ) );
|
|
this.test.assert( utils.isObject( returned ), "create returned an object" );
|
|
this.test.assert( this.hasKeys( returned, workflowCreateKeys ), "create returned the proper keys" );
|
|
this.test.assert( this.api.isEncodedId( returned.history ),
|
|
"history id is proper: " + returned.history );
|
|
this.test.assert( utils.isArray( returned.outputs ),
|
|
"create.outputs is an array: length " + returned.outputs.length );
|
|
this.test.assert( returned.outputs.length >= 1, "there is at least one output" );
|
|
for( var i=0; i<returned.outputs.length; i+=1 ){
|
|
this.test.assert( this.api.isEncodedId( returned.outputs[i] ),
|
|
"output id is proper: " + returned.outputs[i] );
|
|
}
|
|
|
|
var counter = 0;
|
|
this.waitFor(
|
|
function checkHdas(){
|
|
if( counter % 4 !== 0 ){
|
|
counter += 1;
|
|
return false;
|
|
}
|
|
counter += 1;
|
|
|
|
var outputs = this.api.hdas.index( currentHistory.id, returned.outputs );
|
|
//this.debug( 'outputs:\n' + this.jsonStr( outputs ) );
|
|
for( var i=0; i<outputs.length; i+=1 ){
|
|
var output = outputs[i];
|
|
this.debug( utils.format( 'name: %s, state: %s', output.name, output.state ) );
|
|
if( output.state === 'queued' || output.state === 'running' ){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
function allDone(){
|
|
this.debug( 'DONE' );
|
|
var outputs = this.api.hdas.index( currentHistory.id, returned.outputs );
|
|
this.debug( 'outputs:\n' + this.jsonStr( outputs ) );
|
|
},
|
|
function timeout(){
|
|
this.debug( 'timeout' );
|
|
|
|
},
|
|
45 * 1000
|
|
);
|
|
/*
|
|
*/
|
|
});
|
|
|
|
// ===================================================================
|
|
spaceghost.run( function(){ test.done(); });
|
|
});
|