Skip to content

Commit

Permalink
test: initial e2e test work with new auth mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
g-saracca committed Oct 29, 2024
1 parent 1f1b0cf commit 666a71e
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 72 deletions.
15 changes: 1 addition & 14 deletions tests/e2e-integration/e2e/sections/collection/Collection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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')
})
})
Original file line number Diff line number Diff line change
@@ -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 })

Expand All @@ -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')
})
})
48 changes: 36 additions & 12 deletions tests/e2e-integration/shared/DataverseApiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>('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<T>(
Expand All @@ -27,17 +28,30 @@ export class DataverseApiHelper {
contentType = 'application/json'
): Promise<T> {
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<string>('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
}
Expand All @@ -63,4 +77,14 @@ export class DataverseApiHelper {

return formData
}

static getLocalStorageItem<T>(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
}
}
}
13 changes: 9 additions & 4 deletions tests/e2e-integration/shared/TestsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
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'

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('[email protected]')
cy.get('#password').type('admin')
cy.get('#kc-login').click()
}

static wait(ms: number): Promise<void> {
Expand All @@ -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<void> {
Expand Down
29 changes: 12 additions & 17 deletions tests/support/commands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -77,25 +78,19 @@ Cypress.Commands.add('mountSuperuser', (component: ReactNode) => {
return cy.customMount(<SessionProvider repository={userRepository}>{component}</SessionProvider>)
})

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) => {
Expand Down
1 change: 1 addition & 0 deletions tests/support/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare global {
mountAuthenticated: typeof mount
mountSuperuser: typeof mount
loginAsAdmin(go?: string): Chainable<JQuery<HTMLElement>>
logout(): Chainable<JQuery<HTMLElement>>
getApiToken(): Chainable<string>
compareDate(date: Date, expectedDate: Date): Chainable
}
Expand Down

0 comments on commit 666a71e

Please sign in to comment.