20031: Fix move to separate collection test, requires selecting multiple files
[arvados-workbench2.git] / cypress / integration / process.spec.js
index e877c8e342c7131bab39c37dfa23eb6437216686..bdb4fae61ae0f58062fab989752a348dac0adc7f 100644 (file)
@@ -106,13 +106,50 @@ describe('Process tests', function() {
                 },
                 event_type: 'stdout'
             }).then(function(log) {
-                cy.get('[data-cy=process-logs]')
+                cy.get('[data-cy=process-logs]', {timeout: 7000})
                     .should('not.contain', 'No logs yet')
                     .and('contain', 'hello world');
             })
         });
     });
 
+    it('shows process details', function() {
+        createContainerRequest(
+            activeUser,
+            `test_container_request ${Math.floor(Math.random() * 999999)}`,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            cy.loginAs(activeUser);
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.get('[data-cy=process-details]').should('contain', containerRequest.name);
+            cy.get('[data-cy=process-details-attributes-modifiedby-user]').contains(`Active User (${activeUser.user.uuid})`);
+            cy.get('[data-cy=process-details-attributes-runtime-user]').should('not.exist');
+        });
+
+        // Fake submitted by another user
+        cy.intercept({method: 'GET', url: '**/arvados/v1/container_requests/*'}, (req) => {
+            req.reply((res) => {
+                res.body.modified_by_user_uuid = 'zzzzz-tpzed-000000000000000';
+            });
+        });
+
+        createContainerRequest(
+            activeUser,
+            `test_container_request ${Math.floor(Math.random() * 999999)}`,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            cy.loginAs(activeUser);
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.get('[data-cy=process-details]').should('contain', containerRequest.name);
+            cy.get('[data-cy=process-details-attributes-modifiedby-user]').contains(`zzzzz-tpzed-000000000000000`);
+            cy.get('[data-cy=process-details-attributes-runtime-user]').contains(`Active User (${activeUser.user.uuid})`);
+        });
+    });
+
     it('filters process logs by event type', function() {
         const nodeInfoLogs = [
             'Host Information',
@@ -169,7 +206,7 @@ describe('Process tests', function() {
                 cy.loginAs(activeUser);
                 cy.goToPath(`/processes/${containerRequest.uuid}`);
                 // Should show main logs by default
-                cy.get('[data-cy=process-logs-filter]').should('contain', 'Main logs');
+                cy.get('[data-cy=process-logs-filter]', {timeout: 7000}).should('contain', 'Main logs');
                 cy.get('[data-cy=process-logs]')
                     .should('contain', stdoutLogs[Math.floor(Math.random() * stdoutLogs.length)])
                     .and('not.contain', nodeInfoLogs[Math.floor(Math.random() * nodeInfoLogs.length)])
@@ -263,14 +300,14 @@ describe('Process tests', function() {
 
         cy.getAll('@containerRequest').then(function([containerRequest]) {
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-runtime-status-retry-warning]')
+            cy.get('[data-cy=process-runtime-status-retry-warning]', {timeout: 7000})
                 .should('contain', 'Process retried 1 time');
         });
 
         cy.getAll('@containerRequest').then(function([containerRequest]) {
             containerCount = 3;
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-runtime-status-retry-warning]')
+            cy.get('[data-cy=process-runtime-status-retry-warning]', {timeout: 7000})
                 .should('contain', 'Process retried 2 times');
         });
     });
@@ -403,6 +440,9 @@ describe('Process tests', function() {
                                 "location": "keep:00000000000000000000000000000000+03/input3-2.txt"
                             }
                         ]
+                    },
+                    {
+                        "$import": "import_path"
                     }
                 ]
             }
@@ -426,6 +466,9 @@ describe('Process tests', function() {
                         "basename": "11111111111111111111111111111111+03",
                         "class": "Directory",
                         "location": "keep:11111111111111111111111111111111+03"
+                    },
+                    {
+                        "$import": "import_path"
                     }
                 ]
             }
@@ -442,7 +485,10 @@ describe('Process tests', function() {
                 "input_int_array": [
                     1,
                     3,
-                    5
+                    5,
+                    {
+                        "$import": "import_path"
+                    }
                 ]
             }
         },
