Explorar el Código

Fix and update Cypress End To End tests

All Cypress tests have been refactored and updated to run.
Sergiu Miclea hace 7 años
padre
commit
4629e3c7fa
Se han modificado 28 ficheros con 565 adiciones y 622 borrados
  1. 1 1
      package.json
  2. 13 18
      private/cypress/config.template.js
  3. 1 1
      private/cypress/integration/0 - cleanup/Cleanup.js
  4. 1 3
      private/cypress/integration/1 - login/Invalid Login.js
  5. 6 6
      private/cypress/integration/2 - create endpoints/Create Azure Endpoint.js
  6. 12 11
      private/cypress/integration/2 - create endpoints/Create OCI Endpoint.js
  7. 17 10
      private/cypress/integration/2 - create endpoints/Create Openstack Endpoint.js
  8. 5 5
      private/cypress/integration/2 - create endpoints/Create VmWare Endpoint.js
  9. 9 9
      private/cypress/integration/3 - duplicate endpoints/Duplicate Azure Endpoint.js
  10. 9 9
      private/cypress/integration/3 - duplicate endpoints/Duplicate OCI Endpoint.js
  11. 33 32
      private/cypress/integration/4 - migrations and replicas/Openstack - OCI Migration.js
  12. 35 27
      private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/1 - Create replica.js
  13. 17 22
      private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/2 - Scheduler Operations.js
  14. 2 2
      private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/3 - Delete replica.js
  15. 0 119
      private/cypress/integration/4 - migrations and replicas/VmWare - Openstack Migration.js
  16. 5 7
      private/cypress/integration/5 - delete endpoints/Delete Azure endpoint.js
  17. 5 7
      private/cypress/integration/5 - delete endpoints/Delete OCI endpoint.js
  18. 12 18
      private/cypress/integration/5 - delete endpoints/Delete Openstack and VmWare endpoints.js
  19. 10 23
      private/cypress/integration/6 - users and projects/1 - Create a project.js
  20. 24 37
      private/cypress/integration/6 - users and projects/2 - Add a new user as a member.js
  21. 15 28
      private/cypress/integration/6 - users and projects/3 - Add existing user as a member.js
  22. 13 26
      private/cypress/integration/6 - users and projects/4 - Create a user.js
  23. 13 25
      private/cypress/integration/6 - users and projects/5 - Edit and delete user.js
  24. 13 25
      private/cypress/integration/6 - users and projects/6 - Edit and delete project.js
  25. 17 2
      private/cypress/support/commands.js
  26. 2 1
      src/components/organisms/Navigation/Navigation.jsx
  27. 1 1
      src/components/pages/EndpointDetailsPage/EndpointDetailsPage.jsx
  28. 274 147
      yarn.lock

+ 1 - 1
package.json

@@ -37,7 +37,7 @@
     "@storybook/react": "^3.2.15",
     "babel-eslint": "^8.0.1",
     "babel-jest": "^21.2.0",
-    "cypress": "3.0.3",
+    "cypress": "^3.2.0",
     "enzyme": "^3.9.0",
     "enzyme-adapter-react-16": "^1.11.2",
     "eslint": "^4.8.0",

+ 13 - 18
private/cypress/config.template.js

