Sfoglia il codice sorgente

Add support for Cypress 'Run All Tests'

Made the login process programmatically using Cypress Request API
instead of using the UI, thus allowing the tests to run sequentially
automatically instead of manually running them one after the other.

NOTE: A new parameter has been added to `private/cypress/config.js`:
`coriolisUrl`, since Cypress now needs to know the Coriolis URL in order
to be able to login with its API. The `config.template.js` has been
updated to reflect this.
Sergiu Miclea 8 anni fa
parent
commit
d300b4413a
23 ha cambiato i file con 127 aggiunte e 105 eliminazioni
  1. 3 3
      cypress.json
  2. 1 0
      private/cypress/config.template.js
  3. 1 1
      private/cypress/integration/login/Invalid Login.js
  4. 2 5
      private/cypress/integration/migration/1 - Create Openstack Endpoint.js
  5. 2 6
      private/cypress/integration/migration/2 - Create VmWare Endpoint.js
  6. 2 5
      private/cypress/integration/migration/3 - Create VmWare Openstack Migration.js
  7. 3 7
      private/cypress/integration/migration/4 - Cancel first running migration.js
  8. 2 7
      private/cypress/integration/migration/6 - Delete first migration.js
  9. 2 5
      private/cypress/integration/migration/7 - Delete e2e Openstack endpoint.js
  10. 2 5
      private/cypress/integration/migration/8 - Delete e2e VmWare endpoint.js
  11. 2 5
      private/cypress/integration/replica/1 - Create Azure Endpoint.js
  12. 2 6
      private/cypress/integration/replica/2 - Create VmWare Endpoint.js
  13. 9 9
      private/cypress/integration/replica/3 - Create VmWare Azure Replica.js
  14. 3 7
      private/cypress/integration/replica/4 - Cancel first running replica.js
  15. 2 7
      private/cypress/integration/replica/5 - Cannot delete used endpoint.js
  16. 2 7
      private/cypress/integration/replica/6 - Delete first replica.js
  17. 2 5
      private/cypress/integration/replica/7 - Delete e2e Azure endpoint.js
  18. 2 5
      private/cypress/integration/replica/8 - Delete e2e VmWare endpoint.js
  19. 3 8
      private/cypress/integration/scheduler/Scheduler Operations.js
  20. 73 0
      private/cypress/support/commands.js
  21. 2 0
      private/cypress/support/index.js
  22. 4 1
      src/components/atoms/StatusPill/index.jsx
  23. 1 1
      src/components/organisms/DetailsContentHeader/index.jsx

+ 3 - 3
cypress.json

@@ -4,10 +4,10 @@
   "integrationFolder": "private/cypress/integration",
   "pluginsFile": false,
   "screenshotsFolder": "private/cypress/screenshots",
-  "supportFile": false,
   "videosFolder": "private/cypress/videos",
+  "supportFile": "private/cypress/support/index.js",
   "viewportWidth": 1280,
   "viewportHeight": 660,
-  "defaultCommandTimeout":	7000,
+  "defaultCommandTimeout": 7000,
   "execTimeout": 90000
-}
+}

+ 1 - 0
private/cypress/config.template.js