@@ -457,7 +503,10 @@ describe('Process tests', function() {
             input: {
                 "input_long_array": [
                     10,
-                    20
+                    20,
+                    {
+                        "$import": "import_path"
+                    }
                 ]
             }
         },
@@ -473,7 +522,10 @@ describe('Process tests', function() {
                 "input_float_array": [
                     10.2,
                     10.4,
-                    10.6
+                    10.6,
+                    {
+                        "$import": "import_path"
+                    }
                 ]
             }
         },
@@ -489,7 +541,10 @@ describe('Process tests', function() {
                 "input_double_array": [
                     20.1,
                     20.2,
-                    20.3
+                    20.3,
+                    {
+                        "$import": "import_path"
+                    }
                 ]
             }
         },
@@ -505,9 +560,91 @@ describe('Process tests', function() {
                 "input_string_array": [
                     "Hello",
                     "World",
-                    "!"
+                    "!",
+                    {
+                        "$import": "import_path"
+                    }
                 ]
             }
+        },
+        {
+            definition: {
+                "id": "#main/input_bool_include",
+                "type": "boolean"
+            },
+            input: {
+                "input_bool_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_int_include",
+                "type": "int"
+            },
+            input: {
+                "input_int_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_float_include",
+                "type": "float"
+            },
+            input: {
+                "input_float_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_string_include",
+                "type": "string"
+            },
+            input: {
+                "input_string_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_file_include",
+                "type": "File"
+            },
+            input: {
+                "input_file_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_directory_include",
+                "type": "Directory"
+            },
+            input: {
+                "input_directory_include": {
+                    "$include": "include_path"
+                }
+            }
+        },
+        {
+            definition: {
+                "id": "#main/input_file_url",
+                "type": "File"
+            },
+            input: {
+                "input_file_url": {
+                    "basename": "index.html",
+                    "class": "File",
+                    "location": "http://example.com/index.html"
+                  }
+            }
         }
     ];
 
@@ -869,13 +1006,11 @@ describe('Process tests', function() {
             cy.goToPath(`/processes/${containerRequest.uuid}`);
             cy.get('[data-cy=process-io-card] h6').contains('Inputs')
                 .parents('[data-cy=process-io-card]').within(() => {
-                    cy.wait(2000);
-                    cy.waitForDom();
                     verifyIOParameter('input_file', null, "Label Description", 'input1.tar', '00000000000000000000000000000000+01');
                     verifyIOParameter('input_file', null, "Label Description", 'input1-2.txt', undefined, true);
                     verifyIOParameter('input_file', null, "Label Description", 'input1-3.txt', undefined, true);
                     verifyIOParameter('input_file', null, "Label Description", 'input1-4.txt', undefined, true);
-                    verifyIOParameter('input_dir', null, "Doc Description", 'No value', '11111111111111111111111111111111+01');
+                    verifyIOParameter('input_dir', null, "Doc Description", '/', '11111111111111111111111111111111+01');
                     verifyIOParameter('input_bool', null, "Doc desc 1, Doc desc 2", 'true');
                     verifyIOParameter('input_int', null, null, '1');
                     verifyIOParameter('input_long', null, null, '1');
@@ -885,18 +1020,27 @@ describe('Process tests', function() {
                     verifyIOParameter('input_file_array', null, null, 'input2.tar', '00000000000000000000000000000000+02');
                     verifyIOParameter('input_file_array', null, null, 'input3.tar', undefined, true);
                     verifyIOParameter('input_file_array', null, null, 'input3-2.txt', undefined, true);
-                    verifyIOParameter('input_dir_array', null, null, 'No value', '11111111111111111111111111111111+02');
-                    verifyIOParameter('input_dir_array', null, null, 'No value', '11111111111111111111111111111111+03', true);
-                    verifyIOParameter('input_int_array', null, null, ["1", "3", "5"]);
-                    verifyIOParameter('input_long_array', null, null, ["10", "20"]);
-                    verifyIOParameter('input_float_array', null, null, ["10.2", "10.4", "10.6"]);
-                    verifyIOParameter('input_double_array', null, null, ["20.1", "20.2", "20.3"]);
-                    verifyIOParameter('input_string_array', null, null, ["Hello", "World", "!"]);
+                    verifyIOParameter('input_file_array', null, null, 'Cannot display value', undefined, true);
+                    verifyIOParameter('input_dir_array', null, null, '/', '11111111111111111111111111111111+02');
+                    verifyIOParameter('input_dir_array', null, null, '/', '11111111111111111111111111111111+03', true);
+                    verifyIOParameter('input_dir_array', null, null, 'Cannot display value', undefined, true);
+                    verifyIOParameter('input_int_array', null, null, ["1", "3", "5", "Cannot display value"]);
+                    verifyIOParameter('input_long_array', null, null, ["10", "20", "Cannot display value"]);
+                    verifyIOParameter('input_float_array', null, null, ["10.2", "10.4", "10.6", "Cannot display value"]);
+                    verifyIOParameter('input_double_array', null, null, ["20.1", "20.2", "20.3", "Cannot display value"]);
+                    verifyIOParameter('input_string_array', null, null, ["Hello", "World", "!", "Cannot display value"]);
+                    verifyIOParameter('input_bool_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_int_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_float_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_string_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_file_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_directory_include', null, null, "Cannot display value");
+                    verifyIOParameter('input_file_url', null, null, "http://example.com/index.html");
                 });
             cy.get('[data-cy=process-io-card] h6').contains('Outputs')
                 .parents('[data-cy=process-io-card]').within((ctx) => {
                     cy.get(ctx).scrollIntoView();
-                    cy.waitForDom().get('[data-cy="io-preview-image-toggle"]').click();
+                    cy.get('[data-cy="io-preview-image-toggle"]').click({waitForAnimations: false});
                     const outPdh = testOutputCollection.portable_data_hash;
 
                     verifyIOParameter('output_file', null, "Label Description", 'cat.png', `${outPdh}`);
@@ -1000,4 +1144,217 @@ describe('Process tests', function() {
         });
     });
 
+
+    it('allows copying processes', function() {
+        const crName = 'first_container_request';
+        const copiedCrName = 'copied_container_request';
+        createContainerRequest(
+            activeUser,
+            crName,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            cy.loginAs(activeUser);
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.get('[data-cy=process-details]').should('contain', crName);
+
+            cy.get('[data-cy=process-details]').find('button[title="More options"]').click();
+            cy.get('ul[data-cy=context-menu]').contains("Copy and re-run process").click();
+        });
+
+        cy.get('[data-cy=form-dialog]').within(() => {
+            cy.get('input[name=name]').clear().type(copiedCrName);
+            cy.get('[data-cy=projects-tree-home-tree-picker]').click();
+            cy.get('[data-cy=form-submit-btn]').click();
+        });
+
+        cy.get('[data-cy=process-details]').should('contain', copiedCrName);
+        cy.get('[data-cy=process-details]').find('button').contains('Run');
+    });
+
+    const getFakeContainer = (fakeContainerUuid) => ({
+        href: `/containers/${fakeContainerUuid}`,
+        kind: "arvados#container",
+        etag: "ecfosljpnxfari9a8m7e4yv06",
+        uuid: fakeContainerUuid,
+        owner_uuid: "zzzzz-tpzed-000000000000000",
+        created_at: "2023-02-13T15:55:47.308915000Z",
+        modified_by_client_uuid: "zzzzz-ozdt8-q6dzdi1lcc03155",
+        modified_by_user_uuid: "zzzzz-tpzed-000000000000000",
+        modified_at: "2023-02-15T19:12:45.987086000Z",
+        command: [
+          "arvados-cwl-runner",
+          "--api=containers",
+          "--local",
+          "--project-uuid=zzzzz-j7d0g-yr18k784zplfeza",
+          "/var/lib/cwl/workflow.json#main",
+          "/var/lib/cwl/cwl.input.json",
+        ],
+        container_image: "4ad7d11381df349e464694762db14e04+303",
+        cwd: "/var/spool/cwl",
+        environment: {},
+        exit_code: null,
+        finished_at: null,
+        locked_by_uuid: null,
+        log: null,
+        output: null,
+        output_path: "/var/spool/cwl",
+        progress: null,
+        runtime_constraints: {
+          API: true,
+          cuda: {
+            device_count: 0,
+            driver_version: "",
+            hardware_capability: "",
+          },
+          keep_cache_disk: 2147483648,
+          keep_cache_ram: 0,
+          ram: 1342177280,
+          vcpus: 1,
+        },
+        runtime_status: {},
+        started_at: null,
+        auth_uuid: null,
+        scheduling_parameters: {
+          max_run_time: 0,
+          partitions: [],
+          preemptible: false,
+        },
+        runtime_user_uuid: "zzzzz-tpzed-vllbpebicy84rd5",
+        runtime_auth_scopes: ["all"],
+        lock_count: 2,
+        gateway_address: null,
+        interactive_session_started: false,
+        output_storage_classes: ["default"],
+        output_properties: {},
+        cost: 0.0,
+        subrequests_cost: 0.0,
+      });
+
+    it('shows cancel button when appropriate', function() {
+        // Ignore collection requests
+        cy.intercept({method: 'GET', url: `**/arvados/v1/collections/*`}, {
+            statusCode: 200,
+            body: {}
+        });
+
+        // Uncommitted container
+        const crUncommitted = `Test process ${Math.floor(Math.random() * 999999)}`;
+        createContainerRequest(
+            activeUser,
+            crUncommitted,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Uncommitted')
+        .then(function(containerRequest) {
+            // Navigate to process and verify run / cancel button
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.waitForDom();
+            cy.get('[data-cy=process-details]').should('contain', crUncommitted);
+            cy.get('[data-cy=process-run-button]').should('exist');
+            cy.get('[data-cy=process-cancel-button]').should('not.exist');
+        });
+
+        // Queued container
+        const crQueued = `Test process ${Math.floor(Math.random() * 999999)}`;
+        const fakeCrUuid = 'zzzzz-dz642-000000000000001';
+        createContainerRequest(
+            activeUser,
+            crQueued,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            // Fake container uuid
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container_requests/${containerRequest.uuid}`}, (req) => {
+                req.reply((res) => {
+                    res.body.output_uuid = fakeCrUuid;
+                    res.body.priority = 500;
+                    res.body.state = "Committed";
+                });
+            });
+
+            // Fake container
+            const container = getFakeContainer(fakeCrUuid);
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrUuid}`}, {
+                statusCode: 200,
+                body: {...container, state: "Queued", priority: 500}
+            });
+
+            // Navigate to process and verify cancel button
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.waitForDom();
+            cy.get('[data-cy=process-details]').should('contain', crQueued);
+            cy.get('[data-cy=process-cancel-button]').contains('Cancel');
+        });
+
+        // Locked container
+        const crLocked = `Test process ${Math.floor(Math.random() * 999999)}`;
+        const fakeCrLockedUuid = 'zzzzz-dz642-000000000000002';
+        createContainerRequest(
+            activeUser,
+            crLocked,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            // Fake container uuid
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container_requests/${containerRequest.uuid}`}, (req) => {
+                req.reply((res) => {
+                    res.body.output_uuid = fakeCrLockedUuid;
+                    res.body.priority = 500;
+                    res.body.state = "Committed";
+                });
+            });
+
+            // Fake container
+            const container = getFakeContainer(fakeCrLockedUuid);
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrLockedUuid}`}, {
+                statusCode: 200,
+                body: {...container, state: "Locked", priority: 500}
+            });
+
+            // Navigate to process and verify cancel button
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.waitForDom();
+            cy.get('[data-cy=process-details]').should('contain', crLocked);
+            cy.get('[data-cy=process-cancel-button]').contains('Cancel');
+        });
+
+        // On Hold container
+        const crOnHold = `Test process ${Math.floor(Math.random() * 999999)}`;
+        const fakeCrOnHoldUuid = 'zzzzz-dz642-000000000000003';
+        createContainerRequest(
+            activeUser,
+            crOnHold,
+            'arvados/jobs',
+            ['echo', 'hello world'],
+            false, 'Committed')
+        .then(function(containerRequest) {
+            // Fake container uuid
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container_requests/${containerRequest.uuid}`}, (req) => {
+                req.reply((res) => {
+                    res.body.output_uuid = fakeCrOnHoldUuid;
+                    res.body.priority = 0;
+                    res.body.state = "Committed";
+                });
+            });
+
+            // Fake container
+            const container = getFakeContainer(fakeCrOnHoldUuid);
+            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrOnHoldUuid}`}, {
+                statusCode: 200,
+                body: {...container, state: "Queued", priority: 0}
+            });
+
+            // Navigate to process and verify cancel button
+            cy.goToPath(`/processes/${containerRequest.uuid}`);
+            cy.waitForDom();
+            cy.get('[data-cy=process-details]').should('contain', crOnHold);
+            cy.get('[data-cy=process-run-button]').should('exist');
+            cy.get('[data-cy=process-cancel-button]').should('not.exist');
+        });
+    });
+
 });