From a38aa63121a044d89165390c764518c2ceabca4a Mon Sep 17 00:00:00 2001 From: Pawel Baran <98280057+pawel-baran-se@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:49:49 +0100 Subject: [PATCH] test(e2e-login): e2e login tests added to cypress (#87) --- .github/workflows/docker-build.yml | 2 + cypress.config.ts | 5 ++ cypress/e2e/loginKeycloak.spec.js | 78 +++++++++++++++++++ cypress/support/commands.ts | 15 ++++ cypress/support/e2e.ts | 4 + docker-compose/compose.test.yml | 15 +++- src/app/[locale]/settings/page.tsx | 4 +- src/app/[locale]/templates/page.tsx | 7 +- .../authentication/AuthenticationPrompt.tsx | 2 +- .../authentication/NotAllowedPrompt.tsx | 2 +- src/layout/menu/BottomMenu.tsx | 8 +- src/layout/menu/MainMenu.tsx | 2 +- 12 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 cypress/e2e/loginKeycloak.spec.js diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index d4512c53..e23396da 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -97,6 +97,8 @@ jobs: env: SPLIT: ${{ strategy.job-total }} SPLIT_INDEX: ${{ strategy.job-index }} + TEST_ADMIN_USER_PASSWORD: ${{ secrets.TEST_ADMIN_USER_PASSWORD }} + TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }} - name: E2E test collect artifact id: test_artifact diff --git a/cypress.config.ts b/cypress.config.ts index 31b265a7..7cd4f9c4 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -33,5 +33,10 @@ export default defineConfig({ MNESTIX_BACKEND_API_URL: 'http://localhost:5064', AAS_DISCOVERY_API_URL: 'http://localhost:5064/discovery', MNESTIX_API_KEY: process.env.MNESTIX_BACKEND_API_KEY, + TEST_ADMIN_USER_LOGIN: process.env.TEST_ADMIN_USER_LOGIN, + TEST_ADMIN_USER_PASSWORD: process.env.TEST_ADMIN_USER_PASSWORD, + TEST_USER_LOGIN: process.env.TEST_USER_LOGIN, + TEST_USER_PASSWORD: process.env.TEST_USER_PASSWORD, + KEYCLOAK_ISSUER: process.env.KEYCLOAK_ISSUER, }, }); diff --git a/cypress/e2e/loginKeycloak.spec.js b/cypress/e2e/loginKeycloak.spec.js new file mode 100644 index 00000000..842db95a --- /dev/null +++ b/cypress/e2e/loginKeycloak.spec.js @@ -0,0 +1,78 @@ +describe('Login Keycloak user roles', function () { + const adminTestUser = { + login: Cypress.env('TEST_ADMIN_USER_LOGIN'), + password: Cypress.env('TEST_ADMIN_USER_PASSWORD'), + }; + const testUser = { + login: Cypress.env('TEST_USER_LOGIN'), + password: Cypress.env('TEST_USER_PASSWORD'), + }; + + beforeEach(function () { + cy.visit('/'); + }); + it('should be possible to login', () => { + cy.getByTestId('header-burgermenu').click(); + cy.getByTestId('login-button').should('exist'); + }); + + it('should not be able to access templates without login', () => { + cy.visit('/templates'); + cy.getByTestId('authentication-prompt-lock').should('exist'); + }); + + it('should show correct admin user login and icon', () => { + cy.keycloakLogin(adminTestUser.login, adminTestUser.password); + cy.getByTestId('header-burgermenu').click(); + + cy.getByTestId('user-info-box').should('have.text', 'admin@test.com'); + cy.getByTestId('admin-icon').should('exist'); + cy.getByTestId('login-button').should('be.not.exist'); + cy.keycloakLogout(); + }); + + it('should navigate to settings when logged in as admin user', () => { + cy.keycloakLogin(adminTestUser.login, adminTestUser.password); + cy.getByTestId('header-burgermenu').click(); + + cy.getByTestId('settings-menu-icon').should('exist').click(); + cy.getByTestId('settings-route-page').should('exist'); + cy.getByTestId('settings-header').should('have.text', 'Settings'); + + cy.getByTestId('header-burgermenu').click(); + cy.keycloakLogout(); + }); + + it('should show correct user login and icon', () => { + cy.keycloakLogin(testUser.login, testUser.password); + cy.getByTestId('header-burgermenu').click(); + + cy.getByTestId('user-info-box').should('have.text', 'user@test.com'); + cy.getByTestId('user-icon').should('exist'); + cy.getByTestId('login-button').should('be.not.exist'); + cy.keycloakLogout(); + }); + + it('should navigate to template when logged in as a user', () => { + cy.keycloakLogin(testUser.login, testUser.password); + + cy.visit('/templates'); + cy.getByTestId('templates-route-page').should('exist'); + cy.getByTestId('templates-header').should('include.text', 'Templates'); + + cy.getByTestId('header-burgermenu').click(); + cy.keycloakLogout(); + }); + + it('should block settings route when logged in as s user', () => { + cy.keycloakLogin(testUser.login, testUser.password); + + cy.visit('/settings'); + cy.getByTestId('not-allowed-prompt-lock').should('exist'); + + cy.getByTestId('header-burgermenu').click(); + cy.getByTestId('settings-menu-icon').should('not.exist'); + + cy.keycloakLogout(); + }); +}); diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 71e5c862..ed0baca8 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -180,3 +180,18 @@ Cypress.Commands.add('deleteThumbnailFromAas', (aasId: string) => { const encodedAasId = btoa(aasId).replace(/=+$/g, ''); cy.repoRequest('DELETE', '/shells/' + encodedAasId + '/asset-information/thumbnail', null); }); + +Cypress.Commands.add('keycloakLogin', (login: string, password: string) => { + cy.getByTestId('header-burgermenu').click(); + cy.getByTestId('login-button').click(); + cy.origin(Cypress.env('KEYCLOAK_ISSUER'), { args: { login, password } }, ({ login, password }) => { + cy.get('#username').invoke('focus').type(login); + cy.get('#password').invoke('focus').type(password, { log: false }); + cy.get('#kc-login').invoke('focus').click(); + }); + cy.get('button').click(); +}); + +Cypress.Commands.add('keycloakLogout', () => { + cy.getByTestId('logout-button').click(); +}); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 28d882dc..aa1b8ffa 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -119,6 +119,10 @@ declare global { uploadThumbnailToAas(aasId: string): Chainable; deleteThumbnailFromAas(aasId: string): Chainable; + + keycloakLogin(login: string, password: string): Chainable; + + keycloakLogout(): Chainable; } } } diff --git a/docker-compose/compose.test.yml b/docker-compose/compose.test.yml index 38e6a0de..48aeeaab 100644 --- a/docker-compose/compose.test.yml +++ b/docker-compose/compose.test.yml @@ -1,7 +1,7 @@ services: cypress-test: container_name: cypress-test - profiles: ['', 'tests'] + profiles: [ '', 'tests' ] build: dockerfile: cypress.dockerfile environment: @@ -12,7 +12,12 @@ services: CYPRESS_AAS_DISCOVERY_API_URL: 'http://mnestix-api:5064/discovery' MNESTIX_BACKEND_API_KEY: ${MNESTIX_BACKEND_API_KEY:-verySecureApiKey} ELECTRON_ENABLE_LOGGING: 1 - SPLIT: ${SPLIT:-0} + TEST_ADMIN_USER_LOGIN: ${TEST_ADMIN_USER_LOGIN:-test_admin} + TEST_ADMIN_USER_PASSWORD: ${TEST_ADMIN_USER_PASSWORD:-test_admin} + TEST_USER_LOGIN: ${TEST_USER_LOGIN:-test_user} + TEST_USER_PASSWORD: ${TEST_USER_PASSWORD:-test_user} + KEYCLOAK_ISSUER: 'https://mnestix-keycloak.azurewebsites.net' + SPLIT: ${SPLIT:-1} SPLIT_INDEX: ${SPLIT_INDEX:-0} volumes: - ./cypress-artifacts/screenshots:/cypress_Tests/cypress/screenshots @@ -31,3 +36,9 @@ services: SUBMODEL_REPO_API_URL: 'http://mnestix-api:5064/repo' DISCOVERY_API_URL: 'http://mnestix-api:5064/discovery' MNESTIX_BACKEND_API_URL: 'http://mnestix-api:5064' + AUTHENTICATION_FEATURE_FLAG: 'true' + NEXTAUTH_URL: 'http://mnestix-browser:3000/' + KEYCLOAK_ENABLED: 'true' + KEYCLOAK_CLIENT_ID: 'mnestix-cypress-e2e-client' + KEYCLOAK_ISSUER: 'https://mnestix-keycloak.azurewebsites.net' + KEYCLOAK_REALM: 'Mnestix' \ No newline at end of file diff --git a/src/app/[locale]/settings/page.tsx b/src/app/[locale]/settings/page.tsx index 97bfdfe5..7ad9abf4 100644 --- a/src/app/[locale]/settings/page.tsx +++ b/src/app/[locale]/settings/page.tsx @@ -52,8 +52,8 @@ export default function Page() { return ( - - + + } /> diff --git a/src/app/[locale]/templates/page.tsx b/src/app/[locale]/templates/page.tsx index 8c4d607e..bc12cb37 100644 --- a/src/app/[locale]/templates/page.tsx +++ b/src/app/[locale]/templates/page.tsx @@ -200,8 +200,11 @@ export default function Page() { return ( - - + + } />