@@ -18,7 +18,7 @@ export default {
   nodeServer: 'http://localhost:3000/',
   coriolisUrl: '',
   username: 'cypress',
-  password: '',
+  password: 'cypress',
   endpoints: {
     azure: {
       username: '',
@@ -31,14 +31,16 @@ export default {
       host: '',
     },
     openstack: {
-      userDomainName: 'Default',
+      userDomainName: '',
       authUrl: '',
-      projectName: 'admin',
+      projectName: '',
       projectDomainName: '',
       password: '',
-      username: 'admin',
+      username: '',
       glanceApiVersion: 2,
       identityVersion: 3,
+      allowUntrusted: true,
+      allowUntrustedSwift: true,
     },
     oci: {
       privateKeyData: '',
@@ -50,25 +52,18 @@ export default {
   },
   wizard: {
     azure: {
-      resourceGroup: { label: '', value: '' },
-    },
-    openstack: {
-      network: '',
+      resourceGroup: { label: 'Coriolis', value: 'coriolis' },
     },
     oci: {
-      compartment: {
-        label: '', value: '',
-      },
-      migrSubnetId: {
-        label: '', value: '',
-      },
+      compartment: '',
+      migrSubnetId: '',
       availabilityDomain: '',
     },
     instancesSearch: {
-      vmwareSearchText: 'ubuntu 14.04',
-      vmwareItemIndex: 1,
-      ociSearchText: 'ubuntu',
-      ociItemIndex: 0,
+      vmwareSearchText: '',
+      vmwareItemIndex: 0,
+      openstackSearchText: '',
+      openstackItemIndex: 0,
     },
   },
 }

+ 1 - 1
private/cypress/integration/0 - cleanup/Cleanup.js

@@ -24,7 +24,7 @@ describe('Cleaning up Cypress environment', () => {
   })
 
   it('Loaded the UI', () => {
-    cy.get('[data-test-id="navigation-item-replicas"]').should('exist')
+    cy.getById('navigation-item-replicas').should('exist')
     cy.cleanup()
   })
 

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

@@ -16,8 +16,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import config from '../../config'
 
-declare var cy: any
-
 describe('Coriolis Login Failed', () => {
   before(() => {
     cy.logout()
@@ -38,6 +36,6 @@ describe('Coriolis Login Failed', () => {
     cy.get('button').click()
     cy.wait('@login')
 
-    cy.get('#app').should('contain', 'The username or password did not match.')
+    cy.get('#app').should('contain', 'Incorrect credentials.')
   })
 })

+ 6 - 6
private/cypress/integration/2 - create endpoints/Create Azure Endpoint.js

@@ -27,13 +27,13 @@ describe('Create Azure Endpoint', () => {
 
   it('Shows new Azure endpoint dialog', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Endpoint').click()
-    cy.get('div[data-test-id="cProvider-endpointLogo-azure"]').click()
+    cy.getById('newItemDropdown-listItem-Endpoint').click()
+    cy.getById('cProvider-endpointLogo-azure').click()
   })
 
   it('Fills Azure connection info', () => {
     cy.get('input[placeholder="Name"]').type('e2e-azure-test')
-    cy.get('div[data-test-id="endpointField-switch-allow_untrusted"]').click()
+    cy.getById('endpointField-switch-allow_untrusted').click()
     cy.get('input[placeholder="Username"]').type(config.endpoints.azure.username)
     cy.get('input[placeholder="Password"]').type(config.endpoints.azure.password)
     cy.get('input[placeholder="Subscription ID"]').type(config.endpoints.azure.subscriptionId)
@@ -42,11 +42,11 @@ describe('Create Azure Endpoint', () => {
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
     cy.get('button').contains('Validate and save').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="endpointStatus"]').should('contain', 'Endpoint is Valid')
+    cy.getById('endpointStatus').should('contain', 'Endpoint is Valid')
   })
 
   it('Added Endpoint to endpoint list', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test"]').should('contain', 'e2e-azure-test')
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-azure-test').should('contain', 'e2e-azure-test')
   })
 })

+ 12 - 11
private/cypress/integration/2 - create endpoints/Create OCI Endpoint.js

@@ -27,26 +27,27 @@ describe('Create OCI Endpoint', () => {
 
   it('Shows new OCI endpoint dialog', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Endpoint').click()
-    cy.get('div[data-test-id="cProvider-endpointLogo-oci"]').click()
+    cy.getById('newItemDropdown-listItem-Endpoint').click()
+    cy.getById('cProvider-endpointLogo-oci').click()
   })
 
   it('Fills OCI connection info', () => {
-    cy.get('input[data-test-id="endpointField-textInput-name"]').type('e2e-oci-test')
-    cy.get('textarea[data-test-id="endpointField-textArea-private_key_data"]').type(config.endpoints.oci.privateKeyData, { delay: 0 })
-    cy.get('input[data-test-id="endpointField-textInput-region"]').type(config.endpoints.oci.region)
-    cy.get('input[data-test-id="endpointField-textInput-tenancy"]').type(config.endpoints.oci.tenancy)
-    cy.get('input[data-test-id="endpointField-textInput-user"]').type(config.endpoints.oci.user)
-    cy.get('input[data-test-id="endpointField-textInput-private_key_passphrase"]').type(config.endpoints.oci.privateKeyPassphrase)
+    cy.getById('endpointField-textInput-name', 'input').type('e2e-oci-test')
+    cy.getById('endpointField-textArea-private_key_data', 'textarea')
+      .type(config.endpoints.oci.privateKeyData, { delay: 0 })
+    cy.getById('endpointField-textInput-region', 'input').type(config.endpoints.oci.region)
+    cy.getById('endpointField-textInput-tenancy', 'input').type(config.endpoints.oci.tenancy)
+    cy.getById('endpointField-textInput-user', 'input').type(config.endpoints.oci.user)
+    cy.getById('endpointField-textInput-private_key_passphrase', 'input').type(config.endpoints.oci.privateKeyPassphrase)
     cy.server()
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
     cy.get('button').contains('Validate and save').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="endpointStatus"]').should('contain', 'Endpoint is Valid')
+    cy.getById('endpointStatus').should('contain', 'Endpoint is Valid')
   })
 
   it('Added Endpoint to endpoint list', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-oci-test"]').should('contain', 'e2e-oci-test')
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-oci-test').should('contain', 'e2e-oci-test')
   })
 })

+ 17 - 10
private/cypress/integration/2 - create endpoints/Create Openstack Endpoint.js

@@ -27,8 +27,8 @@ describe('Create Openstack Endpoint', () => {
 
   it('Shows new Openstack endpoint dialog', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Endpoint').click()
-    cy.get('div[data-test-id="cProvider-endpointLogo-openstack"]').click()
+    cy.getById('newItemDropdown-listItem-Endpoint').click()
+    cy.getById('cProvider-endpointLogo-openstack').click()
   })
 
   it('Fills Openstack connection info', () => {
@@ -36,24 +36,31 @@ describe('Create Openstack Endpoint', () => {
     cy.get('input[placeholder="Name"]').type('e2e-openstack-test')
     cy.get('input[placeholder="Username"]').type(config.endpoints.openstack.username)
     cy.get('input[placeholder="Password"]').type(config.endpoints.openstack.password)
-    cy.get('input[placeholder="Auth URL"]').type(config.endpoints.openstack.authUrl)
+    cy.get('input[placeholder="Authentication URL"]').type(config.endpoints.openstack.authUrl)
     cy.get('input[placeholder="Project Name"]').type(config.endpoints.openstack.projectName)
-    cy.get('div[data-test-id="endpointField-dropdown-glance_api_version"]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('2').click()
-    cy.get('div[data-test-id="endpointField-dropdown-identity_api_version"]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('3').click()
+    cy.getById('endpointField-dropdown-glance_api_version').first().click()
+    cy.getById('dropdownListItem').contains('2').click()
+    cy.getById('endpointField-dropdown-identity_api_version').first().click()
+    cy.getById('dropdownListItem').contains('3').click()
     cy.get('input[placeholder="Project Domain Name"]').type(config.endpoints.openstack.projectDomainName)
     cy.get('input[placeholder="User Domain Name"]').type(config.endpoints.openstack.userDomainName)
 
+    if (config.endpoints.openstack.allowUntrusted) {
+      cy.getById('endpointField-switch-allow_untrusted').click()
+    }
+    if (config.endpoints.openstack.allowUntrustedSwift) {
+      cy.getById('endpointField-switch-allow_untrusted_swift').click()
+    }
+
     cy.server()
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
     cy.get('button').contains('Validate and save').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="endpointStatus"]').should('contain', 'Endpoint is Valid')
+    cy.getById('endpointStatus').should('contain', 'Endpoint is Valid')
   })
 
   it('Added Openstack to endpoint list', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-openstack-test"]').should('contain', 'e2e-openstack-test')
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-openstack-test').should('contain', 'e2e-openstack-test')
   })
 })

+ 5 - 5
private/cypress/integration/2 - create endpoints/Create VmWare Endpoint.js

@@ -27,8 +27,8 @@ describe('Create VmWare Endpoint', () => {
 
   it('Shows new VmWare endpoint dialog', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Endpoint').click()
-    cy.get('div[data-test-id="cProvider-endpointLogo-vmware_vsphere"]').click()
+    cy.getById('newItemDropdown-listItem-Endpoint').click()
+    cy.getById('cProvider-endpointLogo-vmware_vsphere').click()
   })
 
   it('Fills VmWare connection info', () => {
@@ -41,11 +41,11 @@ describe('Create VmWare Endpoint', () => {
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
     cy.get('button').contains('Validate and save').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="endpointStatus"]').should('contain', 'Endpoint is Valid')
+    cy.getById('endpointStatus').should('contain', 'Endpoint is Valid')
   })
 
   it('Added Endpoint to endpoint list', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-vmware-test"]').should('contain', 'e2e-vmware-test')
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-vmware-test').should('contain', 'e2e-vmware-test')
   })
 })

+ 9 - 9
private/cypress/integration/3 - duplicate endpoints/Duplicate Azure Endpoint.js

@@ -24,11 +24,11 @@ describe('Duplicate Azure Endpoint', () => {
   })
 
   it('Creates duplicate', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test"]').should('contain', 'e2e-azure-test')
-    cy.get('div[data-test-id="endpointListItem-checkbox-e2e-azure-test"]').click()
-    cy.get('div[data-test-id="dropdown-dropdownButton"]').contains('Select an action').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('Duplicate').click()
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-azure-test').should('contain', 'e2e-azure-test')
+    cy.getById('endpointListItem-checkbox-e2e-azure-test').click()
+    cy.getById('dropdown-dropdownButton').contains('Select an action').click()
+    cy.getById('dropdownListItem').contains('Duplicate').click()
     cy.server()
     cy.route({ url: '**/endpoints', method: 'POST' }).as('duplicate')
     cy.get('button').contains('Duplicate').click()
@@ -39,9 +39,9 @@ describe('Duplicate Azure Endpoint', () => {
     cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test (copy)"').click()
     cy.server()
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
-    cy.get('button[data-test-id="edContent-validateButton"]').click()
+    cy.getById('edContent-validateButton').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="eValidation-title"]').should('contain', 'Endpoint is Valid')
+    cy.getById('eValidation-title').should('contain', 'Endpoint is Valid')
     cy.get('button').contains('Dismiss').click()
   })
 
@@ -49,10 +49,10 @@ describe('Duplicate Azure Endpoint', () => {
     cy.server()
     cy.route({ url: '**/replicas/detail', method: 'GET' }).as('replicas')
     cy.route({ url: '**/migrations/detail', method: 'GET' }).as('migrations')
-    cy.get('button[data-test-id="edContent-deleteButton"]').click()
+    cy.getById('edContent-deleteButton').click()
     cy.wait(['@replicas', '@migrations'])
     cy.route({ url: '**/secrets/**', method: 'DELETE' }).as('delete')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@delete')
   })
 })

+ 9 - 9
private/cypress/integration/3 - duplicate endpoints/Duplicate OCI Endpoint.js

