From 528b2c7933bd356807ef4f2e1762bd2e5d09039a Mon Sep 17 00:00:00 2001 From: amisskii <124462506+amisskii@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:53:28 +0200 Subject: [PATCH] chore(test): enhance Detail Page Locators, ARIA Labels, and Add Navigation Tests (#8196) * refactor: add aria labels and roles Signed-off-by: Anton Misskii * chore: change resources details pages Signed-off-by: Anton Misskii * chore(test): add navigation tests Signed-off-by: Anton Misskii * refactor: unit tests refactoring Signed-off-by: Anton Misskii * chore: use playExpect instead of waitFor Signed-off-by: Anton Misskii --- .../renderer/src/lib/ui/DetailsPage.spec.ts | 6 +- .../src/lib/ui/EngineFormPage.spec.ts | 6 +- packages/renderer/src/lib/ui/FormPage.spec.ts | 6 +- .../ui/src/lib/layouts/DetailsPage.spec.ts | 6 +- packages/ui/src/lib/layouts/FormPage.spec.ts | 8 +-- packages/ui/src/lib/layouts/Page.spec.ts | 20 ++----- packages/ui/src/lib/layouts/Page.svelte | 19 ++++--- tests/playwright/src/index.ts | 1 + .../src/model/pages/container-details-page.ts | 30 +++------- .../src/model/pages/details-page.ts | 56 +++++++++++++++++++ .../src/model/pages/image-details-page.ts | 34 ++++------- .../src/model/pages/pods-details-page.ts | 36 ++++-------- .../src/model/pages/volume-details-page.ts | 27 ++------- .../src/specs/container-smoke.spec.ts | 13 +++++ .../playwright/src/specs/image-smoke.spec.ts | 11 ++++ tests/playwright/src/specs/pod-smoke.spec.ts | 15 ++++- .../playwright/src/specs/volume-smoke.spec.ts | 15 +++++ 17 files changed, 178 insertions(+), 131 deletions(-) create mode 100644 tests/playwright/src/model/pages/details-page.ts diff --git a/packages/renderer/src/lib/ui/DetailsPage.spec.ts b/packages/renderer/src/lib/ui/DetailsPage.spec.ts index bbfdf856d75..c106dc2b28e 100644 --- a/packages/renderer/src/lib/ui/DetailsPage.spec.ts +++ b/packages/renderer/src/lib/ui/DetailsPage.spec.ts @@ -51,14 +51,14 @@ test('Expect title is defined', async () => { expect(titleElement).toHaveTextContent(title); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; currentPage.set({ name: name, path: '/' } as TinroBreadcrumb); render(DetailsPage, { title: 'No Title', }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -71,7 +71,7 @@ test('Expect backlink is defined', async () => { title: 'No Title', }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/renderer/src/lib/ui/EngineFormPage.spec.ts b/packages/renderer/src/lib/ui/EngineFormPage.spec.ts index e46e5e1b710..8cd8cbbc402 100644 --- a/packages/renderer/src/lib/ui/EngineFormPage.spec.ts +++ b/packages/renderer/src/lib/ui/EngineFormPage.spec.ts @@ -52,14 +52,14 @@ test('Expect to see empty screen', async () => { expect(titleElement).toBeInTheDocument(); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; currentPage.set({ name: name, path: '/' } as TinroBreadcrumb); render(EngineFormPage, { title: 'No Title', }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -72,7 +72,7 @@ test('Expect backlink is defined', async () => { title: 'No Title', }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/renderer/src/lib/ui/FormPage.spec.ts b/packages/renderer/src/lib/ui/FormPage.spec.ts index 8328001efb0..8dc7f07fc50 100644 --- a/packages/renderer/src/lib/ui/FormPage.spec.ts +++ b/packages/renderer/src/lib/ui/FormPage.spec.ts @@ -51,14 +51,14 @@ test('Expect title is defined', async () => { expect(titleElement).toHaveTextContent(title); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; currentPage.set({ name: name, path: '/' } as TinroBreadcrumb); render(FormPage, { title: 'No Title', }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -71,7 +71,7 @@ test('Expect backlink is defined', async () => { title: 'No Title', }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/ui/src/lib/layouts/DetailsPage.spec.ts b/packages/ui/src/lib/layouts/DetailsPage.spec.ts index cb1385bdd49..254308642a9 100644 --- a/packages/ui/src/lib/layouts/DetailsPage.spec.ts +++ b/packages/ui/src/lib/layouts/DetailsPage.spec.ts @@ -39,14 +39,14 @@ test('Expect title is defined', async () => { expect(titleElement).toHaveTextContent(title); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; render(DetailsPage, { title: 'No Title', breadcrumbRightPart: name, }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -60,7 +60,7 @@ test('Expect backlink is defined', async () => { onbreadcrumbClick: breadcrumbClickMock, }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/ui/src/lib/layouts/FormPage.spec.ts b/packages/ui/src/lib/layouts/FormPage.spec.ts index 0291a47198e..23e72fd6146 100644 --- a/packages/ui/src/lib/layouts/FormPage.spec.ts +++ b/packages/ui/src/lib/layouts/FormPage.spec.ts @@ -44,21 +44,21 @@ test('Expect no backlink or close is defined', async () => { title: 'No Title', }); - const backElement = screen.queryByLabelText('back'); + const backElement = screen.queryByLabelText('Back'); expect(backElement).not.toBeInTheDocument(); const closeElement = screen.queryByTitle('Close'); expect(closeElement).toBeInTheDocument(); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; render(FormPage, { title: 'No Title', breadcrumbRightPart: name, }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -74,7 +74,7 @@ test('Expect backlink is defined', async () => { onbreadcrumbClick: breadcrumbClickMock, }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/ui/src/lib/layouts/Page.spec.ts b/packages/ui/src/lib/layouts/Page.spec.ts index c62e9c6e0a1..78da1b50f1f 100644 --- a/packages/ui/src/lib/layouts/Page.spec.ts +++ b/packages/ui/src/lib/layouts/Page.spec.ts @@ -39,38 +39,26 @@ test('Expect title is defined', async () => { expect(titleElement).toHaveTextContent(title); }); -test('Expect name is defined', async () => { - const name = 'My Dummy Name'; - render(Page, { - title: 'No Title', - breadcrumbRightPart: name, - }); - - const nameElement = screen.getByLabelText('name'); - expect(nameElement).toBeInTheDocument(); - expect(nameElement).toHaveTextContent(name); -}); - test('Expect no backlink or close is defined', async () => { render(Page, { title: 'No Title', }); - const backElement = screen.queryByLabelText('back'); + const backElement = screen.queryByLabelText('Back'); expect(backElement).not.toBeInTheDocument(); const closeElement = screen.queryByTitle('Close'); expect(closeElement).toBeInTheDocument(); }); -test('Expect name is defined', async () => { +test('Expect page name is defined', async () => { const name = 'My Dummy Name'; render(Page, { title: 'No Title', breadcrumbRightPart: name, }); - const nameElement = screen.getByLabelText('name'); + const nameElement = screen.getByLabelText('Page Name'); expect(nameElement).toBeInTheDocument(); expect(nameElement).toHaveTextContent(name); }); @@ -86,7 +74,7 @@ test('Expect backlink is defined', async () => { onbreadcrumbClick: breadcrumbClickMock, }); - const backElement = screen.getByLabelText('back'); + const backElement = screen.getByLabelText('Back'); expect(backElement).toBeInTheDocument(); expect(backElement).toHaveTextContent(backName); diff --git a/packages/ui/src/lib/layouts/Page.svelte b/packages/ui/src/lib/layouts/Page.svelte index 2b990a5af07..e9c83a6ddb4 100644 --- a/packages/ui/src/lib/layouts/Page.svelte +++ b/packages/ui/src/lib/layouts/Page.svelte @@ -37,17 +37,20 @@ function handleKeydown(e: KeyboardEvent): void {
-
+
{#if showBreadcrumb} -
+
-
+
@@ -94,8 +97,10 @@ function handleKeydown(e: KeyboardEvent): void { {#if inProgress} {/if} - -
+
+ +
+
diff --git a/tests/playwright/src/index.ts b/tests/playwright/src/index.ts index 14c4ee918fc..ec3a318573f 100644 --- a/tests/playwright/src/index.ts +++ b/tests/playwright/src/index.ts @@ -43,6 +43,7 @@ export * from './model/pages/container-details-page'; export * from './model/pages/containers-page'; export * from './model/pages/create-pod-page'; export * from './model/pages/dashboard-page'; +export * from './model/pages/details-page'; export * from './model/pages/extension-card-page'; export * from './model/pages/extension-catalog-card-page'; export * from './model/pages/extension-details-page'; diff --git a/tests/playwright/src/model/pages/container-details-page.ts b/tests/playwright/src/model/pages/container-details-page.ts index 94b6bcd8c3b..e44b05d161a 100644 --- a/tests/playwright/src/model/pages/container-details-page.ts +++ b/tests/playwright/src/model/pages/container-details-page.ts @@ -21,15 +21,10 @@ import { expect as playExpect } from '@playwright/test'; import { handleConfirmationDialog } from '../../utility/operations'; import { ContainerState } from '../core/states'; -import { BasePage } from './base-page'; import { ContainersPage } from './containers-page'; +import { DetailsPage } from './details-page'; -export class ContainerDetailsPage extends BasePage { - readonly labelName: Locator; - readonly heading: Locator; - readonly closeLink: Locator; - readonly backToContainersLink: Locator; - readonly containerName: string; +export class ContainerDetailsPage extends DetailsPage { readonly stopButton: Locator; readonly deleteButton: Locator; @@ -40,25 +35,14 @@ export class ContainerDetailsPage extends BasePage { static readonly INSPECT_TAB = 'Inspect'; constructor(page: Page, name: string) { - super(page); - this.containerName = name; - this.labelName = page.getByLabel('name').and(page.getByText('Container Details')); - this.heading = page.getByRole('heading', { name: this.containerName }); - this.closeLink = page.getByRole('link', { name: 'Close Details' }); - this.backToContainersLink = page.getByRole('link', { name: 'Go back to Containers' }); - this.stopButton = this.page.getByRole('button').and(this.page.getByLabel('Stop Container')); - this.deleteButton = this.page.getByRole('button').and(this.page.getByLabel('Delete Container')); - } - - async activateTab(tabName: string): Promise { - const tabItem = this.page.getByRole('link', { name: tabName, exact: true }); - await playExpect(tabItem).toBeVisible(); - await tabItem.click(); + super(page, name); + this.stopButton = this.controlActions.getByRole('button').and(this.page.getByLabel('Stop Container')); + this.deleteButton = this.controlActions.getByRole('button').and(this.page.getByLabel('Delete Container')); } async getStateLocator(): Promise { await this.activateTab(ContainerDetailsPage.SUMMARY_TAB); - const summaryTable = this.getPage().getByRole('table'); + const summaryTable = this.tabContent.getByRole('table'); const stateRow = summaryTable.locator('tr:has-text("State")'); const stateCell = stateRow.getByRole('cell').nth(1); await playExpect(stateCell).toBeVisible(); @@ -93,7 +77,7 @@ export class ContainerDetailsPage extends BasePage { async getContainerPort(): Promise { await this.activateTab(ContainerDetailsPage.SUMMARY_TAB); - const summaryTable = this.getPage().getByRole('table'); + const summaryTable = this.tabContent.getByRole('table'); const portsRow = summaryTable.locator('tr:has-text("Ports")'); const portsCell = portsRow.getByRole('cell').nth(1); await playExpect(portsCell).toBeVisible(); diff --git a/tests/playwright/src/model/pages/details-page.ts b/tests/playwright/src/model/pages/details-page.ts new file mode 100644 index 00000000000..ebde0bc9a43 --- /dev/null +++ b/tests/playwright/src/model/pages/details-page.ts @@ -0,0 +1,56 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { expect as playExpect, type Locator, type Page } from '@playwright/test'; + +import { BasePage } from './base-page'; + +export abstract class DetailsPage extends BasePage { + readonly header: Locator; + readonly tabs: Locator; + readonly tabContent: Locator; + readonly controlActions: Locator; + readonly closeButton: Locator; + readonly backLink: Locator; + readonly pageName: Locator; + readonly resourceName: string; + readonly heading: Locator; + readonly breadcrumb: Locator; + + constructor(page: Page, resourceName: string) { + super(page); + this.resourceName = resourceName; + + this.tabContent = page.getByRole('region', { name: 'Tab Content' }); + this.header = page.getByRole('region', { name: 'Header' }); + this.tabs = page.getByRole('region', { name: 'Tabs' }); + this.breadcrumb = this.header.getByRole('navigation', { name: 'Breadcrumb' }); + this.controlActions = this.header.getByRole('group', { name: 'Control Actions' }); + this.heading = this.header.getByRole('heading', { name: this.resourceName }); + this.closeButton = this.breadcrumb.getByRole('button', { name: 'Close' }); + this.backLink = this.breadcrumb.getByRole('link', { name: 'Back' }); + this.pageName = this.breadcrumb.getByRole('region', { name: 'Page Name' }); + } + + async activateTab(tabName: string): Promise { + const tabItem = this.tabs.getByRole('link', { name: tabName, exact: true }); + await playExpect(tabItem).toBeVisible(); + await tabItem.click(); + return this; + } +} diff --git a/tests/playwright/src/model/pages/image-details-page.ts b/tests/playwright/src/model/pages/image-details-page.ts index 53bd0742e44..3f4784de9f1 100644 --- a/tests/playwright/src/model/pages/image-details-page.ts +++ b/tests/playwright/src/model/pages/image-details-page.ts @@ -21,23 +21,18 @@ import { expect as playExpect } from '@playwright/test'; import type { PodmanDesktopRunner } from '../../runner/podman-desktop-runner'; import { handleConfirmationDialog } from '../../utility/operations'; -import { BasePage } from './base-page'; +import { DetailsPage } from './details-page'; import { ImageEditPage } from './image-edit-page'; import { ImagesPage } from './images-page'; import { RunImagePage } from './run-image-page'; -export class ImageDetailsPage extends BasePage { - readonly name: Locator; - readonly imageName: string; - readonly heading: Locator; +export class ImageDetailsPage extends DetailsPage { readonly runImageButton: Locator; readonly deleteButton: Locator; readonly editButton: Locator; readonly summaryTab: Locator; readonly historyTab: Locator; readonly inspectTab: Locator; - readonly closeLink: Locator; - readonly backToImagesLink: Locator; readonly actionsButton: Locator; readonly buildDiskImageButton: Locator; readonly saveImagebutton: Locator; @@ -46,21 +41,16 @@ export class ImageDetailsPage extends BasePage { readonly browseButton: Locator; constructor(page: Page, name: string) { - super(page); - this.name = page.getByLabel('name').and(page.getByText('Image Details')); - this.imageName = name; - this.heading = page.getByRole('heading', { name: this.imageName }); - this.runImageButton = page.getByRole('button', { name: 'Run Image' }); - this.deleteButton = page.getByRole('button', { name: 'Delete Image' }); - this.editButton = page.getByRole('button', { name: 'Edit Image' }); - this.summaryTab = page.getByText('Summary'); - this.historyTab = page.getByText('History'); - this.inspectTab = page.getByText('Inspect'); - this.closeLink = page.getByRole('link', { name: 'Close Details' }); - this.backToImagesLink = page.getByRole('link', { name: 'Go back to Images' }); + super(page, name); + this.runImageButton = this.controlActions.getByRole('button', { name: 'Run Image' }); + this.deleteButton = this.controlActions.getByRole('button', { name: 'Delete Image' }); + this.editButton = this.controlActions.getByRole('button', { name: 'Edit Image' }); + this.summaryTab = this.tabs.getByText('Summary'); + this.historyTab = this.tabs.getByText('History'); + this.inspectTab = this.tabs.getByText('Inspect'); this.actionsButton = page.getByRole('button', { name: 'kebab menu' }); this.buildDiskImageButton = page.getByTitle('Build Disk Image'); - this.saveImagebutton = page.getByRole('button', { name: 'Save Image', exact: true }); + this.saveImagebutton = this.controlActions.getByRole('button', { name: 'Save Image', exact: true }); this.saveImageInput = page.locator('#input-output-directory'); this.confirmSaveImages = page.getByLabel('Save images', { exact: true }); this.browseButton = page.getByLabel('Select output folder'); @@ -69,13 +59,13 @@ export class ImageDetailsPage extends BasePage { async openRunImage(): Promise { await playExpect(this.runImageButton).toBeEnabled({ timeout: 30000 }); await this.runImageButton.click(); - return new RunImagePage(this.page, this.imageName); + return new RunImagePage(this.page, this.resourceName); } async openEditImage(): Promise { await playExpect(this.editButton).toBeEnabled({ timeout: 30000 }); await this.editButton.click(); - return new ImageEditPage(this.page, this.imageName); + return new ImageEditPage(this.page, this.resourceName); } async deleteImage(): Promise { diff --git a/tests/playwright/src/model/pages/pods-details-page.ts b/tests/playwright/src/model/pages/pods-details-page.ts index 6b64e2526ea..eb42dd5f245 100644 --- a/tests/playwright/src/model/pages/pods-details-page.ts +++ b/tests/playwright/src/model/pages/pods-details-page.ts @@ -22,15 +22,10 @@ import { expect as playExpect } from '@playwright/test'; import { handleConfirmationDialog } from '../../utility/operations'; import { PodState } from '../core/states'; import { NavigationBar } from '../workbench/navigation'; -import { BasePage } from './base-page'; +import { DetailsPage } from './details-page'; import { PodsPage } from './pods-page'; -export class PodDetailsPage extends BasePage { - readonly labelName: Locator; - readonly heading: Locator; - readonly closeLink: Locator; - readonly backToPodsLink: Locator; - readonly podName: string; +export class PodDetailsPage extends DetailsPage { readonly startButton: Locator; readonly stopButton: Locator; readonly restartButton: Locator; @@ -42,26 +37,19 @@ export class PodDetailsPage extends BasePage { static readonly KUBE_TAB = 'Kube'; constructor(page: Page, name: string) { - super(page); - this.podName = name; - this.labelName = page.getByLabel('name').and(page.getByText('Pod Details')); - this.heading = page.getByRole('heading', { name: this.podName }); - this.closeLink = page.getByRole('link', { name: 'Close Details' }); - this.backToPodsLink = page.getByRole('link', { name: 'Go back to Pods' }); - this.startButton = this.page.getByRole('button').and(this.page.getByLabel('Start Pod', { exact: true })); - this.stopButton = this.page.getByRole('button').and(this.page.getByLabel('Stop Pod', { exact: true })); - this.restartButton = this.page.getByRole('button').and(this.page.getByLabel('Restart Pod', { exact: true })); - this.deleteButton = this.page.getByRole('button').and(this.page.getByLabel('Delete Pod', { exact: true })); - } - - async activateTab(tabName: string): Promise { - const tabItem = this.page.getByRole('link', { name: tabName }); - await playExpect(tabItem).toBeEnabled(); - await tabItem.click(); + super(page, name); + this.startButton = this.controlActions.getByRole('button').and(this.page.getByLabel('Start Pod', { exact: true })); + this.stopButton = this.controlActions.getByRole('button').and(this.page.getByLabel('Stop Pod', { exact: true })); + this.restartButton = this.controlActions + .getByRole('button') + .and(this.page.getByLabel('Restart Pod', { exact: true })); + this.deleteButton = this.controlActions + .getByRole('button') + .and(this.page.getByLabel('Delete Pod', { exact: true })); } async getState(): Promise { - const currentState = await this.page.getByRole('status').getAttribute('title'); + const currentState = await this.header.getByRole('status').getAttribute('title'); for (const state of Object.values(PodState)) { if (currentState === state) return state; } diff --git a/tests/playwright/src/model/pages/volume-details-page.ts b/tests/playwright/src/model/pages/volume-details-page.ts index e6c5af13aa7..58729b59e3b 100644 --- a/tests/playwright/src/model/pages/volume-details-page.ts +++ b/tests/playwright/src/model/pages/volume-details-page.ts @@ -20,39 +20,22 @@ import type { Locator, Page } from '@playwright/test'; import { expect as playExpect } from '@playwright/test'; import { handleConfirmationDialog } from '../../utility/operations'; -import { BasePage } from './base-page'; +import { DetailsPage } from './details-page'; import { VolumesPage } from './volumes-page'; -export class VolumeDetailsPage extends BasePage { - readonly labelName: Locator; - readonly heading: Locator; - readonly closeLink: Locator; - readonly backToVolumesLink: Locator; - readonly volumeName: string; +export class VolumeDetailsPage extends DetailsPage { readonly deleteButton: Locator; static readonly SUMMARY_TAB = 'Summary'; constructor(page: Page, name: string) { - super(page); - this.volumeName = name; - this.labelName = page.getByLabel('name').and(page.getByText('Volume Details')); - this.heading = page.getByRole('heading', { name: this.volumeName }); - this.closeLink = page.getByRole('link', { name: 'Close Details' }); - this.backToVolumesLink = page.getByRole('link', { name: 'Go back to Volumes' }); - this.deleteButton = page.getByRole('button', { name: 'Delete Volume' }); - } - - async activateTab(tabName: string): Promise { - const tabItem = this.page.getByRole('link', { name: tabName, exact: true }); - await tabItem.waitFor({ state: 'visible', timeout: 2000 }); - await tabItem.click(); - return this; + super(page, name); + this.deleteButton = this.controlActions.getByRole('button', { name: 'Delete Volume' }); } async getStateLocator(): Promise { await this.activateTab(VolumeDetailsPage.SUMMARY_TAB); - const summaryTable = this.getPage().getByRole('table'); + const summaryTable = this.tabContent.getByRole('table'); const stateRow = summaryTable.locator('tr:has-text("State")'); const stateCell = stateRow.getByRole('cell').nth(1); await stateCell.waitFor({ state: 'visible', timeout: 500 }); diff --git a/tests/playwright/src/specs/container-smoke.spec.ts b/tests/playwright/src/specs/container-smoke.spec.ts index 0db95a599b8..d950103c8d5 100644 --- a/tests/playwright/src/specs/container-smoke.spec.ts +++ b/tests/playwright/src/specs/container-smoke.spec.ts @@ -113,7 +113,20 @@ describe('Verification of container creation workflow', async () => { images = await navigationBar.openImages(); playExpect(await images.getCurrentStatusOfImage(imageToPull)).toBe('USED'); }); + test('Test navigation between pages', async () => { + const navigationBar = new NavigationBar(page); + const containers = await navigationBar.openContainers(); + const containersDetails = await containers.openContainersDetails(containerToRun); + await playExpect(containersDetails.heading).toBeVisible(); + await containersDetails.backLink.click(); + await playExpect(containers.heading).toBeVisible(); + + await containers.openContainersDetails(containerToRun); + await playExpect(containersDetails.heading).toBeVisible(); + await containersDetails.closeButton.click(); + await playExpect(containers.heading).toBeVisible(); + }); test('Open a container details', async () => { const navigationBar = new NavigationBar(page); const containers = await navigationBar.openContainers(); diff --git a/tests/playwright/src/specs/image-smoke.spec.ts b/tests/playwright/src/specs/image-smoke.spec.ts index a92f0a7df3d..8743cde6e7c 100644 --- a/tests/playwright/src/specs/image-smoke.spec.ts +++ b/tests/playwright/src/specs/image-smoke.spec.ts @@ -76,7 +76,18 @@ describe('Image workflow verification', async () => { playExpect(exists, `${helloContainer} image not present in the list of images`).toBeTruthy(); playExpect(await updatedImages.getCurrentStatusOfImage(helloContainer)).toBe('UNUSED'); }); + test('Test navigation between pages', async () => { + const imagesPage = await navBar.openImages(); + const imageDetailPage = await imagesPage.openImageDetails(helloContainer); + await playExpect(imageDetailPage.heading).toBeVisible(); + await imageDetailPage.backLink.click(); + await playExpect(imagesPage.heading).toBeVisible(); + await imagesPage.openImageDetails(helloContainer); + await playExpect(imageDetailPage.heading).toBeVisible(); + await imageDetailPage.closeButton.click(); + await playExpect(imagesPage.heading).toBeVisible(); + }); test('Check image details', async () => { const imagesPage = await navBar.openImages(); const imageDetailPage = await imagesPage.openImageDetails(helloContainer); diff --git a/tests/playwright/src/specs/pod-smoke.spec.ts b/tests/playwright/src/specs/pod-smoke.spec.ts index 418226d46ea..d4eb6f93d71 100644 --- a/tests/playwright/src/specs/pod-smoke.spec.ts +++ b/tests/playwright/src/specs/pod-smoke.spec.ts @@ -145,7 +145,6 @@ describe.skipIf(process.env.GITHUB_ACTIONS && process.env.RUNNER_OS === 'Linux') .poll(async () => await containerDetails.getState(), { timeout: 15000 }) .toBe(ContainerState.Running.toLowerCase()); }); - test('Podify containers', async () => { const navigationBar = new NavigationBar(page); const containers = await navigationBar.openContainers(); @@ -156,7 +155,21 @@ describe.skipIf(process.env.GITHUB_ACTIONS && process.env.RUNNER_OS === 'Linux') const podDetails = await pods.openPodDetails(podToRun); await playExpect.poll(async () => await podDetails.getState(), { timeout: 15000 }).toBe(PodState.Running); }, 90000); + test('Test navigation between pages', async () => { + const navigationBar = new NavigationBar(page); + const pods = await navigationBar.openPods(); + await playExpect.poll(async () => await pods.podExists(podToRun), { timeout: 10000 }).toBeTruthy(); + const podDetails = await pods.openPodDetails(podToRun); + await playExpect(podDetails.heading).toBeVisible(); + await podDetails.backLink.click(); + await playExpect(pods.heading).toBeVisible(); + + await pods.openPodDetails(podToRun); + await playExpect(podDetails.heading).toBeVisible(); + await podDetails.closeButton.click(); + await playExpect(pods.heading).toBeVisible(); + }); test('Checking pod details', async () => { const navigationBar = new NavigationBar(page); const pods = await navigationBar.openPods(); diff --git a/tests/playwright/src/specs/volume-smoke.spec.ts b/tests/playwright/src/specs/volume-smoke.spec.ts index 323c9679945..923a1d04591 100644 --- a/tests/playwright/src/specs/volume-smoke.spec.ts +++ b/tests/playwright/src/specs/volume-smoke.spec.ts @@ -61,7 +61,22 @@ describe('Volume workflow verification', async () => { await playExpect.poll(async () => await volumesPage.waitForVolumeExists(volumeName)).toBeTruthy(); }); + test('Test navigation between pages', async () => { + const volumesPage = await navBar.openVolumes(); + await playExpect(volumesPage.heading).toBeVisible(); + const volumeRow = await volumesPage.getVolumeRowByName(volumeName); + playExpect(volumeRow).not.toBeUndefined(); + const volumeDetails = await volumesPage.openVolumeDetails(volumeName); + await playExpect(volumeDetails.heading).toBeVisible(); + await volumeDetails.backLink.click(); + await playExpect(volumesPage.heading).toBeVisible(); + + await volumesPage.openVolumeDetails(volumeName); + await playExpect(volumeDetails.heading).toBeVisible(); + await volumeDetails.closeButton.click(); + await playExpect(volumesPage.heading).toBeVisible(); + }); test('Delete volume through details page', async () => { let volumesPage = await navBar.openVolumes(); await playExpect(volumesPage.heading).toBeVisible();