diff --git a/interfaces/IBF-dashboard/src/app/components/layer-control-info-popover/layer-control-info-popover.component.html b/interfaces/IBF-dashboard/src/app/components/layer-control-info-popover/layer-control-info-popover.component.html index 8dd4e0d9f..c23ea7ca5 100644 --- a/interfaces/IBF-dashboard/src/app/components/layer-control-info-popover/layer-control-info-popover.component.html +++ b/interfaces/IBF-dashboard/src/app/components/layer-control-info-popover/layer-control-info-popover.component.html @@ -5,7 +5,7 @@ name="close-circle" size="large" (click)="closePopover()" - data-test="close-matrix-icon" + data-testid="close-matrix-icon" class="popover-close-button" > diff --git a/tests/e2e/Pages/MapComponent.ts b/tests/e2e/Pages/MapComponent.ts index 3fa76edfe..d41dca7c8 100644 --- a/tests/e2e/Pages/MapComponent.ts +++ b/tests/e2e/Pages/MapComponent.ts @@ -21,6 +21,8 @@ class MapComponent extends DashboardPage { readonly redCrossMarker: Locator; readonly gloFASMarker: Locator; readonly alerThresholdLines: Locator; + readonly closeButtonIcon: Locator; + readonly layerInfoContent: Locator; constructor(page: Page) { super(page); @@ -50,6 +52,8 @@ class MapComponent extends DashboardPage { this.alerThresholdLines = this.page.locator( '[stroke="var(--ion-color-ibf-outline-red)"]', ); + this.closeButtonIcon = this.page.getByTestId('close-matrix-icon'); + this.layerInfoContent = this.page.getByTestId('layer-info-content'); } async mapComponentIsVisible() { @@ -156,6 +160,15 @@ class MapComponent extends DashboardPage { } } + async clickInfoButtonByName({ layerName }: { layerName: string }) { + await this.page + .locator(`ion-item`) + .filter({ hasText: layerName }) + .getByRole('button') + .first() + .click(); + } + async retryGetAttribute(locator: Locator, attribute: string, retries = 3) { for (let attempt = 0; attempt < retries; attempt++) { try { @@ -194,6 +207,39 @@ class MapComponent extends DashboardPage { return availableLayers; } + async validateInfoIconInteractions() { + const getLayerRow = this.page.getByTestId('matrix-layer-name'); + const layerCount = await getLayerRow.count(); + + for (let i = 0; i < layerCount; i++) { + try { + await this.page.waitForTimeout(200); + const layerRow = getLayerRow.nth(i); + if (await layerRow.isVisible()) { + const nameAttribute = await layerRow.textContent(); + if (nameAttribute) { + const trimmedName = nameAttribute.trim(); + + await this.clickInfoButtonByName({ layerName: trimmedName }); + await expect( + this.page + .locator('ion-card-header') + .filter({ hasText: trimmedName }), + ).toBeVisible(); + await expect(this.layerInfoContent).toBeVisible(); + await this.closeButtonIcon.click(); + } + } + } catch (error) { + if (error instanceof Error) { + console.error('Error: ', error.message); + } else { + console.error('Unexpected error: ', error); + } + } + } + } + async assertAggregateTitleOnHoverOverMap() { // Declare component const aggregates = new AggregatesComponent(this.page); @@ -203,7 +249,7 @@ class MapComponent extends DashboardPage { await this.page.waitForLoadState('domcontentloaded'); await this.page.waitForSelector('.leaflet-interactive'); - // Assert the that Aggregates title is visible and does not contain the text 'National View' + // Assert that Aggregates title is visible and does not contain the text 'National View' await this.adminBoundry.first().hover(); await expect(aggregates.aggregatesTitleHeader).not.toContainText( diff --git a/tests/e2e/tests/Map/InfoIconsAreInteractiveInLayerComponent.spec.ts b/tests/e2e/tests/Map/InfoIconsAreInteractiveInLayerComponent.spec.ts new file mode 100644 index 000000000..1213810b1 --- /dev/null +++ b/tests/e2e/tests/Map/InfoIconsAreInteractiveInLayerComponent.spec.ts @@ -0,0 +1,63 @@ +import { test } from '@playwright/test'; +import DashboardPage from 'Pages/DashboardPage'; +import MapComponent from 'Pages/MapComponent'; +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 '../../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, + ); +}); +// https://app.qase.io/project/IBF?previewMode=side&suite=3&tab=&case=33 +test( + qase(33, 'Interaction with info icon in map layer component'), + async ({ page }) => { + const dashboard = new DashboardPage(page); + const userState = new UserStateComponent(page); + const map = new MapComponent(page); + + // Navigate to disaster type the data was mocked for + await dashboard.navigateToFloodDisasterType(); + // Assertions + await userState.headerComponentIsVisible({ + countryName: NoTriggerDataSet.CountryName, + }); + // Wait for the page to load + await dashboard.waitForLoaderToDisappear(); + await map.mapComponentIsVisible(); + + // Open the layer menu + await map.isLayerMenuOpen({ layerMenuOpen: false }); + await map.clickLayerMenu(); + await map.isLayerMenuOpen({ layerMenuOpen: true }); + + // Assert layer info icons to be intercative and contain basic required info + await map.validateInfoIconInteractions(); + }, +);