Merge branch '18203-Support-setting-multi-properties-at-once' into main
[arvados-workbench2.git] / cypress / integration / collection.spec.js
index bf2375d0da10a0ff3e575c3d24064afe12a17c28..fd8e65b26f5f9c60cf54edc2b06ba5553f39731f 100644 (file)
@@ -75,7 +75,7 @@ describe('Collection panel tests', function () {
         });
     });
 
-    it('uses the property editor with vocabulary terms', function () {
+    it('uses the property editor (from edit dialog) with vocabulary terms', function () {
         cy.createCollection(adminUser.token, {
             name: `Test collection ${Math.floor(Math.random() * 999999)}`,
             owner_uuid: activeUser.user.uuid,
@@ -85,6 +85,14 @@ describe('Collection panel tests', function () {
                 cy.loginAs(activeUser);
                 cy.goToPath(`/collections/${this.testCollection.uuid}`);
 
+                cy.get('[data-cy=collection-info-panel')
+                    .should('contain', this.testCollection.name)
+                    .and('not.contain', 'Color: Magenta');
+
+                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', 'Properties');
+
                 // Key: Color (IDTAGCOLORS) - Value: Magenta (IDVALCOLORS3)
                 cy.get('[data-cy=resource-properties-form]').within(() => {
                     cy.get('[data-cy=property-field-key]').within(() => {
@@ -96,15 +104,91 @@ describe('Collection panel tests', function () {
                     cy.root().submit();
                 });
                 // Confirm proper vocabulary labels are displayed on the UI.
-                cy.get('[data-cy=collection-properties-panel]')
-                    .should('contain', 'Color')
-                    .and('contain', 'Magenta');
+                cy.get('[data-cy=form-dialog]').should('contain', 'Color: Magenta');
+                cy.get('[data-cy=form-dialog]').contains('Save').click();
+                cy.get('[data-cy=form-dialog]').should('not.exist');
                 // Confirm proper vocabulary IDs were saved on the backend.
                 cy.doRequest('GET', `/arvados/v1/collections/${this.testCollection.uuid}`)
                     .its('body').as('collection')
                     .then(function () {
                         expect(this.collection.properties.IDTAGCOLORS).to.equal('IDVALCOLORS3');
                     });
+                // Confirm the property is displayed on the UI.
+                cy.get('[data-cy=collection-info-panel')
+                    .should('contain', this.testCollection.name)
+                    .and('contain', 'Color: Magenta');
+            });
+    });
+
+    it('uses the editor (from details panel) with vocabulary terms', 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('testCollection').then(function () {
+                cy.loginAs(activeUser);
+                cy.goToPath(`/collections/${this.testCollection.uuid}`);
+
+                cy.get('[data-cy=collection-info-panel')
+                    .should('contain', this.testCollection.name)
+                    .and('not.contain', 'Color: Magenta')
+                    .and('not.contain', 'Size: S');
+                cy.get('[data-cy=additional-info-icon]').click();
+
+                cy.get('[data-cy=details-panel]').within(() => {
+                    cy.get('[data-cy=details-panel-edit-btn]').click();
+                });
+                cy.get('[data-cy=form-dialog').contains('Edit Collection');
+
+                // Key: Color (IDTAGCOLORS) - Value: Magenta (IDVALCOLORS3)
+                cy.get('[data-cy=resource-properties-form]').within(() => {
+                    cy.get('[data-cy=property-field-key]').within(() => {
+                        cy.get('input').type('Color');
+                    });
+                    cy.get('[data-cy=property-field-value]').within(() => {
+                        cy.get('input').type('Magenta');
+                    });
+                    cy.root().submit();
+                });
+                // Confirm proper vocabulary labels are displayed on the UI.
+                cy.get('[data-cy=form-dialog]')
+                    .should('contain', 'Color: Magenta');
+
+                // Case-insensitive on-blur auto-selection test
+                // Key: Size (IDTAGSIZES) - Value: Small (IDVALSIZES2)
+                cy.get('[data-cy=resource-properties-form]').within(() => {
+                    cy.get('[data-cy=property-field-key]').within(() => {
+                        cy.get('input').type('sIzE');
+                    });
+                    cy.get('[data-cy=property-field-value]').within(() => {
+                        cy.get('input').type('sMaLL');
+                    });
+                    // Cannot "type()" TAB on Cypress so let's click another field
+                    // to trigger the onBlur event.
+                    cy.get('[data-cy=property-field-key]').click();
+                    cy.root().submit();
+                });
+                // Confirm proper vocabulary labels are displayed on the UI.
+                cy.get('[data-cy=form-dialog]')
+                    .should('contain', 'Size: S');
+
+                cy.get('[data-cy=form-dialog]').contains('Save').click();
+                cy.get('[data-cy=form-dialog]').should('not.exist');
+
+                // Confirm proper vocabulary IDs were saved on the backend.
+                cy.doRequest('GET', `/arvados/v1/collections/${this.testCollection.uuid}`)
+                    .its('body').as('collection')
+                    .then(function () {
+                        expect(this.collection.properties.IDTAGCOLORS).to.equal('IDVALCOLORS3');
+                        expect(this.collection.properties.IDTAGSIZES).to.equal('IDVALSIZES2');
+                    });
+
+                // Confirm properties display on the UI.
+                cy.get('[data-cy=collection-info-panel')
+                    .should('contain', this.testCollection.name)
+                    .and('contain', 'Color: Magenta')
+                    .and('contain', 'Size: S');
             });
     });
 
@@ -122,12 +206,22 @@ describe('Collection panel tests', function () {
             }).as('sharedGroup').then(function () {
                 // Creates the collection using the admin token so we can set up
                 // a bogus manifest text without block signatures.
-                cy.createCollection(adminUser.token, {
-                    name: 'Test collection',
-                    owner_uuid: this.sharedGroup.uuid,
-                    properties: { someKey: 'someValue' },
-                    manifest_text: `. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n./${subDirName} 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n`
-                })
+                cy.doRequest('GET', '/arvados/v1/config', null, null)
+                    .its('body').should((clusterConfig) => {
+                      expect(clusterConfig.Collections, "clusterConfig").to.have.property("TrustAllContent", false);
+                      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 !== ""
+                          ? clusterConfig.Services.WebDAV.ExternalURL
+                          : clusterConfig.Services.WebDAVDownload.ExternalURL;
+                      expect(inlineUrl).to.not.contain("*");
+                    })
+                    .createCollection(adminUser.token, {
+                      name: 'Test collection',
+                      owner_uuid: this.sharedGroup.uuid,
+                      properties: { someKey: 'someValue' },
+                      manifest_text: `. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n./${subDirName} 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n`
+                    })
                     .as('testCollection').then(function () {
                         // Share the group with active user.
                         cy.createLink(adminUser.token, {
@@ -153,33 +247,13 @@ describe('Collection panel tests', function () {
                             .should('contain', 'Add to favorites')
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Edit collection');
                         cy.get('body').click(); // Collapse the menu avoiding details panel expansion
-                        cy.get('[data-cy=collection-properties-panel]')
-                            .should('contain', 'someKey')
-                            .and('contain', 'someValue')
-                            .and('not.contain', 'anotherKey')
-                            .and('not.contain', 'anotherValue')
-                        if (isWritable === true) {
-                            // Check that properties can be added.
-                            cy.get('[data-cy=resource-properties-form]').within(() => {
-                                cy.get('[data-cy=property-field-key]').within(() => {
-                                    cy.get('input').type('anotherKey');
-                                });
-                                cy.get('[data-cy=property-field-value]').within(() => {
-                                    cy.get('input').type('anotherValue');
-                                });
-                                cy.root().submit();
-                            })
-                            cy.get('[data-cy=collection-properties-panel]')
-                                .should('contain', 'anotherKey')
-                                .and('contain', 'anotherValue')
-                        } else {
-                            // Properties form shouldn't be displayed.
-                            cy.get('[data-cy=resource-properties-form]').should('not.exist');
-                        }
+                        cy.get('[data-cy=collection-info-panel]')
+                            .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');
@@ -187,23 +261,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('contain', 'Open in new tab')
+                            .and('not.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('contain', 'Open in new tab')
+                            .and('not.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()
@@ -260,7 +341,7 @@ describe('Collection panel tests', function () {
                     'bar' // make sure we can go back to the original name as a last step
                 ];
                 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')
@@ -280,63 +361,6 @@ describe('Collection panel tests', function () {
             });
     });
 
-    it.skip('renames a file to a different directory', function () {
-        // Creates the collection using the admin token so we can set up
-        // a bogus manifest text without block signatures.
-        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(function () {
-                cy.loginAs(activeUser);
-                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.get('[data-cy=context-menu]')
-                        .contains('Rename')
-                        .click();
-                    cy.get('[data-cy=form-dialog]')
-                        .should('contain', 'Rename')
-                        .within(() => {
-                            cy.get('input').type(`{selectall}{backspace}${subdir}/foo`);
-                        });
-                    cy.get('[data-cy=form-submit-btn]').click();
-                    cy.get('[data-cy=collection-files-panel]')
-                        .should('not.contain', 'bar')
-                        .and('contain', subdir);
-                    // Look for the "arrow icon" and expand the "subdir" directory.
-                    cy.get('[data-cy=virtual-file-tree] > div > i').click();
-                    // Rename 'subdir/foo' to 'foo'
-                    cy.get('[data-cy=collection-files-panel]')
-                        .contains('foo').rightclick();
-                    cy.get('[data-cy=context-menu]')
-                        .contains('Rename')
-                        .click();
-                    cy.get('[data-cy=form-dialog]')
-                        .should('contain', 'Rename')
-                        .within(() => {
-                            cy.get('input')
-                                .should('have.value', `${subdir}/foo`)
-                                .type(`{selectall}{backspace}bar`);
-                        });
-                    cy.get('[data-cy=form-submit-btn]').click();
-                    cy.get('[data-cy=collection-files-panel]')
-                        .should('contain', subdir) // empty dir kept
-                        .and('contain', 'bar');
-
-                    cy.get('[data-cy=collection-files-panel]')
-                        .contains(subdir).rightclick();
-                    cy.get('[data-cy=context-menu]')
-                        .contains('Remove')
-                        .click();
-                    cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
-                });
-            });
-    });
-
     it('renames a file to a different directory', function () {
         // Creates the collection using the admin token so we can set up
         // a bogus manifest text without block signatures.
@@ -351,7 +375,7 @@ describe('Collection panel tests', function () {
 
                 ['subdir', 'G%C3%BCnter\'s%20file', 'table%&?*2'].forEach((subdir) => {
                     cy.get('[data-cy=collection-files-panel]')
-                        .contains('bar').rightclick({force: true});
+                        .contains('bar').rightclick();
                     cy.get('[data-cy=context-menu]')
                         .contains('Rename')
                         .click();
@@ -364,9 +388,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();
@@ -382,7 +406,6 @@ describe('Collection panel tests', function () {
                         });
                     cy.get('[data-cy=form-submit-btn]').click();
 
-                    cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]')
                         .contains('Home')
                         .click();
@@ -402,6 +425,20 @@ describe('Collection panel tests', function () {
             });
     });
 
+    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.
@@ -562,6 +599,114 @@ describe('Collection panel tests', function () {
         })
     });
 
+    it('moves a collection to a different project', function () {
+        const collName = `Test Collection ${Math.floor(Math.random() * 999999)}`;
+        const projName = `Test Project ${Math.floor(Math.random() * 999999)}`;
+        const fileName = `Test_File_${Math.floor(Math.random() * 999999)}`;
+
+        cy.createCollection(adminUser.token, {
+            name: collName,
+            owner_uuid: activeUser.user.uuid,
+            manifest_text: `. 37b51d194a7513e45b56f6524f2d51f2+3 0:3:${fileName}\n`,
+        }).as('testCollection');
+        cy.createGroup(adminUser.token, {
+            name: projName,
+            group_class: 'project',
+            owner_uuid: activeUser.user.uuid,
+        }).as('testProject');
+
+        cy.getAll('@testCollection', '@testProject')
+            .then(function ([testCollection, testProject]) {
+                cy.loginAs(activeUser);
+                cy.goToPath(`/collections/${testCollection.uuid}`);
+                cy.get('[data-cy=collection-files-panel]').should('contain', fileName);
+                cy.get('[data-cy=collection-info-panel]')
+                    .should('not.contain', projName)
+                    .and('not.contain', testProject.uuid);
+                cy.get('[data-cy=collection-panel-options-btn]').click();
+                cy.get('[data-cy=context-menu]').contains('Move to').click();
+                cy.get('[data-cy=form-dialog]')
+                    .should('contain', 'Move to')
+                    .within(() => {
+                        cy.get('[data-cy=projects-tree-home-tree-picker]')
+                            .find('i')
+                            .click();
+                        cy.get('[data-cy=projects-tree-home-tree-picker]')
+                            .contains(projName)
+                            .click();
+                    });
+                cy.get('[data-cy=form-submit-btn]').click();
+                cy.get('[data-cy=snackbar]')
+                    .contains('Collection has been moved')
+                cy.get('[data-cy=collection-info-panel]')
+                    .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);
+            });
+    });
+
+    it('automatically updates the collection UI contents without using the Refresh button', function () {
+        const collName = `Test Collection ${Math.floor(Math.random() * 999999)}`;
+        const fileName = 'foobar'
+
+        cy.createCollection(adminUser.token, {
+            name: collName,
+            owner_uuid: activeUser.user.uuid,
+        }).as('testCollection');
+
+        cy.getAll('@testCollection').then(function ([testCollection]) {
+            cy.loginAs(activeUser);
+            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', fileName);
+            cy.get('[data-cy=collection-info-panel]').should('contain', collName);
+
+            cy.updateCollection(adminUser.token, testCollection.uuid, {
+                name: `${collName + ' updated'}`,
+                manifest_text: `. 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);
+                cy.get('[data-cy=collection-files-panel]').should('contain', fileName);
+            });
+        });
+    })
+
+    it('makes a copy of an existing collection', function() {
+        const collName = `Test Collection ${Math.floor(Math.random() * 999999)}`;
+        const copyName = `Copy of: ${collName}`;
+
+        cy.createCollection(adminUser.token, {
+            name: collName,
+            owner_uuid: activeUser.user.uuid,
+            manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:some-file\n",
+        }).as('collection').then(function () {
+            cy.loginAs(activeUser)
+            cy.goToPath(`/collections/${this.collection.uuid}`);
+            cy.get('[data-cy=collection-files-panel]')
+                .should('contain', 'some-file');
+            cy.get('[data-cy=collection-panel-options-btn]').click();
+            cy.get('[data-cy=context-menu]').contains('Make a copy').click();
+            cy.get('[data-cy=form-dialog]')
+                .should('contain', 'Make a copy')
+                .within(() => {
+                    cy.get('[data-cy=projects-tree-home-tree-picker]')
+                        .contains('Projects')
+                        .click();
+                    cy.get('[data-cy=form-submit-btn]').click();
+                });
+            cy.get('[data-cy=snackbar]')
+                .contains('Collection has been copied.')
+            cy.get('[data-cy=snackbar-goto-action]').click();
+            cy.get('[data-cy=project-panel]')
+                .contains(copyName).click();
+            cy.get('[data-cy=collection-files-panel]')
+                .should('contain', 'some-file');
+        });
+    });
+
     it('uses the collection version browser to view a previous version', function () {
         const colName = `Test Collection ${Math.floor(Math.random() * 999999)}`;
 
@@ -694,7 +839,36 @@ describe('Collection panel tests', function () {
             });
     });
 
-    it('creates new collection on home project', function () {
+    it('creates collection from selected files of another 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('Create a new collection with selected').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}`).should('exist');
+            });
+    });
+
+    it('creates new collection with properties on home project', function () {
         cy.loginAs(activeUser);
         cy.goToPath(`/projects/${activeUser.user.uuid}`);
         cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
@@ -704,6 +878,8 @@ describe('Collection panel tests', function () {
         cy.get('[data-cy=side-panel-new-collection]').click();
         // Name between brackets tests bugfix #17582
         const collName = `[Test collection (${Math.floor(999999 * Math.random())})]`;
+
+        // Select a storage class.
         cy.get('[data-cy=form-dialog]')
             .should('contain', 'New collection')
             .and('contain', 'Storage classes')
@@ -719,15 +895,42 @@ describe('Collection panel tests', function () {
                 });
                 cy.get('[data-cy=checkbox-foo]').click();
             })
+
+        // Add a property.
+        // Key: Color (IDTAGCOLORS) - Value: Magenta (IDVALCOLORS3)
+        cy.get('[data-cy=form-dialog]').should('not.contain', 'Color: Magenta');
+        cy.get('[data-cy=resource-properties-form]').within(() => {
+            cy.get('[data-cy=property-field-key]').within(() => {
+                cy.get('input').type('Color');
+            });
+            cy.get('[data-cy=property-field-value]').within(() => {
+                cy.get('input').type('Magenta');
+            });
+            cy.root().submit();
+        });
+        // Confirm proper vocabulary labels are displayed on the UI.
+        cy.get('[data-cy=form-dialog]').should('contain', 'Color: Magenta');
+
         cy.get('[data-cy=form-submit-btn]').click();
-        // Confirm that the user was taken to the newly created thing
+        // Confirm that the user was taken to the newly created collection
         cy.get('[data-cy=form-dialog]').should('not.exist');
         cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
         cy.get('[data-cy=breadcrumb-last]').should('contain', collName);
         cy.get('[data-cy=collection-info-panel]')
             .should('contain', 'default')
             .and('contain', 'foo')
+            .and('contain', 'Color: Magenta')
             .and('not.contain', 'bar');
+        // Confirm that the collection's properties has the real values.
+        cy.doRequest('GET', '/arvados/v1/collections', null, {
+            filters: `[["name", "=", "${collName}"]]`,
+        })
+        .its('body.items').as('collections')
+        .then(function() {
+            expect(this.collections).to.have.lengthOf(1);
+            expect(this.collections[0].properties).to.have.property(
+                'IDTAGCOLORS', 'IDVALCOLORS3');
+        });
     });
 
     it('shows responsible person for collection if available', () => {
@@ -735,17 +938,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]) {
@@ -760,4 +961,137 @@ describe('Collection panel tests', function () {
                     .contains(adminUser.user.uuid);
             });
     });
+
+    describe('file upload', () => {
+        beforeEach(() => {
+            cy.createCollection(adminUser.token, {
+                name: `Test collection ${Math.floor(Math.random() * 999999)}`,
+                owner_uuid: activeUser.user.uuid,
+                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.get('[data-cy=form-submit-btn]').should('not.exist');
+                            cy.get('[data-cy=collection-files-right-panel]')
+                                 .contains('5mb_b.bin').should('exist');
+                        });
+                    });
+                });
+        });
+
+        it('allows to cancel running upload', () => {
+            cy.getAll('@testCollection1')
+                .then(function([testCollection1]) {
+                    cy.loginAs(activeUser);
+
+                    cy.goToPath(`/collections/${testCollection1.uuid}`);
+
+                    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_a.bin');
+                        cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_b.bin');
+
+                        cy.get('[data-cy=form-submit-btn]').click();
+
+                        cy.get('button').contains('Cancel').click();
+
+                        cy.get('[data-cy=form-submit-btn]').should('not.exist');
+                    });
+                });
+        });
+
+        it('allows to cancel single file from the running upload', () => {
+            cy.getAll('@testCollection1')
+                .then(function([testCollection1]) {
+                    cy.loginAs(activeUser);
+
+                    cy.goToPath(`/collections/${testCollection1.uuid}`);
+
+                    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_a.bin');
+                        cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_b.bin');
+
+                        cy.get('[data-cy=form-submit-btn]').click();
+
+                        cy.get('button[aria-label=Remove]').eq(1).click();
+
+                        cy.get('[data-cy=form-submit-btn]').should('not.exist');
+
+                        cy.get('[data-cy=collection-files-panel]').contains('5mb_a.bin').should('exist');
+                    });
+                });
+        });
+
+        it('allows to cancel all files from the running upload', () => {
+            cy.getAll('@testCollection1')
+                .then(function([testCollection1]) {
+                    cy.loginAs(activeUser);
+
+                    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 => {
+                        cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_a.bin');
+                        cy.get('[data-cy=drag-and-drop]').upload(content, '5mb_b.bin');
+
+                        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('[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');
+                    });
+                });
+        });
+    });
 })