1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 describe('Registered workflow panel tests', function() {
10 // Only set up common users once. These aren't set up as aliases because
11 // aliases are cleaned up after every test. Also it doesn't make sense
12 // to set the same users on beforeEach() over and over again, so we
13 // separate a little from Cypress' 'Best Practices' here.
14 cy.getUser('admin', 'Admin', 'User', true, true)
15 .as('adminUser').then(function() {
16 adminUser = this.adminUser;
19 cy.getUser('user', 'Active', 'User', false, true)
20 .as('activeUser').then(function() {
21 activeUser = this.activeUser;
26 it('should handle null definition', function() {
27 cy.createResource(activeUser.token, "workflows", {workflow: {name: "Test wf"}})
28 .then(function(workflowResource) {
29 cy.loginAs(activeUser);
30 cy.goToPath(`/workflows/${workflowResource.uuid}`);
31 cy.get('[data-cy=registered-workflow-info-panel]').should('contain', workflowResource.name);
32 cy.get('[data-cy=workflow-details-attributes-modifiedby-user]').contains(`Active User (${activeUser.user.uuid})`);
36 it('should handle malformed definition', function() {
37 cy.createResource(activeUser.token, "workflows", {workflow: {name: "Test wf", definition: "zap:"}})
38 .then(function(workflowResource) {
39 cy.loginAs(activeUser);
40 cy.goToPath(`/workflows/${workflowResource.uuid}`);
41 cy.get('[data-cy=registered-workflow-info-panel]').should('contain', workflowResource.name);
42 cy.get('[data-cy=workflow-details-attributes-modifiedby-user]').contains(`Active User (${activeUser.user.uuid})`);
46 it('should handle malformed run', function() {
47 cy.createResource(activeUser.token, "workflows", {workflow: {
49 definition: JSON.stringify({
59 "class": "SubworkflowFeatureRequirement"
64 "id": "#main/cat1-testcli.cwl (v1.2.0-109-g9b091ed)",
66 "label": "cat1-testcli.cwl (v1.2.0-109-g9b091ed)",
69 "id": "#main/step/args"
72 "run": `keep:undefined/bar`
78 "http://arvados.org/cwl#gitBranch": "1.2.1_proposed",
79 "http://arvados.org/cwl#gitCommit": "9b091ed7e0bef98b3312e9478c52b89ba25792de",
80 "http://arvados.org/cwl#gitCommitter": "GitHub <noreply@github.com>",
81 "http://arvados.org/cwl#gitDate": "Sun, 11 Sep 2022 21:24:42 +0200",
82 "http://arvados.org/cwl#gitDescribe": "v1.2.0-109-g9b091ed",
83 "http://arvados.org/cwl#gitOrigin": "git@github.com:common-workflow-language/cwl-v1.2",
84 "http://arvados.org/cwl#gitPath": "tests/cat1-testcli.cwl",
85 "http://arvados.org/cwl#gitStatus": ""
87 }}).then(function(workflowResource) {
88 cy.loginAs(activeUser);
89 cy.goToPath(`/workflows/${workflowResource.uuid}`);
90 cy.get('[data-cy=registered-workflow-info-panel]').should('contain', workflowResource.name);
91 cy.get('[data-cy=workflow-details-attributes-modifiedby-user]').contains(`Active User (${activeUser.user.uuid})`);
95 const verifyIOParameter = (name, label, doc, val, collection) => {
96 cy.get('table tr').contains(name).parents('tr').within(($mainRow) => {
97 label && cy.contains(label);
100 if (Array.isArray(val)) {
101 val.forEach(v => cy.contains(v));
107 cy.contains(collection);
112 it('shows workflow details', function() {
113 cy.createCollection(adminUser.token, {
114 name: `Test collection ${Math.floor(Math.random() * 999999)}`,
115 owner_uuid: activeUser.user.uuid,
116 manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
118 .then(function(collectionResource) {
119 cy.createResource(activeUser.token, "workflows", {workflow: {
121 definition: JSON.stringify({
128 "class": "DockerRequirement",
129 "dockerPull": "python:2-slim"
139 "id": "#main/numbering",
147 "basename": "args.py",
149 "location": "keep:de738550734533c5027997c87dc5488e+53/args.py",
154 "id": "#main/args.py",
161 "outputSource": "#main/step/args",
164 "name": "_:b0adccc1-502d-476f-8a5b-c8ef7119e2dc",
171 "class": "SubworkflowFeatureRequirement"
176 "id": "#main/cat1-testcli.cwl (v1.2.0-109-g9b091ed)",
179 "id": "#main/step/file1",
180 "source": "#main/file1"
183 "id": "#main/step/numbering",
184 "source": "#main/numbering"
187 "id": "#main/step/args.py",
188 "source": "#main/args.py"
191 "label": "cat1-testcli.cwl (v1.2.0-109-g9b091ed)",
194 "id": "#main/step/args"
197 "run": `keep:${collectionResource.portable_data_hash}/bar`
202 "cwlVersion": "v1.2",
203 "http://arvados.org/cwl#gitBranch": "1.2.1_proposed",
204 "http://arvados.org/cwl#gitCommit": "9b091ed7e0bef98b3312e9478c52b89ba25792de",
205 "http://arvados.org/cwl#gitCommitter": "GitHub <noreply@github.com>",
206 "http://arvados.org/cwl#gitDate": "Sun, 11 Sep 2022 21:24:42 +0200",
207 "http://arvados.org/cwl#gitDescribe": "v1.2.0-109-g9b091ed",
208 "http://arvados.org/cwl#gitOrigin": "git@github.com:common-workflow-language/cwl-v1.2",
209 "http://arvados.org/cwl#gitPath": "tests/cat1-testcli.cwl",
210 "http://arvados.org/cwl#gitStatus": ""
212 }}).then(function(workflowResource) {
213 cy.loginAs(activeUser);
214 cy.goToPath(`/workflows/${workflowResource.uuid}`);
215 cy.get('[data-cy=registered-workflow-info-panel]').should('contain', workflowResource.name);
216 cy.get('[data-cy=workflow-details-attributes-modifiedby-user]').contains(`Active User (${activeUser.user.uuid})`);
217 cy.get('[data-cy=registered-workflow-info-panel')
218 .should('contain', 'gitCommit: 9b091ed7e0bef98b3312e9478c52b89ba25792de')
220 cy.get('[data-cy=process-io-card] h6').contains('Input Parameters')
221 .parents('[data-cy=process-io-card]').within(() => {
222 verifyIOParameter('file1', null, '', '', '');
223 verifyIOParameter('numbering', null, '', '', '');
224 verifyIOParameter('args.py', null, '', 'args.py', 'de738550734533c5027997c87dc5488e+53');
226 cy.get('[data-cy=process-io-card] h6').contains('Output Parameters')
227 .parents('[data-cy=process-io-card]').within(() => {
228 verifyIOParameter('args', null, '', '', '');
230 cy.get('[data-cy=collection-files-panel]').within(() => {
231 cy.get('[data-cy=collection-files-right-panel]', { timeout: 5000 })
232 .should('contain', 'bar');
238 it('can delete a workflow', function() {
239 cy.createResource(activeUser.token, "workflows", {workflow: {name: "Test wf"}})
240 .then(function(workflowResource) {
241 cy.loginAs(activeUser);
242 cy.goToPath(`/projects/${activeUser.user.uuid}`);
243 cy.get('[data-cy=project-panel] table tbody').contains(workflowResource.name).rightclick();
244 cy.get('[data-cy=context-menu]').contains('Delete Workflow').click();
245 cy.get('[data-cy=confirmation-dialog-ok-btn]').should('exist').click();
246 cy.get('[data-cy=project-panel] table tbody').should('not.contain', workflowResource.name);
250 it('can delete multiple workflows', function() {
251 const wfNames = ["Test wf1", "Test wf2", "Test wf3"];
253 wfNames.forEach((wfName) => {
254 cy.createResource(activeUser.token, "workflows", {workflow: {name: wfName}})
257 cy.loginAs(activeUser);
259 wfNames.forEach((wfName) => {
260 cy.get('tr').contains('td', wfName).should('exist').parent('tr').find('input[type="checkbox"]').click();
263 cy.waitForDom().get('[data-cy=multiselect-button]', {timeout: 10000}).should('be.visible')
264 cy.get('[data-cy=multiselect-button]', {timeout: 10000}).should('have.length', '1').trigger('mouseover');
265 cy.get('body').contains('Delete Workflow', {timeout: 10000}).should('exist')
266 cy.get('[data-cy=multiselect-button]').eq(0).click();
267 cy.get('[data-cy=confirmation-dialog-ok-btn]').should('exist').click();
269 wfNames.forEach((wfName) => {
270 cy.get('tr').contains(wfName).should('not.exist');
274 it('cannot delete readonly workflow', function() {
276 owningUser: adminUser,
277 targetUser: activeUser,
278 projectName: 'mySharedReadonlyProject',
281 cy.getAll('@mySharedReadonlyProject')
282 .then(function ([mySharedReadonlyProject]) {
283 cy.createResource(adminUser.token, "workflows", {workflow: {name: "Test wf", owner_uuid: mySharedReadonlyProject.uuid}})
284 .then(function(workflowResource) {
285 cy.loginAs(activeUser);
286 cy.goToPath(`/shared-with-me`);
287 cy.contains("mySharedReadonlyProject").click();
288 cy.get('[data-cy=project-panel] table tbody').contains(workflowResource.name).rightclick();
289 cy.get('[data-cy=context-menu]').should("not.contain", 'Delete Workflow');
294 it('shows the appropriate buttons in the multiselect toolbar', () => {
296 const msButtonTooltips = [
299 'Copy link to clipboard',
305 cy.createResource(activeUser.token, "workflows", {workflow: {name: "Test wf"}})
306 .then(function(workflowResource) {
307 cy.loginAs(activeUser);
308 cy.get("[data-cy=side-panel-tree]").contains("Home Projects").click();
310 cy.get('[data-cy=data-table-row]').contains(workflowResource.name).should('exist').parents('td').click()
311 cy.get('[data-cy=multiselect-button]').should('have.length', msButtonTooltips.length)
312 for (let i = 0; i < msButtonTooltips.length; i++) {
313 cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseover');
314 cy.get('body').contains(msButtonTooltips[i]).should('exist')
315 cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseout');