15768: fixed rerun bug Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox@curii...
authorLisa Knox <lisaknox83@gmail.com>
Tue, 19 Sep 2023 22:33:57 +0000 (18:33 -0400)
committerLisa Knox <lisaknox83@gmail.com>
Tue, 19 Sep 2023 22:33:57 +0000 (18:33 -0400)
cypress/integration/process.spec.js
src/components/data-explorer/data-explorer.test.tsx
src/services/collection-service/collection-service.ts
src/views-components/context-menu/action-sets/process-resource-action-set.ts
src/views-components/multiselect-toolbar/ms-collection-action-set.ts
src/views-components/multiselect-toolbar/ms-process-action-set.ts

index bdb4fae61ae0f58062fab989752a348dac0adc7f..d6c9a606d0ffe959156ea75f294b277284f85567 100644 (file)
@@ -2,28 +2,28 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-describe('Process tests', function() {
+describe("Process tests", function () {
     let activeUser;
     let adminUser;
 
-    before(function() {
+    before(function () {
         // Only set up common users once. These aren't set up as aliases because
         // aliases are cleaned up after every test. Also it doesn't make sense
         // to set the same users on beforeEach() over and over again, so we
         // separate a little from Cypress' 'Best Practices' here.
-        cy.getUser('admin', 'Admin', 'User', true, true)
-            .as('adminUser').then(function() {
+        cy.getUser("admin", "Admin", "User", true, true)
+            .as("adminUser")
+            .then(function () {
                 adminUser = this.adminUser;
-            }
-        );
-        cy.getUser('user', 'Active', 'User', false, true)
-            .as('activeUser').then(function() {
+            });
+        cy.getUser("user", "Active", "User", false, true)
+            .as("activeUser")
+            .then(function () {
                 activeUser = this.activeUser;
-            }
-        );
+            });
     });
 
-    beforeEach(function() {
+    beforeEach(function () {
         cy.clearCookies();
         cy.clearLocalStorage();
     });
@@ -31,42 +31,46 @@ describe('Process tests', function() {
     function setupDockerImage(image_name) {
         // Create a collection that will be used as a docker image for the tests.
         cy.createCollection(adminUser.token, {
-            name: 'docker_image',
-            manifest_text: ". d21353cfe035e3e384563ee55eadbb2f+67108864 5c77a43e329b9838cbec18ff42790e57+55605760 0:122714624:sha256:d8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678.tar\n"
-        }).as('dockerImage').then(function(dockerImage) {
-            // Give read permissions to the active user on the docker image.
-            cy.createLink(adminUser.token, {
-                link_class: 'permission',
-                name: 'can_read',
-                tail_uuid: activeUser.user.uuid,
-                head_uuid: dockerImage.uuid
-            }).as('dockerImagePermission').then(function() {
-                // Set-up docker image collection tags
-                cy.createLink(activeUser.token, {
-                    link_class: 'docker_image_repo+tag',
-                    name: image_name,
-                    head_uuid: dockerImage.uuid,
-                }).as('dockerImageRepoTag');
-                cy.createLink(activeUser.token, {
-                    link_class: 'docker_image_hash',
-                    name: 'sha256:d8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678',
+            name: "docker_image",
+            manifest_text:
+                ". d21353cfe035e3e384563ee55eadbb2f+67108864 5c77a43e329b9838cbec18ff42790e57+55605760 0:122714624:sha256:d8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678.tar\n",
+        })
+            .as("dockerImage")
+            .then(function (dockerImage) {
+                // Give read permissions to the active user on the docker image.
+                cy.createLink(adminUser.token, {
+                    link_class: "permission",
+                    name: "can_read",
+                    tail_uuid: activeUser.user.uuid,
                     head_uuid: dockerImage.uuid,
-                }).as('dockerImageHash');
-            })
-        });
-        return cy.getAll('@dockerImage', '@dockerImageRepoTag', '@dockerImageHash',
-            '@dockerImagePermission').then(function([dockerImage]) {
-                return dockerImage;
+                })
+                    .as("dockerImagePermission")
+                    .then(function () {
+                        // Set-up docker image collection tags
+                        cy.createLink(activeUser.token, {
+                            link_class: "docker_image_repo+tag",
+                            name: image_name,
+                            head_uuid: dockerImage.uuid,
+                        }).as("dockerImageRepoTag");
+                        cy.createLink(activeUser.token, {
+                            link_class: "docker_image_hash",
+                            name: "sha256:d8309758b8fe2c81034ffc8a10c36460b77db7bc5e7b448c4e5b684f9d95a678",
+                            head_uuid: dockerImage.uuid,
+                        }).as("dockerImageHash");
+                    });
             });
+        return cy.getAll("@dockerImage", "@dockerImageRepoTag", "@dockerImageHash", "@dockerImagePermission").then(function ([dockerImage]) {
+            return dockerImage;
+        });
     }
 
-    function createContainerRequest(user, name, docker_image, command, reuse = false, state = 'Uncommitted') {
-        return setupDockerImage(docker_image).then(function(dockerImage) {
+    function createContainerRequest(user, name, docker_image, command, reuse = false, state = "Uncommitted") {
+        return setupDockerImage(docker_image).then(function (dockerImage) {
             return cy.createContainerRequest(user.token, {
                 name: name,
                 command: command,
                 container_image: dockerImage.portable_data_hash, // for some reason, docker_image doesn't work here
-                output_path: 'stdout.txt',
+                output_path: "stdout.txt",
                 priority: 1,
                 runtime_constraints: {
                     vcpus: 1,
@@ -76,1104 +80,1075 @@ describe('Process tests', function() {
                 state: state,
                 mounts: {
                     foo: {
-                        kind: 'tmp',
-                        path: '/tmp/foo',
-                    }
-                }
+                        kind: "tmp",
+                        path: "/tmp/foo",
+                    },
+                },
             });
         });
     }
 
-    it('shows process logs', function() {
-        const crName = 'test_container_request';
-        createContainerRequest(
-            activeUser,
-            crName,
-            'arvados/jobs',
-            ['echo', 'hello world'],
-            false, 'Committed')
-        .then(function(containerRequest) {
+    it("shows process logs", function () {
+        const crName = "test_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-logs]')
-                .should('contain', 'No logs yet')
-                .and('not.contain', 'hello world');
+            cy.get("[data-cy=process-details]").should("contain", crName);
+            cy.get("[data-cy=process-logs]").should("contain", "No logs yet").and("not.contain", "hello world");
             cy.createLog(activeUser.token, {
                 object_uuid: containerRequest.container_uuid,
                 properties: {
-                    text: 'hello world'
+                    text: "hello world",
                 },
-                event_type: 'stdout'
-            }).then(function(log) {
-                cy.get('[data-cy=process-logs]', {timeout: 7000})
-                    .should('not.contain', 'No logs yet')
-                    .and('contain', 'hello world');
-            })
+                event_type: "stdout",
+            }).then(function (log) {
+                cy.get("[data-cy=process-logs]", { timeout: 7000 }).should("not.contain", "No logs yet").and("contain", "hello world");
+            });
         });
     });
 
-    it('shows process details', function() {
+    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) {
+            "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');
+            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';
+        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) {
+            "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})`);
+            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() {
+    it("filters process logs by event type", function () {
         const nodeInfoLogs = [
-            'Host Information',
-            'Linux compute-99cb150b26149780de44b929577e1aed-19rgca8vobuvc4p 5.4.0-1059-azure #62~18.04.1-Ubuntu SMP Tue Sep 14 17:53:18 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux',
-            'CPU Information',
-            'processor  : 0',
-            'vendor_id  : GenuineIntel',
-            'cpu family : 6',
-            'model      : 79',
-            'model name : Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz'
+            "Host Information",
+            "Linux compute-99cb150b26149780de44b929577e1aed-19rgca8vobuvc4p 5.4.0-1059-azure #62~18.04.1-Ubuntu SMP Tue Sep 14 17:53:18 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux",
+            "CPU Information",
+            "processor  : 0",
+            "vendor_id  : GenuineIntel",
+            "cpu family : 6",
+            "model      : 79",
+            "model name : Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz",
         ];
         const crunchRunLogs = [
-            '2022-03-22T13:56:22.542417997Z using local keepstore process (pid 3733) at http://localhost:46837, writing logs to keepstore.txt in log collection',
-            '2022-03-22T13:56:26.237571754Z crunch-run 2.4.0~dev20220321141729 (go1.17.1) started',
-            '2022-03-22T13:56:26.244704134Z crunch-run process has uid=0(root) gid=0(root) groups=0(root)',
-            '2022-03-22T13:56:26.244862836Z Executing container \'zzzzz-dz642-1wokwvcct9s9du3\' using docker runtime',
-            '2022-03-22T13:56:26.245037738Z Executing on host \'compute-99cb150b26149780de44b929577e1aed-19rgca8vobuvc4p\'',
+            "2022-03-22T13:56:22.542417997Z using local keepstore process (pid 3733) at http://localhost:46837, writing logs to keepstore.txt in log collection",
+            "2022-03-22T13:56:26.237571754Z crunch-run 2.4.0~dev20220321141729 (go1.17.1) started",
+            "2022-03-22T13:56:26.244704134Z crunch-run process has uid=0(root) gid=0(root) groups=0(root)",
+            "2022-03-22T13:56:26.244862836Z Executing container 'zzzzz-dz642-1wokwvcct9s9du3' using docker runtime",
+            "2022-03-22T13:56:26.245037738Z Executing on host 'compute-99cb150b26149780de44b929577e1aed-19rgca8vobuvc4p'",
         ];
         const stdoutLogs = [
-            'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dui nisi, hendrerit porta sapien a, pretium dignissim purus.',
-            'Integer viverra, mauris finibus aliquet ultricies, dui mauris cursus justo, ut venenatis nibh ex eget neque.',
-            'In hac habitasse platea dictumst.',
-            'Fusce fringilla turpis id accumsan faucibus. Donec congue congue ex non posuere. In semper mi quis tristique rhoncus.',
-            'Interdum et malesuada fames ac ante ipsum primis in faucibus.',
-            'Quisque fermentum tortor ex, ut suscipit velit feugiat faucibus.',
-            'Donec vitae porta risus, at luctus nulla. Mauris gravida iaculis ipsum, id sagittis tortor egestas ac.',
-            'Maecenas condimentum volutpat nulla. Integer lacinia maximus risus eu posuere.',
-            'Donec vitae leo id augue gravida bibendum.',
-            'Nam libero libero, pretium ac faucibus elementum, mattis nec ex.',
-            'Nullam id laoreet nibh. Vivamus tellus metus, pretium quis justo ut, bibendum varius metus. Pellentesque vitae accumsan lorem, quis tincidunt augue.',
-            'Aliquam viverra nisi nulla, et efficitur dolor mattis in.',
-            'Sed at enim sit amet nulla tincidunt mattis. Aenean eget aliquet ex, non ultrices ex. Nulla ex tortor, vestibulum aliquam tempor ac, aliquam vel est.',
-            'Fusce auctor faucibus libero id venenatis. Etiam sodales, odio eu cursus efficitur, quam sem blandit ex, quis porttitor enim dui quis lectus. In id tincidunt felis.',
-            'Phasellus non ex quis arcu tempus faucibus molestie in sapien.',
-            'Duis tristique semper dolor, vitae pulvinar risus.',
-            'Aliquam tortor elit, luctus nec tortor eget, porta tristique nulla.',
-            'Nulla eget mollis ipsum.',
+            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dui nisi, hendrerit porta sapien a, pretium dignissim purus.",
+            "Integer viverra, mauris finibus aliquet ultricies, dui mauris cursus justo, ut venenatis nibh ex eget neque.",
+            "In hac habitasse platea dictumst.",
+            "Fusce fringilla turpis id accumsan faucibus. Donec congue congue ex non posuere. In semper mi quis tristique rhoncus.",
+            "Interdum et malesuada fames ac ante ipsum primis in faucibus.",
+            "Quisque fermentum tortor ex, ut suscipit velit feugiat faucibus.",
+            "Donec vitae porta risus, at luctus nulla. Mauris gravida iaculis ipsum, id sagittis tortor egestas ac.",
+            "Maecenas condimentum volutpat nulla. Integer lacinia maximus risus eu posuere.",
+            "Donec vitae leo id augue gravida bibendum.",
+            "Nam libero libero, pretium ac faucibus elementum, mattis nec ex.",
+            "Nullam id laoreet nibh. Vivamus tellus metus, pretium quis justo ut, bibendum varius metus. Pellentesque vitae accumsan lorem, quis tincidunt augue.",
+            "Aliquam viverra nisi nulla, et efficitur dolor mattis in.",
+            "Sed at enim sit amet nulla tincidunt mattis. Aenean eget aliquet ex, non ultrices ex. Nulla ex tortor, vestibulum aliquam tempor ac, aliquam vel est.",
+            "Fusce auctor faucibus libero id venenatis. Etiam sodales, odio eu cursus efficitur, quam sem blandit ex, quis porttitor enim dui quis lectus. In id tincidunt felis.",
+            "Phasellus non ex quis arcu tempus faucibus molestie in sapien.",
+            "Duis tristique semper dolor, vitae pulvinar risus.",
+            "Aliquam tortor elit, luctus nec tortor eget, porta tristique nulla.",
+            "Nulla eget mollis ipsum.",
         ];
 
-        createContainerRequest(
-            activeUser,
-            'test_container_request',
-            'arvados/jobs',
-            ['echo', 'hello world'],
-            false, 'Committed')
-        .then(function(containerRequest) {
-            cy.logsForContainer(activeUser.token, containerRequest.container_uuid,
-                'node-info', nodeInfoLogs).as('nodeInfoLogs');
-            cy.logsForContainer(activeUser.token, containerRequest.container_uuid,
-                'crunch-run', crunchRunLogs).as('crunchRunLogs');
-            cy.logsForContainer(activeUser.token, containerRequest.container_uuid,
-                'stdout', stdoutLogs).as('stdoutLogs');
-            cy.getAll('@stdoutLogs', '@nodeInfoLogs', '@crunchRunLogs').then(function() {
+        createContainerRequest(activeUser, "test_container_request", "arvados/jobs", ["echo", "hello world"], false, "Committed").then(function (
+            containerRequest
+        ) {
+            cy.logsForContainer(activeUser.token, containerRequest.container_uuid, "node-info", nodeInfoLogs).as("nodeInfoLogs");
+            cy.logsForContainer(activeUser.token, containerRequest.container_uuid, "crunch-run", crunchRunLogs).as("crunchRunLogs");
+            cy.logsForContainer(activeUser.token, containerRequest.container_uuid, "stdout", stdoutLogs).as("stdoutLogs");
+            cy.getAll("@stdoutLogs", "@nodeInfoLogs", "@crunchRunLogs").then(function () {
                 cy.loginAs(activeUser);
                 cy.goToPath(`/processes/${containerRequest.uuid}`);
                 // Should show main logs by default
-                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)])
-                    .and('contain', crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
+                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)])
+                    .and("contain", crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
                 // Select 'All logs'
-                cy.get('[data-cy=process-logs-filter]').click();
-                cy.get('body').contains('li', 'All logs').click();
-                cy.get('[data-cy=process-logs]')
-                    .should('contain', stdoutLogs[Math.floor(Math.random() * stdoutLogs.length)])
-                    .and('contain', nodeInfoLogs[Math.floor(Math.random() * nodeInfoLogs.length)])
-                    .and('contain', crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
+                cy.get("[data-cy=process-logs-filter]").click();
+                cy.get("body").contains("li", "All logs").click();
+                cy.get("[data-cy=process-logs]")
+                    .should("contain", stdoutLogs[Math.floor(Math.random() * stdoutLogs.length)])
+                    .and("contain", nodeInfoLogs[Math.floor(Math.random() * nodeInfoLogs.length)])
+                    .and("contain", crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
                 // Select 'node-info' logs
-                cy.get('[data-cy=process-logs-filter]').click();
-                cy.get('body').contains('li', 'node-info').click();
-                cy.get('[data-cy=process-logs]')
-                    .should('not.contain', stdoutLogs[Math.floor(Math.random() * stdoutLogs.length)])
-                    .and('contain', nodeInfoLogs[Math.floor(Math.random() * nodeInfoLogs.length)])
-                    .and('not.contain', crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
+                cy.get("[data-cy=process-logs-filter]").click();
+                cy.get("body").contains("li", "node-info").click();
+                cy.get("[data-cy=process-logs]")
+                    .should("not.contain", stdoutLogs[Math.floor(Math.random() * stdoutLogs.length)])
+                    .and("contain", nodeInfoLogs[Math.floor(Math.random() * nodeInfoLogs.length)])
+                    .and("not.contain", crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
                 // Select 'stdout' logs
-                cy.get('[data-cy=process-logs-filter]').click();
-                cy.get('body').contains('li', 'stdout').click();
-                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)])
-                    .and('not.contain', crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
+                cy.get("[data-cy=process-logs-filter]").click();
+                cy.get("body").contains("li", "stdout").click();
+                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)])
+                    .and("not.contain", crunchRunLogs[Math.floor(Math.random() * crunchRunLogs.length)]);
             });
         });
     });
 
-    it('should show runtime status indicators', function() {
+    it("should show runtime status indicators", function () {
         // Setup running container with runtime_status error & warning messages
-        createContainerRequest(
-            activeUser,
-            'test_container_request',
-            'arvados/jobs',
-            ['echo', 'hello world'],
-            false, 'Committed')
-        .as('containerRequest')
-        .then(function(containerRequest) {
-            expect(containerRequest.state).to.equal('Committed');
-            expect(containerRequest.container_uuid).not.to.be.equal('');
-
-            cy.getContainer(activeUser.token, containerRequest.container_uuid)
-            .then(function(queuedContainer) {
-                expect(queuedContainer.state).to.be.equal('Queued');
-            });
-            cy.updateContainer(adminUser.token, containerRequest.container_uuid, {
-                state: 'Locked'
-            }).then(function(lockedContainer) {
-                expect(lockedContainer.state).to.be.equal('Locked');
-
-                cy.updateContainer(adminUser.token, lockedContainer.uuid, {
-                    state: 'Running',
-                    runtime_status: {
-                        error: 'Something went wrong',
-                        errorDetail: 'Process exited with status 1',
-                        warning: 'Free disk space is low',
-                    }
-                })
-                .as('runningContainer')
-                .then(function(runningContainer) {
-                    expect(runningContainer.state).to.be.equal('Running');
-                    expect(runningContainer.runtime_status).to.be.deep.equal({
-                        'error': 'Something went wrong',
-                        'errorDetail': 'Process exited with status 1',
-                        'warning': 'Free disk space is low',
-                    });
+        createContainerRequest(activeUser, "test_container_request", "arvados/jobs", ["echo", "hello world"], false, "Committed")
+            .as("containerRequest")
+            .then(function (containerRequest) {
+                expect(containerRequest.state).to.equal("Committed");
+                expect(containerRequest.container_uuid).not.to.be.equal("");
+
+                cy.getContainer(activeUser.token, containerRequest.container_uuid).then(function (queuedContainer) {
+                    expect(queuedContainer.state).to.be.equal("Queued");
                 });
-            })
-        });
+                cy.updateContainer(adminUser.token, containerRequest.container_uuid, {
+                    state: "Locked",
+                }).then(function (lockedContainer) {
+                    expect(lockedContainer.state).to.be.equal("Locked");
+
+                    cy.updateContainer(adminUser.token, lockedContainer.uuid, {
+                        state: "Running",
+                        runtime_status: {
+                            error: "Something went wrong",
+                            errorDetail: "Process exited with status 1",
+                            warning: "Free disk space is low",
+                        },
+                    })
+                        .as("runningContainer")
+                        .then(function (runningContainer) {
+                            expect(runningContainer.state).to.be.equal("Running");
+                            expect(runningContainer.runtime_status).to.be.deep.equal({
+                                error: "Something went wrong",
+                                errorDetail: "Process exited with status 1",
+                                warning: "Free disk space is low",
+                            });
+                        });
+                });
+            });
         // Test that the UI shows the error and warning messages
-        cy.getAll('@containerRequest', '@runningContainer').then(function([containerRequest]) {
+        cy.getAll("@containerRequest", "@runningContainer").then(function ([containerRequest]) {
             cy.loginAs(activeUser);
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-runtime-status-error]')
-                .should('contain', 'Something went wrong')
-                .and('contain', 'Process exited with status 1');
-            cy.get('[data-cy=process-runtime-status-warning]')
-                .should('contain', 'Free disk space is low')
-                .and('contain', 'No additional warning details available');
+            cy.get("[data-cy=process-runtime-status-error]").should("contain", "Something went wrong").and("contain", "Process exited with status 1");
+            cy.get("[data-cy=process-runtime-status-warning]")
+                .should("contain", "Free disk space is low")
+                .and("contain", "No additional warning details available");
         });
 
-
         // Force container_count for testing
         let containerCount = 2;
-        cy.intercept({method: 'GET', url: '**/arvados/v1/container_requests/*'}, (req) => {
-            req.reply((res) => {
+        cy.intercept({ method: "GET", url: "**/arvados/v1/container_requests/*" }, req => {
+            req.reply(res => {
                 res.body.container_count = containerCount;
             });
         });
 
-        cy.getAll('@containerRequest').then(function([containerRequest]) {
+        cy.getAll("@containerRequest").then(function ([containerRequest]) {
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-runtime-status-retry-warning]', {timeout: 7000})
-                .should('contain', 'Process retried 1 time');
+            cy.get("[data-cy=process-runtime-status-retry-warning]", { timeout: 7000 }).should("contain", "Process retried 1 time");
         });
 
-        cy.getAll('@containerRequest').then(function([containerRequest]) {
+        cy.getAll("@containerRequest").then(function ([containerRequest]) {
             containerCount = 3;
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-runtime-status-retry-warning]', {timeout: 7000})
-                .should('contain', 'Process retried 2 times');
+            cy.get("[data-cy=process-runtime-status-retry-warning]", { timeout: 7000 }).should("contain", "Process retried 2 times");
         });
     });
 
-
     const testInputs = [
         {
             definition: {
-                "id": "#main/input_file",
-                "label": "Label Description",
-                "type": "File"
+                id: "#main/input_file",
+                label: "Label Description",
+                type: "File",
             },
             input: {
-                "input_file": {
-                    "basename": "input1.tar",
-                    "class": "File",
-                    "location": "keep:00000000000000000000000000000000+01/input1.tar",
-                    "secondaryFiles": [
+                input_file: {
+                    basename: "input1.tar",
+                    class: "File",
+                    location: "keep:00000000000000000000000000000000+01/input1.tar",
+                    secondaryFiles: [
                         {
-                            "basename": "input1-2.txt",
-                            "class": "File",
-                            "location": "keep:00000000000000000000000000000000+01/input1-2.txt"
+                            basename: "input1-2.txt",
+                            class: "File",
+                            location: "keep:00000000000000000000000000000000+01/input1-2.txt",
                         },
                         {
-                            "basename": "input1-3.txt",
-                            "class": "File",
-                            "location": "keep:00000000000000000000000000000000+01/input1-3.txt"
+                            basename: "input1-3.txt",
+                            class: "File",
+                            location: "keep:00000000000000000000000000000000+01/input1-3.txt",
                         },
                         {
-                            "basename": "input1-4.txt",
-                            "class": "File",
-                            "location": "keep:00000000000000000000000000000000+01/input1-4.txt"
-                        }
-                    ]
-                }
-            }
+                            basename: "input1-4.txt",
+                            class: "File",
+                            location: "keep:00000000000000000000000000000000+01/input1-4.txt",
+                        },
+                    ],
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_dir",
-                "doc": "Doc Description",
-                "type": "Directory"
+                id: "#main/input_dir",
+                doc: "Doc Description",
+                type: "Directory",
             },
             input: {
-                "input_dir": {
-                    "basename": "11111111111111111111111111111111+01",
-                    "class": "Directory",
-                    "location": "keep:11111111111111111111111111111111+01"
-                }
-            }
+                input_dir: {
+                    basename: "11111111111111111111111111111111+01",
+                    class: "Directory",
+                    location: "keep:11111111111111111111111111111111+01",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_bool",
-                "doc": ["Doc desc 1", "Doc desc 2"],
-                "type": "boolean"
+                id: "#main/input_bool",
+                doc: ["Doc desc 1", "Doc desc 2"],
+                type: "boolean",
             },
             input: {
-                "input_bool": true,
-            }
+                input_bool: true,
+            },
         },
         {
             definition: {
-                "id": "#main/input_int",
-                "type": "int"
+                id: "#main/input_int",
+                type: "int",
             },
             input: {
-                "input_int": 1,
-            }
+                input_int: 1,
+            },
         },
         {
             definition: {
-                "id": "#main/input_long",
-                "type": "long"
+                id: "#main/input_long",
+                type: "long",
             },
             input: {
-                "input_long" : 1,
-            }
+                input_long: 1,
+            },
         },
         {
             definition: {
-                "id": "#main/input_float",
-                "type": "float"
+                id: "#main/input_float",
+                type: "float",
             },
             input: {
-                "input_float": 1.5,
-            }
+                input_float: 1.5,
+            },
         },
         {
             definition: {
-                "id": "#main/input_double",
-                "type": "double"
+                id: "#main/input_double",
+                type: "double",
             },
             input: {
-                "input_double": 1.3,
-            }
+                input_double: 1.3,
+            },
         },
         {
             definition: {
-                "id": "#main/input_string",
-                "type": "string"
+                id: "#main/input_string",
+                type: "string",
             },
             input: {
-                "input_string": "Hello World",
-            }
+                input_string: "Hello World",
+            },
         },
         {
             definition: {
-                "id": "#main/input_file_array",
-                "type": {
-                  "items": "File",
-                  "type": "array"
-                }
+                id: "#main/input_file_array",
+                type: {
+                    items: "File",
+                    type: "array",
+                },
             },
             input: {
-                "input_file_array": [
+                input_file_array: [
                     {
-                        "basename": "input2.tar",
-                        "class": "File",
-                        "location": "keep:00000000000000000000000000000000+02/input2.tar"
+                        basename: "input2.tar",
+                        class: "File",
+                        location: "keep:00000000000000000000000000000000+02/input2.tar",
                     },
                     {
-                        "basename": "input3.tar",
-                        "class": "File",
-                        "location": "keep:00000000000000000000000000000000+03/input3.tar",
-                        "secondaryFiles": [
+                        basename: "input3.tar",
+                        class: "File",
+                        location: "keep:00000000000000000000000000000000+03/input3.tar",
+                        secondaryFiles: [
                             {
-                                "basename": "input3-2.txt",
-                                "class": "File",
-                                "location": "keep:00000000000000000000000000000000+03/input3-2.txt"
-                            }
-                        ]
+                                basename: "input3-2.txt",
+                                class: "File",
+                                location: "keep:00000000000000000000000000000000+03/input3-2.txt",
+                            },
+                        ],
                     },
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_dir_array",
-                "type": {
-                  "items": "Directory",
-                  "type": "array"
-                }
+                id: "#main/input_dir_array",
+                type: {
+                    items: "Directory",
+                    type: "array",
+                },
             },
             input: {
-                "input_dir_array": [
+                input_dir_array: [
                     {
-                        "basename": "11111111111111111111111111111111+02",
-                        "class": "Directory",
-                        "location": "keep:11111111111111111111111111111111+02"
+                        basename: "11111111111111111111111111111111+02",
+                        class: "Directory",
+                        location: "keep:11111111111111111111111111111111+02",
                     },
                     {
-                        "basename": "11111111111111111111111111111111+03",
-                        "class": "Directory",
-                        "location": "keep:11111111111111111111111111111111+03"
+                        basename: "11111111111111111111111111111111+03",
+                        class: "Directory",
+                        location: "keep:11111111111111111111111111111111+03",
                     },
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_int_array",
-                "type": {
-                  "items": "int",
-                  "type": "array"
-                }
+                id: "#main/input_int_array",
+                type: {
+                    items: "int",
+                    type: "array",
+                },
             },
             input: {
-                "input_int_array": [
+                input_int_array: [
                     1,
                     3,
                     5,
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_long_array",
-                "type": {
-                  "items": "long",
-                  "type": "array"
-                }
+                id: "#main/input_long_array",
+                type: {
+                    items: "long",
+                    type: "array",
+                },
             },
             input: {
-                "input_long_array": [
+                input_long_array: [
                     10,
                     20,
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_float_array",
-                "type": {
-                  "items": "float",
-                  "type": "array"
-                }
+                id: "#main/input_float_array",
+                type: {
+                    items: "float",
+                    type: "array",
+                },
             },
             input: {
-                "input_float_array": [
+                input_float_array: [
                     10.2,
                     10.4,
                     10.6,
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_double_array",
-                "type": {
-                  "items": "double",
-                  "type": "array"
-                }
+                id: "#main/input_double_array",
+                type: {
+                    items: "double",
+                    type: "array",
+                },
             },
             input: {
-                "input_double_array": [
+                input_double_array: [
                     20.1,
                     20.2,
                     20.3,
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_string_array",
-                "type": {
-                  "items": "string",
-                  "type": "array"
-                }
+                id: "#main/input_string_array",
+                type: {
+                    items: "string",
+                    type: "array",
+                },
             },
             input: {
-                "input_string_array": [
+                input_string_array: [
                     "Hello",
                     "World",
                     "!",
                     {
-                        "$import": "import_path"
-                    }
-                ]
-            }
+                        $import: "import_path",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/input_bool_include",
-                "type": "boolean"
+                id: "#main/input_bool_include",
+                type: "boolean",
             },
             input: {
-                "input_bool_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_bool_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_int_include",
-                "type": "int"
+                id: "#main/input_int_include",
+                type: "int",
             },
             input: {
-                "input_int_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_int_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_float_include",
-                "type": "float"
+                id: "#main/input_float_include",
+                type: "float",
             },
             input: {
-                "input_float_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_float_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_string_include",
-                "type": "string"
+                id: "#main/input_string_include",
+                type: "string",
             },
             input: {
-                "input_string_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_string_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_file_include",
-                "type": "File"
+                id: "#main/input_file_include",
+                type: "File",
             },
             input: {
-                "input_file_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_file_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_directory_include",
-                "type": "Directory"
+                id: "#main/input_directory_include",
+                type: "Directory",
             },
             input: {
-                "input_directory_include": {
-                    "$include": "include_path"
-                }
-            }
+                input_directory_include: {
+                    $include: "include_path",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/input_file_url",
-                "type": "File"
+                id: "#main/input_file_url",
+                type: "File",
             },
             input: {
-                "input_file_url": {
-                    "basename": "index.html",
-                    "class": "File",
-                    "location": "http://example.com/index.html"
-                  }
-            }
-        }
+                input_file_url: {
+                    basename: "index.html",
+                    class: "File",
+                    location: "http://example.com/index.html",
+                },
+            },
+        },
     ];
 
     const testOutputs = [
         {
             definition: {
-                "id": "#main/output_file",
-                "label": "Label Description",
-                "type": "File"
+                id: "#main/output_file",
+                label: "Label Description",
+                type: "File",
             },
             output: {
-                "output_file": {
-                    "basename": "cat.png",
-                    "class": "File",
-                    "location": "cat.png"
-                }
-            }
+                output_file: {
+                    basename: "cat.png",
+                    class: "File",
+                    location: "cat.png",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/output_file_with_secondary",
-                "doc": "Doc Description",
-                "type": "File"
+                id: "#main/output_file_with_secondary",
+                doc: "Doc Description",
+                type: "File",
             },
             output: {
-                "output_file_with_secondary": {
-                    "basename": "main.dat",
-                    "class": "File",
-                    "location": "main.dat",
-                    "secondaryFiles": [
+                output_file_with_secondary: {
+                    basename: "main.dat",
+                    class: "File",
+                    location: "main.dat",
+                    secondaryFiles: [
                         {
-                            "basename": "secondary.dat",
-                            "class": "File",
-                            "location": "secondary.dat"
+                            basename: "secondary.dat",
+                            class: "File",
+                            location: "secondary.dat",
                         },
                         {
-                            "basename": "secondary2.dat",
-                            "class": "File",
-                            "location": "secondary2.dat"
-                        }
-                    ]
-                }
-            }
+                            basename: "secondary2.dat",
+                            class: "File",
+                            location: "secondary2.dat",
+                        },
+                    ],
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/output_dir",
-                "doc": ["Doc desc 1", "Doc desc 2"],
-                "type": "Directory"
+                id: "#main/output_dir",
+                doc: ["Doc desc 1", "Doc desc 2"],
+                type: "Directory",
             },
             output: {
-                "output_dir": {
-                    "basename": "outdir1",
-                    "class": "Directory",
-                    "location": "outdir1"
-                }
-            }
+                output_dir: {
+                    basename: "outdir1",
+                    class: "Directory",
+                    location: "outdir1",
+                },
+            },
         },
         {
             definition: {
-                "id": "#main/output_bool",
-                "type": "boolean"
+                id: "#main/output_bool",
+                type: "boolean",
             },
             output: {
-                "output_bool": true
-            }
+                output_bool: true,
+            },
         },
         {
             definition: {
-                "id": "#main/output_int",
-                "type": "int"
+                id: "#main/output_int",
+                type: "int",
             },
             output: {
-                "output_int": 1
-            }
+                output_int: 1,
+            },
         },
         {
             definition: {
-                "id": "#main/output_long",
-                "type": "long"
+                id: "#main/output_long",
+                type: "long",
             },
             output: {
-                "output_long": 1
-            }
+                output_long: 1,
+            },
         },
         {
             definition: {
-                "id": "#main/output_float",
-                "type": "float"
+                id: "#main/output_float",
+                type: "float",
             },
             output: {
-                "output_float": 100.5
-            }
+                output_float: 100.5,
+            },
         },
         {
             definition: {
-                "id": "#main/output_double",
-                "type": "double"
+                id: "#main/output_double",
+                type: "double",
             },
             output: {
-                "output_double": 100.3
-            }
+                output_double: 100.3,
+            },
         },
         {
             definition: {
-                "id": "#main/output_string",
-                "type": "string"
+                id: "#main/output_string",
+                type: "string",
             },
             output: {
-                "output_string": "Hello output"
-            }
+                output_string: "Hello output",
+            },
         },
         {
             definition: {
-                "id": "#main/output_file_array",
-                "type": {
-                    "items": "File",
-                    "type": "array"
-                }
+                id: "#main/output_file_array",
+                type: {
+                    items: "File",
+                    type: "array",
+                },
             },
             output: {
-                "output_file_array": [
+                output_file_array: [
                     {
-                        "basename": "output2.tar",
-                        "class": "File",
-                        "location": "output2.tar"
+                        basename: "output2.tar",
+                        class: "File",
+                        location: "output2.tar",
                     },
                     {
-                        "basename": "output3.tar",
-                        "class": "File",
-                        "location": "output3.tar"
-                    }
-                ]
-            }
+                        basename: "output3.tar",
+                        class: "File",
+                        location: "output3.tar",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/output_dir_array",
-                "type": {
-                    "items": "Directory",
-                    "type": "array"
-                }
+                id: "#main/output_dir_array",
+                type: {
+                    items: "Directory",
+                    type: "array",
+                },
             },
             output: {
-                "output_dir_array": [
+                output_dir_array: [
                     {
-                        "basename": "outdir2",
-                        "class": "Directory",
-                        "location": "outdir2"
+                        basename: "outdir2",
+                        class: "Directory",
+                        location: "outdir2",
                     },
                     {
-                        "basename": "outdir3",
-                        "class": "Directory",
-                        "location": "outdir3"
-                    }
-                ]
-            }
+                        basename: "outdir3",
+                        class: "Directory",
+                        location: "outdir3",
+                    },
+                ],
+            },
         },
         {
             definition: {
-                "id": "#main/output_int_array",
-                "type": {
-                    "items": "int",
-                    "type": "array"
-                }
+                id: "#main/output_int_array",
+                type: {
+                    items: "int",
+                    type: "array",
+                },
             },
             output: {
-                "output_int_array": [
-                    10,
-                    11,
-                    12
-                ]
-            }
+                output_int_array: [10, 11, 12],
+            },
         },
         {
             definition: {
-                "id": "#main/output_long_array",
-                "type": {
-                    "items": "long",
-                    "type": "array"
-                }
+                id: "#main/output_long_array",
+                type: {
+                    items: "long",
+                    type: "array",
+                },
             },
             output: {
-                "output_long_array": [
-                    51,
-                    52
-                ]
-            }
+                output_long_array: [51, 52],
+            },
         },
         {
             definition: {
-                "id": "#main/output_float_array",
-                "type": {
-                    "items": "float",
-                    "type": "array"
-                }
+                id: "#main/output_float_array",
+                type: {
+                    items: "float",
+                    type: "array",
+                },
             },
             output: {
-                "output_float_array": [
-                    100.2,
-                    100.4,
-                    100.6
-                ]
-            }
+                output_float_array: [100.2, 100.4, 100.6],
+            },
         },
         {
             definition: {
-                "id": "#main/output_double_array",
-                "type": {
-                    "items": "double",
-                    "type": "array"
-                }
+                id: "#main/output_double_array",
+                type: {
+                    items: "double",
+                    type: "array",
+                },
             },
             output: {
-                "output_double_array": [
-                    100.1,
-                    100.2,
-                    100.3
-                ]
-            }
+                output_double_array: [100.1, 100.2, 100.3],
+            },
         },
         {
             definition: {
-                "id": "#main/output_string_array",
-                "type": {
-                    "items": "string",
-                    "type": "array"
-                }
+                id: "#main/output_string_array",
+                type: {
+                    items: "string",
+                    type: "array",
+                },
             },
             output: {
-                "output_string_array": [
-                    "Hello",
-                    "Output",
-                    "!"
-                ]
-            }
-        }
+                output_string_array: ["Hello", "Output", "!"],
+            },
+        },
     ];
 
     const verifyIOParameter = (name, label, doc, val, collection, multipleRows) => {
-        cy.get('table tr').contains(name).parents('tr').within(($mainRow) => {
-            label && cy.contains(label);
-
-            if (multipleRows) {
-                cy.get($mainRow).nextUntil('[data-cy="process-io-param"]').as('secondaryRows');
-                if (val) {
-                    if (Array.isArray(val)) {
-                        val.forEach(v => cy.get('@secondaryRows').contains(v));
-                    } else {
-                        cy.get('@secondaryRows').contains(val);
+        cy.get("table tr")
+            .contains(name)
+            .parents("tr")
+            .within($mainRow => {
+                label && cy.contains(label);
+
+                if (multipleRows) {
+                    cy.get($mainRow).nextUntil('[data-cy="process-io-param"]').as("secondaryRows");
+                    if (val) {
+                        if (Array.isArray(val)) {
+                            val.forEach(v => cy.get("@secondaryRows").contains(v));
+                        } else {
+                            cy.get("@secondaryRows").contains(val);
+                        }
                     }
-                }
-                if (collection) {
-                    cy.get('@secondaryRows').contains(collection);
-                }
-            } else {
-                if (val) {
-                    if (Array.isArray(val)) {
-                        val.forEach(v => cy.contains(v));
-                    } else {
-                        cy.contains(val);
+                    if (collection) {
+                        cy.get("@secondaryRows").contains(collection);
+                    }
+                } else {
+                    if (val) {
+                        if (Array.isArray(val)) {
+                            val.forEach(v => cy.contains(v));
+                        } else {
+                            cy.contains(val);
+                        }
+                    }
+                    if (collection) {
+                        cy.contains(collection);
                     }
                 }
-                if (collection) {
-                    cy.contains(collection);
-                }
-            }
-
-
-        });
+            });
     };
 
     const verifyIOParameterImage = (name, url) => {
-        cy.get('table tr').contains(name).parents('tr').within(() => {
-            cy.get('[alt="Inline Preview"]')
-                .should('be.visible')
-                .and(($img) => {
-                    expect($img[0].naturalWidth).to.be.greaterThan(0);
-                    expect($img[0].src).contains(url);
-                })
-        });
+        cy.get("table tr")
+            .contains(name)
+            .parents("tr")
+            .within(() => {
+                cy.get('[alt="Inline Preview"]')
+                    .should("be.visible")
+                    .and($img => {
+                        expect($img[0].naturalWidth).to.be.greaterThan(0);
+                        expect($img[0].src).contains(url);
+                    });
+            });
     };
 
-    it('displays IO parameters with keep links and previews', function() {
+    it("displays IO parameters with keep links and previews", function () {
         // Create output collection for real files
         cy.createCollection(adminUser.token, {
             name: `Test collection ${Math.floor(Math.random() * 999999)}`,
             owner_uuid: activeUser.user.uuid,
-        }).then((testOutputCollection) => {
-                    cy.loginAs(activeUser);
+        }).then(testOutputCollection => {
+            cy.loginAs(activeUser);
 
-                    cy.goToPath(`/collections/${testOutputCollection.uuid}`);
+            cy.goToPath(`/collections/${testOutputCollection.uuid}`);
 
-                    cy.get('[data-cy=upload-button]').click();
+            cy.get("[data-cy=upload-button]").click();
 
-                    cy.fixture('files/cat.png', 'base64').then(content => {
-                        cy.get('[data-cy=drag-and-drop]').upload(content, 'cat.png');
-                        cy.get('[data-cy=form-submit-btn]').click();
-                        cy.waitForDom().get('[data-cy=form-submit-btn]').should('not.exist');
-                        // Confirm final collection state.
-                        cy.get('[data-cy=collection-files-panel]')
-                            .contains('cat.png').should('exist');
-                    });
+            cy.fixture("files/cat.png", "base64").then(content => {
+                cy.get("[data-cy=drag-and-drop]").upload(content, "cat.png");
+                cy.get("[data-cy=form-submit-btn]").click();
+                cy.waitForDom().get("[data-cy=form-submit-btn]").should("not.exist");
+                // Confirm final collection state.
+                cy.get("[data-cy=collection-files-panel]").contains("cat.png").should("exist");
+            });
 
-                    cy.getCollection(activeUser.token, testOutputCollection.uuid).as('testOutputCollection');
-                });
+            cy.getCollection(activeUser.token, testOutputCollection.uuid).as("testOutputCollection");
+        });
 
         // Get updated collection pdh
-        cy.getAll('@testOutputCollection').then(([testOutputCollection]) => {
+        cy.getAll("@testOutputCollection").then(([testOutputCollection]) => {
             // Add output uuid and inputs to container request
-            cy.intercept({method: 'GET', url: '**/arvados/v1/container_requests/*'}, (req) => {
-                req.reply((res) => {
+            cy.intercept({ method: "GET", url: "**/arvados/v1/container_requests/*" }, req => {
+                req.reply(res => {
                     res.body.output_uuid = testOutputCollection.uuid;
                     res.body.mounts["/var/lib/cwl/cwl.input.json"] = {
-                        content: testInputs.map((param) => (param.input)).reduce((acc, val) => (Object.assign(acc, val)), {})
+                        content: testInputs.map(param => param.input).reduce((acc, val) => Object.assign(acc, val), {}),
                     };
                     res.body.mounts["/var/lib/cwl/workflow.json"] = {
                         content: {
-                            $graph: [{
-                                id: "#main",
-                                inputs: testInputs.map((input) => (input.definition)),
-                                outputs: testOutputs.map((output) => (output.definition))
-                            }]
-                        }
+                            $graph: [
+                                {
+                                    id: "#main",
+                                    inputs: testInputs.map(input => input.definition),
+                                    outputs: testOutputs.map(output => output.definition),
+                                },
+                            ],
+                        },
                     };
                 });
             });
 
             // Stub fake output collection
-            cy.intercept({method: 'GET', url: `**/arvados/v1/collections/${testOutputCollection.uuid}*`}, {
-                statusCode: 200,
-                body: {
-                    uuid: testOutputCollection.uuid,
-                    portable_data_hash: testOutputCollection.portable_data_hash,
+            cy.intercept(
+                { method: "GET", url: `**/arvados/v1/collections/${testOutputCollection.uuid}*` },
+                {
+                    statusCode: 200,
+                    body: {
+                        uuid: testOutputCollection.uuid,
+                        portable_data_hash: testOutputCollection.portable_data_hash,
+                    },
                 }
-            });
+            );
 
             // Stub fake output json
-            cy.intercept({method: 'GET', url: '**/c%3Dzzzzz-4zz18-zzzzzzzzzzzzzzz/cwl.output.json'}, {
-                statusCode: 200,
-                body: testOutputs.map((param) => (param.output)).reduce((acc, val) => (Object.assign(acc, val)), {})
-            });
+            cy.intercept(
+                { method: "GET", url: "**/c%3Dzzzzz-4zz18-zzzzzzzzzzzzzzz/cwl.output.json" },
+                {
+                    statusCode: 200,
+                    body: testOutputs.map(param => param.output).reduce((acc, val) => Object.assign(acc, val), {}),
+                }
+            );
 
             // Stub webdav response, points to output json
-            cy.intercept({method: 'PROPFIND', url: '*'}, {
-                fixture: 'webdav-propfind-outputs.xml',
-            });
+            cy.intercept(
+                { method: "PROPFIND", url: "*" },
+                {
+                    fixture: "webdav-propfind-outputs.xml",
+                }
+            );
         });
 
-        createContainerRequest(
-            activeUser,
-            'test_container_request',
-            'arvados/jobs',
-            ['echo', 'hello world'],
-            false, 'Committed')
-        .as('containerRequest');
+        createContainerRequest(activeUser, "test_container_request", "arvados/jobs", ["echo", "hello world"], false, "Committed").as(
+            "containerRequest"
+        );
 
-        cy.getAll('@containerRequest', '@testOutputCollection').then(function([containerRequest, testOutputCollection]) {
+        cy.getAll("@containerRequest", "@testOutputCollection").then(function ([containerRequest, testOutputCollection]) {
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-io-card] h6').contains('Inputs')
-                .parents('[data-cy=process-io-card]').within(() => {
-                    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", '/', '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');
-                    verifyIOParameter('input_float', null, null, '1.5');
-                    verifyIOParameter('input_double', null, null, '1.3');
-                    verifyIOParameter('input_string', null, null, 'Hello World');
-                    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_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("Inputs")
+                .parents("[data-cy=process-io-card]")
+                .within(() => {
+                    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", "/", "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");
+                    verifyIOParameter("input_float", null, null, "1.5");
+                    verifyIOParameter("input_double", null, null, "1.3");
+                    verifyIOParameter("input_string", null, null, "Hello World");
+                    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_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("[data-cy=process-io-card] h6")
+                .contains("Outputs")
+                .parents("[data-cy=process-io-card]")
+                .within(ctx => {
                     cy.get(ctx).scrollIntoView();
-                    cy.get('[data-cy="io-preview-image-toggle"]').click({waitForAnimations: false});
+                    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}`);
-                    verifyIOParameterImage('output_file', `/c=${outPdh}/cat.png`);
-                    verifyIOParameter('output_file_with_secondary', null, "Doc Description", 'main.dat', `${outPdh}`);
-                    verifyIOParameter('output_file_with_secondary', null, "Doc Description", 'secondary.dat', undefined, true);
-                    verifyIOParameter('output_file_with_secondary', null, "Doc Description", 'secondary2.dat', undefined, true);
-                    verifyIOParameter('output_dir', null, "Doc desc 1, Doc desc 2", 'outdir1', `${outPdh}`);
-                    verifyIOParameter('output_bool', null, null, 'true');
-                    verifyIOParameter('output_int', null, null, '1');
-                    verifyIOParameter('output_long', null, null, '1');
-                    verifyIOParameter('output_float', null, null, '100.5');
-                    verifyIOParameter('output_double', null, null, '100.3');
-                    verifyIOParameter('output_string', null, null, 'Hello output');
-                    verifyIOParameter('output_file_array', null, null, 'output2.tar', `${outPdh}`);
-                    verifyIOParameter('output_file_array', null, null, 'output3.tar', undefined, true);
-                    verifyIOParameter('output_dir_array', null, null, 'outdir2', `${outPdh}`);
-                    verifyIOParameter('output_dir_array', null, null, 'outdir3', undefined, true);
-                    verifyIOParameter('output_int_array', null, null, ["10", "11", "12"]);
-                    verifyIOParameter('output_long_array', null, null, ["51", "52"]);
-                    verifyIOParameter('output_float_array', null, null, ["100.2", "100.4", "100.6"]);
-                    verifyIOParameter('output_double_array', null, null, ["100.1", "100.2", "100.3"]);
-                    verifyIOParameter('output_string_array', null, null, ["Hello", "Output", "!"]);
+                    verifyIOParameter("output_file", null, "Label Description", "cat.png", `${outPdh}`);
+                    verifyIOParameterImage("output_file", `/c=${outPdh}/cat.png`);
+                    verifyIOParameter("output_file_with_secondary", null, "Doc Description", "main.dat", `${outPdh}`);
+                    verifyIOParameter("output_file_with_secondary", null, "Doc Description", "secondary.dat", undefined, true);
+                    verifyIOParameter("output_file_with_secondary", null, "Doc Description", "secondary2.dat", undefined, true);
+                    verifyIOParameter("output_dir", null, "Doc desc 1, Doc desc 2", "outdir1", `${outPdh}`);
+                    verifyIOParameter("output_bool", null, null, "true");
+                    verifyIOParameter("output_int", null, null, "1");
+                    verifyIOParameter("output_long", null, null, "1");
+                    verifyIOParameter("output_float", null, null, "100.5");
+                    verifyIOParameter("output_double", null, null, "100.3");
+                    verifyIOParameter("output_string", null, null, "Hello output");
+                    verifyIOParameter("output_file_array", null, null, "output2.tar", `${outPdh}`);
+                    verifyIOParameter("output_file_array", null, null, "output3.tar", undefined, true);
+                    verifyIOParameter("output_dir_array", null, null, "outdir2", `${outPdh}`);
+                    verifyIOParameter("output_dir_array", null, null, "outdir3", undefined, true);
+                    verifyIOParameter("output_int_array", null, null, ["10", "11", "12"]);
+                    verifyIOParameter("output_long_array", null, null, ["51", "52"]);
+                    verifyIOParameter("output_float_array", null, null, ["100.2", "100.4", "100.6"]);
+                    verifyIOParameter("output_double_array", null, null, ["100.1", "100.2", "100.3"]);
+                    verifyIOParameter("output_string_array", null, null, ["Hello", "Output", "!"]);
                 });
         });
     });
 
-    it('displays IO parameters with no value', function() {
-
-        const fakeOutputUUID = 'zzzzz-4zz18-abcdefghijklmno';
-        const fakeOutputPDH = '11111111111111111111111111111111+99/';
+    it("displays IO parameters with no value", function () {
+        const fakeOutputUUID = "zzzzz-4zz18-abcdefghijklmno";
+        const fakeOutputPDH = "11111111111111111111111111111111+99/";
 
         cy.loginAs(activeUser);
 
         // Add output uuid and inputs to container request
-        cy.intercept({method: 'GET', url: '**/arvados/v1/container_requests/*'}, (req) => {
-            req.reply((res) => {
+        cy.intercept({ method: "GET", url: "**/arvados/v1/container_requests/*" }, req => {
+            req.reply(res => {
                 res.body.output_uuid = fakeOutputUUID;
                 res.body.mounts["/var/lib/cwl/cwl.input.json"] = {
-                    content: {}
+                    content: {},
                 };
                 res.body.mounts["/var/lib/cwl/workflow.json"] = {
                     content: {
-                        $graph: [{
-                            id: "#main",
-                            inputs: testInputs.map((input) => (input.definition)),
-                            outputs: testOutputs.map((output) => (output.definition))
-                        }]
-                    }
+                        $graph: [
+                            {
+                                id: "#main",
+                                inputs: testInputs.map(input => input.definition),
+                                outputs: testOutputs.map(output => output.definition),
+                            },
+                        ],
+                    },
                 };
             });
         });
 
         // Stub fake output collection
-        cy.intercept({method: 'GET', url: `**/arvados/v1/collections/${fakeOutputUUID}*`}, {
-            statusCode: 200,
-            body: {
-                uuid: fakeOutputUUID,
-                portable_data_hash: fakeOutputPDH,
+        cy.intercept(
+            { method: "GET", url: `**/arvados/v1/collections/${fakeOutputUUID}*` },
+            {
+                statusCode: 200,
+                body: {
+                    uuid: fakeOutputUUID,
+                    portable_data_hash: fakeOutputPDH,
+                },
             }
-        });
+        );
 
         // Stub fake output json
-        cy.intercept({method: 'GET', url: `**/c%3D${fakeOutputUUID}/cwl.output.json`}, {
-            statusCode: 200,
-            body: {}
-        });
+        cy.intercept(
+            { method: "GET", url: `**/c%3D${fakeOutputUUID}/cwl.output.json` },
+            {
+                statusCode: 200,
+                body: {},
+            }
+        );
 
-        cy.readFile('cypress/fixtures/webdav-propfind-outputs.xml').then((data) => {
+        cy.readFile("cypress/fixtures/webdav-propfind-outputs.xml").then(data => {
             // Stub webdav response, points to output json
-            cy.intercept({method: 'PROPFIND', url: '*'}, {
-                statusCode: 200,
-                body: data.replace(/zzzzz-4zz18-zzzzzzzzzzzzzzz/g, fakeOutputUUID)
-            });
+            cy.intercept(
+                { method: "PROPFIND", url: "*" },
+                {
+                    statusCode: 200,
+                    body: data.replace(/zzzzz-4zz18-zzzzzzzzzzzzzzz/g, fakeOutputUUID),
+                }
+            );
         });
 
-        createContainerRequest(
-            activeUser,
-            'test_container_request',
-            'arvados/jobs',
-            ['echo', 'hello world'],
-            false, 'Committed')
-        .as('containerRequest');
+        createContainerRequest(activeUser, "test_container_request", "arvados/jobs", ["echo", "hello world"], false, "Committed").as(
+            "containerRequest"
+        );
 
-        cy.getAll('@containerRequest').then(function([containerRequest]) {
+        cy.getAll("@containerRequest").then(function ([containerRequest]) {
             cy.goToPath(`/processes/${containerRequest.uuid}`);
-            cy.get('[data-cy=process-io-card] h6').contains('Inputs')
-                .parents('[data-cy=process-io-card]').within(() => {
+            cy.get("[data-cy=process-io-card] h6")
+                .contains("Inputs")
+                .parents("[data-cy=process-io-card]")
+                .within(() => {
                     cy.wait(2000);
                     cy.waitForDom();
-                    cy.get('tbody tr').each((item) => {
-                        cy.wrap(item).contains('No value');
+                    cy.get("tbody tr").each(item => {
+                        cy.wrap(item).contains("No value");
                     });
                 });
-            cy.get('[data-cy=process-io-card] h6').contains('Outputs')
-                .parents('[data-cy=process-io-card]').within(() => {
-                    cy.get('tbody tr').each((item) => {
-                        cy.wrap(item).contains('No value');
+            cy.get("[data-cy=process-io-card] h6")
+                .contains("Outputs")
+                .parents("[data-cy=process-io-card]")
+                .within(() => {
+                    cy.get("tbody tr").each(item => {
+                        cy.wrap(item).contains("No value");
                     });
                 });
         });
     });
 
-
-    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) {
+    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]").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=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=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');
+        cy.get("[data-cy=process-details]").should("contain", copiedCrName);
+        cy.get("[data-cy=process-details]").find("button").contains("Run");
     });
 
-    const getFakeContainer = (fakeContainerUuid) => ({
+    const getFakeContainer = fakeContainerUuid => ({
         href: `/containers/${fakeContainerUuid}`,
         kind: "arvados#container",
         etag: "ecfosljpnxfari9a8m7e4yv06",
@@ -1184,12 +1159,12 @@ describe('Process tests', function() {
         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",
+            "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",
@@ -1202,24 +1177,24 @@ describe('Process tests', function() {
         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,
+            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,
+            max_run_time: 0,
+            partitions: [],
+            preemptible: false,
         },
         runtime_user_uuid: "zzzzz-tpzed-vllbpebicy84rd5",
         runtime_auth_scopes: ["all"],
@@ -1230,45 +1205,38 @@ describe('Process tests', function() {
         output_properties: {},
         cost: 0.0,
         subrequests_cost: 0.0,
-      });
+    });
 
-    it('shows cancel button when appropriate', function() {
+    it("shows cancel button when appropriate", function () {
         // Ignore collection requests
-        cy.intercept({method: 'GET', url: `**/arvados/v1/collections/*`}, {
-            statusCode: 200,
-            body: {}
-        });
+        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) {
+        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');
+            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) {
+        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) => {
+            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";
@@ -1277,31 +1245,28 @@ describe('Process tests', function() {
 
             // Fake container
             const container = getFakeContainer(fakeCrUuid);
-            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrUuid}`}, {
-                statusCode: 200,
-                body: {...container, state: "Queued", priority: 500}
-            });
+            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');
+            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) {
+        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) => {
+            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";
@@ -1310,31 +1275,28 @@ describe('Process tests', function() {
 
             // Fake container
             const container = getFakeContainer(fakeCrLockedUuid);
-            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrLockedUuid}`}, {
-                statusCode: 200,
-                body: {...container, state: "Locked", priority: 500}
-            });
+            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');
+            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) {
+        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) => {
+            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";
@@ -1343,18 +1305,20 @@ describe('Process tests', function() {
 
             // Fake container
             const container = getFakeContainer(fakeCrOnHoldUuid);
-            cy.intercept({method: 'GET', url: `**/arvados/v1/container/${fakeCrOnHoldUuid}`}, {
-                statusCode: 200,
-                body: {...container, state: "Queued", priority: 0}
-            });
+            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');
+            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");
         });
     });
-
 });
index ffb21417693db35b7c52b8ab91f83439f80baf73..b86567a54c4a73cde90e2c5ef115df5df63037ce 100644 (file)
@@ -56,74 +56,80 @@ describe("<DataExplorer />", () => {
         expect(onSearch).toHaveBeenCalledWith("new value");
     });
 
-    // it("communicates with <ColumnSelector/>", () => {
-    //     const onColumnToggle = jest.fn();
-    //     const onSetColumns = jest.fn();
-    //     const columns = [{ name: "Column 1", render: jest.fn(), selected: true, configurable: true, sortDirection: SortDirection.ASC, filters: {} }];
-    //     const dataExplorer = mount(
-    //         <DataExplorer
-    //             {...mockDataExplorerProps()}
-    //             columns={columns}
-    //             onColumnToggle={onColumnToggle}
-    //             items={[{ name: "item 1" }]}
-    //             onSetColumns={onSetColumns}
-    //         />
-    //     );
-    //     expect(dataExplorer.find(ColumnSelector).prop("columns")).toBe(columns);
-    //     dataExplorer.find(ColumnSelector).prop("onColumnToggle")("columns");
-    //     expect(onColumnToggle).toHaveBeenCalledWith("columns");
-    // });
+    it("communicates with <ColumnSelector/>", () => {
+        const onColumnToggle = jest.fn();
+        const onSetColumns = jest.fn();
+        const columns = [{ name: "Column 1", render: jest.fn(), selected: true, configurable: true, sortDirection: SortDirection.ASC, filters: {} }];
+        const dataExplorer = mount(
+            <Provider store={store}>
+                <DataExplorer
+                    {...mockDataExplorerProps()}
+                    columns={columns}
+                    onColumnToggle={onColumnToggle}
+                    items={[{ name: "item 1" }]}
+                    onSetColumns={onSetColumns}
+                />
+            </Provider>
+        );
+        expect(dataExplorer.find(ColumnSelector).prop("columns")).toBe(columns);
+        dataExplorer.find(ColumnSelector).prop("onColumnToggle")("columns");
+        expect(onColumnToggle).toHaveBeenCalledWith("columns");
+    });
 
-    // it("communicates with <DataTable/>", () => {
-    //     const onFiltersChange = jest.fn();
-    //     const onSortToggle = jest.fn();
-    //     const onRowClick = jest.fn();
-    //     const onSetColumns = jest.fn();
-    //     const columns = [{ name: "Column 1", render: jest.fn(), selected: true, configurable: true, sortDirection: SortDirection.ASC, filters: {} }];
-    //     const items = [{ name: "item 1" }];
-    //     const dataExplorer = mount(
-    //         <DataExplorer
-    //             {...mockDataExplorerProps()}
-    //             columns={columns}
-    //             items={items}
-    //             onFiltersChange={onFiltersChange}
-    //             onSortToggle={onSortToggle}
-    //             onRowClick={onRowClick}
-    //             onSetColumns={onSetColumns}
-    //         />
-    //     );
-    //     expect(dataExplorer.find(DataTable).prop("columns").slice(1, 2)).toEqual(columns);
-    //     expect(dataExplorer.find(DataTable).prop("items")).toBe(items);
-    //     dataExplorer.find(DataTable).prop("onRowClick")("event", "rowClick");
-    //     dataExplorer.find(DataTable).prop("onFiltersChange")("filtersChange");
-    //     dataExplorer.find(DataTable).prop("onSortToggle")("sortToggle");
-    //     expect(onFiltersChange).toHaveBeenCalledWith("filtersChange");
-    //     expect(onSortToggle).toHaveBeenCalledWith("sortToggle");
-    //     expect(onRowClick).toHaveBeenCalledWith("rowClick");
-    // });
+    it("communicates with <DataTable/>", () => {
+        const onFiltersChange = jest.fn();
+        const onSortToggle = jest.fn();
+        const onRowClick = jest.fn();
+        const onSetColumns = jest.fn();
+        const columns = [{ name: "Column 1", render: jest.fn(), selected: true, configurable: true, sortDirection: SortDirection.ASC, filters: {} }];
+        const items = [{ name: "item 1" }];
+        const dataExplorer = mount(
+            <Provider store={store}>
+                <DataExplorer
+                    {...mockDataExplorerProps()}
+                    columns={columns}
+                    items={items}
+                    onFiltersChange={onFiltersChange}
+                    onSortToggle={onSortToggle}
+                    onRowClick={onRowClick}
+                    onSetColumns={onSetColumns}
+                />
+            </Provider>
+        );
+        expect(dataExplorer.find(DataTable).prop("columns").slice(1, 2)).toEqual(columns);
+        expect(dataExplorer.find(DataTable).prop("items")).toBe(items);
+        dataExplorer.find(DataTable).prop("onRowClick")("event", "rowClick");
+        dataExplorer.find(DataTable).prop("onFiltersChange")("filtersChange");
+        dataExplorer.find(DataTable).prop("onSortToggle")("sortToggle");
+        expect(onFiltersChange).toHaveBeenCalledWith("filtersChange");
+        expect(onSortToggle).toHaveBeenCalledWith("sortToggle");
+        expect(onRowClick).toHaveBeenCalledWith("rowClick");
+    });
 
-    // it("communicates with <TablePagination/>", () => {
-    //     const onChangePage = jest.fn();
-    //     const onChangeRowsPerPage = jest.fn();
-    //     const onSetColumns = jest.fn();
-    //     const dataExplorer = mount(
-    //         <DataExplorer
-    //             {...mockDataExplorerProps()}
-    //             items={[{ name: "item 1" }]}
-    //             page={10}
-    //             rowsPerPage={50}
-    //             onChangePage={onChangePage}
-    //             onChangeRowsPerPage={onChangeRowsPerPage}
-    //             onSetColumns={onSetColumns}
-    //         />
-    //     );
-    //     expect(dataExplorer.find(TablePagination).prop("page")).toEqual(10);
-    //     expect(dataExplorer.find(TablePagination).prop("rowsPerPage")).toEqual(50);
-    //     dataExplorer.find(TablePagination).prop("onChangePage")(undefined, 6);
-    //     dataExplorer.find(TablePagination).prop("onChangeRowsPerPage")({ target: { value: 10 } });
-    //     expect(onChangePage).toHaveBeenCalledWith(6);
-    //     expect(onChangeRowsPerPage).toHaveBeenCalledWith(10);
-    // });
+    it("communicates with <TablePagination/>", () => {
+        const onChangePage = jest.fn();
+        const onChangeRowsPerPage = jest.fn();
+        const onSetColumns = jest.fn();
+        const dataExplorer = mount(
+            <Provider store={store}>
+                <DataExplorer
+                    {...mockDataExplorerProps()}
+                    items={[{ name: "item 1" }]}
+                    page={10}
+                    rowsPerPage={50}
+                    onChangePage={onChangePage}
+                    onChangeRowsPerPage={onChangeRowsPerPage}
+                    onSetColumns={onSetColumns}
+                />
+            </Provider>
+        );
+        expect(dataExplorer.find(TablePagination).prop("page")).toEqual(10);
+        expect(dataExplorer.find(TablePagination).prop("rowsPerPage")).toEqual(50);
+        dataExplorer.find(TablePagination).prop("onChangePage")(undefined, 6);
+        dataExplorer.find(TablePagination).prop("onChangeRowsPerPage")({ target: { value: 10 } });
+        expect(onChangePage).toHaveBeenCalledWith(6);
+        expect(onChangeRowsPerPage).toHaveBeenCalledWith(10);
+    });
 });
 
 const mockDataExplorerProps = () => ({
index 74cf75956f7cec87a36abb8f0fdcaee5b7e0883e..4bd989e07c160144e71c74ebc7f8968f6e3039e8 100644 (file)
@@ -15,19 +15,19 @@ import { CommonService } from "services/common-service/common-service";
 
 export type UploadProgress = (fileId: number, loaded: number, total: number, currentTime: number) => void;
 
-export const emptyCollectionPdh = 'd41d8cd98f00b204e9800998ecf8427e+0';
+export const emptyCollectionPdh = "d41d8cd98f00b204e9800998ecf8427e+0";
 
 export class CollectionService extends TrashableResourceService<CollectionResource> {
     constructor(serverApi: AxiosInstance, private webdavClient: WebDAV, private authService: AuthService, actions: ApiActions) {
         super(serverApi, "collections", actions, [
-            'fileCount',
-            'fileSizeTotal',
-            'replicationConfirmed',
-            'replicationConfirmedAt',
-            'storageClassesConfirmed',
-            'storageClassesConfirmedAt',
-            'unsignedManifestText',
-            'version',
+            "fileCount",
+            "fileSizeTotal",
+            "replicationConfirmed",
+            "replicationConfirmedAt",
+            "storageClassesConfirmed",
+            "storageClassesConfirmedAt",
+            "unsignedManifestText",
+            "version",
         ]);
     }
 
@@ -42,7 +42,7 @@ export class CollectionService extends TrashableResourceService<CollectionResour
     }
 
     update(uuid: string, data: Partial<CollectionResource>, showErrors?: boolean) {
-        const select = [...Object.keys(data), 'version', 'modifiedAt'];
+        const select = [...Object.keys(data), "version", "modifiedAt"];
         return super.update(uuid, { ...data, preserveVersion: true }, showErrors, select);
     }
 
@@ -51,15 +51,16 @@ export class CollectionService extends TrashableResourceService<CollectionResour
         if (request.responseXML != null) {
             return extractFilesData(request.responseXML);
         }
+
         return Promise.reject();
     }
 
     private combineFilePath(parts: string[]) {
         return parts.reduce((path, part) => {
             // Trim leading and trailing slashes
-            const trimmedPart = part.split('/').filter(Boolean).join('/');
+            const trimmedPart = part.split("/").filter(Boolean).join("/");
             if (trimmedPart.length) {
-                const separator = path.endsWith('/') ? '' : '/';
+                const separator = path.endsWith("/") ? "" : "/";
                 return `${path}${separator}${trimmedPart}`;
             } else {
                 return path;
@@ -70,22 +71,23 @@ export class CollectionService extends TrashableResourceService<CollectionResour
     private replaceFiles(collectionUuid: string, fileMap: {}, showErrors?: boolean) {
         const payload = {
             collection: {
-                preserve_version: true
+                preserve_version: true,
             },
-            replace_files: fileMap
+            replace_files: fileMap,
         };
 
         return CommonService.defaultResponse(
-            this.serverApi
-                .put<CollectionResource>(`/${this.resourceType}/${collectionUuid}`, payload),
+            this.serverApi.put<CollectionResource>(`/${this.resourceType}/${collectionUuid}`, payload),
             this.actions,
             true, // mapKeys
             showErrors
         );
     }
 
-    async uploadFiles(collectionUuid: string, files: File[], onProgress?: UploadProgress, targetLocation: string = '') {
-        if (collectionUuid === "" || files.length === 0) { return; }
+    async uploadFiles(collectionUuid: string, files: File[], onProgress?: UploadProgress, targetLocation: string = "") {
+        if (collectionUuid === "" || files.length === 0) {
+            return;
+        }
         // files have to be uploaded sequentially
         for (let idx = 0; idx < files.length; idx++) {
             await this.uploadFile(collectionUuid, files[idx], idx, onProgress, targetLocation);
@@ -96,34 +98,40 @@ export class CollectionService extends TrashableResourceService<CollectionResour
     async renameFile(collectionUuid: string, collectionPdh: string, oldPath: string, newPath: string) {
         return this.replaceFiles(collectionUuid, {
             [this.combineFilePath([newPath])]: `${collectionPdh}${this.combineFilePath([oldPath])}`,
-            [this.combineFilePath([oldPath])]: '',
+            [this.combineFilePath([oldPath])]: "",
         });
     }
 
     extendFileURL = (file: CollectionDirectory | CollectionFile) => {
-        const baseUrl = this.webdavClient.getBaseUrl().endsWith('/')
-            ? this.webdavClient.getBaseUrl().slice(0, -1)
-            : this.webdavClient.getBaseUrl();
+        const baseUrl = this.webdavClient.getBaseUrl().endsWith("/") ? this.webdavClient.getBaseUrl().slice(0, -1) : this.webdavClient.getBaseUrl();
         const apiToken = this.authService.getApiToken();
-        const encodedApiToken = apiToken ? encodeURI(apiToken) : '';
+        const encodedApiToken = apiToken ? encodeURI(apiToken) : "";
         const userApiToken = `/t=${encodedApiToken}/`;
-        const splittedPrevFileUrl = file.url.split('/');
-        const url = `${baseUrl}/${splittedPrevFileUrl[1]}${userApiToken}${splittedPrevFileUrl.slice(2).join('/')}`;
+        const splittedPrevFileUrl = file.url.split("/");
+        const url = `${baseUrl}/${splittedPrevFileUrl[1]}${userApiToken}${splittedPrevFileUrl.slice(2).join("/")}`;
         return {
             ...file,
-            url
+            url,
         };
-    }
+    };
 
     async getFileContents(file: CollectionFile) {
         return (await this.webdavClient.get(`c=${file.id}`)).response;
     }
 
-    private async uploadFile(collectionUuid: string, file: File, fileId: number, onProgress: UploadProgress = () => { return; }, targetLocation: string = '') {
-        const fileURL = `c=${targetLocation !== '' ? targetLocation : collectionUuid}/${file.name}`.replace('//', '/');
+    private async uploadFile(
+        collectionUuid: string,
+        file: File,
+        fileId: number,
+        onProgress: UploadProgress = () => {
+            return;
+        },
+        targetLocation: string = ""
+    ) {
+        const fileURL = `c=${targetLocation !== "" ? targetLocation : collectionUuid}/${file.name}`.replace("//", "/");
         const requestConfig = {
             headers: {
-                'Content-Type': 'text/octet-stream'
+                "Content-Type": "text/octet-stream",
             },
             onUploadProgress: (e: ProgressEvent) => {
                 onProgress(fileId, e.loaded, e.total, Date.now());
@@ -136,7 +144,7 @@ export class CollectionService extends TrashableResourceService<CollectionResour
         const optimizedFiles = files
             .sort((a, b) => a.length - b.length)
             .reduce((acc, currentPath) => {
-                const parentPathFound = acc.find((parentPath) => currentPath.indexOf(`${parentPath}/`) > -1);
+                const parentPathFound = acc.find(parentPath => currentPath.indexOf(`${parentPath}/`) > -1);
 
                 if (!parentPathFound) {
                     return [...acc, currentPath];
@@ -148,49 +156,54 @@ export class CollectionService extends TrashableResourceService<CollectionResour
         const fileMap = optimizedFiles.reduce((obj, filePath) => {
             return {
                 ...obj,
-                [this.combineFilePath([filePath])]: ''
-            }
-        }, {})
+                [this.combineFilePath([filePath])]: "",
+            };
+        }, {});
 
         return this.replaceFiles(collectionUuid, fileMap, showErrors);
     }
 
     copyFiles(sourcePdh: string, files: string[], destinationCollectionUuid: string, destinationPath: string, showErrors?: boolean) {
         const fileMap = files.reduce((obj, sourceFile) => {
-            const sourceFileName = sourceFile.split('/').filter(Boolean).slice(-1).join("");
+            const sourceFileName = sourceFile.split("/").filter(Boolean).slice(-1).join("");
             return {
                 ...obj,
-                [this.combineFilePath([destinationPath, sourceFileName])]: `${sourcePdh}${this.combineFilePath([sourceFile])}`
+                [this.combineFilePath([destinationPath, sourceFileName])]: `${sourcePdh}${this.combineFilePath([sourceFile])}`,
             };
         }, {});
 
         return this.replaceFiles(destinationCollectionUuid, fileMap, showErrors);
     }
 
-    moveFiles(sourceUuid: string, sourcePdh: string, files: string[], destinationCollectionUuid: string, destinationPath: string, showErrors?: boolean) {
+    moveFiles(
+        sourceUuid: string,
+        sourcePdh: string,
+        files: string[],
+        destinationCollectionUuid: string,
+        destinationPath: string,
+        showErrors?: boolean
+    ) {
         if (sourceUuid === destinationCollectionUuid) {
             const fileMap = files.reduce((obj, sourceFile) => {
-                const sourceFileName = sourceFile.split('/').filter(Boolean).slice(-1).join("");
+                const sourceFileName = sourceFile.split("/").filter(Boolean).slice(-1).join("");
                 return {
                     ...obj,
                     [this.combineFilePath([destinationPath, sourceFileName])]: `${sourcePdh}${this.combineFilePath([sourceFile])}`,
-                    [this.combineFilePath([sourceFile])]: '',
+                    [this.combineFilePath([sourceFile])]: "",
                 };
             }, {});
 
-            return this.replaceFiles(sourceUuid, fileMap, showErrors)
+            return this.replaceFiles(sourceUuid, fileMap, showErrors);
         } else {
-            return this.copyFiles(sourcePdh, files, destinationCollectionUuid, destinationPath, showErrors)
-                .then(() => {
-                    return this.deleteFiles(sourceUuid, files, showErrors);
-                });
+            return this.copyFiles(sourcePdh, files, destinationCollectionUuid, destinationPath, showErrors).then(() => {
+                return this.deleteFiles(sourceUuid, files, showErrors);
+            });
         }
     }
 
     createDirectory(collectionUuid: string, path: string, showErrors?: boolean) {
-        const fileMap = {[this.combineFilePath([path])]: emptyCollectionPdh};
+        const fileMap = { [this.combineFilePath([path])]: emptyCollectionPdh };
 
         return this.replaceFiles(collectionUuid, fileMap, showErrors);
     }
-
 }
index aceebe066b44badc8318cea8d71021b6c993f3de..7d039b13d75d752c7095115f295d604151b7f1ad 100644 (file)
@@ -35,36 +35,32 @@ export const readOnlyProcessResourceActionSet: ContextMenuActionSet = [
         {
             component: ToggleFavoriteAction,
             execute: (dispatch, resources) => {
-                resources.forEach(resource =>
-                    dispatch<any>(toggleFavorite(resource)).then(() => {
-                        dispatch<any>(favoritePanelActions.REQUEST_ITEMS());
-                    })
-                );
+                dispatch<any>(toggleFavorite(resources[0])).then(() => {
+                    dispatch<any>(favoritePanelActions.REQUEST_ITEMS());
+                });
             },
         },
         {
             icon: OpenIcon,
             name: "Open in new tab",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => dispatch<any>(openInNewTabAction(resource)));
+                dispatch<any>(openInNewTabAction(resources[0]));
             },
         },
         {
             icon: ReRunProcessIcon,
             name: "Copy and re-run process",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => dispatch<any>(openCopyProcessDialog(resource)));
+                dispatch<any>(openCopyProcessDialog(resources[0]));
             },
         },
         {
             icon: OutputIcon,
             name: "Outputs",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => {
-                    if (resource.outputUuid) {
-                        dispatch<any>(navigateToOutput(resource.outputUuid));
-                    }
-                });
+                if (resources[0].outputUuid) {
+                    dispatch<any>(navigateToOutput(resources[0].outputUuid));
+                }
             },
         },
         {
@@ -78,7 +74,7 @@ export const readOnlyProcessResourceActionSet: ContextMenuActionSet = [
             icon: AdvancedIcon,
             name: "API Details",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => dispatch<any>(openAdvancedTabDialog(resource.uuid)));
+                dispatch<any>(openAdvancedTabDialog(resources[0].uuid));
             },
         },
     ],
@@ -91,14 +87,14 @@ export const processResourceActionSet: ContextMenuActionSet = [
             icon: RenameIcon,
             name: "Edit process",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => dispatch<any>(openProcessUpdateDialog(resource)));
+                dispatch<any>(openProcessUpdateDialog(resources[0]));
             },
         },
         {
             icon: ShareIcon,
             name: "Share",
             execute: (dispatch, resources) => {
-                resources.forEach(({ uuid }) => dispatch<any>(openSharingDialog(uuid)));
+                dispatch<any>(openSharingDialog(resources[0].uuid));
             },
         },
         {
@@ -125,11 +121,9 @@ export const processResourceAdminActionSet: ContextMenuActionSet = [
             component: TogglePublicFavoriteAction,
             name: "Add to public favorites",
             execute: (dispatch, resources) => {
-                resources.forEach(resource =>
-                    dispatch<any>(togglePublicFavorite(resource)).then(() => {
-                        dispatch<any>(publicFavoritePanelActions.REQUEST_ITEMS());
-                    })
-                );
+                dispatch<any>(togglePublicFavorite(resources[0])).then(() => {
+                    dispatch<any>(publicFavoritePanelActions.REQUEST_ITEMS());
+                });
             },
         },
     ],
index 77215470ddd090b0fe354d47ae1c4ecf4665e6e3..2ea1a99a9e79be5f36aca08c83cab7d419894b7f 100644 (file)
@@ -16,7 +16,6 @@ export const msCollectionActionSet: ContextMenuActionSet = [
             icon: CopyIcon,
             name: "Make a copy",
             execute: (dispatch, [...resources]) => {
-                console.log(resources);
                 if (resources[0].isSingle || resources.length === 1) dispatch<any>(openCollectionCopyDialog(resources[0]));
                 else dispatch<any>(openMultiCollectionCopyDialog(resources[0]));
             },
index cf629993989c299ed3cea16ce1bc572428663104..820fc7999eeb0595c22fba64a7f64cccfd8e61f0 100644 (file)
@@ -14,7 +14,9 @@ export const msProcessActionSet: ContextMenuActionSet = [
             icon: ReRunProcessIcon,
             name: "Copy and re-run process",
             execute: (dispatch, resources) => {
-                resources.forEach(resource => dispatch<any>(openCopyProcessDialog(resource)));
+                for (const resource of [...resources]) {
+                    dispatch<any>(openCopyProcessDialog(resource));
+                }
             },
         },
         {