From 2d5d6bed4027d97b67166ba774b21d841c29491e Mon Sep 17 00:00:00 2001 From: piotrk39 Date: Thu, 10 Oct 2024 11:23:48 +0200 Subject: [PATCH 1/3] Add test and assertions for loginPage & UserState components --- e2e/Pages/LoginPage.ts | 17 +++++++ e2e/Pages/UserStateComponent.ts | 4 ++ .../UserState/SuccessfullyLogOut.spec.ts | 50 +++++++++++++++++++ .../src/app/pages/login/login.page.html | 2 +- 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 e2e/tests/UserState/SuccessfullyLogOut.spec.ts diff --git a/e2e/Pages/LoginPage.ts b/e2e/Pages/LoginPage.ts index c846c087e..e9fbf1b92 100644 --- a/e2e/Pages/LoginPage.ts +++ b/e2e/Pages/LoginPage.ts @@ -1,12 +1,18 @@ +import { expect } from '@playwright/test'; import { Locator, Page } from 'playwright'; +import EnglishTranslations from '../../interfaces/IBF-dashboard/src/assets/i18n/en.json'; import DashboardPage from './DashboardPage'; +const welcomeMessageEnglishTranslation = + EnglishTranslations['login-page'].welcome; + class LoginPage extends DashboardPage { readonly page: Page; readonly usernameInput: Locator; readonly passwordInput: Locator; readonly loginButton: Locator; + readonly welcomeMessage: Locator; constructor(page: Page) { super(page); @@ -14,6 +20,7 @@ class LoginPage extends DashboardPage { this.usernameInput = this.page.getByLabel('E-mail'); this.passwordInput = this.page.locator('input[type="password"]'); this.loginButton = this.page.getByRole('button', { name: 'Log in' }); + this.welcomeMessage = this.page.getByTestId('login-welcome-message'); } async login(username?: string, password?: string) { @@ -25,6 +32,16 @@ class LoginPage extends DashboardPage { await this.passwordInput.fill(password); await this.loginButton.click(); } + + async loginScreenIsVisible() { + // explicitly wait for the email input to avoid timing issues + await this.page.waitForSelector('input[type="email"]'); + + await expect(this.loginButton).toBeVisible(); + await expect(this.welcomeMessage).toHaveText( + welcomeMessageEnglishTranslation, + ); + } } export default LoginPage; diff --git a/e2e/Pages/UserStateComponent.ts b/e2e/Pages/UserStateComponent.ts index 3f54c85b0..db54da130 100644 --- a/e2e/Pages/UserStateComponent.ts +++ b/e2e/Pages/UserStateComponent.ts @@ -44,6 +44,10 @@ class UserStateComponent extends DashboardPage { ); await expect(this.logOutButton).toBeVisible(); } + + async logOut() { + await this.logOutButton.click(); + } } export default UserStateComponent; diff --git a/e2e/tests/UserState/SuccessfullyLogOut.spec.ts b/e2e/tests/UserState/SuccessfullyLogOut.spec.ts new file mode 100644 index 000000000..84d88a808 --- /dev/null +++ b/e2e/tests/UserState/SuccessfullyLogOut.spec.ts @@ -0,0 +1,50 @@ +import { test } from '@playwright/test'; +import DashboardPage from 'Pages/DashboardPage'; +import UserStateComponent from 'Pages/UserStateComponent'; +import { qase } from 'playwright-qase-reporter'; +import { NoTriggerDataSet } from 'testData/testData.enum'; + +import { FloodsScenario } from '../../../services/API-service/src/scripts/enum/mock-scenario.enum'; +import { + getAccessToken, + mockFloods, + resetDB, +} from '../../../services/API-service/test/helpers/utility.helper'; +import LoginPage from '../../Pages/LoginPage'; + +let accessToken: string; + +test.beforeEach(async ({ page }) => { + // Login + const loginPage = new LoginPage(page); + + accessToken = await getAccessToken(); + await resetDB(accessToken); + // We should maybe create one mock for all different disaster types for now we can just use floods + await mockFloods( + FloodsScenario.NoTrigger, + NoTriggerDataSet.CountryCode, + accessToken, + ); + + await page.goto('/'); + await loginPage.login( + NoTriggerDataSet.UserMail, + NoTriggerDataSet.UserPassword, + ); +}); + +test(qase(8, 'Log out from IBF-system'), async ({ page }) => { + const loginPage = new LoginPage(page); + const dashboard = new DashboardPage(page); + const userState = new UserStateComponent(page); + + // Navigate to disaster type the data was mocked for + await dashboard.navigateToFloodDisasterType(); + // Assertions + await userState.headerComponentIsVisible({ + countryName: NoTriggerDataSet.CountryName, + }); + await userState.logOut(); + await loginPage.loginScreenIsVisible(); +}); diff --git a/interfaces/IBF-dashboard/src/app/pages/login/login.page.html b/interfaces/IBF-dashboard/src/app/pages/login/login.page.html index f2e10a00e..b4769fa03 100644 --- a/interfaces/IBF-dashboard/src/app/pages/login/login.page.html +++ b/interfaces/IBF-dashboard/src/app/pages/login/login.page.html @@ -43,7 +43,7 @@ src="assets/icons/IBF_Impact_Based_Forecast_Logo_32x32.svg" > - + From 538d1d23ba5daae314280ffe7c39dcd6975eeef9 Mon Sep 17 00:00:00 2001 From: piotrk39 Date: Thu, 10 Oct 2024 11:30:32 +0200 Subject: [PATCH 2/3] Fix lint issue --- interfaces/IBF-dashboard/src/app/pages/login/login.page.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interfaces/IBF-dashboard/src/app/pages/login/login.page.html b/interfaces/IBF-dashboard/src/app/pages/login/login.page.html index b4769fa03..918ce2931 100644 --- a/interfaces/IBF-dashboard/src/app/pages/login/login.page.html +++ b/interfaces/IBF-dashboard/src/app/pages/login/login.page.html @@ -43,7 +43,10 @@ src="assets/icons/IBF_Impact_Based_Forecast_Logo_32x32.svg" > - + From 4f036e38a29b33621619abb82950758f96f704c7 Mon Sep 17 00:00:00 2001 From: piotrk39 Date: Thu, 10 Oct 2024 17:55:54 +0200 Subject: [PATCH 3/3] Add test for timeline disabled --- e2e/Pages/TimelineComponent.ts | 14 +++++ .../TimelineInactiveInNotrigger.spec.ts | 53 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 e2e/tests/Timeline/TimelineInactiveInNotrigger.spec.ts diff --git a/e2e/Pages/TimelineComponent.ts b/e2e/Pages/TimelineComponent.ts index 56bf8f4f9..e4cf3a948 100644 --- a/e2e/Pages/TimelineComponent.ts +++ b/e2e/Pages/TimelineComponent.ts @@ -25,6 +25,20 @@ class TimelineComponent extends DashboardPage { await expect(timelinePeriods.nth(i)).toBeVisible(); } } + + async timelineIsInactive() { + await this.page.waitForLoadState('domcontentloaded'); + await this.page.waitForSelector('[data-testid="timeline-button"]'); + + const timelinePeriods = this.timeline; + const count = await timelinePeriods.count(); + + expect(count).toBeGreaterThan(0); + for (let i = 0; i < count; i++) { + const button = timelinePeriods.nth(i); + await expect(button).toHaveAttribute('disabled', ''); + } + } } export default TimelineComponent; diff --git a/e2e/tests/Timeline/TimelineInactiveInNotrigger.spec.ts b/e2e/tests/Timeline/TimelineInactiveInNotrigger.spec.ts new file mode 100644 index 000000000..086563b8f --- /dev/null +++ b/e2e/tests/Timeline/TimelineInactiveInNotrigger.spec.ts @@ -0,0 +1,53 @@ +import { test } from '@playwright/test'; +import DashboardPage from 'Pages/DashboardPage'; +import TimelineComponent from 'Pages/TimelineComponent'; +import UserStateComponent from 'Pages/UserStateComponent'; +import { qase } from 'playwright-qase-reporter'; +import { NoTriggerDataSet } from 'testData/testData.enum'; + +import { FloodsScenario } from '../../../services/API-service/src/scripts/enum/mock-scenario.enum'; +import { + getAccessToken, + mockFloods, + resetDB, +} from '../../../services/API-service/test/helpers/utility.helper'; +import LoginPage from '../../Pages/LoginPage'; + +let accessToken: string; + +test.beforeEach(async ({ page }) => { + // Login + const loginPage = new LoginPage(page); + + accessToken = await getAccessToken(); + await resetDB(accessToken); + // We should maybe create one mock for all different disaster types for now we can just use floods + await mockFloods( + FloodsScenario.NoTrigger, + NoTriggerDataSet.CountryCode, + accessToken, + ); + + await page.goto('/'); + await loginPage.login( + NoTriggerDataSet.UserMail, + NoTriggerDataSet.UserPassword, + ); +}); + +test( + qase(14, 'Timeline is deactivated in no-trigger mode'), + async ({ page }) => { + const dashboard = new DashboardPage(page); + const userState = new UserStateComponent(page); + const timeline = new TimelineComponent(page); + + // Navigate to disaster type the data was mocked for + await dashboard.navigateToFloodDisasterType(); + // Assertions + await userState.headerComponentIsVisible({ + countryName: NoTriggerDataSet.CountryName, + }); + await timeline.timelineIsInactive(); + }, +);