@@ -2,6 +2,7 @@
 
 export default {
   nodeServer: 'http://localhost:3000/',
+  coriolisUrl: '',
   username: 'admin',
   password: '',
   endpoints: {

+ 1 - 1
private/cypress/integration/login/Invalid Login.js

@@ -5,7 +5,7 @@ import config from '../../config'
 
 declare var cy: any
 
-describe('Coriolis Login', () => {
+describe('Coriolis Login Failed', () => {
   it('Displays incorrect password', () => {
     cy.server()
     cy.route({ url: '**/identity/**', method: 'POST' }).as('login')

+ 2 - 5
private/cypress/integration/migration/1 - Create Openstack Endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Create Openstack Endpoint', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows new Openstack endpoint dialog', () => {

+ 2 - 6
private/cypress/integration/migration/2 - Create VmWare Endpoint.js

@@ -5,15 +5,11 @@ import config from '../../config'
 
 describe('Create VmWare Endpoint', () => {
   before(() => {
-    cy.server()
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows new VmWare endpoint dialog', () => {

+ 2 - 5
private/cypress/integration/migration/3 - Create VmWare Openstack Migration.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Create VmWare to Openstack Migration', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows Wizard page', () => {

+ 3 - 7
private/cypress/integration/migration/4 - Cancel first running migration.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
 describe('Cancel a running migration', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Cancels migration', () => {
@@ -25,5 +20,6 @@ describe('Cancel a running migration', () => {
     cy.route({ url: '**/actions', method: 'POST' }).as('cancel')
     cy.get('button').contains('Yes').click()
     cy.wait('@cancel')
+    cy.get('div[data-test-id="mainStatusPill-ERROR"]', { timeout: 120000 })
   })
 })

+ 2 - 7
private/cypress/integration/migration/6 - Delete first migration.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
 describe('Delete the first migration', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Deletes migration', () => {

+ 2 - 5
private/cypress/integration/migration/7 - Delete e2e Openstack endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Delete the Openstack endpoint created for e2e testing', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Goes to endpoints page', () => {

+ 2 - 5
private/cypress/integration/migration/8 - Delete e2e VmWare endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Delete the VmWare endpoint created for e2e testing', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Goes to endpoints page', () => {

+ 2 - 5
private/cypress/integration/replica/1 - Create Azure Endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Create Azure Endpoint', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows new Azure endpoint dialog', () => {

+ 2 - 6
private/cypress/integration/replica/2 - Create VmWare Endpoint.js

@@ -5,15 +5,11 @@ import config from '../../config'
 
 describe('Create VmWare Endpoint', () => {
   before(() => {
-    cy.server()
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows new VmWare endpoint dialog', () => {

+ 9 - 9
private/cypress/integration/replica/3 - Create VmWare Azure Replica.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Create VmWare to Azure Replica', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Shows Wizard page', () => {
@@ -49,10 +46,13 @@ describe('Create VmWare to Azure Replica', () => {
 
   it('Fills Azure replica info', () => {
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="dropdown-location"]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.azure.location.label).click()
-    cy.get('div[data-test-id="dropdown-resource_group"]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.azure.resourceGroup.label).click()
+    cy.get('input[placeholder="Location"]').type(config.wizard.azure.location.value)
+    cy.get('input[placeholder="Resource Group"]').type(config.wizard.azure.resourceGroup.value)
+
+    // cy.get('div[data-test-id="dropdown-location"]').first().click()
+    // cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.azure.location.label).click()
+    // cy.get('div[data-test-id="dropdown-resource_group"]').first().click()
+    // cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.azure.resourceGroup.label).click()
   })
 
   it('Selects first available network mapping', () => {

+ 3 - 7
private/cypress/integration/replica/4 - Cancel first running replica.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
 describe('Cancel a running replica', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Cancels replica execution', () => {
@@ -23,5 +18,6 @@ describe('Cancel a running replica', () => {
     cy.route({ url: '**/actions', method: 'POST' }).as('cancel')
     cy.get('button').contains('Yes').click()
     cy.wait('@cancel')
+    cy.get('div[data-test-id="mainStatusPill-ERROR"]', { timeout: 120000 })
   })
 })

+ 2 - 7
private/cypress/integration/replica/5 - Cannot delete used endpoint.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
 describe('Cannot delete used endpoint', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Should show in usage message when trying to delete', () => {

+ 2 - 7
private/cypress/integration/replica/6 - Delete first replica.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
 describe('Delete the first replica', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Delete replica', () => {

+ 2 - 5
private/cypress/integration/replica/7 - Delete e2e Azure endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Delete the Azure endpoint created for e2e testing', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Goes to endpoints page', () => {

+ 2 - 5
private/cypress/integration/replica/8 - Delete e2e VmWare endpoint.js

@@ -5,14 +5,11 @@ import config from '../../config'
 
 describe('Delete the VmWare endpoint created for e2e testing', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Goes to endpoints page', () => {

+ 3 - 8
private/cypress/integration/scheduler/Scheduler Operations.js

@@ -1,18 +1,13 @@
 
 // @flow
 
-import config from '../../config'
-
-describe('Create Azure Endpoint', () => {
+describe('Scheduler Operations', () => {
   before(() => {
-    cy.visit(config.nodeServer)
-    cy.get('input[label="Username"]').type(config.username)
-    cy.get('input[label="Password"]').type(config.password)
-    cy.get('button').click()
+    cy.login()
   })
 
   beforeEach(() => {
-    Cypress.Cookies.preserveOnce('unscopedToken', 'token', 'projectId')
+    Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
   it('Goes to scheduler\'s page', () => {

+ 73 - 0
private/cypress/support/commands.js

@@ -0,0 +1,73 @@
+// @flow
+
+import config from '../config.js'
+
+const identityUrl = `${config.coriolisUrl}identity/auth/tokens`
+const projectsUrl = `${config.coriolisUrl}identity/auth/projects`
+
+declare var expect: any
+
+Cypress.Commands.add('login', () => {
+  let unscopedBody = {
+    auth: {
+      identity: {
+        methods: ['password'],
+        password: {
+          user: {
+            name: config.username,
+            domain: { name: 'default' },
+            password: config.password,
+          },
+        },
+      },
+      scope: 'unscoped',
+    },
+  }
+
+  cy.request({
+    method: 'POST',
+    url: identityUrl,
+    body: unscopedBody,
+  }).then(unscopedResponse => {
+    let unscopedToken = unscopedResponse.headers['x-subject-token']
+    expect(unscopedToken).to.exist
+
+    cy.request({
+      method: 'GET',
+      url: projectsUrl,
+      headers: { 'X-Auth-Token': unscopedToken },
+    }).then(projectsReponse => {
+      let projectId = projectsReponse.body.projects[0].id
+      expect(projectId).to.exist
+
+      let scopedBody = {
+        auth: {
+          identity: {
+            methods: ['token'],
+            token: {
+              id: unscopedToken,
+            },
+          },
+          scope: {
+            project: {
+              id: projectId,
+            },
+          },
+        },
+      }
+
+      cy.request({
+        method: 'POST',
+        url: identityUrl,
+        body: scopedBody,
+      }).then(scopedResponse => {
+        let scopedToken = scopedResponse.headers['x-subject-token']
+        expect(scopedToken).to.exist
+
+        cy.setCookie('token', scopedToken)
+        cy.setCookie('projectId', projectId)
+        cy.visit(config.nodeServer)
+      })
+    })
+  })
+})

+ 2 - 0
private/cypress/support/index.js

@@ -0,0 +1,2 @@
+// @flow
+import './commands'

+ 4 - 1
src/components/atoms/StatusPill/index.jsx

@@ -102,6 +102,7 @@ type Props = {
   secondary: boolean,
   alert: boolean,
   small: boolean,
+  'data-test-id': string,
 }
 @observer
 class StatusPill extends React.Component<Props> {
@@ -110,6 +111,8 @@ class StatusPill extends React.Component<Props> {
   }
 
   render() {
+    const dataTestId = this.props['data-test-id'] ? this.props['data-test-id'] : `statusPill-${this.props.status || 'null'}`
+
     return (
       <Wrapper
         {...this.props}
@@ -118,7 +121,7 @@ class StatusPill extends React.Component<Props> {
         secondary={this.props.secondary}
         alert={this.props.alert}
         small={this.props.small}
-        data-test-id={`statusPill-${this.props.status || 'null'}`}
+        data-test-id={dataTestId}
       >
         {this.props.label || this.props.status}
       </Wrapper>

+ 1 - 1
src/components/organisms/DetailsContentHeader/index.jsx

@@ -126,7 +126,7 @@ class DetailsContentHeader extends React.Component<Props> {
           primary={this.props.primaryInfoPill}
         />
         <StatusPill
-          data-test-id={`statusPill-${statusLabel || ''}`}
+          data-test-id={`mainStatusPill-${statusLabel || ''}`}
           status={this.getStatus()}
           label={statusLabel || ''}
         />