@@ -24,11 +24,11 @@ describe('Duplicate OCI Endpoint', () => {
   })
 
   it('Creates duplicate', () => {
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-oci-test"]').should('contain', 'e2e-oci-test')
-    cy.get('div[data-test-id="endpointListItem-checkbox-e2e-oci-test"]').click()
-    cy.get('div[data-test-id="dropdown-dropdownButton"]').contains('Select an action').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('Duplicate').click()
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-oci-test').should('contain', 'e2e-oci-test')
+    cy.getById('endpointListItem-checkbox-e2e-oci-test').click()
+    cy.getById('dropdown-dropdownButton').contains('Select an action').click()
+    cy.getById('dropdownListItem').contains('Duplicate').click()
     cy.server()
     cy.route({ url: '**/endpoints', method: 'POST' }).as('duplicate')
     cy.get('button').contains('Duplicate').click()
@@ -39,9 +39,9 @@ describe('Duplicate OCI Endpoint', () => {
     cy.get('div[data-test-id="endpointListItem-content-e2e-oci-test (copy)"').click()
     cy.server()
     cy.route({ url: '**/actions', method: 'POST' }).as('validate')
-    cy.get('button[data-test-id="edContent-validateButton"]').click()
+    cy.getById('edContent-validateButton').click()
     cy.wait('@validate')
-    cy.get('div[data-test-id="eValidation-title"]').should('contain', 'Endpoint is Valid')
+    cy.getById('eValidation-title').should('contain', 'Endpoint is Valid')
     cy.get('button').contains('Dismiss').click()
   })
 
@@ -49,10 +49,10 @@ describe('Duplicate OCI Endpoint', () => {
     cy.server()
     cy.route({ url: '**/replicas/detail', method: 'GET' }).as('replicas')
     cy.route({ url: '**/migrations/detail', method: 'GET' }).as('migrations')
-    cy.get('button[data-test-id="edContent-deleteButton"]').click()
+    cy.getById('edContent-deleteButton').click()
     cy.wait(['@replicas', '@migrations'])
     cy.route({ url: '**/secrets/**', method: 'DELETE' }).as('delete')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@delete')
   })
 })

+ 33 - 32
private/cypress/integration/4 - migrations and replicas/Openstack - OCI Migration.js

