diff --git a/cypress.config.ts b/cypress.config.ts index d394b94c6120652beb715cd02534e8d7ab776d4d..79007a3968c6170b1ccae5e03a57cd5ecae9d2b3 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -8,6 +8,8 @@ export default defineConfig({ // implement node event listeners here }, baseUrl: "http://localhost:4200/", - pageLoadTimeout: 8000 + pageLoadTimeout: 8000, + viewportWidth: 1500, + viewportHeight: 900, }, }); diff --git a/cypress/e2e/auth.cy.ts b/cypress/e2e/auth.cy.ts new file mode 100644 index 0000000000000000000000000000000000000000..b0345eeb21dc990df9b1c344d5b2b10ad94fa7b6 --- /dev/null +++ b/cypress/e2e/auth.cy.ts @@ -0,0 +1,121 @@ +describe('user authentication', () => { + beforeEach(() => { + cy.visit(window.location.origin); + }) + //edit profile bug + it('should block unauthenticated user from entering a protected route', () => { + cy.checkProtectedRoutes(); + }); + + it('should display login errors when nothing is typed', () => { + cy.get(':nth-child(1) > .nav-link').click(); + cy.location("pathname").should("equal", '/services'); + cy.get('.btn').should("contain", "Sign In").click(); + cy.origin('https://portal.openslice.eu', () => { + cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth"); + cy.get('#kc-login').click(); + cy.get('#input-error').should('be.visible').and('contain','Invalid username or password.'); + cy.get('[aria-invalid="true"]').should('have.length', 2); //the 2 input fields should have selector aria-invalid = 'true' + + }); + + }); + + it('should display login errors when credentials are wrong', () => { + cy.get(':nth-child(1) > .nav-link').click(); + cy.location("pathname").should("equal", '/services'); + cy.get('.btn').should("contain", "Sign In").click(); + cy.origin('https://portal.openslice.eu', () => { + + cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth"); + + cy.get('#username').type('test').blur(); + cy.get('#password').type('test').blur(); + cy.get('#kc-login').click(); + cy.get('#input-error').should('be.visible').and('contain','Invalid username or password.'); + cy.get('[aria-invalid="true"]').should('have.length', 2); //the 2 input fields should have selector aria-invalid = 'true' + + }); + }); + + it('should login, logout', () => { + cy.loginPath(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn', '/services'); + cy.get('#navbarDropdown2').click(); + cy.window().then((win) => { + expect(win.localStorage.getItem('access_token')).to.exist; + }) + + cy.get(':nth-child(2) > .dropdown > .dropdown-menu > :nth-child(8)').click(); + cy.location("pathname").should("equal", "/"); + }); + + it.skip('forget password should work', () => { + cy.get(':nth-child(1) > .nav-link').click(); + cy.location("pathname").should("equal", '/services'); + cy.get('.btn').should("contain", "Sign In").click(); + cy.origin('https://portal.openslice.eu', () => { + + cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth"); + cy.get(':nth-child(2) > span > a').click(); + cy.location("pathname").should("equal", "/auth/realms/openslice/login-actions/reset-credentials"); + cy.get('#username').should('exist'); + + }); + }); + + context('register form', () => { + beforeEach(() => { + cy.get(':nth-child(1) > .nav-link').click(); + cy.location("pathname").should("equal", '/services'); + cy.get('.btn').should("contain", "Sign In").click(); + cy.origin('https://portal.openslice.eu', () => { + + cy.location("pathname").should("equal", "/auth/realms/openslice/protocol/openid-connect/auth"); + cy.get('#kc-registration > span > a').click(); + cy.location("pathname").should("equal", "/auth/realms/openslice/login-actions/registration"); + + }); + }) + it('register form should not be empty when submitted', () => { + + cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => { + + cy.get('.pf-c-button').click(); + cy.get('#input-error-firstname').should('exist').and('contain', 'Please specify first name.'); + cy.get('#input-error-lastname').should('exist').and('contain', 'Please specify last name.'); + cy.get('#input-error-email').should('exist').and('contain', 'Please specify email.'); + cy.get('#input-error-username').should('exist').and('contain', 'Please specify username.'); + cy.get('#input-error-password').should('exist').and('contain', 'Please specify password.'); + }); + + }); + + it('invalid email', () => { + cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => { + + cy.get('#email').type('email'); + cy.get('.pf-c-button').click(); + cy.get('#input-error-email').should('exist').and('contain','Invalid email address.'); + cy.get('#email').type('@example.com'); + cy.get('.pf-c-button').click(); + cy.get('#input-error-email').should('not.exist'); + }); + }); + + it('confirm password field should be the same with password', () => { + cy.origin('https://portal.openslice.eu/auth/realms/openslice/login-actions/registration', () => { + cy.get('#password').type('123'); + cy.get('#password-confirm').type('1234'); + cy.get('.pf-c-button').click(); + cy.get('#input-error-password-confirm').should('exist').and('contain',"Password confirmation doesn't match."); + cy.get('#password').type('123'); + cy.get('#password-confirm').type('123'); + cy.get('.pf-c-button').click(); + cy.get('#input-error-password-confirm').should('not.exist'); + }); + }); + + + }) + +}) \ No newline at end of file diff --git a/cypress/e2e/user-journeys-logged-in.cy.ts b/cypress/e2e/user-journeys-logged-in.cy.ts index 3dedd502a455f70bc5f01d55b3c097a5671167d8..f1b53dc6d96f9c8a30ebf74f4114e18f3ff4ada7 100644 --- a/cypress/e2e/user-journeys-logged-in.cy.ts +++ b/cypress/e2e/user-journeys-logged-in.cy.ts @@ -11,44 +11,44 @@ describe('logged user journeys', () => { cy.location("pathname").should("equal", "/"); }); it('logs in through services', () => { - cy.loginPath(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn', '/services'); - //back on services marketplace after login - cy.location("pathname").should("equal", "/services/services_marketplace"); - //check every 'Manage Services' dropdown item + cy.loginPath(':nth-child(2) > .container > .row > :nth-child(2) > a > .btn', '/services'); + //back on services marketplace after login + cy.location("pathname").should("equal", "/services/services_marketplace"); + //check every 'Manage Services' dropdown item + cy.get(':nth-child(2) > #navbarDropdown').click(); + let i=0; + cy.get('.show .dropdown-item').each(($el) => { + i++; + cy.wrap($el).click(); // Click the link + cy.get(':nth-child(1) > .cdk-column-actions > .btn').first().click(); + + //does the dialog open? + cy.get('mat-dialog-container').should('exist'); + cy.go('back'); cy.get(':nth-child(2) > #navbarDropdown').click(); - let i=0; - cy.get('.show .dropdown-item').each(($el) => { - i++; - cy.wrap($el).click(); // Click the link - cy.get(':nth-child(1) > .cdk-column-actions > .btn').first().click(); - - //does the dialog open? - cy.get('mat-dialog-container').should('exist'); - cy.go('back'); - cy.get(':nth-child(2) > #navbarDropdown').click(); - if(i>1) { - return false; - } - }); - //access the service specs dropdown - cy.get('#navbarDropdown1').click(); - let j=0; - for(let i=1; i<=2; i++) { - cy.get(`.dropdown-submenu > .dropdown-menu > :nth-child(${i}) `).click(); - cy.location("pathname").should("not.equal", "/services/services_marketplace"); - cy.go('back'); - cy.get(':nth-child(2) > #navbarDropdown').click(); - cy.get('#navbarDropdown1').click(); + if(i>1) { + return false; } - //check the rest dropdown items - cy.get(':nth-child(4) > .dropdown-item').click(); - cy.get('mat-dialog-container').should('exist'); + }); + //access the service specs dropdown + cy.get('#navbarDropdown1').click(); + let j=0; + for(let i=1; i<=2; i++) { + cy.get(`.dropdown-submenu > .dropdown-menu > :nth-child(${i}) `).click(); + cy.location("pathname").should("not.equal", "/services/services_marketplace"); cy.go('back'); cy.get(':nth-child(2) > #navbarDropdown').click(); - - //'Manage Entities' dropdown - cy.manageEntities(':nth-child(3) > #navbarDropdown', '.jumbotron-heading > .btn', 2, 2); - + cy.get('#navbarDropdown1').click(); + } + //check the rest dropdown items + cy.get(':nth-child(4) > .dropdown-item').click(); + cy.get('mat-dialog-container').should('exist'); + cy.go('back'); + cy.get(':nth-child(2) > #navbarDropdown').click(); + + //'Manage Entities' dropdown + cy.manageEntities(':nth-child(3) > #navbarDropdown', '.jumbotron-heading > .btn', 2, 2); + }); it('logs in through resources', () => { cy.loginPath(':nth-child(3) > .container > .row > .order-md-1 > a > .btn', '/resources'); diff --git a/cypress/e2e/user-journeys.cy.ts b/cypress/e2e/user-journeys.cy.ts index 2dc4dc5bc554de4095afdcd97326773eeff5e9f0..32ac038ffeb6f54922fe23224f54f0f366e408d2 100644 --- a/cypress/e2e/user-journeys.cy.ts +++ b/cypress/e2e/user-journeys.cy.ts @@ -50,6 +50,9 @@ describe('user journey', () => { }) }); context('<who we are> links', () => { + beforeEach(() => { + cy.get('[id="contact"]').scrollIntoView().should('be.visible'); + }) it('checks ETSI SDG OpenSlice Link', () => { cy.get('.ng-star-inserted > :nth-child(1) > .text-white').click(); cy.origin('https://osl.etsi.org/', () => { @@ -102,9 +105,9 @@ describe('user journey', () => { //never loads, timeout it.skip('opens terms and conditions', () => { cy.get('[href="https://osl.etsi.org/files/SDG_OSL_Terms_and_Conditions.pdf"]').click(); - // cy.origin('https://osl.etsi.org/files/SDG_OSL_Terms_and_Conditions.pdf/', () => { - // cy.location("pathname").should("equal", "/files/SDG_OSL_Terms_and_Conditions.pdf/") - // }) + cy.origin('https://osl.etsi.org/files/SDG_OSL_Terms_and_Conditions.pdf/', () => { + cy.location("pathname").should("equal", "/files/SDG_OSL_Terms_and_Conditions.pdf/") + }) }) it('checks osl etsi link', () => { cy.get('[target="_blank"]').click(); diff --git a/cypress/screenshots/auth.cy.ts/user authentication -- should block unauthenticated user from entering a protected route (failed).png b/cypress/screenshots/auth.cy.ts/user authentication -- should block unauthenticated user from entering a protected route (failed).png new file mode 100644 index 0000000000000000000000000000000000000000..124174744ad8df08385027dd092c9c75dd7702ee Binary files /dev/null and b/cypress/screenshots/auth.cy.ts/user authentication -- should block unauthenticated user from entering a protected route (failed).png differ diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 14577b31beafd0166f3b6af088026c6e8f222319..ce4b466d11fb847d240aec3f3027baaea08e4a65 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -7,11 +7,29 @@ declare namespace Cypress { navigateToProducts(selector): Chainable<any>, authUser(): Chainable<any>, loginPath(selector, path): Chainable<any>, - manageEntities(selector, button, scndIndx, numOfItems): Chainable<any> + manageEntities(selector, button, scndIndx, numOfItems): Chainable<any>, + checkProtectedRoutes(): Chainable<any> } } - +const protectedRoutes = ['/services/service_catalogs', '/services/service_categories', + '/services/service_specs', '/services/service_spec_update', + '/services/list_nsds', '/services/list_tests', + '/services/service_orders', '/services/service_inventory', + '/services/organizations', '/services/individuals', + '/services/alarms', '/services/action_specs', + '/services/action_rules', '/services/service_order_checkout', + '/services/individual_update/myuser', '/resources/resource_catalogs', + '/resources/resource_categories', '/resources/resource_specs', + '/resources/resource_spec_update', '/resources/resource_inventory', + '/resources/resource_pools', '/resources/resource_reservations', + '/resources/individual_update/myuser', '/testing/service_test_specs', + '/testing/service_tests', '/testing/organizations', '/testing/individuals', + '/testing/individual_update/myuser', '/products/product_catalogs', + '/products/product_categories', '/products/product_offerings', + '/products/product_specs', '/products/organizations', '/products/individuals', + '/products/individual_update/myuser' +]; Cypress.Commands.add('navigateToServices', (selector) => { cy.get(selector).click(); @@ -98,6 +116,7 @@ Cypress.Commands.add('authUser', () => { Cypress.Commands.add('loginPath', (selector, path) => { cy.get(selector).click(); + cy.intercept(path); cy.location("pathname").should("equal", path); cy.authUser(); }) @@ -116,4 +135,13 @@ Cypress.Commands.add('manageEntities', (selector, button, scndIndx, numOfItems) cy.get(button).click(); cy.go('back'); } +}) + +Cypress.Commands.add('checkProtectedRoutes', () => { + for(let route of protectedRoutes) { + cy.intercept(route); + cy.log(route); + cy.visit(route); + cy.location("pathname").should("equal", "/"); + } }) \ No newline at end of file diff --git a/cypress/support/protected.routes.ts b/cypress/support/protected.routes.ts new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391