18946: Fix flaky test
[arvados-workbench2.git] / cypress / integration / collection.spec.js
index 51933887452479e483f42bda461755efb78a4eb5..3dd833d04ebab71d3407887adfc14d07c980b5b6 100644 (file)
@@ -75,6 +75,55 @@ describe('Collection panel tests', function () {
         });
     });
 
+    it('attempts to use a preexisting name creating or updating a collection', function() {
+        const name = `Test collection ${Math.floor(Math.random() * 999999)}`;
+        cy.createCollection(adminUser.token, {
+            name: name,
+            owner_uuid: activeUser.user.uuid,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+        });
+        cy.loginAs(activeUser);
+        cy.goToPath(`/projects/${activeUser.user.uuid}`);
+        cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
+        cy.get('[data-cy=breadcrumb-last]').should('not.exist');
+        // Attempt to create new collection with a duplicate name
+        cy.get('[data-cy=side-panel-button]').click();
+        cy.get('[data-cy=side-panel-new-collection]').click();
+        cy.get('[data-cy=form-dialog]')
+            .should('contain', 'New collection')
+            .within(() => {
+                cy.get('[data-cy=name-field]').within(() => {
+                    cy.get('input').type(name);
+                });
+                cy.get('[data-cy=form-submit-btn]').click();
+            });
+        // Error message should display, allowing editing the name
+        cy.get('[data-cy=form-dialog]').should('exist')
+            .and('contain', 'Collection with the same name already exists')
+            .within(() => {
+                cy.get('[data-cy=name-field]').within(() => {
+                    cy.get('input').type(' renamed');
+                });
+                cy.get('[data-cy=form-submit-btn]').click();
+            });
+        cy.get('[data-cy=form-dialog]').should('not.exist');
+        // Attempt to rename the collection with the duplicate name
+        cy.get('[data-cy=collection-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Edit collection').click();
+        cy.get('[data-cy=form-dialog]')
+            .should('contain', 'Edit Collection')
+            .within(() => {
+                cy.get('[data-cy=name-field]').within(() => {
+                    cy.get('input')
+                        .type('{selectall}{backspace}')
+                        .type(name);
+                });
+                cy.get('[data-cy=form-submit-btn]').click();
+            });
+        cy.get('[data-cy=form-dialog]').should('exist')
+            .and('contain', 'Collection with the same name already exists');
+    });
+
     it('uses the property editor (from edit dialog) with vocabulary terms', function () {
         cy.createCollection(adminUser.token, {
             name: `Test collection ${Math.floor(Math.random() * 999999)}`,
@@ -208,7 +257,7 @@ describe('Collection panel tests', function () {
                 // a bogus manifest text without block signatures.
                 cy.doRequest('GET', '/arvados/v1/config', null, null)
                     .its('body').should((clusterConfig) => {
-                      expect(clusterConfig.Collections, "clusterConfig").to.have.property("TrustAllContent", false);
+                      expect(clusterConfig.Collections, "clusterConfig").to.have.property("TrustAllContent", true);
                       expect(clusterConfig.Services, "clusterConfig").to.have.property("WebDAV").have.property("ExternalURL");
                       expect(clusterConfig.Services, "clusterConfig").to.have.property("WebDAVDownload").have.property("ExternalURL");
                       const inlineUrl = clusterConfig.Services.WebDAV.ExternalURL !== ""
@@ -251,9 +300,9 @@ describe('Collection panel tests', function () {
                             .should('contain', 'someKey: someValue')
                             .and('not.contain', 'anotherKey: anotherValue');
                         // Check that the file listing show both read & write operations
-                        cy.get('[data-cy=collection-files-panel]').within(() => {
-                            cy.wait(1000);
-                            cy.root().should('contain', fileName);
+                        cy.waitForDom().get('[data-cy=collection-files-panel]').within(() => {
+                            cy.get('[data-cy=collection-files-right-panel]', { timeout: 5000 })
+                                .should('contain', fileName);
                             if (isWritable) {
                                 cy.get('[data-cy=upload-button]')
                                     .should(`${isWritable ? '' : 'not.'}contain`, 'Upload data');
@@ -261,23 +310,30 @@ describe('Collection panel tests', function () {
                         });
                         // Test context menus
                         cy.get('[data-cy=collection-files-panel]')
-                            .contains(fileName).rightclick({ force: true });
+                            .contains(fileName).rightclick();
                         cy.get('[data-cy=context-menu]')
                             .should('contain', 'Download')
-                            .and('not.contain', 'Open in new tab')
+                            .and('contain', 'Open in new tab')
                             .and('contain', 'Copy to clipboard')
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Rename')
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Remove');
                         cy.get('body').click(); // Collapse the menu
                         cy.get('[data-cy=collection-files-panel]')
-                            .contains(subDirName).rightclick({ force: true });
+                            .contains(subDirName).rightclick();
                         cy.get('[data-cy=context-menu]')
                             .should('not.contain', 'Download')
-                            .and('not.contain', 'Open in new tab')
+                            .and('contain', 'Open in new tab')
                             .and('contain', 'Copy to clipboard')
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Rename')
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Remove');
                         cy.get('body').click(); // Collapse the menu
+                        // File/dir item 'more options' button
+                        cy.get('[data-cy=file-item-options-btn')
+                            .first()
+                            .click()
+                        cy.get('[data-cy=context-menu]')
+                            .should(`${isWritable ? '' : 'not.'}contain`, 'Remove');
+                        cy.get('body').click(); // Collapse the menu
                         // Hamburger 'more options' menu button
                         cy.get('[data-cy=collection-files-panel-options-btn]')
                             .click()
@@ -333,8 +389,9 @@ describe('Collection panel tests', function () {
                     'table%&?*2',
                     'bar' // make sure we can go back to the original name as a last step
                 ];
+                cy.intercept({method: 'PUT', url: '**/arvados/v1/collections/*'}).as('renameRequest');
                 eachPair(names, (from, to) => {
-                    cy.get('[data-cy=collection-files-panel]')
+                    cy.waitForDom().get('[data-cy=collection-files-panel]')
                         .contains(`${from}`).rightclick();
                     cy.get('[data-cy=context-menu]')
                         .contains('Rename')
@@ -347,6 +404,7 @@ describe('Collection panel tests', function () {
                                 .type(to, { parseSpecialCharSequences: false });
                         });
                     cy.get('[data-cy=form-submit-btn]').click();
+                    cy.wait('@renameRequest');
                     cy.get('[data-cy=collection-files-panel]')
                         .should('not.contain', `${from}`)
                         .and('contain', `${to}`);
@@ -367,8 +425,8 @@ describe('Collection panel tests', function () {
                 cy.goToPath(`/collections/${this.testCollection.uuid}`);
 
                 ['subdir', 'G%C3%BCnter\'s%20file', 'table%&?*2'].forEach((subdir) => {
-                    cy.get('[data-cy=collection-files-panel]')
-                        .contains('bar').rightclick({force: true});
+                    cy.waitForDom().get('[data-cy=collection-files-panel]')
+                        .contains('bar').rightclick();
                     cy.get('[data-cy=context-menu]')
                         .contains('Rename')
                         .click();
@@ -381,9 +439,9 @@ describe('Collection panel tests', function () {
                     cy.get('[data-cy=collection-files-panel]')
                         .should('not.contain', 'bar')
                         .and('contain', subdir);
-                    cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]').contains(subdir).click();
-                    // Rename 'subdir/foo' to 'foo'
+
+                    // Rename 'subdir/foo' to 'bar'
                     cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]')
                         .contains('foo').rightclick();
@@ -399,8 +457,10 @@ describe('Collection panel tests', function () {
                         });
                     cy.get('[data-cy=form-submit-btn]').click();
 
-                    cy.wait(1000);
-                    cy.get('[data-cy=collection-files-panel]')
+                    // need to wait for dialog to dismiss
+                    cy.get('[data-cy=form-dialog]').should('not.exist');
+
+                    cy.waitForDom().get('[data-cy=collection-files-panel]')
                         .contains('Home')
                         .click();
 
@@ -415,10 +475,25 @@ describe('Collection panel tests', function () {
                         .contains('Remove')
                         .click();
                     cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+                    cy.get('[data-cy=form-dialog]').should('not.exist');
                 });
             });
     });
 
+    it('shows collection owner', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+        })
+            .as('testCollection').then((testCollection) => {
+                cy.loginAs(activeUser);
+                cy.goToPath(`/collections/${testCollection.uuid}`);
+                cy.wait(5000);
+                cy.get('[data-cy=collection-info-panel]').contains(`Collection User`);
+            });
+    });
+
     it('tries to rename a file with illegal names', function () {
         // Creates the collection using the admin token so we can set up
         // a bogus manifest text without block signatures.
@@ -608,9 +683,10 @@ describe('Collection panel tests', function () {
                 cy.get('[data-cy=form-dialog]')
                     .should('contain', 'Move to')
                     .within(() => {
+                        // must use .then to avoid selecting instead of expanding https://github.com/cypress-io/cypress/issues/5529
                         cy.get('[data-cy=projects-tree-home-tree-picker]')
                             .find('i')
-                            .click();
+                            .then(el => el.click());
                         cy.get('[data-cy=projects-tree-home-tree-picker]')
                             .contains(projName)
                             .click();
@@ -622,8 +698,48 @@ describe('Collection panel tests', function () {
                     .contains(projName).and('contain', testProject.uuid);
                 // Double check that the collection is in the project
                 cy.goToPath(`/projects/${testProject.uuid}`);
-                cy.get('[data-cy=project-panel]').should('contain', collName);
+                cy.waitForDom().get('[data-cy=project-panel]').should('contain', collName);
+            });
+    });
+
+    it('automatically updates the collection UI contents without using the Refresh button', function () {
+        const collName = `Test Collection ${Math.floor(Math.random() * 999999)}`;
+
+        cy.createCollection(adminUser.token, {
+            name: collName,
+            owner_uuid: activeUser.user.uuid,
+        }).as('testCollection');
+
+        cy.getAll('@testCollection').then(function ([testCollection]) {
+            cy.loginAs(activeUser);
+
+            const files = [
+                "foobar",
+                "anotherFile",
+                "",
+                "finalName",
+            ];
+
+            cy.goToPath(`/collections/${testCollection.uuid}`);
+            cy.get('[data-cy=collection-files-panel]').should('contain', 'This collection is empty');
+            cy.get('[data-cy=collection-files-panel]').should('not.contain', files[0]);
+            cy.get('[data-cy=collection-info-panel]').should('contain', collName);
+
+            files.map((fileName, i, files) => {
+                cy.updateCollection(adminUser.token, testCollection.uuid, {
+                    name: `${collName + ' updated'}`,
+                    manifest_text: fileName ? `. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n` : "",
+                }).as('updatedCollection');
+                cy.getAll('@updatedCollection').then(function ([updatedCollection]) {
+                    expect(updatedCollection.name).to.equal(`${collName + ' updated'}`);
+                    cy.get('[data-cy=collection-info-panel]').should('contain', updatedCollection.name);
+                    fileName
+                        ? cy.get('[data-cy=collection-files-panel]').should('contain', fileName)
+                        : cy.get('[data-cy=collection-files-panel]').should('not.contain', files[i-1]);;
+                });
             });
+
+        });
     });
 
     it('makes a copy of an existing collection', function() {
@@ -699,7 +815,7 @@ describe('Collection panel tests', function () {
                         cy.get('[data-cy=collection-version-browser-select-1]')
                             .should('contain', '1')
                             .and('contain', '6 B')
-                            .and('contain', adminUser.user.uuid);
+                            .and('contain', adminUser.user.full_name);
                         // Version 2: 3 bytes in size (one file removed)
                         cy.get('[data-cy=collection-version-browser-select-2]')
                             .should('contain', '2')
@@ -760,7 +876,7 @@ describe('Collection panel tests', function () {
                     .should('contain', '3').and('contain', '3 B');
 
                 // Check context menus on version browser
-                cy.get('[data-cy=collection-version-browser-select-3]').rightclick()
+                cy.waitForDom().get('[data-cy=collection-version-browser-select-3]').rightclick()
                 cy.get('[data-cy=context-menu]')
                     .should('contain', 'Add to favorites')
                     .and('contain', 'Make a copy')
@@ -791,6 +907,231 @@ describe('Collection panel tests', function () {
             });
     });
 
+    it('copies selected files into new collection', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        })
+            .as('collection').then(function () {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${this.collection.uuid}`);
+
+                cy.get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                });
+
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Copy selected into new collection').click();
+
+                cy.get('[data-cy=form-dialog]').contains('Projects').click();
+
+                cy.get('[data-cy=form-submit-btn]').click();
+
+                cy.waitForDom().get('.layout-pane-primary', { timeout: 12000 }).contains('Projects').click();
+
+                cy.get('main').contains(`Files extracted from: ${this.collection.name}`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+            });
+    });
+
+    it('copies selected files into existing collection', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        }).as('sourceCollection')
+
+        cy.createCollection(adminUser.token, {
+            name: `Destination Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ""
+        }).as('destinationCollection');
+
+        cy.getAll('@sourceCollection', '@destinationCollection').then(function ([sourceCollection, destinationCollection]) {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${sourceCollection.uuid}`);
+
+                cy.get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                });
+
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Copy selected into existing collection').click();
+
+                cy.get('[data-cy=form-dialog]').contains(destinationCollection.name).click();
+
+                cy.get('[data-cy=form-submit-btn]').click();
+                cy.wait(2000);
+
+                cy.goToPath(`/collections/${destinationCollection.uuid}`);
+
+                cy.get('main').contains(destinationCollection.name).should('exist');
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+            });
+    });
+
+    it('copies selected files into separate collections', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        }).as('sourceCollection')
+
+        cy.getAll('@sourceCollection').then(function ([sourceCollection]) {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${sourceCollection.uuid}`);
+
+                // Select both files
+                cy.waitForDom().get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                    cy.get('input[type=checkbox]').last().click();
+                });
+
+                // Copy to separate collections
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Copy selected into separate collections').click();
+                cy.get('[data-cy=form-dialog]').contains('Projects').click();
+                cy.get('[data-cy=form-submit-btn]').click();
+
+                // Verify created collections
+                cy.waitForDom().get('.layout-pane-primary', { timeout: 12000 }).contains('Projects').click();
+                cy.get('main').contains(`File copied from collection ${sourceCollection.name}/foo`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'foo');
+                cy.get('.layout-pane-primary').contains('Projects').click();
+                cy.get('main').contains(`File copied from collection ${sourceCollection.name}/bar`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+
+                // Verify separate collection menu items not present when single file selected
+                // Wait for dom for collection to re-render
+                cy.waitForDom().get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                });
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').should('not.contain', 'Copy selected into separate collections');
+                cy.get('[data-cy=context-menu]').should('not.contain', 'Move selected into separate collections');
+            });
+    });
+
+    it('moves selected files into new collection', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        })
+            .as('collection').then(function () {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${this.collection.uuid}`);
+
+                cy.get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                });
+
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Move selected into new collection').click();
+
+                cy.get('[data-cy=form-dialog]').contains('Projects').click();
+
+                cy.get('[data-cy=form-submit-btn]').click();
+
+                cy.waitForDom().get('.layout-pane-primary', { timeout: 12000 }).contains('Projects').click();
+
+                cy.get('main').contains(`Files moved from: ${this.collection.name}`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+            });
+    });
+
+    it('moves selected files into existing collection', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        }).as('sourceCollection')
+
+        cy.createCollection(adminUser.token, {
+            name: `Destination Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ""
+        }).as('destinationCollection');
+
+        cy.getAll('@sourceCollection', '@destinationCollection').then(function ([sourceCollection, destinationCollection]) {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${sourceCollection.uuid}`);
+
+                cy.get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                });
+
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Move selected into existing collection').click();
+
+                cy.get('[data-cy=form-dialog]').contains(destinationCollection.name).click();
+
+                cy.get('[data-cy=form-submit-btn]').click();
+                cy.wait(2000);
+
+                cy.goToPath(`/collections/${destinationCollection.uuid}`);
+
+                cy.get('main').contains(destinationCollection.name).should('exist');
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+            });
+    });
+
+    it('moves selected files into separate collections', () => {
+        cy.createCollection(adminUser.token, {
+            name: `Test Collection ${Math.floor(Math.random() * 999999)}`,
+            owner_uuid: activeUser.user.uuid,
+            preserve_version: true,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo 0:3:bar\n"
+        }).as('sourceCollection')
+
+        cy.getAll('@sourceCollection').then(function ([sourceCollection]) {
+                // Visit collection, check basic information
+                cy.loginAs(activeUser)
+                cy.goToPath(`/collections/${sourceCollection.uuid}`);
+
+                // Select both files
+                cy.get('[data-cy=collection-files-panel]').within(() => {
+                    cy.get('input[type=checkbox]').first().click();
+                    cy.get('input[type=checkbox]').last().click();
+                });
+
+                // Copy to separate collections
+                cy.get('[data-cy=collection-files-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Move selected into separate collections').click();
+                cy.get('[data-cy=form-dialog]').contains('Projects').click();
+                cy.get('[data-cy=form-submit-btn]').click();
+
+                // Verify created collections
+                cy.waitForDom().get('.layout-pane-primary', { timeout: 12000 }).contains('Projects').click();
+                cy.get('main').contains(`File moved from collection ${sourceCollection.name}/foo`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'foo');
+                cy.get('.layout-pane-primary').contains('Projects').click();
+                cy.get('main').contains(`File moved from collection ${sourceCollection.name}/bar`).click();
+                cy.get('[data-cy=collection-files-panel]')
+                        .and('contain', 'bar');
+            });
+    });
+
     it('creates new collection with properties on home project', function () {
         cy.loginAs(activeUser);
         cy.goToPath(`/projects/${activeUser.user.uuid}`);
@@ -834,6 +1175,10 @@ describe('Collection panel tests', function () {
         // Confirm proper vocabulary labels are displayed on the UI.
         cy.get('[data-cy=form-dialog]').should('contain', 'Color: Magenta');
 
+        // Value field should not complain about being required just after
+        // adding a new property. See #19732
+        cy.get('[data-cy=form-dialog]').should('not.contain', 'This field is required');
+
         cy.get('[data-cy=form-submit-btn]').click();
         // Confirm that the user was taken to the newly created collection
         cy.get('[data-cy=form-dialog]').should('not.exist');
@@ -861,17 +1206,15 @@ describe('Collection panel tests', function () {
             name: `Test collection ${Math.floor(Math.random() * 999999)}`,
             owner_uuid: activeUser.user.uuid,
             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
-        })
-            .as('testCollection1');
+        }).as('testCollection1');
 
         cy.createCollection(adminUser.token, {
             name: `Test collection ${Math.floor(Math.random() * 999999)}`,
             owner_uuid: adminUser.user.uuid,
             manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
-        })
-            .as('testCollection2').then(function (testCollection2) {
-                cy.shareWith(adminUser.token, activeUser.user.uuid, testCollection2.uuid, 'can_write');
-            });
+        }).as('testCollection2').then(function (testCollection2) {
+            cy.shareWith(adminUser.token, activeUser.user.uuid, testCollection2.uuid, 'can_write');
+        });
 
         cy.getAll('@testCollection1', '@testCollection2')
             .then(function ([testCollection1, testCollection2]) {
@@ -892,9 +1235,41 @@ describe('Collection panel tests', function () {
             cy.createCollection(adminUser.token, {
                 name: `Test collection ${Math.floor(Math.random() * 999999)}`,
                 owner_uuid: activeUser.user.uuid,
-                manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
-            })
-                .as('testCollection1');
+                manifest_text: "./subdir 37b51d194a7513e45b56f6524f2d51f2+3 0:3:foo\n. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+            }).as('testCollection1');
+        });
+
+        it('uploads a file and checks the collection UI to be fresh', () => {
+            cy.getAll('@testCollection1')
+                .then(function([testCollection1]) {
+                    cy.loginAs(activeUser);
+                    cy.goToPath(`/collections/${testCollection1.uuid}`);
+                    cy.get('[data-cy=upload-button]').click();
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('5mb_a.bin').should('not.exist');
+                    cy.get('[data-cy=collection-file-count]').should('contain', '2');
+                    cy.fixture('files/5mb.bin', 'base64').then(content => {
+                        cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_a.bin');
+                        cy.get('[data-cy=form-submit-btn]').click();
+                        cy.get('[data-cy=form-submit-btn]').should('not.exist');
+                        cy.get('[data-cy=collection-files-panel]')
+                            .contains('5mb_a.bin').should('exist');
+                        cy.get('[data-cy=collection-file-count]').should('contain', '3');
+
+                        cy.get('[data-cy=collection-files-panel]').contains('subdir').click();
+                        cy.get('[data-cy=upload-button]').click();
+                        cy.fixture('files/5mb.bin', 'base64').then(content => {
+                            cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_b.bin');
+                            cy.get('[data-cy=form-submit-btn]').click();
+                            cy.waitForDom().get('[data-cy=form-submit-btn]').should('not.exist');
+                            // subdir gets unselected, I think this is a bug but
+                            // for the time being let's just make sure the test works.
+                            cy.get('[data-cy=collection-files-panel]').contains('subdir').click();
+                            cy.waitForDom().get('[data-cy=collection-files-right-panel]')
+                                 .contains('5mb_b.bin').should('exist');
+                        });
+                    });
+                });
         });
 
         it('allows to cancel running upload', () => {
@@ -950,6 +1325,14 @@ describe('Collection panel tests', function () {
 
                     cy.goToPath(`/collections/${testCollection1.uuid}`);
 
+                    // Confirm initial collection state.
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('bar').should('exist');
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('5mb_a.bin').should('not.exist');
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('5mb_b.bin').should('not.exist');
+
                     cy.get('[data-cy=upload-button]').click();
 
                     cy.fixture('files/5mb.bin', 'base64').then(content => {
@@ -959,9 +1342,25 @@ describe('Collection panel tests', function () {
                         cy.get('[data-cy=form-submit-btn]').click();
 
                         cy.get('button[aria-label=Remove]').should('exist');
-                        cy.get('button[aria-label=Remove]').click({ multiple: true, force: true });
+                        cy.get('button[aria-label=Remove]')
+                            .click({ multiple: true, force: true });
 
                         cy.get('[data-cy=form-submit-btn]').should('not.exist');
+
+                        // Confirm final collection state.
+                        cy.get('[data-cy=collection-files-panel]')
+                            .contains('bar').should('exist');
+                        // The following fails, but doesn't seem to happen
+                        // in the real world. Maybe there's a race between
+                        // the PUT request finishing and the 'Remove' button
+                        // dissapearing, because sometimes just one of the 2
+                        // files gets uploaded.
+                        // Maybe this will be needed to simulate a slow network:
+                        // https://docs.cypress.io/api/commands/intercept#Convenience-functions-1
+                        // cy.get('[data-cy=collection-files-panel]')
+                        //     .contains('5mb_a.bin').should('not.exist');
+                        // cy.get('[data-cy=collection-files-panel]')
+                        //     .contains('5mb_b.bin').should('not.exist');
                     });
                 });
         });