@@ -27,7 +27,7 @@ describe('Create Openstack to OCI Migration', () => {
 
   it('Shows Wizard page', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Migration').click()
+    cy.getById('newItemDropdown-listItem-Migration').click()
     cy.get('#app').should('contain', 'New Migration')
   })
 
@@ -35,42 +35,42 @@ describe('Create Openstack to OCI Migration', () => {
     cy.server()
     cy.route({ url: '**/instances**', method: 'GET' }).as('sourceInstances')
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-openstack"]').first().click()
+    cy.getById('wEndpointList-dropdown-openstack').first().click()
     cy.get('div').contains('e2e-openstack-test').click()
     cy.wait('@sourceInstances')
   })
 
+  it('Searches and selects instances', () => {
+    cy.get('button').contains('Next').click()
+    // cy.server()
+    // cy.route({ url: '**/instances**', method: 'GET' }).as('search')
+    cy.get('input[placeholder="Search VMs"]').type(config.wizard.instancesSearch.openstackSearchText)
+    // cy.wait('@search')
+    cy.getById('wInstances-instanceItem').contains(config.wizard.instancesSearch.openstackSearchText)
+    cy.getById('wInstances-instanceItem').its('length').should('be.gt', 0)
+    cy.getById('wInstances-instanceItem').eq(config.wizard.instancesSearch.openstackItemIndex).click()
+  })
+
   it('Chooses OCI as Target Cloud', () => {
     cy.server()
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-oci"]').first().click()
+    cy.getById('wEndpointList-dropdown-oci').first().click()
     cy.route({ url: '**/destination-options', method: 'GET' }).as('destOptions')
     cy.get('div').contains('e2e-oci-test').click()
     cy.wait('@destOptions')
   })
 
-  it('Searches and selects instances', () => {
-    cy.get('button').contains('Next').click()
-    cy.server()
-    cy.route({ url: '**/instances**', method: 'GET' }).as('search')
-    cy.get('input[placeholder="Search VMs"]').type(config.wizard.instancesSearch.ociSearchText)
-    cy.wait('@search')
-    cy.get('div[data-test-id="wInstances-instanceItem"]').contains(config.wizard.instancesSearch.ociSearchText)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').its('length').should('be.gt', 0)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').eq(config.wizard.instancesSearch.ociItemIndex).click()
-  })
-
   it('Fills OCI migration info', () => {
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wOptionsField-enumDropdown-compartment"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.oci.compartment.label).click()
-    cy.get('div[data-test-id="wOptionsField-enumDropdown-availability_domain"]').click()
+    cy.getById('wOptionsField-enumDropdown-compartment').click()
+    cy.getById('dropdownListItem').contains(config.wizard.oci.compartment).click()
+    cy.getById('wOptionsField-enumDropdown-availability_domain').click()
     cy.server()
     cy.route({ url: '**/destination-options**', method: 'GET' }).as('destOptions')
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.oci.availabilityDomain).click()
+    cy.getById('dropdownListItem').contains(config.wizard.oci.availabilityDomain).click()
     cy.wait('@destOptions')
-    cy.get('div[data-test-id="wOptionsField-enumDropdown-migr_subnet_id"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.oci.migrSubnetId.label).click()
+    cy.getById('wOptionsField-enumDropdown-migr_subnet_id').click()
+    cy.getById('dropdownListItem').contains(config.wizard.oci.migrSubnetId).click()
   })
 
   it('Selects first available network mapping', () => {
@@ -80,9 +80,9 @@ describe('Create Openstack to OCI Migration', () => {
     cy.get('button').contains('Next').click()
     cy.wait(['@networks', '@instances'])
     cy.get('button').contains('Next').should('be.disabled')
-    cy.get('div[data-test-id="networkItem"]').its('length').should('be.gt', 0)
+    cy.getById('networkItem').its('length').should('be.gt', 0)
     cy.get('div[value="Select ..."]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').first().click()
+    cy.getById('dropdownListItem').first().click()
     cy.get('button').contains('Next').should('not.be.disabled')
   })
 
@@ -92,10 +92,10 @@ describe('Create Openstack to OCI Migration', () => {
     cy.get('#app').should('contain', 'e2e-openstack-test')
     cy.get('#app').should('contain', 'e2e-oci-test')
     cy.get('#app').should('contain', 'Coriolis Migration')
-    cy.get('#app').should('contain', 'Migration Options')
-    cy.get('div[data-test-id="wSummary-optionValue-compartment"]').should('contain', config.wizard.oci.compartment.value)
-    cy.get('div[data-test-id="wSummary-optionValue-availability_domain"]').should('contain', config.wizard.oci.availabilityDomain)
-    cy.get('div[data-test-id="wSummary-optionValue-migr_subnet_id"]').should('contain', config.wizard.oci.migrSubnetId.value)
+    cy.get('#app').should('contain', 'Migration Target Options')
+    cy.getById('wSummary-optionValue-compartment').should('contain', 'ocid1.compartment')
+    cy.getById('wSummary-optionValue-availability_domain').should('contain', config.wizard.oci.availabilityDomain)
+    cy.getById('wSummary-optionValue-migr_subnet_id').should('contain', 'ocid1.subnet')
   })
 
   it('Executes migration', () => {
@@ -106,24 +106,25 @@ describe('Create Openstack to OCI Migration', () => {
   })
 
   it('Shows running migration page', () => {
-    cy.get('div[data-test-id="statusPill-RUNNING"]').should('exist')
+    cy.getById('statusPill-RUNNING').should('exist')
   })
 
   it('Cancels migration', () => {
+    cy.getById('dcHeader-actionButton').click()
+    cy.get('*[data-test-id="actionDropdown-listItem-Cancel"]', { timeout: 10000 }).click()
     cy.server()
-    cy.get('button', { timeout: 10000 }).contains('Cancel').click()
     cy.route({ url: '**/actions', method: 'POST' }).as('cancel')
-    cy.get('button').contains('Yes').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@cancel')
     cy.get('div[data-test-id="dcHeader-statusPill-ERROR"]', { timeout: 120000 })
   })
 
   it('Deletes migration', () => {
-    cy.get('a[data-test-id="detailsNavigation-"]').click()
-    cy.get('button').contains('Delete Migration').click()
+    cy.getById('dcHeader-actionButton').click()
+    cy.getById('actionDropdown-listItem-Delete Migration').click()
     cy.server()
     cy.route({ url: '**/migrations/**', method: 'DELETE' }).as('delete')
-    cy.get('button').contains('Yes').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@delete')
   })
 })

+ 35 - 27
private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/1 - Create replica.js

@@ -27,7 +27,7 @@ describe('Create VmWare to Azure Replica', () => {
 
   it('Shows Wizard page', () => {
     cy.get('div').contains('New').click()
-    cy.get('a').contains('Replica').click()
+    cy.getById('newItemDropdown-listItem-Replica').click()
     cy.get('#app').should('contain', 'New Replica')
   })
 
@@ -35,34 +35,37 @@ describe('Create VmWare to Azure Replica', () => {
     cy.server()
     cy.route({ url: '**/instances**', method: 'GET' }).as('sourceInstances')
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-vmware_vsphere"]').first().click()
+    cy.getById('wEndpointList-dropdown-vmware_vsphere').first().click()
     cy.get('div').contains('e2e-vmware-test').click()
     cy.wait('@sourceInstances')
   })
 
-  it('Chooses Azure as Target Cloud', () => {
-    cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-azure"]').first().click()
-    cy.get('div').contains('e2e-azure-test').click()
-  })
-
   it('Searches and selects instances', () => {
     cy.get('button').contains('Next').click()
     cy.server()
     cy.route({ url: '**/instances**', method: 'GET' }).as('search')
     cy.get('input[placeholder="Search VMs"]').type(config.wizard.instancesSearch.vmwareSearchText)
     cy.wait('@search')
-    cy.get('div[data-test-id="wInstances-instanceItem"]').contains(config.wizard.instancesSearch.vmwareSearchText)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').its('length').should('be.gt', 0)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').eq(config.wizard.instancesSearch.vmwareItemIndex).click()
+    cy.getById('wInstances-instanceItem').contains(config.wizard.instancesSearch.vmwareSearchText)
+    cy.getById('wInstances-instanceItem').its('length').should('be.gt', 0)
+    cy.getById('wInstances-instanceItem').eq(config.wizard.instancesSearch.vmwareItemIndex).click()
+  })
+
+  it('Chooses Azure as Target Cloud', () => {
+    cy.get('button').contains('Next').click()
+    cy.getById('wEndpointList-dropdown-azure').first().click()
+    cy.server()
+    cy.route({ url: '**/destination-options**', method: 'GET' }).as('dest-options')
+    cy.get('div').contains('e2e-azure-test').click()
+    cy.wait('@dest-options')
   })
 
   it('Fills Azure replica info', () => {
     cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wOptionsField-enumDropdown-resource_group"]').first().click()
+    cy.getById('acDropdown-wrapper').first().click()
     cy.server()
     cy.route({ url: '**/destination-options**', method: 'GET' }).as('dest-options')
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.azure.resourceGroup.label).click()
+    cy.getById('ad-listItem').contains(config.wizard.azure.resourceGroup).click()
     cy.wait('@dest-options')
   })
 
@@ -73,15 +76,20 @@ describe('Create VmWare to Azure Replica', () => {
     cy.get('button').contains('Next').click()
     cy.wait(['@networks', '@instances'])
     cy.get('button').contains('Next').should('be.disabled')
-    cy.get('div[data-test-id="networkItem"]').its('length').should('be.gt', 0)
+    cy.getById('networkItem').its('length').should('be.gt', 0)
     cy.get('div[value="Select ..."]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').first().click()
+    cy.getById('dropdownListItem').first().click()
     cy.get('button').contains('Next').should('not.be.disabled')
   })
 
+  it('Shows storage screen', () => {
+    cy.get('button').contains('Next').click()
+    cy.getById('wpContent-header').should('contain', 'Storage')
+  })
+
   it('Shows schedule page', () => {
     cy.get('button').contains('Next').click()
-    cy.get('#app').should('contain', 'Schedule')
+    cy.getById('wpContent-header').should('contain', 'Schedule')
   })
 
   it('Shows summary page', () => {
@@ -90,8 +98,8 @@ describe('Create VmWare to Azure Replica', () => {
     cy.get('#app').should('contain', 'e2e-vmware-test')
     cy.get('#app').should('contain', 'e2e-azure-test')
     cy.get('#app').should('contain', 'Coriolis Replica')
-    cy.get('#app').should('contain', 'Replica Options')
-    cy.get('div[data-test-id="wSummary-optionValue-resource_group"]').should('contain', config.wizard.azure.resourceGroup.value)
+    cy.get('#app').should('contain', 'Replica Target Options')
+    cy.getById('wSummary-optionValue-resource_group').should('contain', config.wizard.azure.resourceGroup)
   })
 
   it('Executes replica', () => {
@@ -102,24 +110,24 @@ describe('Create VmWare to Azure Replica', () => {
   })
 
   it('Shows running replica page', () => {
-    cy.get('div[data-test-id="statusPill-RUNNING"]').should('exist')
+    cy.getById('statusPill-RUNNING').should('exist')
   })
 
   it('Cancels replica execution', () => {
     cy.server()
-    cy.get('button').contains('Cancel Execution').click()
+    cy.getById('executions-cancelButton').click()
     cy.route({ url: '**/actions', method: 'POST' }).as('cancel')
-    cy.get('button').contains('Yes').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@cancel')
     cy.get('div[data-test-id="dcHeader-statusPill-ERROR"]', { timeout: 120000 })
   })
 
   it('Should show in usage message when trying to delete', () => {
-    cy.get('div[data-test-id="dcHeader-backButton"]').click()
-    cy.get('a[data-test-id="navigation-item-endpoints"]').click()
-    cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test"]').click()
-    cy.get('button').contains('Delete Endpoint').click()
-    cy.get('div[data-test-id="alertModal"]').should('contain', 'The endpoint can\'t be deleted because it is in use by replicas or migrations.')
-    cy.get('button[data-test-id="aModal-dismissButton"]').click()
+    cy.getById('dcHeader-backButton').click()
+    cy.getById('navigation-smallMenuItem-endpoints').click()
+    cy.getById('endpointListItem-content-e2e-azure-test').click()
+    cy.getById('edContent-deleteButton').click()
+    cy.getById('alertModal').should('contain', 'The endpoint can\'t be deleted because it is in use by replicas or migrations.')
+    cy.getById('aModal-dismissButton').click()
   })
 })

+ 17 - 22
private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/2 - Scheduler Operations.js

@@ -23,57 +23,52 @@ describe('Scheduler Operations', () => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  it('Goes to scheduler\'s page', () => {
+  it('Creates a schedule', () => {
     cy.server()
     cy.route('GET', '**/executions/detail').as('execution')
-    cy.get('div[data-test-id="mainListItem-content"]').first().click()
+    cy.getById('mainListItem-content').first().click()
     cy.wait('@execution')
-    cy.get('a').contains('Schedule').click()
-    cy.get('button').should('contain', 'Add Schedule')
-  })
-
-  it('Creates a schedule', () => {
-    cy.server()
+    cy.getById('detailsNavigation-schedule').click()
     cy.route('POST', '**/schedules').as('schedule')
-    cy.get('button').contains('Add Schedule').click()
+    cy.getById('schedule-noScheduleAddButton').click()
     cy.wait('@schedule')
-    cy.get('div[data-test-id="scheduleItem-saveButton"]').should('not.be.visible')
+    cy.getById('scheduleItem-saveButton').should('not.be.visible')
   })
 
   it('Changes the month', () => {
-    cy.get('div[data-test-id="scheduleItem-monthDropdown"]').last().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('October').click()
-    cy.get('div[data-test-id="scheduleItem-monthDropdown"]').last().should('contain', 'October')
-    cy.get('div[data-test-id="scheduleItem-saveButton"]').should('be.visible')
+    cy.getById('scheduleItem-monthDropdown').last().click()
+    cy.getById('dropdownListItem').contains('October').click()
+    cy.getById('scheduleItem-monthDropdown').last().should('contain', 'October')
+    cy.getById('scheduleItem-saveButton').should('be.visible')
   })
 
   it('Changes the hour', () => {
-    cy.get('div[data-test-id="scheduleItem-hourDropdown"]').last().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('04').click()
-    cy.get('div[data-test-id="scheduleItem-hourDropdown"]').last().should('contain', '04')
+    cy.getById('scheduleItem-hourDropdown').last().click()
+    cy.getById('dropdownListItem').contains('04').click()
+    cy.getById('scheduleItem-hourDropdown').last().should('contain', '04')
   })
 
   it('Changes timezone', () => {
-    cy.get('[data-test-id="schedule-timezoneDropdown"]').click()
+    cy.getById('schedule-timezoneDropdown').click()
     cy.get('div').contains('UTC').click()
     let utcTime = 4 + (new Date().getTimezoneOffset() / 60)
     if (utcTime < 10) {
       utcTime = `0${utcTime}`
     }
     utcTime = utcTime.toString()
-    cy.get('div[data-test-id="scheduleItem-hourDropdown"]').last().should('contain', utcTime)
+    cy.getById('scheduleItem-hourDropdown').last().should('contain', utcTime)
   })
 
   it('Saves the changes', () => {
     cy.server()
     cy.route('PUT', '**/schedules/**').as('schedule')
-    cy.get('div[data-test-id="scheduleItem-saveButton"]').should('be.visible').last().click()
+    cy.getById('scheduleItem-saveButton').should('be.visible').last().click()
     cy.wait('@schedule')
-    cy.get('div[data-test-id="scheduleItem-saveButton"]').should('not.be.visible')
+    cy.getById('scheduleItem-saveButton').should('not.be.visible')
   })
 
   it('Deletes the last schedule', () => {
-    cy.get('div[data-test-id="scheduleItem-deleteButton"]').last().click()
+    cy.getById('scheduleItem-deleteButton').last().click()
     cy.server()
     cy.route('DELETE', '**/schedules/**').as('schedule')
     cy.get('button').contains('Yes').click()

+ 2 - 2
private/cypress/integration/4 - migrations and replicas/VmWare - Azure Replica/3 - Delete replica.js

@@ -26,13 +26,13 @@ describe('Delete replica', () => {
   it('Goes to replica page', () => {
     cy.server()
     cy.route('GET', '**/executions/detail').as('execution')
-    cy.get('div[data-test-id="mainListItem-content"]').first().click()
+    cy.getById('mainListItem-content').first().click()
     cy.wait('@execution')
   })
 
   it('Deletes replica', () => {
     cy.server()
-    cy.get('button[data-test-id="rdContent-deleteButton"]').click()
+    cy.getById('rdContent-deleteButton').click()
     cy.route({ url: '**/replicas/**', method: 'DELETE' }).as('delete')
     cy.get('button').contains('Yes').click()
     cy.wait('@delete')

+ 0 - 119
private/cypress/integration/4 - migrations and replicas/VmWare - Openstack Migration.js

@@ -1,119 +0,0 @@
-/*
-Copyright (C) 2018  Cloudbase Solutions SRL
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation, either version 3 of the
-License, or (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-// @flow
-
-import config from '../../config'
-
-describe('Create VmWare to Openstack Migration', () => {
-  before(() => {
-    cy.login()
-  })
-
-  beforeEach(() => {
-    Cypress.Cookies.preserveOnce('token', 'projectId')
-  })
-
-  it('Shows Wizard page', () => {
-    cy.get('div').contains('New').click()
-    cy.get('a').contains('Migration').click()
-    cy.get('#app').should('contain', 'New Migration')
-  })
-
-  it('Chooses VmWare as Source Cloud', () => {
-    cy.server()
-    cy.route({ url: '**/instances**', method: 'GET' }).as('sourceInstances')
-    cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-vmware_vsphere"]').first().click()
-    cy.get('div').contains('e2e-vmware-test').click()
-    cy.wait('@sourceInstances')
-  })
-
-  it('Chooses Openstack as Target Cloud', () => {
-    cy.get('button').contains('Next').click()
-    cy.get('div[data-test-id="wEndpointList-dropdown-openstack"]').first().click()
-    cy.get('div').contains('e2e-openstack-test').click()
-  })
-
-  it('Searches and selects instances', () => {
-    cy.get('button').contains('Next').click()
-    cy.server()
-    cy.route({ url: '**/instances**', method: 'GET' }).as('search')
-    cy.get('input[placeholder="Search VMs"]').type(config.wizard.instancesSearch.vmwareSearchText)
-    cy.wait('@search')
-    cy.get('div[data-test-id="wInstances-instanceItem"]').contains(config.wizard.instancesSearch.vmwareSearchText)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').its('length').should('be.gt', 0)
-    cy.get('div[data-test-id="wInstances-instanceItem"]').eq(config.wizard.instancesSearch.vmwareItemIndex).click()
-  })
-
-  it('Fills Openstack migration info', () => {
-    cy.get('button').contains('Next').click()
-    cy.get('div').contains('Advanced').click()
-    cy.get('input[placeholder="Description"]').type('VmWare Openstack Migration')
-  })
-
-  it('Selects network mapping', () => {
-    cy.server()
-    cy.route({ url: '**/networks**', method: 'GET' }).as('networks')
-    cy.route({ url: '**/instances/**', method: 'GET' }).as('instances')
-    cy.get('button').contains('Next').click()
-    cy.wait(['@networks', '@instances'])
-    cy.get('button').contains('Next').should('be.disabled')
-    cy.get('div[data-test-id="networkItem"]').its('length').should('be.gt', 0)
-    cy.get('div[value="Select ..."]').first().click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains(config.wizard.openstack.network).click()
-    cy.get('button').contains('Next').should('not.be.disabled')
-  })
-
-  it('Shows summary page', () => {
-    cy.get('button').contains('Next').click()
-    cy.get('#app').should('contain', 'Summary')
-    cy.get('#app').should('contain', 'e2e-vmware-test')
-    cy.get('#app').should('contain', 'e2e-openstack-test')
-    cy.get('#app').should('contain', 'Coriolis Migration')
-    cy.get('#app').should('contain', 'Migration Options')
-    cy.get('#app').should('contain', 'VmWare Openstack Migration')
-    cy.get('#app').should('contain', 'Networks')
-    cy.get('#app').should('contain', 'Instances')
-  })
-
-  it('Executes migration', () => {
-    cy.server()
-    cy.route({ url: '**/migrations', method: 'POST' }).as('migration')
-    cy.get('button').contains('Finish').click()
-    cy.wait('@migration')
-  })
-
-  it('Shows running migration page', () => {
-    cy.get('div[data-test-id="statusPill-RUNNING"]').should('exist')
-  })
-
-  it('Cancels migration', () => {
-    cy.server()
-    cy.get('button', { timeout: 10000 }).contains('Cancel').click()
-    cy.route({ url: '**/actions', method: 'POST' }).as('cancel')
-    cy.get('button').contains('Yes').click()
-    cy.wait('@cancel')
-    cy.get('div[data-test-id="dcHeader-statusPill-ERROR"]', { timeout: 120000 })
-  })
-
-  it('Deletes migration', () => {
-    cy.get('a[data-test-id="detailsNavigation-"]').click()
-    cy.get('button').contains('Delete Migration').click()
-    cy.server()
-    cy.route({ url: '**/migrations/**', method: 'DELETE' }).as('delete')
-    cy.get('button').contains('Yes').click()
-    cy.wait('@delete')
-  })
-})

+ 5 - 7
private/cypress/integration/5 - delete endpoints/Delete Azure endpoint.js

@@ -14,9 +14,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 // @flow
 
-import config from '../../config'
-import DomUtils from '../../../../src/utils/DomUtils'
-
 describe('Delete the Azure endpoint created for e2e testing', () => {
   before(() => {
     cy.login()
@@ -27,20 +24,21 @@ describe('Delete the Azure endpoint created for e2e testing', () => {
   })
 
   it('Goes to endpoints page', () => {
-    cy.get('#app').should('contain', 'Coriolis Replicas')
-    cy.visit(`${config.nodeServer}${DomUtils.urlHashPrefix}endpoints`)
+    cy.getById('navigation-smallMenuItem-endpoints').click()
     cy.get('#app').should('contain', 'Coriolis Endpoints')
   })
 
   it('Delete e2e Azure endpoint', () => {
-    cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test"]').should('contain', 'e2e-azure-test')
-    cy.get('div[data-test-id="endpointListItem-content-e2e-azure-test"]').first().click()
+    cy.getById('endpointListItem-content-e2e-azure-test').should('contain', 'e2e-azure-test')
+    cy.getById('endpointListItem-content-e2e-azure-test').first().click()
     cy.server()
     cy.route({ url: '**/migrations/**', method: 'GET' }).as('migrations')
     cy.route({ url: '**/replicas/**', method: 'GET' }).as('replicas')
     cy.get('button').contains('Delete Endpoint').click()
     cy.wait(['@migrations', '@replicas'])
+    cy.route({ url: '**/endpoints/**', method: 'DELETE' }).as('delete')
     cy.get('button').contains('Yes').click()
+    cy.wait('@delete')
   })
 })
 

+ 5 - 7
private/cypress/integration/5 - delete endpoints/Delete OCI endpoint.js

@@ -14,9 +14,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 // @flow
 
-import config from '../../config'
-import DomUtils from '../../../../src/utils/DomUtils'
-
 describe('Delete the OCI endpoint created for e2e testing', () => {
   before(() => {
     cy.login()
@@ -27,20 +24,21 @@ describe('Delete the OCI endpoint created for e2e testing', () => {
   })
 
   it('Goes to endpoints page', () => {
-    cy.get('#app').should('contain', 'Coriolis Replicas')
-    cy.visit(`${config.nodeServer}${DomUtils.urlHashPrefix}endpoints`)
+    cy.getById('navigation-smallMenuItem-endpoints').click()
     cy.get('#app').should('contain', 'Coriolis Endpoints')
   })
 
   it('Delete e2e OCI endpoint', () => {
-    cy.get('div[data-test-id="endpointListItem-content-e2e-oci-test"]').should('contain', 'e2e-oci-test')
-    cy.get('div[data-test-id="endpointListItem-content-e2e-oci-test"]').first().click()
+    cy.getById('endpointListItem-content-e2e-oci-test').should('contain', 'e2e-oci-test')
+    cy.getById('endpointListItem-content-e2e-oci-test').first().click()
     cy.server()
     cy.route({ url: '**/migrations/**', method: 'GET' }).as('migrations')
     cy.route({ url: '**/replicas/**', method: 'GET' }).as('replicas')
     cy.get('button').contains('Delete Endpoint').click()
     cy.wait(['@migrations', '@replicas'])
+    cy.route({ url: '**/endpoints/**', method: 'DELETE' }).as('delete')
     cy.get('button').contains('Yes').click()
+    cy.wait('@delete')
   })
 })
 

+ 12 - 18
private/cypress/integration/5 - delete endpoints/Delete Openstack and VmWare endpoints.js

@@ -14,11 +14,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 // @flow
 
-import config from '../../config'
-import DomUtils from '../../../../src/utils/DomUtils'
-
-declare var expect: any
-
 describe('Delete the Openstack and VmWare endpoints created for e2e testing', () => {
   before(() => {
     cy.login()
@@ -29,27 +24,26 @@ describe('Delete the Openstack and VmWare endpoints created for e2e testing', ()
   })
 
   it('Goes to endpoints page', () => {
-    cy.get('#app').should('contain', 'Coriolis Replicas')
-    cy.visit(`${config.nodeServer}${DomUtils.urlHashPrefix}endpoints`)
+    cy.getById('navigation-smallMenuItem-endpoints').click()
     cy.get('#app').should('contain', 'Coriolis Endpoints')
   })
 
   it('Selects both endpoints', () => {
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-openstack-test"]').should('have.length', 1)
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-vmware-test"]').should('have.length', 1)
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-openstack-test"]').click()
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-vmware-test"]').click()
-    cy.get('[data-test-id="mainListFilter-selectionText"]').should('contain', '2 of 2')
+    cy.getById('endpointListItem-checkbox-e2e-openstack-test').should('have.length', 1)
+    cy.getById('endpointListItem-checkbox-e2e-vmware-test').should('have.length', 1)
+    cy.getById('endpointListItem-checkbox-e2e-openstack-test').click()
+    cy.getById('endpointListItem-checkbox-e2e-vmware-test').click()
+    cy.getById('mainListFilter-selectionText').should('contain', '2 of 2')
   })
 
   it('Deletes selected endpoints', () => {
-    cy.get('div[data-test-id="dropdown-dropdownButton"]').contains('Select an action').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('Delete').click()
+    cy.getById('dropdown-dropdownButton').contains('Select an action').click()
+    cy.getById('dropdownListItem').contains('Delete').click()
     cy.server()
-    cy.route({ url: '**/secrets/**', method: 'DELETE' }).as('delete')
-    cy.get('[data-test-id="aModal-yesButton"]').click()
+    cy.route({ url: '**/endpoints/**', method: 'DELETE' }).as('delete')
+    cy.getById('aModal-yesButton').click()
     cy.wait(['@delete', '@delete'])
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-openstack-test"]').should('have.length', 0)
-    cy.get('[data-test-id="endpointListItem-checkbox-e2e-vmware-test"]').should('have.length', 0)
+    cy.getById('endpointListItem-checkbox-e2e-openstack-test').should('have.length', 0)
+    cy.getById('endpointListItem-checkbox-e2e-vmware-test').should('have.length', 0)
   })
 })

+ 10 - 23
private/cypress/integration/6 - users and projects/1 - Create a project.js

@@ -12,50 +12,37 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/constants'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Create a project', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows projects page', () => {
-    cy.get('a[data-test-id="navigation-item-projects"]').click()
+    cy.getById('navigation-smallMenuItem-projects').click()
     cy.title().should('eq', 'Projects')
   })
 
   it('Shows new project modal', () => {
-    cy.get('div[data-test-id="newItemDropdown-button"]').click()
-    cy.get('a[data-test-id="newItemDropdown-listItem-Project"]').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'New Project')
+    cy.getById('newItemDropdown-button').click()
+    cy.getById('newItemDropdown-listItem-Project').click()
+    cy.getById('modal-title').should('contain', 'New Project')
   })
 
   it('Creates project', () => {
-    cy.get('input[data-test-id="endpointField-textInput-project_name"]').type('cypress-project')
-    cy.get('input[data-test-id="endpointField-textInput-description"]').type('Project created by Cypress')
+    cy.getById('endpointField-textInput-project_name').last().type('cypress-project')
+    cy.getById('endpointField-textInput-description').last().type('Project created by Cypress')
     cy.server()
     cy.route({ url: '**/projects/', method: 'POST' }).as('addProject')
     cy.route({ url: '**/roles/**', method: 'PUT' }).as('addRole')
     cy.get('button').contains('New Project').click()
     cy.wait(['@addProject', '@addRole'])
-    cy.get('div[data-test-id="plItem-content"]').should('contain', 'cypress-project')
-    cy.get('div[data-test-id="plItem-content"]').should('contain', 'Project created by Cypress')
+    cy.getById('plItem-content').should('contain', 'cypress-project')
+    cy.getById('plItem-content').should('contain', 'Project created by Cypress')
   })
 })

+ 24 - 37
private/cypress/integration/6 - users and projects/2 - Add a new user as a member.js

@@ -12,74 +12,61 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/config'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Adds a new user as a member to the project', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows projects details page', () => {
-    cy.get('a[data-test-id="navigation-item-projects"]').click()
-    cy.get('div[data-test-id="plItem-content"]').contains('cypress-project').click()
+    cy.getById('navigation-smallMenuItem-projects').click()
+    cy.getById('plItem-content').contains('cypress-project').click()
     cy.title().should('eq', 'Project Details')
   })
 
   it('Opens add member modal', () => {
     cy.get('button').contains('Add Member').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'Add Project Member')
+    cy.getById('modal-title').should('contain', 'Add Project Member')
   })
 
   it('Creates new user', () => {
-    cy.get('div[data-test-id="toggleButtonBar-new"]').click()
-    cy.get('input[data-test-id="endpointField-textInput-username"]').type('cypress-member-user')
-    cy.get('input[data-test-id="endpointField-textInput-description"]').type('User created by Cypress in Add Project Member modal')
-    cy.get('div[data-test-id="endpointField-dropdown-Primary Project"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('cypress-project').click()
-    cy.get('div[data-test-id="endpointField-multidropdown-role(s)"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('_member_').click()
-    cy.get('input[data-test-id="endpointField-textInput-password"]').type('cypress-member-user')
-    cy.get('input[data-test-id="endpointField-textInput-confirm_password"]').type('cypress-member-user')
+    cy.getById('toggleButtonBar-new').click()
+    cy.getById('endpointField-textInput-username').last().type('cypress-member-user')
+    cy.getById('endpointField-textInput-description').last().type('User created by Cypress in Add Project Member modal')
+    cy.getById('endpointField-dropdown-Primary Project').click()
+    cy.getById('dropdownListItem').contains('cypress-project').click()
+    cy.getById('endpointField-multidropdown-role(s)').click()
+    cy.getById('dropdownListItem').contains('_member_').click()
+    cy.getById('endpointField-textInput-password').last().type('cypress-member-user')
+    cy.getById('endpointField-textInput-confirm_password').last().type('cypress-member-user')
     cy.server()
     cy.route({ url: '**/users', method: 'POST' }).as('addUser')
     cy.route({ url: '**/roles/**', method: 'PUT' }).as('addRole')
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('button[data-test-id="pmModal-addButton"]').contains('Add Member').click()
+    cy.getById('pmModal-addButton').contains('Add Member').click()
     cy.wait(['@addUser', '@addRole', '@getRoles'])
-    cy.get('a[data-test-id="pdContent-users-cypress-member-user"]').its('length').should('eq', 1)
-    cy.get('div[data-test-id="pdContent-roles-cypress-member-user"]').should('contain', '_member_')
+    cy.getById('pdContent-users-cypress-member-user').its('length').should('eq', 1)
+    cy.getById('pdContent-roles-cypress-member-user').should('contain', '_member_')
   })
 
   it('Adds admin as its role', () => {
-    cy.get('div[data-test-id="pdContent-roles-cypress-member-user"]').click()
-    cy.get('div[data-test-id="dropdownLink-listItem"]').contains('admin').click()
-    cy.get('div[data-test-id="pdContent-roles-cypress-member-user"]').should('contain', '_member_, admin')
+    cy.getById('pdContent-roles-cypress-member-user').click()
+    cy.getById('dropdownLink-listItem').contains('admin').click()
+    cy.getById('pdContent-roles-cypress-member-user').should('contain', '_member_, admin')
   })
 
   it('Removes user from project', () => {
-    cy.get('div[data-test-id="pdContent-actions-cypress-member-user"]').click()
-    cy.get('div[data-test-id="dropdownLink-listItem"]').contains('Remove').click()
+    cy.getById('pdContent-actions-cypress-member-user').click()
+    cy.getById('dropdownLink-listItem').contains('Remove').click()
     cy.server()
     cy.route({ url: '**/roles/**', method: 'DELETE' }).as('deleteRole')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@deleteRole')
-    cy.get('a[data-test-id="pdContent-users-cypress-member-user"]').should('not.exist')
+    cy.getById('pdContent-users-cypress-member-user').should('not.exist')
   })
 })

+ 15 - 28
private/cypress/integration/6 - users and projects/3 - Add existing user as a member.js

@@ -12,63 +12,50 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/config'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Adds existing user as a member to the project', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows projects details page', () => {
-    cy.get('a[data-test-id="navigation-item-projects"]').click()
-    cy.get('div[data-test-id="plItem-content"]').contains('cypress-project').click()
+    cy.getById('navigation-smallMenuItem-projects').click()
+    cy.getById('plItem-content').contains('cypress-project').click()
   })
 
   it('Opens add member modal', () => {
     cy.get('button').contains('Add Member').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'Add Project Member')
+    cy.getById('modal-title').should('contain', 'Add Project Member')
   })
 
   it('Adds existing user', () => {
-    cy.get('input[data-test-id="acInput-text"]').type('cy')
-    cy.get('div[data-test-id="ad-listItem"]').contains('cypress-member-user').click()
-    cy.get('div[data-test-id="endpointField-multidropdown-role(s)"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('_member_').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('admin').click()
-    cy.get('div[data-test-id="modal-title"]').click()
+    cy.getById('acInput-text').last().type('cy')
+    cy.getById('ad-listItem').contains('cypress-member-user').click()
+    cy.getById('endpointField-multidropdown-role(s)').click()
+    cy.getById('dropdownListItem').contains('_member_').click()
+    cy.getById('dropdownListItem').contains('admin').click()
+    cy.getById('modal-title').click()
     cy.server()
     cy.route({ url: '**/roles/**', method: 'PUT' }).as('addRoles')
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('button[data-test-id="pmModal-addButton"]').click()
+    cy.getById('pmModal-addButton').click()
     cy.wait(['@addRoles', '@getRoles'])
-    cy.get('div[data-test-id="pdContent-roles-cypress-member-user"]').should('contain', '_member_, admin')
+    cy.getById('pdContent-roles-cypress-member-user').should('contain', '_member_, admin')
   })
 
   it('Deletes the user', () => {
     cy.server()
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('a[data-test-id="pdContent-users-cypress-member-user"]').click()
+    cy.getById('pdContent-users-cypress-member-user').click()
     cy.wait('@getRoles')
     cy.get('button').contains('Delete user').click()
     cy.route({ url: '**/users/**', method: 'DELETE' }).as('deleteUser')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait('@deleteUser')
   })
 })

+ 13 - 26
private/cypress/integration/6 - users and projects/4 - Create a user.js

@@ -12,53 +12,40 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/config'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Create a user', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows users page', () => {
-    cy.get('a[data-test-id="navigation-item-users"]').click()
+    cy.getById('navigation-smallMenuItem-users').click()
     cy.title().should('eq', 'Users')
   })
 
   it('Shows new user modal', () => {
-    cy.get('div[data-test-id="newItemDropdown-button"]').click()
-    cy.get('a[data-test-id="newItemDropdown-listItem-User"]').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'New User')
+    cy.getById('newItemDropdown-button').click()
+    cy.getById('newItemDropdown-listItem-User').click()
+    cy.getById('modal-title').should('contain', 'New User')
   })
 
   it('Creates user', () => {
-    cy.get('input[data-test-id="endpointField-textInput-username"]').type('cypress-user')
-    cy.get('input[data-test-id="endpointField-textInput-description"]').type('User created by Cypress')
-    cy.get('div[data-test-id="endpointField-dropdown-Primary Project"]').click()
-    cy.get('div[data-test-id="dropdownListItem"]').contains('cypress-project').click()
-    cy.get('input[data-test-id="endpointField-textInput-new_password"]').type('cypress-user')
-    cy.get('input[data-test-id="endpointField-textInput-confirm_password"]').type('cypress-user')
+    cy.getById('endpointField-textInput-username').last().type('cypress-user')
+    cy.getById('endpointField-textInput-description').last().type('User created by Cypress')
+    cy.getById('endpointField-dropdown-Primary Project').click()
+    cy.getById('dropdownListItem').contains('cypress-project').click()
+    cy.getById('endpointField-textInput-new_password').last().type('cypress-user')
+    cy.getById('endpointField-textInput-confirm_password').last().type('cypress-user')
     cy.server()
     cy.route({ url: '**/users', method: 'POST' }).as('addUser')
     cy.route({ url: '**/roles/**', method: 'PUT' }).as('addRole')
     cy.get('button').contains('New User').click()
     cy.wait(['@addUser', '@addRole'])
-    cy.get('div[data-test-id="ulItem-name"]').contains('cypress-user').should('exist')
+    cy.getById('ulItem-name').contains('cypress-user').should('exist')
   })
 })

