17308: Adds project creation with properties integration test.
authorLucas Di Pentima <lucas@di-pentima.com.ar>
Tue, 2 Feb 2021 16:20:17 +0000 (13:20 -0300)
committerLucas Di Pentima <lucas@di-pentima.com.ar>
Tue, 2 Feb 2021 16:20:17 +0000 (13:20 -0300)
Also reorganizes some test cases, and removes code duplication on the create
new project dialog for the property editor form.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas@di-pentima.com.ar>

cypress/integration/collection.spec.js [moved from cypress/integration/collection-panel.spec.js with 93% similarity]
cypress/integration/project.spec.js [new file with mode: 0644]
cypress/integration/side-panel.spec.js
src/views-components/project-properties/create-project-properties-form.tsx
src/views-components/resource-properties-form/resource-properties-form.tsx

similarity index 93%
rename from cypress/integration/collection-panel.spec.js
rename to cypress/integration/collection.spec.js
index 3e241cebbea390a58d164e5e2be93dedfab042c9..67df16ab93ba35ff8cd6a46c0dd245d91bfa1e83 100644 (file)
@@ -38,7 +38,7 @@ describe('Collection panel tests', function() {
             cy.doSearch(`${this.testCollection.uuid}`);
 
             // Key: Color (IDTAGCOLORS) - Value: Magenta (IDVALCOLORS3)
-            cy.get('[data-cy=collection-properties-form]').within(() => {
+            cy.get('[data-cy=resource-properties-form]').within(() => {
                 cy.get('[data-cy=property-field-key]').within(() => {
                     cy.get('input').type('Color');
                 });
@@ -107,7 +107,7 @@ describe('Collection panel tests', function() {
                         .and('not.contain', 'anotherValue')
                     if (isWritable === true) {
                         // Check that properties can be added.
-                        cy.get('[data-cy=collection-properties-form]').within(() => {
+                        cy.get('[data-cy=resource-properties-form]').within(() => {
                             cy.get('[data-cy=property-field-key]').within(() => {
                                 cy.get('input').type('anotherKey');
                             });
@@ -121,7 +121,7 @@ describe('Collection panel tests', function() {
                             .and('contain', 'anotherValue')
                     } else {
                         // Properties form shouldn't be displayed.
-                        cy.get('[data-cy=collection-properties-form]').should('not.exist');
+                        cy.get('[data-cy=resource-properties-form]').should('not.exist');
                     }
                     // Check that the file listing show both read & write operations
                     cy.get('[data-cy=collection-files-panel]').within(() => {
@@ -468,4 +468,30 @@ describe('Collection panel tests', function() {
                 .should('contain', 'foo').and('contain', 'bar');
         });
     });
+
+    it('creates new collection on home project', function() {
+        cy.loginAs(activeUser);
+        cy.doSearch(`${activeUser.user.uuid}`);
+        cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
+        cy.get('[data-cy=breadcrumb-last]').should('not.exist');
+        // Create new collection
+        cy.get('[data-cy=side-panel-button]').click();
+        cy.get('[data-cy=side-panel-new-collection]').click();
+        const collName = `Test collection (${Math.floor(999999 * Math.random())})`;
+        cy.get('[data-cy=form-dialog]')
+            .should('contain', 'New collection')
+            .within(() => {
+                cy.get('[data-cy=parent-field]').within(() => {
+                    cy.get('input').should('have.value', 'Home project');
+                })
+                cy.get('[data-cy=name-field]').within(() => {
+                    cy.get('input').type(collName);
+                })
+            })
+        cy.get('[data-cy=form-submit-btn]').click();
+        // Confirm that the user was taken to the newly created thing
+        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);
+    });
 })
diff --git a/cypress/integration/project.spec.js b/cypress/integration/project.spec.js
new file mode 100644 (file)
index 0000000..42d26d7
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+describe('Project tests', function() {
+    let activeUser;
+    let adminUser;
+
+    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() {
+                adminUser = this.adminUser;
+            }
+        );
+        cy.getUser('user', 'Active', 'User', false, true)
+            .as('activeUser').then(function() {
+                activeUser = this.activeUser;
+            }
+        );
+    });
+
+    beforeEach(function() {
+        cy.clearCookies();
+        cy.clearLocalStorage();
+    });
+
+    it.only('adds creates a new project with properties', function() {
+        const projName = `Test project (${Math.floor(999999 * Math.random())})`;
+        cy.loginAs(activeUser);
+        cy.get('[data-cy=side-panel-button]').click();
+        cy.get('[data-cy=side-panel-new-project]').click();
+        cy.get('[data-cy=form-dialog]')
+            .should('contain', 'New project')
+            .within(() => {
+                cy.get('[data-cy=name-field]').within(() => {
+                    cy.get('input').type(projName);
+                });
+
+            });
+        // 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');
+
+        // Create project and confirm the properties' real values.
+        cy.get('[data-cy=form-submit-btn]').click();
+        cy.get('[data-cy=breadcrumb-last]').should('contain', projName);
+        cy.doRequest('GET', '/arvados/v1/groups', null, {
+            filters: `[["name", "=", "${projName}"], ["group_class", "=", "project"]]`,
+        })
+        .its('body.items').as('projects')
+        .then(function() {
+            expect(this.projects).to.have.lengthOf(1);
+            expect(this.projects[0].properties).to.deep.equal(
+                {IDTAGCOLORS: 'IDVALCOLORS3'});
+        });
+    });
+
+    it('creates new project on home project and then a subproject inside it', function() {
+        const createProject = function(name, parentName) {
+            cy.get('[data-cy=side-panel-button]').click();
+            cy.get('[data-cy=side-panel-new-project]').click();
+            cy.get('[data-cy=form-dialog]')
+                .should('contain', 'New project')
+                .within(() => {
+                    cy.get('[data-cy=parent-field]').within(() => {
+                        cy.get('input').invoke('val').then((val) => {
+                            expect(val).to.include(parentName);
+                        });
+                    });
+                    cy.get('[data-cy=name-field]').within(() => {
+                        cy.get('input').type(name);
+                    });
+                });
+            cy.get('[data-cy=form-submit-btn]').click();
+        }
+
+        cy.loginAs(activeUser);
+        cy.doSearch(`${activeUser.user.uuid}`);
+        cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
+        cy.get('[data-cy=breadcrumb-last]').should('not.exist');
+        // Create new project
+        const projName = `Test project (${Math.floor(999999 * Math.random())})`;
+        createProject(projName, 'Home project');
+        // Confirm that the user was taken to the newly created thing
+        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', projName);
+        // Create a subproject
+        const subProjName = `Test project (${Math.floor(999999 * Math.random())})`;
+        createProject(subProjName, projName);
+        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', subProjName);
+    });
+})
\ No newline at end of file
index fe9d840010350c216a4d7f1e730f9685544cea55..309037ec58a9536112f62133cb2b46fa84936f69 100644 (file)
@@ -75,68 +75,4 @@ describe('Side panel tests', function() {
                 .and('be.disabled');
         })
     })
-
-    it('creates new collection on home project', function() {
-        cy.loginAs(activeUser);
-        cy.doSearch(`${activeUser.user.uuid}`);
-        cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
-        cy.get('[data-cy=breadcrumb-last]').should('not.exist');
-        // Create new collection
-        cy.get('[data-cy=side-panel-button]').click();
-        cy.get('[data-cy=side-panel-new-collection]').click();
-        const collName = `Test collection (${Math.floor(999999 * Math.random())})`;
-        cy.get('[data-cy=form-dialog]')
-            .should('contain', 'New collection')
-            .within(() => {
-                cy.get('[data-cy=parent-field]').within(() => {
-                    cy.get('input').should('have.value', 'Home project');
-                })
-                cy.get('[data-cy=name-field]').within(() => {
-                    cy.get('input').type(collName);
-                })
-            })
-        cy.get('[data-cy=form-submit-btn]').click();
-        // Confirm that the user was taken to the newly created thing
-        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);
-    })
-
-    it('creates new project on home project and then a subproject inside it', function() {
-        const createProject = function(name, parentName) {
-            cy.get('[data-cy=side-panel-button]').click();
-            cy.get('[data-cy=side-panel-new-project]').click();
-            cy.get('[data-cy=form-dialog]')
-                .should('contain', 'New project')
-                .within(() => {
-                    cy.get('[data-cy=parent-field]').within(() => {
-                        cy.get('input').invoke('val').then((val) => {
-                            expect(val).to.include(parentName);
-                        })
-                    })
-                    cy.get('[data-cy=name-field]').within(() => {
-                        cy.get('input').type(name);
-                    })
-                })
-            cy.get('[data-cy=form-submit-btn]').click();
-        }
-
-        cy.loginAs(activeUser);
-        cy.doSearch(`${activeUser.user.uuid}`);
-        cy.get('[data-cy=breadcrumb-first]').should('contain', 'Projects');
-        cy.get('[data-cy=breadcrumb-last]').should('not.exist');
-        // Create new project
-        const projName = `Test project (${Math.floor(999999 * Math.random())})`;
-        createProject(projName, 'Home project');
-        // Confirm that the user was taken to the newly created thing
-        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', projName);
-        // Create a subproject
-        const subProjName = `Test project (${Math.floor(999999 * Math.random())})`;
-        createProject(subProjName, projName);
-        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', subProjName);
-    })
 })
\ No newline at end of file
index 385afff7684c1ae8cca710422580de008f29c243..648547733409ea4eef8f1e25164cd457f77f326d 100644 (file)
@@ -2,48 +2,26 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from 'react';
-import { reduxForm, reset, InjectedFormProps } from 'redux-form';
-import { PROJECT_CREATE_PROPERTIES_FORM_NAME, addPropertyToCreateProjectForm } from '~/store/projects/project-create-actions';
-import { ResourcePropertiesFormData } from '~/views-components/resource-properties-form/resource-properties-form';
-import { StyleRulesCallback, WithStyles, withStyles, Grid } from '@material-ui/core';
-import { ArvadosTheme } from '~/common/custom-theme';
-import { PropertyKeyField } from '~/views-components/resource-properties-form/property-key-field';
-import { PropertyValueField } from '~/views-components/resource-properties-form/property-value-field';
-import { Button } from '~/views-components/resource-properties-form/resource-properties-form';
+import { reduxForm, reset } from 'redux-form';
+import { withStyles } from '@material-ui/core';
+import {
+    PROJECT_CREATE_PROPERTIES_FORM_NAME,
+    addPropertyToCreateProjectForm
+} from '~/store/projects/project-create-actions';
+import {
+    ResourcePropertiesForm,
+    ResourcePropertiesFormData
+} from '~/views-components/resource-properties-form/resource-properties-form';
 
-type CssRules = 'root';
-
-const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
-    root: {
-        paddingTop: theme.spacing.unit,
-        margin: 0
-    }
-});
-
-type CreateProjectPropertiesFormProps = InjectedFormProps<ResourcePropertiesFormData> & WithStyles<CssRules>;
-
-const Form = withStyles(styles)(
-    ({ handleSubmit, submitting, invalid, classes }: CreateProjectPropertiesFormProps) =>
-        <Grid container spacing={16} className={classes.root}>
-            <Grid item xs={5}>
-                <PropertyKeyField />
-            </Grid>
-            <Grid item xs={5}>
-                <PropertyValueField />
-            </Grid>
-            <Grid item xs={2}>
-                <Button
-                    disabled={invalid}
-                    loading={submitting}
-                    color='primary'
-                    variant='contained'
-                    onClick={handleSubmit}>
-                    Add
-                </Button>
-            </Grid>
-        </Grid>
-);
+const Form = withStyles(
+    ({ spacing }) => (
+        { container:
+            {
+                paddingTop: spacing.unit,
+                margin: 0,
+            }
+        })
+    )(ResourcePropertiesForm);
 
 export const CreateProjectPropertiesForm = reduxForm<ResourcePropertiesFormData>({
     form: PROJECT_CREATE_PROPERTIES_FORM_NAME,
index c8d0959a11f2afec7fd288ee83c8b692a53ef0a7..e8d2fc58e565616e30349d331c1528aad498d53d 100644 (file)
@@ -20,7 +20,7 @@ export interface ResourcePropertiesFormData {
 export type ResourcePropertiesFormProps = InjectedFormProps<ResourcePropertiesFormData> & WithStyles<GridClassKey>;
 
 export const ResourcePropertiesForm = ({ handleSubmit, submitting, invalid, classes }: ResourcePropertiesFormProps ) =>
-    <form data-cy='collection-properties-form' onSubmit={handleSubmit}>
+    <form data-cy='resource-properties-form' onSubmit={handleSubmit}>
         <Grid container spacing={16} classes={classes}>
             <Grid item xs>
                 <PropertyKeyField />