From 34c33d7cf9f44950b0fb93da1a31191c1b5d89b8 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Dec 2021 14:04:11 -0600 Subject: [PATCH 01/17] Make it easier to override default test UUIDS in cypress.json --- cypress.json | 7 ++++++- cypress/support/index.ts | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cypress.json b/cypress.json index e06de8e4c5..dfa75fdc57 100644 --- a/cypress.json +++ b/cypress.json @@ -6,5 +6,10 @@ "pluginsFile": "cypress/plugins/index.ts", "fixturesFolder": "cypress/fixtures", "baseUrl": "http://localhost:4000", - "retries": 2 + "retries": 2, + "env": { + "DSPACE_TEST_COMMUNITY": "0958c910-2037-42a9-81c7-dca80e3892b4", + "DSPACE_TEST_COLLECTION": "282164f5-d325-4740-8dd1-fa4d6d3e7200", + "DSPACE_TEST_ENTITY_PUBLICATION": "e98b0f27-5c19-49a0-960d-eb6ad5287067" + } } \ No newline at end of file diff --git a/cypress/support/index.ts b/cypress/support/index.ts index e8b10b9cfb..5a30a5e002 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -21,6 +21,10 @@ import 'cypress-axe'; // Global constants used in tests -export const TEST_COLLECTION = '282164f5-d325-4740-8dd1-fa4d6d3e7200'; -export const TEST_COMMUNITY = '0958c910-2037-42a9-81c7-dca80e3892b4'; -export const TEST_ENTITY_PUBLICATION = 'e98b0f27-5c19-49a0-960d-eb6ad5287067'; +// May be overridden in our cypress.json config file using specified environment variables. +// Default UUIDs listed here are all in the Demo Entities Data set available at +// https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data +// (This is the data set used in our CI environment) +export const TEST_COLLECTION = Cypress.env("DSPACE_TEST_COLLECTION") || '282164f5-d325-4740-8dd1-fa4d6d3e7200'; +export const TEST_COMMUNITY = Cypress.env("DSPACE_TEST_COMMUNITY") || '0958c910-2037-42a9-81c7-dca80e3892b4'; +export const TEST_ENTITY_PUBLICATION = Cypress.env("DSPACE_TEST_ENTITY_PUBLICATION") || 'e98b0f27-5c19-49a0-960d-eb6ad5287067'; From 1f1c55d9dc7c8040420fccca5db01912a32ca3d8 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 17 Dec 2021 17:06:06 -0600 Subject: [PATCH 02/17] Add login e2e tests. Tweak cypress retries so they don't apply to running e2e locally via GUI --- cypress.json | 5 +- cypress/integration/login-modal.spec.ts | 77 +++++++++++++++++++++++++ cypress/support/index.ts | 6 +- 3 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 cypress/integration/login-modal.spec.ts diff --git a/cypress.json b/cypress.json index dfa75fdc57..2f3a1e8fe1 100644 --- a/cypress.json +++ b/cypress.json @@ -6,7 +6,10 @@ "pluginsFile": "cypress/plugins/index.ts", "fixturesFolder": "cypress/fixtures", "baseUrl": "http://localhost:4000", - "retries": 2, + "retries": { + "runMode": 2, + "openMode": 0 + }, "env": { "DSPACE_TEST_COMMUNITY": "0958c910-2037-42a9-81c7-dca80e3892b4", "DSPACE_TEST_COLLECTION": "282164f5-d325-4740-8dd1-fa4d6d3e7200", diff --git a/cypress/integration/login-modal.spec.ts b/cypress/integration/login-modal.spec.ts new file mode 100644 index 0000000000..da0eb4802a --- /dev/null +++ b/cypress/integration/login-modal.spec.ts @@ -0,0 +1,77 @@ +import { TEST_ENTITY_PUBLICATION } from 'cypress/support'; + +const page = { + openLoginMenu() { + // Click the closed "Log In" dropdown menu (to open Login menu) + cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + }, + submitLoginAndPassword() { + // In opened Login modal, fill out email & password, then click submit + cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type('dspacedemo+admin@gmail.com'); + cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('dspace'); + cy.get('ds-themed-navbar ds-log-in-password button[type = "submit"]').click(); + }, + submitLoginAndPasswordByPressingEnter() { + // In opened Login modal, fill out email & password, then click Enter + cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type('dspacedemo+admin@gmail.com'); + cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('dspace'); + cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('{enter}'); + }, +}; + +describe('Login Modal', () => { + it('should login when clicking button', () => { + cy.visit('/'); + + // Open login menu in header & verify tag is visible + page.openLoginMenu(); + cy.get('ds-log-in').should('be.visible'); + + // Login, and the tag should no longer exist + page.submitLoginAndPassword(); + cy.get('ds-log-in').should('not.exist'); + + // Open login menu again, verify user menu & logout button now available + page.openLoginMenu(); + cy.get('ds-user-menu').should('be.visible'); + cy.get('ds-log-out').should('be.visible'); + }); + + it('should login when clicking enter', () => { + cy.visit('/'); + + // Open login menu in header & verify tag is visible + page.openLoginMenu(); + cy.get('.form-login').should('be.visible'); + + // Login, and the tag should no longer exist + page.submitLoginAndPasswordByPressingEnter(); + cy.get('.form-login').should('not.exist'); + + // Open login menu again, verify user menu & logout button now available + page.openLoginMenu(); + cy.get('ds-user-menu').should('be.visible'); + cy.get('ds-log-out').should('be.visible'); + }); + + it('should stay on same page after login', () => { + const ENTITYPAGE = '/entities/publication/' + TEST_ENTITY_PUBLICATION; + cy.visit(ENTITYPAGE); + + // Open login menu in header & verify tag is visible + page.openLoginMenu(); + cy.get('ds-log-in').should('be.visible'); + + // Login, and the tag should no longer exist + page.submitLoginAndPassword(); + cy.get('ds-log-in').should('not.exist'); + + // Verify we are still on the same page + cy.url().should('include', ENTITYPAGE); + + // Open login menu again, verify user menu & logout button now available + page.openLoginMenu(); + cy.get('ds-user-menu').should('be.visible'); + cy.get('ds-log-out').should('be.visible'); + }); +}); diff --git a/cypress/support/index.ts b/cypress/support/index.ts index 5a30a5e002..de00a33534 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -25,6 +25,6 @@ import 'cypress-axe'; // Default UUIDs listed here are all in the Demo Entities Data set available at // https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data // (This is the data set used in our CI environment) -export const TEST_COLLECTION = Cypress.env("DSPACE_TEST_COLLECTION") || '282164f5-d325-4740-8dd1-fa4d6d3e7200'; -export const TEST_COMMUNITY = Cypress.env("DSPACE_TEST_COMMUNITY") || '0958c910-2037-42a9-81c7-dca80e3892b4'; -export const TEST_ENTITY_PUBLICATION = Cypress.env("DSPACE_TEST_ENTITY_PUBLICATION") || 'e98b0f27-5c19-49a0-960d-eb6ad5287067'; +export const TEST_COLLECTION = Cypress.env('DSPACE_TEST_COLLECTION') || '282164f5-d325-4740-8dd1-fa4d6d3e7200'; +export const TEST_COMMUNITY = Cypress.env('DSPACE_TEST_COMMUNITY') || '0958c910-2037-42a9-81c7-dca80e3892b4'; +export const TEST_ENTITY_PUBLICATION = Cypress.env('DSPACE_TEST_ENTITY_PUBLICATION') || 'e98b0f27-5c19-49a0-960d-eb6ad5287067'; From cb91ccbc33f7ed28f3bbdecffd3e51471ed93c86 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Tue, 21 Dec 2021 17:14:27 -0600 Subject: [PATCH 03/17] Refactor to use custom commands for login/logout & make admin user configurable --- cypress.json | 2 + cypress/integration/login-modal.spec.ts | 53 +++++++++------ cypress/support/commands.ts | 88 +++++++++++++------------ cypress/support/index.ts | 14 +++- 4 files changed, 93 insertions(+), 64 deletions(-) diff --git a/cypress.json b/cypress.json index 2f3a1e8fe1..104a672377 100644 --- a/cypress.json +++ b/cypress.json @@ -11,6 +11,8 @@ "openMode": 0 }, "env": { + "DSPACE_TEST_ADMIN_USER": "dspacedemo+admin@gmail.com", + "DSPACE_TEST_ADMIN_PASSWORD": "dspace", "DSPACE_TEST_COMMUNITY": "0958c910-2037-42a9-81c7-dca80e3892b4", "DSPACE_TEST_COLLECTION": "282164f5-d325-4740-8dd1-fa4d6d3e7200", "DSPACE_TEST_ENTITY_PUBLICATION": "e98b0f27-5c19-49a0-960d-eb6ad5287067" diff --git a/cypress/integration/login-modal.spec.ts b/cypress/integration/login-modal.spec.ts index da0eb4802a..a71101e591 100644 --- a/cypress/integration/login-modal.spec.ts +++ b/cypress/integration/login-modal.spec.ts @@ -1,34 +1,27 @@ -import { TEST_ENTITY_PUBLICATION } from 'cypress/support'; +import { TEST_ADMIN_PASSWORD, TEST_ADMIN_USER, TEST_ENTITY_PUBLICATION } from 'cypress/support'; const page = { openLoginMenu() { // Click the closed "Log In" dropdown menu (to open Login menu) cy.get('ds-auth-nav-menu.navbar-collapsed').click(); }, - submitLoginAndPassword() { - // In opened Login modal, fill out email & password, then click submit - cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type('dspacedemo+admin@gmail.com'); - cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('dspace'); - cy.get('ds-themed-navbar ds-log-in-password button[type = "submit"]').click(); - }, - submitLoginAndPasswordByPressingEnter() { + submitLoginAndPasswordByPressingEnter(email, password) { // In opened Login modal, fill out email & password, then click Enter - cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type('dspacedemo+admin@gmail.com'); - cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('dspace'); + cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type(email); + cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type(password); cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('{enter}'); - }, + } }; describe('Login Modal', () => { it('should login when clicking button', () => { cy.visit('/'); - // Open login menu in header & verify tag is visible - page.openLoginMenu(); - cy.get('ds-log-in').should('be.visible'); + // Login menu should exist + cy.get('ds-log-in').should('exist'); // Login, and the tag should no longer exist - page.submitLoginAndPassword(); + cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('ds-log-in').should('not.exist'); // Open login menu again, verify user menu & logout button now available @@ -37,7 +30,7 @@ describe('Login Modal', () => { cy.get('ds-log-out').should('be.visible'); }); - it('should login when clicking enter', () => { + it('should login when clicking enter key', () => { cy.visit('/'); // Open login menu in header & verify tag is visible @@ -45,7 +38,7 @@ describe('Login Modal', () => { cy.get('.form-login').should('be.visible'); // Login, and the tag should no longer exist - page.submitLoginAndPasswordByPressingEnter(); + page.submitLoginAndPasswordByPressingEnter(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('.form-login').should('not.exist'); // Open login menu again, verify user menu & logout button now available @@ -58,12 +51,11 @@ describe('Login Modal', () => { const ENTITYPAGE = '/entities/publication/' + TEST_ENTITY_PUBLICATION; cy.visit(ENTITYPAGE); - // Open login menu in header & verify tag is visible - page.openLoginMenu(); - cy.get('ds-log-in').should('be.visible'); + // Login menu should exist + cy.get('ds-log-in').should('exist'); // Login, and the tag should no longer exist - page.submitLoginAndPassword(); + cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('ds-log-in').should('not.exist'); // Verify we are still on the same page @@ -74,4 +66,23 @@ describe('Login Modal', () => { cy.get('ds-user-menu').should('be.visible'); cy.get('ds-log-out').should('be.visible'); }); + + it('logout should work', () => { + cy.visit('/'); + + cy.get('ds-log-in').should('exist'); + cy.get('ds-log-out').should('not.exist'); + + // Click login + cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); + + cy.get('ds-log-in').should('not.exist'); + cy.get('ds-log-out').should('exist'); + + // Click logout + cy.logout(); + + cy.get('ds-log-in').should('exist'); + cy.get('ds-log-out').should('not.exist'); + }); }); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index af1f44a0fc..b1994299fb 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,43 +1,49 @@ // *********************************************** -// This example namespace declaration will help -// with Intellisense and code completion in your -// IDE or Text Editor. +// This File is for Custom Cypress commands. +// See docs at https://docs.cypress.io/api/cypress-api/custom-commands // *********************************************** -// declare namespace Cypress { -// interface Chainable { -// customCommand(param: any): typeof customCommand; -// } -// } -// -// function customCommand(param: any): void { -// console.warn(param); -// } -// -// NOTE: You can use it like so: -// Cypress.Commands.add('customCommand', customCommand); -// -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add("login", (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) +// Declare Cypress namespace to help with Intellisense & code completion in IDEs +// ALL custom commands MUST be listed here for code completion to work +// tslint:disable-next-line:no-namespace +declare namespace Cypress { + interface Chainable { + login(email: string, password: string): typeof login; + logout(): typeof logout; + } +} + +/** + * Login from any page via DSpace's header menu + * @param email email to login as + * @param password password to login as + */ +function login(email: string, password: string): void { + // Click the closed "Log In" dropdown menu (to open Login menu) + cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + // Enter email + cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type(email); + // Enter password + cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type(password); + // Click login button + cy.get('ds-themed-navbar ds-log-in-password button[type = "submit"]').click(); +} +// Add as a Cypress command (i.e. assign to 'cy.login') +Cypress.Commands.add('login', login); + + +/** + * Logout from any page via DSpace's header menu. + * NOTE: Also waits until logout completes before next command will be run. + */ + function logout(): void { + // Click the closed User dropdown menu (to open user menu in header) + cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + // This is the POST command that will actually log us out + cy.intercept('POST', '/server/api/authn/logout').as('logout'); + // Click logout button + cy.get('ds-themed-navbar ds-log-out button').click(); + // Wait until above POST command responds before continuing + cy.wait('@logout'); +} +// Add as a Cypress command (i.e. assign to 'cy.logout') +Cypress.Commands.add('logout', logout); diff --git a/cypress/support/index.ts b/cypress/support/index.ts index de00a33534..9c29d45e3e 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -13,18 +13,28 @@ // https://on.cypress.io/configuration // *********************************************************** -// When a command from ./commands is ready to use, import with `import './commands'` syntax -// import './commands'; +// Import all custom Commands (from commands.ts) for all tests +import './commands'; // Import Cypress Axe tools for all tests // https://github.com/component-driven/cypress-axe import 'cypress-axe'; +// Runs once before the first test in each "block" +before(() => { + // Pre-agree to all Klaro cookies by setting the klaro-anonymous cookie + // This just ensures it doesn't get in the way of matching other objects in the page. + cy.setCookie('klaro-anonymous', '{%22authentication%22:true%2C%22preferences%22:true%2C%22acknowledgement%22:true%2C%22google-analytics%22:true}'); +}); + + // Global constants used in tests // May be overridden in our cypress.json config file using specified environment variables. // Default UUIDs listed here are all in the Demo Entities Data set available at // https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data // (This is the data set used in our CI environment) +export const TEST_ADMIN_USER = Cypress.env('DSPACE_TEST_ADMIN_USER') || 'dspacedemo+admin@gmail.com'; +export const TEST_ADMIN_PASSWORD = Cypress.env('DSPACE_TEST_ADMIN_PASSWORD') || 'dspace'; export const TEST_COLLECTION = Cypress.env('DSPACE_TEST_COLLECTION') || '282164f5-d325-4740-8dd1-fa4d6d3e7200'; export const TEST_COMMUNITY = Cypress.env('DSPACE_TEST_COMMUNITY') || '0958c910-2037-42a9-81c7-dca80e3892b4'; export const TEST_ENTITY_PUBLICATION = Cypress.env('DSPACE_TEST_ENTITY_PUBLICATION') || 'e98b0f27-5c19-49a0-960d-eb6ad5287067'; From 794aa33c8f1ef75947da5e3b697b0ce6cee339c0 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Fri, 7 Jan 2022 15:11:12 -0600 Subject: [PATCH 04/17] Refactor to use "data-e2e" attributes in code to make selecting fields/buttons easier in e2e tests --- cypress/integration/homepage.spec.ts | 4 +- cypress/integration/login-modal.spec.ts | 60 +++++++++++++------ cypress/integration/search-navbar.spec.ts | 23 +++++-- cypress/integration/search-page.spec.ts | 14 ++--- cypress/support/commands.ts | 12 ++-- .../search-navbar.component.html | 4 +- .../auth-nav-menu.component.html | 4 +- src/app/shared/log-in/log-in.component.html | 4 +- .../password/log-in-password.component.html | 8 ++- src/app/shared/log-out/log-out.component.html | 2 +- .../search-form/search-form.component.html | 4 +- .../view-mode-switch.component.html | 9 ++- 12 files changed, 94 insertions(+), 54 deletions(-) diff --git a/cypress/integration/homepage.spec.ts b/cypress/integration/homepage.spec.ts index ddde260bc7..7685c2c108 100644 --- a/cypress/integration/homepage.spec.ts +++ b/cypress/integration/homepage.spec.ts @@ -16,8 +16,8 @@ describe('Homepage', () => { it('should have a working search box', () => { const queryString = 'test'; - cy.get('ds-search-form input[name="query"]').type(queryString); - cy.get('ds-search-form button.search-button').click(); + cy.get('[data-e2e="search-box"]').type(queryString); + cy.get('[data-e2e="search-button"]').click(); cy.url().should('include', '/search'); cy.url().should('include', 'query=' + encodeURI(queryString)); }); diff --git a/cypress/integration/login-modal.spec.ts b/cypress/integration/login-modal.spec.ts index a71101e591..82b322c4a9 100644 --- a/cypress/integration/login-modal.spec.ts +++ b/cypress/integration/login-modal.spec.ts @@ -2,14 +2,18 @@ import { TEST_ADMIN_PASSWORD, TEST_ADMIN_USER, TEST_ENTITY_PUBLICATION } from 'c const page = { openLoginMenu() { - // Click the closed "Log In" dropdown menu (to open Login menu) - cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + // Click the "Log In" dropdown menu in header + cy.get('ds-themed-navbar [data-e2e="login-menu"]').click(); + }, + openUserMenu() { + // Once logged in, click the User menu in header + cy.get('ds-themed-navbar [data-e2e="user-menu"]').click(); }, submitLoginAndPasswordByPressingEnter(email, password) { // In opened Login modal, fill out email & password, then click Enter - cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type(email); - cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type(password); - cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type('{enter}'); + cy.get('ds-themed-navbar [data-e2e="email"]').type(email); + cy.get('ds-themed-navbar [data-e2e="password"]').type(password); + cy.get('ds-themed-navbar [data-e2e="password"]').type('{enter}'); } }; @@ -24,8 +28,8 @@ describe('Login Modal', () => { cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('ds-log-in').should('not.exist'); - // Open login menu again, verify user menu & logout button now available - page.openLoginMenu(); + // Open user menu, verify user menu & logout button now available + page.openUserMenu(); cy.get('ds-user-menu').should('be.visible'); cy.get('ds-log-out').should('be.visible'); }); @@ -41,8 +45,8 @@ describe('Login Modal', () => { page.submitLoginAndPasswordByPressingEnter(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('.form-login').should('not.exist'); - // Open login menu again, verify user menu & logout button now available - page.openLoginMenu(); + // Open user menu, verify user menu & logout button now available + page.openUserMenu(); cy.get('ds-user-menu').should('be.visible'); cy.get('ds-log-out').should('be.visible'); }); @@ -51,23 +55,15 @@ describe('Login Modal', () => { const ENTITYPAGE = '/entities/publication/' + TEST_ENTITY_PUBLICATION; cy.visit(ENTITYPAGE); - // Login menu should exist - cy.get('ds-log-in').should('exist'); - // Login, and the tag should no longer exist cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD); cy.get('ds-log-in').should('not.exist'); // Verify we are still on the same page cy.url().should('include', ENTITYPAGE); - - // Open login menu again, verify user menu & logout button now available - page.openLoginMenu(); - cy.get('ds-user-menu').should('be.visible'); - cy.get('ds-log-out').should('be.visible'); }); - it('logout should work', () => { + it('should support logout', () => { cy.visit('/'); cy.get('ds-log-in').should('exist'); @@ -85,4 +81,32 @@ describe('Login Modal', () => { cy.get('ds-log-in').should('exist'); cy.get('ds-log-out').should('not.exist'); }); + + it('should allow new user registration', () => { + cy.visit('/'); + + page.openLoginMenu(); + + // Registration link should be visible + cy.get('ds-themed-navbar [data-e2e="register"]').should('be.visible'); + + // Click registration link & you should go to registration page + cy.get('ds-themed-navbar [data-e2e="register"]').click(); + cy.location('pathname').should('eq', '/register'); + cy.get('ds-register-email').should('exist'); + }); + + it('should allow forgot password', () => { + cy.visit('/'); + + page.openLoginMenu(); + + // Forgot password link should be visible + cy.get('ds-themed-navbar [data-e2e="forgot"]').should('be.visible'); + + // Click link & you should go to Forgot Password page + cy.get('ds-themed-navbar [data-e2e="forgot"]').click(); + cy.location('pathname').should('eq', '/forgot'); + cy.get('ds-forgot-email').should('exist'); + }); }); diff --git a/cypress/integration/search-navbar.spec.ts b/cypress/integration/search-navbar.spec.ts index 19a3d56ed4..53e713412e 100644 --- a/cypress/integration/search-navbar.spec.ts +++ b/cypress/integration/search-navbar.spec.ts @@ -1,15 +1,15 @@ const page = { fillOutQueryInNavBar(query) { // Click the magnifying glass - cy.get('.navbar-container #search-navbar-container form a').click(); + cy.get('ds-themed-navbar [data-e2e="header-search-icon"]').click(); // Fill out a query in input that appears - cy.get('.navbar-container #search-navbar-container form input[name = "query"]').type(query); + cy.get('ds-themed-navbar [data-e2e="header-search-box"]').type(query); }, submitQueryByPressingEnter() { - cy.get('.navbar-container #search-navbar-container form input[name = "query"]').type('{enter}'); + cy.get('ds-themed-navbar [data-e2e="header-search-box"]').type('{enter}'); }, submitQueryByPressingIcon() { - cy.get('.navbar-container #search-navbar-container form .submit-icon').click(); + cy.get('ds-themed-navbar [data-e2e="header-search-icon"]').click(); } }; @@ -19,30 +19,45 @@ describe('Search from Navigation Bar', () => { it('should go to search page with correct query if submitted (from home)', () => { cy.visit('/'); + // This is the GET command that will actually run the search + cy.intercept('GET', '/server/api/discover/search/objects*').as('search-results'); + // Run the search page.fillOutQueryInNavBar(query); page.submitQueryByPressingEnter(); // New URL should include query param cy.url().should('include', 'query=' + query); + // Wait for search results to come back from the above GET command + cy.wait('@search-results'); // At least one search result should be displayed cy.get('ds-item-search-result-list-element').should('be.visible'); }); it('should go to search page with correct query if submitted (from search)', () => { cy.visit('/search'); + // This is the GET command that will actually run the search + cy.intercept('GET', '/server/api/discover/search/objects*').as('search-results'); + // Run the search page.fillOutQueryInNavBar(query); page.submitQueryByPressingEnter(); // New URL should include query param cy.url().should('include', 'query=' + query); + // Wait for search results to come back from the above GET command + cy.wait('@search-results'); // At least one search result should be displayed cy.get('ds-item-search-result-list-element').should('be.visible'); }); it('should allow user to also submit query by clicking icon', () => { cy.visit('/'); + // This is the GET command that will actually run the search + cy.intercept('GET', '/server/api/discover/search/objects*').as('search-results'); + // Run the search page.fillOutQueryInNavBar(query); page.submitQueryByPressingIcon(); // New URL should include query param cy.url().should('include', 'query=' + query); + // Wait for search results to come back from the above GET command + cy.wait('@search-results'); // At least one search result should be displayed cy.get('ds-item-search-result-list-element').should('be.visible'); }); diff --git a/cypress/integration/search-page.spec.ts b/cypress/integration/search-page.spec.ts index 859c765d2e..0765884952 100644 --- a/cypress/integration/search-page.spec.ts +++ b/cypress/integration/search-page.spec.ts @@ -2,21 +2,18 @@ import { Options } from 'cypress-axe'; import { testA11y } from 'cypress/support/utils'; describe('Search Page', () => { - // unique ID of the search form (for selecting specific elements below) - const SEARCHFORM_ID = '#search-form'; - it('should contain query value when navigating to page with query parameter', () => { const queryString = 'test query'; cy.visit('/search?query=' + queryString); - cy.get(SEARCHFORM_ID + ' input[name="query"]').should('have.value', queryString); + cy.get('[data-e2e="search-box"]').should('have.value', queryString); }); it('should redirect to the correct url when query was set and submit button was triggered', () => { const queryString = 'Another interesting query string'; cy.visit('/search'); // Type query in searchbox & click search button - cy.get(SEARCHFORM_ID + ' input[name="query"]').type(queryString); - cy.get(SEARCHFORM_ID + ' button.search-button').click(); + cy.get('[data-e2e="search-box"]').type(queryString); + cy.get('[data-e2e="search-button"]').click(); cy.url().should('include', 'query=' + encodeURI(queryString)); }); @@ -51,9 +48,8 @@ describe('Search Page', () => { it('should pass accessibility tests in Grid view', () => { cy.visit('/search'); - // Click to display grid view - // TODO: These buttons should likely have an easier way to uniquely select - cy.get('#search-sidebar-content > ds-view-mode-switch > .btn-group > [href="/search?view=grid"] > .fas').click(); + // Click button in sidebar to display grid view + cy.get('ds-search-sidebar [data-e2e="grid-view"]').click(); // tag must be loaded cy.get('ds-search-page').should('exist'); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index b1994299fb..67e604d2e7 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -19,13 +19,13 @@ declare namespace Cypress { */ function login(email: string, password: string): void { // Click the closed "Log In" dropdown menu (to open Login menu) - cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + cy.get('ds-themed-navbar [data-e2e="login-menu"]').click(); // Enter email - cy.get('ds-themed-navbar ds-log-in-password input[type = "email"]').type(email); + cy.get('ds-themed-navbar [data-e2e="email"]').type(email); // Enter password - cy.get('ds-themed-navbar ds-log-in-password input[type = "password"]').type(password); + cy.get('ds-themed-navbar [data-e2e="password"]').type(password); // Click login button - cy.get('ds-themed-navbar ds-log-in-password button[type = "submit"]').click(); + cy.get('ds-themed-navbar [data-e2e="login-button"]').click(); } // Add as a Cypress command (i.e. assign to 'cy.login') Cypress.Commands.add('login', login); @@ -37,11 +37,11 @@ Cypress.Commands.add('login', login); */ function logout(): void { // Click the closed User dropdown menu (to open user menu in header) - cy.get('ds-auth-nav-menu.navbar-collapsed').click(); + cy.get('ds-themed-navbar [data-e2e="user-menu"]').click(); // This is the POST command that will actually log us out cy.intercept('POST', '/server/api/authn/logout').as('logout'); // Click logout button - cy.get('ds-themed-navbar ds-log-out button').click(); + cy.get('ds-themed-navbar [data-e2e="logout-button"]').click(); // Wait until above POST command responds before continuing cy.wait('@logout'); } diff --git a/src/app/search-navbar/search-navbar.component.html b/src/app/search-navbar/search-navbar.component.html index 693c7daef8..05b3d13b1b 100644 --- a/src/app/search-navbar/search-navbar.component.html +++ b/src/app/search-navbar/search-navbar.component.html @@ -3,8 +3,8 @@
- + class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" data-e2e="header-search-box"> +
diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html index 80fdeda394..3f06f9f42c 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html @@ -1,7 +1,7 @@