+ 13 - 25
private/cypress/integration/6 - users and projects/5 - Edit and delete user.js

@@ -12,54 +12,42 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/config'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Edit created user', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows user details page', () => {
-    cy.get('a[data-test-id="navigation-item-users"]').click()
+    cy.getById('navigation-smallMenuItem-users').click()
     cy.server()
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('div[data-test-id="ulItem-name"]').contains('cypress-user').click()
+    cy.getById('ulItem-name').contains('cypress-user').click()
     cy.wait('@getRoles')
     cy.title().should('eq', 'User Details')
-    cy.get('div[data-test-id="dcHeader-title"]').should('contain', 'cypress-user')
+    cy.getById('dcHeader-title').should('contain', 'cypress-user')
   })
 
   it('Opens user edit modal', () => {
-    cy.get('button').contains('Edit user').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'Update User')
+    cy.getById('dcHeader-actionButton').click()
+    cy.getById('actionDropdown-listItem-Edit user').click()
+    cy.getById('modal-title').should('contain', 'Update User')
   })
 
   it('Edits user', () => {
-    cy.get('input[data-test-id="endpointField-textInput-username"]').clear()
-    cy.get('input[data-test-id="endpointField-textInput-username"]').type('user-cypress')
+    cy.getById('endpointField-textInput-username').last().clear()
+    cy.getById('endpointField-textInput-username').last().type('user-cypress')
     cy.server()
     cy.route({ url: '**/users/**', method: 'PATCH' }).as('updateUser')
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
     cy.get('button').contains('Update User').click()
     cy.wait(['@updateUser', '@getRoles'])
-    cy.get('div[data-test-id="dcHeader-title"]').should('contain', 'user-cypress')
+    cy.getById('dcHeader-title').should('contain', 'user-cypress')
   })
 
   it('Deletes the user', () => {
@@ -67,8 +55,8 @@ describe('Edit created user', () => {
     cy.get('button').contains('Delete user').click()
     cy.route({ url: '**/users/**', method: 'DELETE' }).as('deleteUser')
     cy.route({ url: '**/users', method: 'GET' }).as('getUsers')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait(['@deleteUser', '@getUsers'])
-    cy.get('div[data-test-id="ulItem-name"]').contains('user-cypress').should('not.exist')
+    cy.getById('ulItem-name').contains('user-cypress').should('not.exist')
   })
 })

