From fe051b4fe45815d2ce50f13b86ad528f520aa078 Mon Sep 17 00:00:00 2001 From: Jan Sudczak Date: Tue, 29 Jan 2019 15:12:44 +0100 Subject: [PATCH] E2e tests with both routing types (#386) * Introduce cy.expectPathToBe() command * Make tets working with hashRouting * Add isHashRoutingOn() * Remove unused import * create cy.expectSearchToBe() --- .../luigi-sample-angular/cypress.json | 3 +- .../e2e/support/commands.js | 44 +++++++++-- .../e2e/tests/context-switcher.spec.js | 8 +- .../e2e/tests/login-flow.spec.js | 4 +- .../e2e/tests/luigi-client-features.spec.js | 76 +++++++------------ .../e2e/tests/navigation.spec.js | 54 +++++++------ .../luigi-sample-angular/package-lock.json | 24 +++--- .../luigi-sample-angular/package.json | 2 +- 8 files changed, 111 insertions(+), 104 deletions(-) diff --git a/core/examples/luigi-sample-angular/cypress.json b/core/examples/luigi-sample-angular/cypress.json index 2d69d6b596..866969d308 100644 --- a/core/examples/luigi-sample-angular/cypress.json +++ b/core/examples/luigi-sample-angular/cypress.json @@ -7,5 +7,6 @@ "screenshotsFolder": "e2e/screenshots", "chromeWebSecurity": false, "viewportWidth": 1250, - "viewportHeight": 790 + "viewportHeight": 790, + "baseUrl": "http://localhost:4200/" } diff --git a/core/examples/luigi-sample-angular/e2e/support/commands.js b/core/examples/luigi-sample-angular/e2e/support/commands.js index 60046556d8..727b876179 100644 --- a/core/examples/luigi-sample-angular/e2e/support/commands.js +++ b/core/examples/luigi-sample-angular/e2e/support/commands.js @@ -13,18 +13,15 @@ Cypress.Commands.add('login', (email, password) => { cy.get('#login-button').click(); cy.get('.fd-shellbar').contains('Overview'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); - }); + cy.expectPathToBe('/overview'); }); Cypress.Commands.add('goToFeaturesPage', iframe => { cy.wrap(iframe) .contains('linkManager()') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2'); - }); + cy.expectPathToBe('/projects/pr2'); + cy.wrap(iframe).should('contain', 'LuigiClient uxManager methods:'); cy.wrap(iframe).should('contain', 'LuigiClient linkManager methods:'); }); @@ -34,3 +31,38 @@ Cypress.Commands.add('goToOverviewPage', () => { .contains('Overview') .click(); }); + +export const isHashRoutingOn = () => { + const appWindow = cy.state('window'); + const { useHashRouting } = + appWindow && appWindow.Luigi && appWindow.Luigi.config + ? appWindow.Luigi.config.routing + : false; + return useHashRouting; +}; + +Cypress.Commands.add('expectPathToBe', pathWithoutHash => + cy.location().should(location => { + const useHashRouting = isHashRoutingOn(); + const actualPath = useHashRouting ? location.hash : location.pathname; + const pathToCheck = useHashRouting + ? '#' + pathWithoutHash + : pathWithoutHash; + expect(actualPath).to.eq(pathToCheck); + }) +); + +Cypress.Commands.add('expectSearchToBe', (searchString, a) => { + // notice that location.hash DOES keep url params ('?a=b') while location.pathname does NOT + cy.location().should(locationContext => { + const useHashRouting = isHashRoutingOn(); + const actualPath = useHashRouting + ? locationContext.hash + : locationContext.pathname; + if (useHashRouting) { + expect('?' + actualPath.split('?')[1]).to.eq(searchString); + } else { + expect(locationContext.search).to.eq(searchString); + } + }); +}); diff --git a/core/examples/luigi-sample-angular/e2e/tests/context-switcher.spec.js b/core/examples/luigi-sample-angular/e2e/tests/context-switcher.spec.js index 467f5a9c81..e3b7300669 100644 --- a/core/examples/luigi-sample-angular/e2e/tests/context-switcher.spec.js +++ b/core/examples/luigi-sample-angular/e2e/tests/context-switcher.spec.js @@ -15,9 +15,7 @@ describe('Context switcher', () => { .contains('New Environment (bottom)') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/create-environment'); - }); + cy.expectPathToBe('/create-environment'); // default label cy.get('.fd-product-menu') @@ -29,9 +27,7 @@ describe('Context switcher', () => { .contains('Environment 1') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/environments/env1'); - }); + cy.expectPathToBe('/environments/env1'); // check label cy.get('.fd-product-menu .fd-popover__control button').should( diff --git a/core/examples/luigi-sample-angular/e2e/tests/login-flow.spec.js b/core/examples/luigi-sample-angular/e2e/tests/login-flow.spec.js index a63859f51e..403e69a7c9 100644 --- a/core/examples/luigi-sample-angular/e2e/tests/login-flow.spec.js +++ b/core/examples/luigi-sample-angular/e2e/tests/login-flow.spec.js @@ -14,9 +14,7 @@ describe('Login Flow', () => { cy.get('.sap-icon--customer').click(); cy.contains('Logout').click(); cy.get('body').should('contain', 'Logout successful'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/logout.html'); - }); + cy.expectPathToBe('/logout.html'); //login again cy.contains('Login again').click(); diff --git a/core/examples/luigi-sample-angular/e2e/tests/luigi-client-features.spec.js b/core/examples/luigi-sample-angular/e2e/tests/luigi-client-features.spec.js index 6c8cc4fc07..04b23f748c 100644 --- a/core/examples/luigi-sample-angular/e2e/tests/luigi-client-features.spec.js +++ b/core/examples/luigi-sample-angular/e2e/tests/luigi-client-features.spec.js @@ -1,6 +1,7 @@ +import { isHashRoutingOn } from '../support/commands'; describe('Luigi client features', () => { beforeEach(() => { - cy.visit('http://localhost:4200'); + cy.visit('/'); cy.login('tets', 'tets'); //wait for the iFrame to be loaded @@ -16,18 +17,16 @@ describe('Luigi client features', () => { cy.wrap($iframeBody) .contains('absolute: to overview') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); - }); + cy.expectPathToBe('/overview'); + cy.goToFeaturesPage($iframeBody); //navigate using relative path cy.wrap($iframeBody) .contains('relative: to stakeholders') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/users/groups/stakeholders'); - }); + cy.expectPathToBe('/projects/pr2/users/groups/stakeholders'); + cy.goToOverviewPage(); cy.goToFeaturesPage($iframeBody); @@ -35,9 +34,8 @@ describe('Luigi client features', () => { cy.wrap($iframeBody) .contains('closest parent: to stakeholders') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/users/groups/stakeholders'); - }); + cy.expectPathToBe('/projects/pr2/users/groups/stakeholders'); + cy.goToOverviewPage(); cy.goToFeaturesPage($iframeBody); @@ -45,16 +43,13 @@ describe('Luigi client features', () => { cy.wrap($iframeBody) .contains('parent by name: project to settings') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/settings'); - }); + cy.expectPathToBe('/projects/pr2/settings'); + cy.wrap($iframeBody).should('contain', 'Settings'); cy.wrap($iframeBody) .contains('Click here') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2'); - }); + cy.expectPathToBe('/projects/pr2'); //navigate with params cy.wrap($iframeBody) @@ -62,32 +57,25 @@ describe('Luigi client features', () => { .click(); cy.wrap($iframeBody).should('contain', 'Called with params:'); cy.wrap($iframeBody).should('contain', '"foo": "bar"'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/settings'); - expect(loc.search).to.eq('?~foo=bar&'); - }); + + cy.expectSearchToBe('?~foo=bar&'); + cy.wrap($iframeBody) .contains('Click here') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2'); - }); + cy.expectPathToBe('/projects/pr2'); //don't navigate cy.wrap($iframeBody) .contains('parent by name: with nonexisting context') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2'); - }); + cy.expectPathToBe('/projects/pr2'); //navigate with preserve view functionality cy.wrap($iframeBody) .contains('with preserved view: project to global settings and back') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/settings'); - }); + cy.expectPathToBe('/settings'); //wait for the second iFrame to be loaded cy.wait(500); @@ -104,9 +92,7 @@ describe('Luigi client features', () => { cy.wrap($preserveViewiFrameBody) .find('button') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2'); - }); + cy.expectPathToBe('/projects/pr2'); }); // check if path exists @@ -158,9 +144,8 @@ describe('Luigi client features', () => { cy.wrap($iframeBody) .contains('Partly wrong link') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/miscellaneous2'); - }); + cy.expectPathToBe('/projects/pr2/miscellaneous2'); + cy.get('.fd-alert').contains( 'Could not map the exact target node for the requested route projects/pr2/miscellaneous2/maskopatol' ); @@ -178,9 +163,8 @@ describe('Luigi client features', () => { cy.wrap($iframeBody) .contains('Totally wrong link') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); - }); + cy.expectPathToBe('/overview'); + cy.get('.fd-alert').contains( 'Could not find the requested route maskopatol/has/a/child' ); @@ -264,17 +248,13 @@ describe('Luigi client features', () => { cy.get('[data-cy=confirmation-modal]').should('be.visible'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); //the location is unchanged - }); + cy.expectPathToBe('/overview'); //the location is unchanged cy.get('[data-cy=modal-no]').click(); cy.get('[data-cy=confirmation-modal]').should('not.be.visible'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); //the location is still unchanged after "No" clicked - }); + cy.expectPathToBe('/overview'); //the location is still unchanged after "No" clicked }); }); it("Unsaved changes - should proceed when 'Yes' was pressed in modal", () => { @@ -291,17 +271,13 @@ describe('Luigi client features', () => { cy.get('[data-cy=confirmation-modal]').should('be.visible'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/overview'); //the location is unchanged - }); + cy.expectPathToBe('/overview'); //the location is unchanged cy.get('[data-cy=modal-yes]').click(); cy.get('[data-cy=confirmation-modal]').should('not.be.visible'); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects'); //the location is changed after "Yes" clicked - }); + cy.expectPathToBe('/projects'); //the location is changed after "Yes" clicked }); }); }); diff --git a/core/examples/luigi-sample-angular/e2e/tests/navigation.spec.js b/core/examples/luigi-sample-angular/e2e/tests/navigation.spec.js index e5da5f3f94..488b21c30e 100644 --- a/core/examples/luigi-sample-angular/e2e/tests/navigation.spec.js +++ b/core/examples/luigi-sample-angular/e2e/tests/navigation.spec.js @@ -1,6 +1,6 @@ describe('Navigation', () => { beforeEach(() => { - cy.visit('http://localhost:4200'); + cy.visit('/'); cy.login('tets@email.com', 'tets'); }); @@ -18,9 +18,8 @@ describe('Navigation', () => { .click(); //project one page - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr1'); - }); + cy.expectPathToBe('/projects/pr1'); + cy.get('.fd-app__sidebar').should('not.contain', 'Project One'); cy.get('.fd-app__sidebar').should('contain', 'Miscellaneous2'); cy.get('.fd-app__sidebar') @@ -28,21 +27,26 @@ describe('Navigation', () => { .click(); //default child node example - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr1/dps/dps2'); - }); + cy.expectPathToBe('/projects/pr1/dps/dps2'); + cy.get('.fd-app__sidebar').should('contain', 'First Child'); cy.get('.fd-app__sidebar').should('contain', 'Second Child'); }); it('Icon instead of label in TopNav', () => { - cy.visit('http://localhost:4200/'); + cy.visit('/'); cy.get('button[title="Settings"]>.fd-top-nav__icon').should('exist'); cy.get('button[title="Settings"]').should('contain', ''); }); it('Icon with label in LeftNav', () => { - cy.visit('http://localhost:4200/projects/pr1'); + cy.get('.fd-shellbar') + .contains('Projects') + .click(); + cy.get('.fd-app__sidebar .fd-side-nav__item') + .contains('Project One') + .click(); + cy.get('.fd-side-nav__subitem') .contains('Project Settings') .find('.fd-side-nav__icon') @@ -95,9 +99,7 @@ describe('Navigation', () => { .click(); }); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr1/avengers/thor'); - }); + cy.expectPathToBe('/projects/pr1/avengers/thor'); cy.get('.fd-app__sidebar').should('contain', 'Keep Selected Example'); }); @@ -130,9 +132,7 @@ describe('Navigation', () => { .contains('Go to absolute path') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/settings'); - }); + cy.expectPathToBe('/settings'); //go to relative path from the parent node goToAnotherNodeFeature(); @@ -140,9 +140,7 @@ describe('Navigation', () => { .contains('Go to relative path') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/dps/dps1'); - }); + cy.expectPathToBe('/projects/pr2/dps/dps1'); //go to relative path from node that is a sibiling goToAnotherNodeFeature(); @@ -150,21 +148,27 @@ describe('Navigation', () => { .contains('Keep Selected Example') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/avengers'); - }); + cy.expectPathToBe('/projects/pr2/avengers'); cy.get('.fd-app__sidebar .fd-side-nav__item') .contains('Go to relative path') .click(); - cy.location().should(loc => { - expect(loc.pathname).to.eq('/projects/pr2/dps/dps1'); - }); + cy.expectPathToBe('/projects/pr2/dps/dps1'); }); it('Left navigation hidden', () => { - cy.visit('http://localhost:4200/projects/pr1/hideSideNav'); + cy.get('.fd-shellbar') + .contains('Projects') + .click(); + cy.get('.fd-app__sidebar .fd-side-nav__item') + .contains('Project One') + .click(); + + cy.get('.fd-app__sidebar') + .contains('Hide left navigation') + .click(); + cy.get('.no-side-nav').should('exist'); cy.get('.fd-app__sidebar').should('not.be.visible'); }); diff --git a/core/examples/luigi-sample-angular/package-lock.json b/core/examples/luigi-sample-angular/package-lock.json index 5984ffdf40..6f8902823f 100644 --- a/core/examples/luigi-sample-angular/package-lock.json +++ b/core/examples/luigi-sample-angular/package-lock.json @@ -1790,7 +1790,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -2448,7 +2448,7 @@ }, "ansi-escapes": { "version": "1.4.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, @@ -5205,7 +5205,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -5472,7 +5472,7 @@ }, "mkdirp": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", "dev": true, "requires": { @@ -7194,7 +7194,7 @@ }, "is-ci": { "version": "1.0.10", - "resolved": "http://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", "dev": true, "requires": { @@ -7816,7 +7816,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -7889,7 +7889,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -7943,7 +7943,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -8919,7 +8919,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -8972,7 +8972,7 @@ }, "ora": { "version": "0.2.3", - "resolved": "http://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", "dev": true, "requires": { @@ -8990,7 +8990,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -10313,7 +10313,7 @@ }, "slice-ansi": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, diff --git a/core/examples/luigi-sample-angular/package.json b/core/examples/luigi-sample-angular/package.json index 86f4e3aa2a..5548914c63 100644 --- a/core/examples/luigi-sample-angular/package.json +++ b/core/examples/luigi-sample-angular/package.json @@ -50,7 +50,7 @@ "babel-preset-minify": "^0.5.0", "codelyzer": "^4.4.1", "concurrently": "^4.1.0", - "cypress": "^3.1.0", + "cypress": "^3.1.4", "ts-node": "~3.2.0", "tslint": "~5.7.0", "typescript": "~2.7.2",