mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
Refactor to ensure cy.login() custom command logs in programmatically (which is faster). Move UI login tests to login-modal.spec.ts
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
"openMode": 0
|
"openMode": 0
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
|
"DSPACE_TEST_REST_BASE_URL": "http://localhost:8080",
|
||||||
"DSPACE_TEST_ADMIN_USER": "dspacedemo+admin@gmail.com",
|
"DSPACE_TEST_ADMIN_USER": "dspacedemo+admin@gmail.com",
|
||||||
"DSPACE_TEST_ADMIN_PASSWORD": "dspace",
|
"DSPACE_TEST_ADMIN_PASSWORD": "dspace",
|
||||||
"DSPACE_TEST_COMMUNITY": "0958c910-2037-42a9-81c7-dca80e3892b4",
|
"DSPACE_TEST_COMMUNITY": "0958c910-2037-42a9-81c7-dca80e3892b4",
|
||||||
|
@@ -9,33 +9,57 @@ const page = {
|
|||||||
// Once logged in, click the User menu in header
|
// Once logged in, click the User menu in header
|
||||||
cy.get('ds-themed-navbar [data-e2e="user-menu"]').click();
|
cy.get('ds-themed-navbar [data-e2e="user-menu"]').click();
|
||||||
},
|
},
|
||||||
|
submitLoginAndPasswordByPressingButton(email, password) {
|
||||||
|
// Enter email
|
||||||
|
cy.get('ds-themed-navbar [data-e2e="email"]').type(email);
|
||||||
|
// Enter password
|
||||||
|
cy.get('ds-themed-navbar [data-e2e="password"]').type(password);
|
||||||
|
// Click login button
|
||||||
|
cy.get('ds-themed-navbar [data-e2e="login-button"]').click();
|
||||||
|
},
|
||||||
submitLoginAndPasswordByPressingEnter(email, password) {
|
submitLoginAndPasswordByPressingEnter(email, password) {
|
||||||
// In opened Login modal, fill out email & password, then click Enter
|
// In opened Login modal, fill out email & password, then click Enter
|
||||||
cy.get('ds-themed-navbar [data-e2e="email"]').type(email);
|
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(password);
|
||||||
cy.get('ds-themed-navbar [data-e2e="password"]').type('{enter}');
|
cy.get('ds-themed-navbar [data-e2e="password"]').type('{enter}');
|
||||||
|
},
|
||||||
|
submitLogoutByPressingButton() {
|
||||||
|
// 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 [data-e2e="logout-button"]').click();
|
||||||
|
// Wait until above POST command responds before continuing
|
||||||
|
// (This ensures next action waits until logout completes)
|
||||||
|
cy.wait('@logout');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Login Modal', () => {
|
describe('Login Modal', () => {
|
||||||
it('should login when clicking button', () => {
|
it('should login when clicking button & stay on same page', () => {
|
||||||
cy.visit('/');
|
const ENTITYPAGE = '/entities/publication/' + TEST_ENTITY_PUBLICATION;
|
||||||
|
cy.visit(ENTITYPAGE);
|
||||||
|
|
||||||
// Login menu should exist
|
// Login menu should exist
|
||||||
cy.get('ds-log-in').should('exist');
|
cy.get('ds-log-in').should('exist');
|
||||||
|
|
||||||
// Login, and the <ds-log-in> tag should no longer exist
|
// Login, and the <ds-log-in> tag should no longer exist
|
||||||
cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD);
|
page.openLoginMenu();
|
||||||
|
cy.get('.form-login').should('be.visible');
|
||||||
|
|
||||||
|
page.submitLoginAndPasswordByPressingButton(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD);
|
||||||
cy.get('ds-log-in').should('not.exist');
|
cy.get('ds-log-in').should('not.exist');
|
||||||
|
|
||||||
|
// Verify we are still on the same page
|
||||||
|
cy.url().should('include', ENTITYPAGE);
|
||||||
|
|
||||||
// Open user menu, verify user menu & logout button now available
|
// Open user menu, verify user menu & logout button now available
|
||||||
page.openUserMenu();
|
page.openUserMenu();
|
||||||
cy.get('ds-user-menu').should('be.visible');
|
cy.get('ds-user-menu').should('be.visible');
|
||||||
cy.get('ds-log-out').should('be.visible');
|
cy.get('ds-log-out').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should login when clicking enter key', () => {
|
it('should login when clicking enter key & stay on same page', () => {
|
||||||
cy.visit('/');
|
cy.visit('/home');
|
||||||
|
|
||||||
// Open login menu in header & verify <ds-log-in> tag is visible
|
// Open login menu in header & verify <ds-log-in> tag is visible
|
||||||
page.openLoginMenu();
|
page.openLoginMenu();
|
||||||
@@ -45,39 +69,29 @@ describe('Login Modal', () => {
|
|||||||
page.submitLoginAndPasswordByPressingEnter(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD);
|
page.submitLoginAndPasswordByPressingEnter(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD);
|
||||||
cy.get('.form-login').should('not.exist');
|
cy.get('.form-login').should('not.exist');
|
||||||
|
|
||||||
|
// Verify we are still on homepage
|
||||||
|
cy.url().should('include', '/home');
|
||||||
|
|
||||||
// Open user menu, verify user menu & logout button now available
|
// Open user menu, verify user menu & logout button now available
|
||||||
page.openUserMenu();
|
page.openUserMenu();
|
||||||
cy.get('ds-user-menu').should('be.visible');
|
cy.get('ds-user-menu').should('be.visible');
|
||||||
cy.get('ds-log-out').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);
|
|
||||||
|
|
||||||
// Login, and the <ds-log-in> 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);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support logout', () => {
|
it('should support logout', () => {
|
||||||
|
// First authenticate & access homepage
|
||||||
|
cy.login(TEST_ADMIN_USER, TEST_ADMIN_PASSWORD);
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
|
||||||
cy.get('ds-log-in').should('exist');
|
// Verify ds-log-in tag doesn't exist, but ds-log-out tag does 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-in').should('not.exist');
|
||||||
cy.get('ds-log-out').should('exist');
|
cy.get('ds-log-out').should('exist');
|
||||||
|
|
||||||
// Click logout
|
// Click logout button
|
||||||
cy.logout();
|
page.openUserMenu();
|
||||||
|
page.submitLogoutByPressingButton();
|
||||||
|
|
||||||
|
// Verify ds-log-in tag now exists
|
||||||
cy.get('ds-log-in').should('exist');
|
cy.get('ds-log-in').should('exist');
|
||||||
cy.get('ds-log-out').should('not.exist');
|
cy.get('ds-log-out').should('not.exist');
|
||||||
});
|
});
|
||||||
|
@@ -2,48 +2,63 @@
|
|||||||
// This File is for Custom Cypress commands.
|
// This File is for Custom Cypress commands.
|
||||||
// See docs at https://docs.cypress.io/api/cypress-api/custom-commands
|
// See docs at https://docs.cypress.io/api/cypress-api/custom-commands
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
|
|
||||||
|
import { AuthTokenInfo, TOKENITEM } from 'src/app/core/auth/models/auth-token-info.model';
|
||||||
|
import { TEST_REST_BASE_URL } from '.';
|
||||||
|
|
||||||
// Declare Cypress namespace to help with Intellisense & code completion in IDEs
|
// Declare Cypress namespace to help with Intellisense & code completion in IDEs
|
||||||
// ALL custom commands MUST be listed here for code completion to work
|
// ALL custom commands MUST be listed here for code completion to work
|
||||||
// tslint:disable-next-line:no-namespace
|
// tslint:disable-next-line:no-namespace
|
||||||
declare namespace Cypress {
|
declare global {
|
||||||
|
namespace Cypress {
|
||||||
interface Chainable<Subject = any> {
|
interface Chainable<Subject = any> {
|
||||||
|
/**
|
||||||
|
* Login to backend before accessing the next page. Ensures that the next
|
||||||
|
* call to "cy.visit()" will be authenticated as this user.
|
||||||
|
* @param email email to login as
|
||||||
|
* @param password password to login as
|
||||||
|
*/
|
||||||
login(email: string, password: string): typeof login;
|
login(email: string, password: string): typeof login;
|
||||||
logout(): typeof logout;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login from any page via DSpace's header menu
|
* Login user via REST API directly, and pass authentication token to UI via
|
||||||
|
* the UI's dsAuthInfo cookie.
|
||||||
* @param email email to login as
|
* @param email email to login as
|
||||||
* @param password password to login as
|
* @param password password to login as
|
||||||
*/
|
*/
|
||||||
function login(email: string, password: string): void {
|
function login(email: string, password: string): void {
|
||||||
// Click the closed "Log In" dropdown menu (to open Login menu)
|
// To login via REST, first we have to do a GET to obtain a valid CSRF token
|
||||||
cy.get('ds-themed-navbar [data-e2e="login-menu"]').click();
|
cy.request( TEST_REST_BASE_URL + '/server/api/authn/status' )
|
||||||
// Enter email
|
.then((response) => {
|
||||||
cy.get('ds-themed-navbar [data-e2e="email"]').type(email);
|
// We should receive a CSRF token returned in a response header
|
||||||
// Enter password
|
expect(response.headers).to.have.property('dspace-xsrf-token');
|
||||||
cy.get('ds-themed-navbar [data-e2e="password"]').type(password);
|
const csrfToken = response.headers['dspace-xsrf-token'];
|
||||||
// Click login button
|
|
||||||
cy.get('ds-themed-navbar [data-e2e="login-button"]').click();
|
// Now, send login POST request including that CSRF token
|
||||||
|
cy.request({
|
||||||
|
method: 'POST',
|
||||||
|
url: TEST_REST_BASE_URL + '/server/api/authn/login',
|
||||||
|
headers: { 'X-XSRF-TOKEN' : csrfToken},
|
||||||
|
form: true, // indicates the body should be form urlencoded
|
||||||
|
body: { user: email, password: password }
|
||||||
|
}).then((resp) => {
|
||||||
|
// We expect a successful login
|
||||||
|
expect(resp.status).to.eq(200);
|
||||||
|
// We expect to have a valid authorization header returned (with our auth token)
|
||||||
|
expect(resp.headers).to.have.property('authorization');
|
||||||
|
|
||||||
|
// Initialize our AuthTokenInfo object from the authorization header.
|
||||||
|
const authheader = resp.headers.authorization as string;
|
||||||
|
const authinfo: AuthTokenInfo = new AuthTokenInfo(authheader);
|
||||||
|
|
||||||
|
// Save our AuthTokenInfo object to our dsAuthInfo UI cookie
|
||||||
|
// This ensures the UI will recognize we are logged in on next "visit()"
|
||||||
|
cy.setCookie(TOKENITEM, JSON.stringify(authinfo));
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Add as a Cypress command (i.e. assign to 'cy.login')
|
// Add as a Cypress command (i.e. assign to 'cy.login')
|
||||||
Cypress.Commands.add('login', 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-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 [data-e2e="logout-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);
|
|
||||||
|
@@ -33,6 +33,7 @@ before(() => {
|
|||||||
// Default UUIDs listed here are all in the Demo Entities Data set available at
|
// 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
|
// https://github.com/DSpace-Labs/AIP-Files/releases/tag/demo-entities-data
|
||||||
// (This is the data set used in our CI environment)
|
// (This is the data set used in our CI environment)
|
||||||
|
export const TEST_REST_BASE_URL = Cypress.env('DSPACE_TEST_REST_BASE_URL') || 'http://localhost:8080';
|
||||||
export const TEST_ADMIN_USER = Cypress.env('DSPACE_TEST_ADMIN_USER') || 'dspacedemo+admin@gmail.com';
|
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_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_COLLECTION = Cypress.env('DSPACE_TEST_COLLECTION') || '282164f5-d325-4740-8dd1-fa4d6d3e7200';
|
||||||
|
Reference in New Issue
Block a user