+ 13 - 25
private/cypress/integration/6 - users and projects/6 - Edit and delete project.js

@@ -12,53 +12,41 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { navigationMenu } from '../../../../src/config'
-
-const isEnabled: () => boolean = () => {
-  let usersEnabled = navigationMenu.find(i => i.value === 'users' && i.disabled === false)
-  let projectsEnabled = navigationMenu.find(i => i.value === 'projects' && i.disabled === false)
-  return Boolean(usersEnabled && projectsEnabled)
-}
+// @flow
 
 describe('Edit created project', () => {
   before(() => {
-    if (isEnabled()) {
-      cy.login()
-    }
+    cy.login()
   })
 
   beforeEach(() => {
     Cypress.Cookies.preserveOnce('token', 'projectId')
   })
 
-  if (!isEnabled()) {
-    it('Users and projects management is disabled!', () => { })
-    return
-  }
-
   it('Shows project details page', () => {
-    cy.get('a[data-test-id="navigation-item-projects"]').click()
+    cy.getById('navigation-smallMenuItem-projects').click()
     cy.server()
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('div[data-test-id="plItem-content"]').contains('cypress-project').click()
+    cy.getById('plItem-content').contains('cypress-project').click()
     cy.wait('@getRoles')
     cy.title().should('eq', 'Project Details')
-    cy.get('div[data-test-id="dcHeader-title"]').should('contain', 'cypress-project')
+    cy.getById('dcHeader-title').should('contain', 'cypress-project')
   })
 
   it('Opens project edit modal', () => {
-    cy.get('button').contains('Edit Project').click()
-    cy.get('div[data-test-id="modal-title"]').should('contain', 'Update Project')
+    cy.getById('dcHeader-actionButton').click()
+    cy.getById('actionDropdown-listItem-Edit Project').click()
+    cy.getById('modal-title').should('contain', 'Update Project')
   })
 
   it('Edits project', () => {
-    cy.get('input[data-test-id="endpointField-textInput-project_name"]').clear()
-    cy.get('input[data-test-id="endpointField-textInput-project_name').type('project-cypress')
+    cy.getById('endpointField-textInput-project_name').last().clear()
+    cy.get('input[data-test-id="endpointField-textInput-project_name').last().type('project-cypress')
     cy.server()
     cy.route({ url: '**/projects/**', method: 'PATCH' }).as('updateProject')
     cy.get('button').contains('Update Project').click()
     cy.wait('@updateProject')
-    cy.get('div[data-test-id="dcHeader-title"]').should('contain', 'project-cypress')
+    cy.getById('dcHeader-title').should('contain', 'project-cypress')
   })
 
   it('Deletes the project', () => {
@@ -66,8 +54,8 @@ describe('Edit created project', () => {
     cy.get('button').contains('Delete Project').click()
     cy.route({ url: '**/projects/**', method: 'DELETE' }).as('deleteProject')
     cy.route({ url: '**/role_assignments**', method: 'GET' }).as('getRoles')
-    cy.get('button[data-test-id="aModal-yesButton"]').click()
+    cy.getById('aModal-yesButton').click()
     cy.wait(['@deleteProject', '@getRoles'])
-    cy.get('div[data-test-id="plItem-content"]').contains('project-cypress').should('not.exist')
+    cy.getById('plItem-content').contains('project-cypress').should('not.exist')
   })
 })

+ 17 - 2
private/cypress/support/commands.js

@@ -20,8 +20,6 @@ const identityUrl = `${config.coriolisUrl}identity/auth/tokens`
 const projectsUrl = `${config.coriolisUrl}identity/auth/projects`
 const coriolisUrl = `${config.coriolisUrl}coriolis`
 
-declare var expect: any
-
 Cypress.Commands.add('login', () => {
   let unscopedBody = {
     auth: {
@@ -45,6 +43,8 @@ Cypress.Commands.add('login', () => {
     body: unscopedBody,
   }).then(unscopedResponse => {
     let unscopedToken = unscopedResponse.headers['x-subject-token']
+
+    // $FlowIssue
     expect(unscopedToken).to.exist
 
     cy.request({
@@ -56,6 +56,7 @@ Cypress.Commands.add('login', () => {
       let cypressProject = projects.find(p => p.name === 'cypress')
       let projectId = cypressProject ? cypressProject.id : projects[0].id
 
+      // $FlowIssue
       expect(projectId).to.exist
 
       let scopedBody = {
@@ -80,6 +81,7 @@ Cypress.Commands.add('login', () => {
         body: scopedBody,
       }).then(scopedResponse => {
         let scopedToken = scopedResponse.headers['x-subject-token']
+        // $FlowIssue
         expect(scopedToken).to.exist
 
         cy.setCookie('token', scopedToken)
@@ -187,3 +189,16 @@ Cypress.Commands.add('cleanup', () => {
     }))))
   })
 })
+
+Cypress.Commands.add('getById', (id, type) => {
+  return cy.get(`${type || ''}[data-test-id="${id}"]`)
+})
+
+Cypress.Commands.add('getServerConfig', () => {
+  return cy.request({
+    url: `${config.nodeServer}config`,
+    method: 'GET',
+  }).then(response => {
+    return response.body
+  })
+})

+ 2 - 1
src/components/organisms/Navigation/Navigation.jsx

@@ -215,7 +215,7 @@ const CbsLogoSmall = styled.a`
   display: flex;
   transition: opacity ${ANIMATION};
 `
-
+export const TEST_ID = 'navigation'
 type Props = {
   currentPage?: string,
   className?: string,
@@ -380,6 +380,7 @@ class Navigation extends React.Component<Props> {
                 key={item.value}
                 selected={this.props.currentPage === item.value}
                 to={`/${item.value}`}
+                data-test-id={`${TEST_ID}-smallMenuItem-${item.value}`}
               >
                 <SmallMenuBackground />
                 {bullet ? <SmallMenuItemBullet bullet={bullet} /> : null}

+ 1 - 1
src/components/pages/EndpointDetailsPage/EndpointDetailsPage.jsx

@@ -119,11 +119,11 @@ class EndpointDetailsPage extends React.Component<Props, State> {
 
   handleDeleteEndpointConfirmation() {
     this.setState({ showDeleteEndpointConfirmation: false })
-    this.props.history.push('/endpoints')
     let endpoint = this.getEndpoint()
     if (endpoint) {
       endpointStore.delete(endpoint)
     }
+    this.props.history.push('/endpoints')
   }
 
   handleCloseDeleteEndpointConfirmation() {

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 274 - 147
yarn.lock


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio