diff --git a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts index 8af6e0b6f..4bd7e6d3c 100644 --- a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts +++ b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts @@ -5,13 +5,9 @@ import { CollectionHelper } from '../../../shared/collection/CollectionHelper' describe('Collection Page', () => { const title = faker.lorem.sentence() - before(() => { - TestsUtils.setup() - TestsUtils.login() - }) - beforeEach(() => { TestsUtils.login() + TestsUtils.setup() }) it('successfully loads root collection when accessing the home', () => { @@ -73,15 +69,6 @@ describe('Collection Page', () => { .should('exist') }) - it('log out Dataverse Admin user', () => { - cy.visit('/spa/collections') - cy.findAllByText(/Root/i).should('exist') - - cy.findByText(/Dataverse Admin/i).click() - cy.findByRole('button', { name: /Log Out/i }).click() - cy.findByText(/Dataverse Admin/i).should('not.exist') - }) - describe.skip('Currently skipping all tests as we are only rendering an infinite scrollable container. Please refactor these tests if a toggle button is added to switch between pagination and infinite scroll.', () => { it('navigates to the correct page of the datasets list when passing the page query param', () => { cy.wrap(DatasetHelper.createMany(12), { timeout: 10000 }).then(() => { diff --git a/tests/e2e-integration/e2e/sections/create-collection/CreateCollection.spec.tsx b/tests/e2e-integration/e2e/sections/create-collection/CreateCollection.spec.tsx index 0fc42fe36..c0a22da7f 100644 --- a/tests/e2e-integration/e2e/sections/create-collection/CreateCollection.spec.tsx +++ b/tests/e2e-integration/e2e/sections/create-collection/CreateCollection.spec.tsx @@ -1,17 +1,22 @@ import { TestsUtils } from '../../../shared/TestsUtils' import { faker } from '@faker-js/faker' +const CREATE_COLLECTION_PAGE_URL = '/spa/collections/root/create' + describe('Create Collection', () => { - before(() => { + beforeEach(() => { + TestsUtils.login() TestsUtils.setup() }) - beforeEach(() => { - TestsUtils.login() + it('visits the Create Collection Page as a logged in user', () => { + cy.visit(CREATE_COLLECTION_PAGE_URL) + + cy.findByRole('heading', { name: 'Create Collection' }).should('exist') }) it('navigates to the collection page after submitting a valid form', () => { - cy.visit('/spa/collections/root/create') + cy.visit(CREATE_COLLECTION_PAGE_URL) const collectionName = faker.lorem.words(3) @@ -29,7 +34,7 @@ describe('Create Collection', () => { }) it('shows correct selected facets from parent collection in Browse/Search facets section', () => { - cy.visit('/spa/collections/root/create') + cy.visit(CREATE_COLLECTION_PAGE_URL) const collectionName = faker.lorem.words(3) @@ -87,11 +92,29 @@ describe('Create Collection', () => { }) }) - it('redirects to the Log in page when the user is not authenticated', () => { - cy.wrap(TestsUtils.logout()) + it('should redirect the user to the Login page when the user is not authenticated', () => { + TestsUtils.logout() + + // Visit a protected route 🔐, ProtectedRoute component should redirect automatically to the Keycloack login page + cy.visit(CREATE_COLLECTION_PAGE_URL) + + // Check if the Keycloak login form is present + cy.get('#kc-form-login').should('exist') + }) + + it('should redirect the user back to the create collection page after a successful login', () => { + TestsUtils.logout() + + cy.visit(CREATE_COLLECTION_PAGE_URL) + + // Check if the Keycloak login form is present + cy.get('#kc-form-login').should('exist') + + TestsUtils.enterCredentialsInKeycloak() + + // Check if the user is redirected back to the create collection page + cy.url().should('eq', `${Cypress.config().baseUrl as string}${CREATE_COLLECTION_PAGE_URL}`) - cy.visit('/spa/collections/root/create') - cy.get('#login-container').should('exist') - cy.url().should('include', '/loginpage.xhtml') + cy.findByRole('heading', { name: 'Create Collection' }).should('exist') }) }) diff --git a/tests/e2e-integration/e2e/sections/create-dataset/CreateDataset.spec.tsx b/tests/e2e-integration/e2e/sections/create-dataset/CreateDataset.spec.tsx index 430dece32..a31b2c112 100644 --- a/tests/e2e-integration/e2e/sections/create-dataset/CreateDataset.spec.tsx +++ b/tests/e2e-integration/e2e/sections/create-dataset/CreateDataset.spec.tsx @@ -1,23 +1,22 @@ import { TestsUtils } from '../../../shared/TestsUtils' import { DatasetLabelValue } from '../../../../../src/dataset/domain/models/Dataset' -describe('Create Dataset', () => { - before(() => { - TestsUtils.setup() - }) +const CREATE_DATASET_PAGE_URL = '/spa/datasets/root/create' +describe('Create Dataset', () => { beforeEach(() => { TestsUtils.login() + TestsUtils.setup() }) it('visits the Create Dataset Page as a logged in user', () => { - cy.visit('/spa/datasets/root/create') + cy.visit(CREATE_DATASET_PAGE_URL) cy.findByRole('heading', { name: 'Create Dataset' }).should('exist') }) it('navigates to the new dataset after submitting a valid form', () => { - cy.visit('/spa/datasets/root/create') + cy.visit(CREATE_DATASET_PAGE_URL) cy.findByLabelText(/^Title/i).type('Test Dataset Title', { force: true }) @@ -43,19 +42,30 @@ describe('Create Dataset', () => { cy.findByText(DatasetLabelValue.UNPUBLISHED).should('exist') }) - it('navigates to the home if the user cancels the form', () => { - cy.visit('/spa/datasets/root/create') + it('should redirect the user to the Login page when the user is not authenticated', () => { + TestsUtils.logout() - cy.findByText(/Cancel/i).click() + // Visit a protected route 🔐, ProtectedRoute component should redirect automatically to the Keycloack login page + cy.visit(CREATE_DATASET_PAGE_URL) - cy.findByRole('heading', { name: 'Root' }).should('exist') + // Check if the Keycloak login form is present + cy.get('#kc-form-login').should('exist') }) - it('redirects to the Log In page when the user is not authenticated', () => { - cy.wrap(TestsUtils.logout()) + it('should redirect the user back to the create dataset page after a successful login', () => { + TestsUtils.logout() - cy.visit('/spa/datasets/root/create') - cy.get('#login-container').should('exist') - cy.url().should('include', '/loginpage.xhtml') + cy.visit(CREATE_DATASET_PAGE_URL) + + // Check if the Keycloak login form is present + cy.get('#kc-form-login').should('exist') + + // Enter the credentials in the Keycloak login form + TestsUtils.enterCredentialsInKeycloak() + + // Check if the user is redirected back to the create dataset page + cy.url().should('eq', `${Cypress.config().baseUrl as string}${CREATE_DATASET_PAGE_URL}`) + + cy.findByRole('heading', { name: 'Create Dataset' }).should('exist') }) }) diff --git a/tests/e2e-integration/shared/DataverseApiHelper.ts b/tests/e2e-integration/shared/DataverseApiHelper.ts index 6473ac937..2bf22883e 100644 --- a/tests/e2e-integration/shared/DataverseApiHelper.ts +++ b/tests/e2e-integration/shared/DataverseApiHelper.ts @@ -7,16 +7,17 @@ export class DataverseApiHelper { static setup() { this.API_URL = `${TestsUtils.DATAVERSE_BACKEND_URL}/api` - // TODO - Replace with an ajax call to the API - cy.getApiToken().then((token) => { - this.API_TOKEN = token - }) - void this.request('/admin/settings/:MaxEmbargoDurationInMonths', 'PUT', -1) - void this.request( - '/admin/settings/:AnonymizedFieldTypeNames', - 'PUT', - 'author, datasetContact, contributor, depositor, grantNumber, publication' - ) + const token = this.getLocalStorageItem('ROCP_token') + + if (token) { + console.log('Setting embargo and anonymized field types') + void this.request('/admin/settings/:MaxEmbargoDurationInMonths', 'PUT', -1) + void this.request( + '/admin/settings/:AnonymizedFieldTypeNames', + 'PUT', + 'author, datasetContact, contributor, depositor, grantNumber, publication' + ) + } } static async request( @@ -27,17 +28,30 @@ export class DataverseApiHelper { contentType = 'application/json' ): Promise { const isFormData = contentType === 'multipart/form-data' + const config: AxiosRequestConfig = { url: `${this.API_URL}${url}`, method: method, headers: { - 'X-Dataverse-key': this.API_TOKEN, 'Content-Type': contentType }, // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - data: isFormData ? this.createFormData(data) : data + data: isFormData ? this.createFormData(data) : data, + withCredentials: false } + // Intercept the request to add the token + axios.interceptors.request.use((config) => { + const token = this.getLocalStorageItem('ROCP_token') + + console.log('%cRequest with Token:', 'background: green; color: white;', token) + + if (token) { + config.headers.Authorization = `Bearer ${token}` + } + return config + }) + const response: { data: { data: T } } = await axios(config) return response.data.data } @@ -63,4 +77,14 @@ export class DataverseApiHelper { return formData } + + static getLocalStorageItem(key: string): T | null { + try { + const item = localStorage.getItem(key) + return item ? (JSON.parse(item) as T) : null + } catch (error) { + console.error(`Error parsing localStorage key "${key}":`, error) + return null + } + } } diff --git a/tests/e2e-integration/shared/TestsUtils.ts b/tests/e2e-integration/shared/TestsUtils.ts index 78ee00b96..5dd0ad702 100644 --- a/tests/e2e-integration/shared/TestsUtils.ts +++ b/tests/e2e-integration/shared/TestsUtils.ts @@ -1,7 +1,6 @@ import { ApiConfig } from '@iqss/dataverse-client-javascript/dist/core' import { DataverseApiHelper } from './DataverseApiHelper' import { DataverseApiAuthMechanism } from '@iqss/dataverse-client-javascript/dist/core/infra/repositories/ApiConfig' -import { UserJSDataverseRepository } from '../../../src/users/infrastructure/repositories/UserJSDataverseRepository' import { DatasetHelper } from './datasets/DatasetHelper' import { DATAVERSE_BACKEND_URL } from '../../../src/config' @@ -9,12 +8,18 @@ export class TestsUtils { static readonly DATAVERSE_BACKEND_URL = DATAVERSE_BACKEND_URL static setup() { - ApiConfig.init(`${this.DATAVERSE_BACKEND_URL}/api/v1`, DataverseApiAuthMechanism.SESSION_COOKIE) + ApiConfig.init(`${this.DATAVERSE_BACKEND_URL}/api/v1`, DataverseApiAuthMechanism.BEARER_TOKEN) DataverseApiHelper.setup() } static login() { - return cy.loginAsAdmin() // TODO - Replace with an ajax call to the API + return cy.loginAsAdmin() + } + + static enterCredentialsInKeycloak() { + cy.get('#username').type('dataverse-admin@mailinator.com') + cy.get('#password').type('admin') + cy.get('#kc-login').click() } static wait(ms: number): Promise { @@ -24,7 +29,7 @@ export class TestsUtils { } static logout() { - return new UserJSDataverseRepository().removeAuthenticated() + return cy.logout() } static async waitForNoLocks(persistentId: string, maxRetries = 20, delay = 1000): Promise { diff --git a/tests/support/commands.tsx b/tests/support/commands.tsx index 87a412ac2..726c85b83 100644 --- a/tests/support/commands.tsx +++ b/tests/support/commands.tsx @@ -46,6 +46,7 @@ import i18next from '../../src/i18n' import { UserRepository } from '../../src/users/domain/repositories/UserRepository' import { SessionProvider } from '../../src/sections/session/SessionProvider' import { MemoryRouter } from 'react-router-dom' +import { TestsUtils } from '@tests/e2e-integration/shared/TestsUtils' // Define your custom mount function @@ -77,25 +78,19 @@ Cypress.Commands.add('mountSuperuser', (component: ReactNode) => { return cy.customMount({component}) }) -Cypress.Commands.add('loginAsAdmin', (go?: string) => { - cy.visit('/') - cy.get('#topNavBar').then((navbar) => { - if (navbar.find('ul > li:nth-child(6) > a').text().includes('Log In')) { - cy.findAllByRole('link', { name: /Log In/i }) - .first() - .click() - cy.findByLabelText('Username/Email').type('dataverseAdmin') - cy.findByLabelText('Password').type('admin1') - cy.findByRole('button', { name: /Log In/i }).click() - cy.findAllByText(/Dataverse Admin/i).should('exist') - if (go) cy.visit(go) - } - }) +Cypress.Commands.add('loginAsAdmin', () => { + cy.visit('/spa/') + cy.findByTestId('oidc-login').click() + + TestsUtils.enterCredentialsInKeycloak() + + cy.url().should('eq', `${Cypress.config().baseUrl as string}/spa`) }) -Cypress.Commands.add('getApiToken', () => { - cy.loginAsAdmin('/dataverseuser.xhtml?selectTab=dataRelatedToMe') - return cy.findByRole('link', { name: 'API Token' }).click().get('#apiToken code').invoke('text') +Cypress.Commands.add('logout', () => { + cy.visit('/spa/') + cy.get('#dropdown-user').click() + cy.findByTestId('oidc-logout').click() }) Cypress.Commands.add('compareDate', (date, expectedDate) => { diff --git a/tests/support/component.ts b/tests/support/component.ts index 67c84174e..ad869ebb0 100644 --- a/tests/support/component.ts +++ b/tests/support/component.ts @@ -37,6 +37,7 @@ declare global { mountAuthenticated: typeof mount mountSuperuser: typeof mount loginAsAdmin(go?: string): Chainable> + logout(): Chainable> getApiToken(): Chainable compareDate(date: Date, expectedDate: Date): Chainable }