From 2bcb5f61f3f0a7fc3e74f78a96bff6c4c56af69a Mon Sep 17 00:00:00 2001 From: Tibor Dancs Date: Mon, 4 Mar 2024 15:42:05 +0100 Subject: [PATCH] chore(test): implementing podman machine creation through onboarding workflow e2e test (#5800) * chore(test): implementing podman machine creation through onboarding workflow e2e test Signed-off-by: Tibor Dancs (tdancs old laptop podman-desktop windows testing) --------- Signed-off-by: Tibor Dancs Co-authored-by: Vladimir Lazar <106525396+cbr7@users.noreply.github.com> --- .../src/lib/onboarding/Onboarding.svelte | 2 + tests/src/model/pages/dashboard-page.ts | 5 +- tests/src/model/pages/onboarding-page.ts | 39 ++++ .../pages/podman-machine-details-page.ts | 44 ++++ .../src/model/pages/podman-onboarding-page.ts | 62 ++++++ tests/src/model/pages/resources-page.ts | 2 + .../resources-podman-connections-page.ts | 45 +++++ tests/src/podman-machine-onboarding.spec.ts | 191 ++++++++++++++++++ tests/src/utility/operations.ts | 44 +++- 9 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 tests/src/model/pages/onboarding-page.ts create mode 100644 tests/src/model/pages/podman-machine-details-page.ts create mode 100644 tests/src/model/pages/podman-onboarding-page.ts create mode 100644 tests/src/model/pages/resources-podman-connections-page.ts create mode 100644 tests/src/podman-machine-onboarding.spec.ts diff --git a/packages/renderer/src/lib/onboarding/Onboarding.svelte b/packages/renderer/src/lib/onboarding/Onboarding.svelte index 12f8e1a29cb48..416d4e1d054e1 100644 --- a/packages/renderer/src/lib/onboarding/Onboarding.svelte +++ b/packages/renderer/src/lib/onboarding/Onboarding.svelte @@ -298,6 +298,8 @@ function handleEscape({ key }: any) {
diff --git a/tests/src/model/pages/dashboard-page.ts b/tests/src/model/pages/dashboard-page.ts index 9880e35042773..4d64436ad6b06 100644 --- a/tests/src/model/pages/dashboard-page.ts +++ b/tests/src/model/pages/dashboard-page.ts @@ -24,6 +24,7 @@ export class DashboardPage extends BasePage { readonly header: Locator; readonly content: Locator; readonly heading: Locator; + readonly notificationsBox: Locator; readonly featuredExtensions: Locator; readonly devSandboxProvider: Locator; readonly devSandboxBox: Locator; @@ -37,9 +38,11 @@ export class DashboardPage extends BasePage { this.mainPage = page.getByRole('region', { name: 'Dashboard' }); this.header = this.mainPage.getByRole('region', { name: 'header' }); this.content = this.mainPage.getByRole('region', { name: 'content' }); - this.featuredExtensions = page.getByLabel('FeaturedExtensions'); this.heading = page.getByRole('heading', { name: 'Dashboard' }); + this.notificationsBox = this.content.getByRole('region', { name: 'Notifications Box' }); + this.featuredExtensions = page.getByLabel('FeaturedExtensions'); + this.devSandboxProvider = page.getByLabel('Developer Sandbox Provider'); this.devSandboxBox = this.featuredExtensions.getByLabel('Developer Sandbox'); this.devSandboxEnabledStatus = this.devSandboxProvider.getByText('RUNNING'); diff --git a/tests/src/model/pages/onboarding-page.ts b/tests/src/model/pages/onboarding-page.ts new file mode 100644 index 0000000000000..4f1447d091f20 --- /dev/null +++ b/tests/src/model/pages/onboarding-page.ts @@ -0,0 +1,39 @@ +/********************************************************************** + * 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 type { Locator, Page } from '@playwright/test'; +import { BasePage } from './base-page'; + +export class OnboardingPage extends BasePage { + readonly mainPage: Locator; + readonly header: Locator; + readonly onboardingComponent: Locator; + readonly onboardingStatusMessage: Locator; + readonly nextStepButton: Locator; + readonly cancelSetupButtion: Locator; + + constructor(page: Page) { + super(page); + this.mainPage = page.getByRole('region', { name: 'Onboarding Body' }); + this.header = this.mainPage.getByRole('heading', { name: 'Header' }); + this.onboardingComponent = this.mainPage.getByLabel('Onboarding Component'); + this.onboardingStatusMessage = this.mainPage.getByLabel('Onboarding Status Message'); + this.nextStepButton = this.mainPage.getByRole('button', { name: 'Next Step' }); + this.cancelSetupButtion = this.mainPage.getByRole('button', { name: 'Cancel Setup' }); + } +} diff --git a/tests/src/model/pages/podman-machine-details-page.ts b/tests/src/model/pages/podman-machine-details-page.ts new file mode 100644 index 0000000000000..3647896d28c84 --- /dev/null +++ b/tests/src/model/pages/podman-machine-details-page.ts @@ -0,0 +1,44 @@ +/********************************************************************** + * 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 type { Locator, Page } from '@playwright/test'; +import { ResourcesPage } from './resources-page'; + +export class PodmanMachineDetails extends ResourcesPage { + readonly podmanMachineName: Locator; + readonly podmanMachineStatus: Locator; + readonly podmanMachineConnectionActions: Locator; + readonly podmanMachineStartButton: Locator; + readonly podmanMachineRestartButton: Locator; + readonly podmanMachineStopButton: Locator; + readonly podmanMachineDeleteButton: Locator; + + constructor(page: Page) { + super(page); + this.podmanMachineName = this.getPage().getByRole('heading', { name: 'Podman Machine' }); + this.podmanMachineStatus = this.getPage().getByLabel('Connection Status Label'); + this.podmanMachineConnectionActions = this.getPage().getByRole('group', { name: 'Connection Actions' }); + this.podmanMachineStartButton = this.podmanMachineConnectionActions.getByRole('button', { + name: 'Start', + exact: true, + }); + this.podmanMachineRestartButton = this.podmanMachineConnectionActions.getByRole('button', { name: 'Restart' }); + this.podmanMachineStopButton = this.podmanMachineConnectionActions.getByRole('button', { name: 'Stop' }); + this.podmanMachineDeleteButton = this.podmanMachineConnectionActions.getByRole('button', { name: 'Delete' }); + } +} diff --git a/tests/src/model/pages/podman-onboarding-page.ts b/tests/src/model/pages/podman-onboarding-page.ts new file mode 100644 index 0000000000000..5ea5a9e25a291 --- /dev/null +++ b/tests/src/model/pages/podman-onboarding-page.ts @@ -0,0 +1,62 @@ +/********************************************************************** + * 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 type { Locator, Page } from '@playwright/test'; +import { OnboardingPage } from './onboarding-page'; + +export class PodmanOnboardingPage extends OnboardingPage { + readonly podmanAutostartToggle: Locator; + readonly createMachinePageTitle: Locator; + readonly podmanMachineConfiguration: Locator; + readonly podmanMachineName: Locator; + readonly podmanMachineCPUs: Locator; + readonly podmanMachineMemory: Locator; + readonly podmanMachineDiskSize: Locator; + readonly podmanMachineImage: Locator; + readonly podmanMachineRootfulCheckbox: Locator; + readonly podmanMachineUserModeNetworkingCheckbox: Locator; + readonly podmanMachineStartAfterCreationCheckbox: Locator; + readonly podmanMachineCreateButton: Locator; + readonly podmanMachineShowLogsButton: Locator; + + constructor(page: Page) { + super(page); + this.podmanAutostartToggle = this.mainPage.getByRole('checkbox', { + name: 'Autostart Podman engine when launching Podman Desktop', + }); + this.createMachinePageTitle = this.onboardingComponent.getByLabel('title'); + this.podmanMachineConfiguration = this.mainPage.getByRole('form', { name: 'Properties Information' }); + this.podmanMachineName = this.podmanMachineConfiguration.getByRole('textbox', { name: 'Name' }); + this.podmanMachineCPUs = this.podmanMachineConfiguration.getByRole('slider', { name: 'CPU(s)' }); + this.podmanMachineMemory = this.podmanMachineConfiguration.getByRole('slider', { name: 'Memory' }); + this.podmanMachineDiskSize = this.podmanMachineConfiguration.getByRole('slider', { name: 'Disk size' }); + this.podmanMachineImage = this.podmanMachineConfiguration.getByRole('textbox', { name: 'Image Path (Optional)' }); + this.podmanMachineRootfulCheckbox = this.podmanMachineConfiguration.getByRole('checkbox', { + name: 'Machine with root privileges', + }); + this.podmanMachineUserModeNetworkingCheckbox = this.podmanMachineConfiguration.getByRole('checkbox', { + name: 'User mode networking', + exact: false, + }); + this.podmanMachineStartAfterCreationCheckbox = this.podmanMachineConfiguration.getByRole('checkbox', { + name: 'Start the machine now', + }); + this.podmanMachineCreateButton = this.podmanMachineConfiguration.getByRole('button', { name: 'Create' }); + this.podmanMachineShowLogsButton = this.mainPage.getByRole('button', { name: 'Show Logs' }); + } +} diff --git a/tests/src/model/pages/resources-page.ts b/tests/src/model/pages/resources-page.ts index 7f85df631c8ad..5ddaa3adea093 100644 --- a/tests/src/model/pages/resources-page.ts +++ b/tests/src/model/pages/resources-page.ts @@ -22,10 +22,12 @@ import { SettingsPage } from './settings-page'; export class ResourcesPage extends SettingsPage { readonly heading: Locator; readonly featuredProviderResources: Locator; + readonly podmanResources: Locator; constructor(page: Page) { super(page, 'Resources'); this.heading = page.getByRole('heading', { name: 'Resources' }); this.featuredProviderResources = page.getByRole('region', { name: 'Featured Provider Resources' }); + this.podmanResources = this.featuredProviderResources.getByRole('region', { name: 'podman', exact: true }); } } diff --git a/tests/src/model/pages/resources-podman-connections-page.ts b/tests/src/model/pages/resources-podman-connections-page.ts new file mode 100644 index 0000000000000..d0b84941b3dbf --- /dev/null +++ b/tests/src/model/pages/resources-podman-connections-page.ts @@ -0,0 +1,45 @@ +/********************************************************************** + * 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 type { Locator, Page } from '@playwright/test'; +import { ResourcesPage } from './resources-page'; + +export class ResourcesPodmanConnections extends ResourcesPage { + readonly providerConnections: Locator; + readonly podmanMachineElement: Locator; + readonly machineConnectionStatus: Locator; + readonly machineDetailsButton: Locator; + readonly machineConnectionActions: Locator; + readonly machineStartButton: Locator; + readonly machineRestartButton: Locator; + readonly machineStopButton: Locator; + readonly machineDeleteButton: Locator; + + constructor(page: Page, machineVisibleName: string) { + super(page); + this.providerConnections = this.podmanResources.getByRole('region', { name: 'Provider Connections' }); + this.podmanMachineElement = this.providerConnections.getByRole('region', { name: machineVisibleName }); + this.machineConnectionStatus = this.podmanMachineElement.getByLabel('Connection Status Label'); + this.machineDetailsButton = this.podmanMachineElement.getByRole('button', { name: 'Podman details' }); + this.machineConnectionActions = this.podmanMachineElement.getByRole('group', { name: 'Connection Actions' }); + this.machineStartButton = this.machineConnectionActions.getByRole('button', { name: 'Start', exact: true }); + this.machineRestartButton = this.machineConnectionActions.getByRole('button', { name: 'Restart' }); + this.machineStopButton = this.machineConnectionActions.getByRole('button', { name: 'Stop' }); + this.machineDeleteButton = this.machineConnectionActions.getByRole('button', { name: 'Delete' }); + } +} diff --git a/tests/src/podman-machine-onboarding.spec.ts b/tests/src/podman-machine-onboarding.spec.ts new file mode 100644 index 0000000000000..bc2aef5e6283d --- /dev/null +++ b/tests/src/podman-machine-onboarding.spec.ts @@ -0,0 +1,191 @@ +/********************************************************************** + * 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 type { Page } from 'playwright'; +import type { RunnerTestContext } from './testContext/runner-test-context'; +import { afterAll, beforeAll, test, describe, beforeEach } from 'vitest'; +import { PodmanDesktopRunner } from './runner/podman-desktop-runner'; +import { WelcomePage } from './model/pages/welcome-page'; +import type { DashboardPage } from './model/pages/dashboard-page'; +import type { Locator } from '@playwright/test'; +import { expect as playExpect } from '@playwright/test'; +import { NavigationBar } from './model/workbench/navigation'; +import type { SettingsBar } from './model/pages/settings-bar'; +import { ResourcesPage } from './model/pages/resources-page'; +import { deletePodmanMachine } from './utility/operations'; +import { PodmanOnboardingPage } from './model/pages/podman-onboarding-page'; +import { ResourcesPodmanConnections } from './model/pages/resources-podman-connections-page'; +import { PodmanMachineDetails } from './model/pages/podman-machine-details-page'; + +const PODMAN_MACHINE_STARTUP_TIMEOUT: number = 360_000; +const PODMAN_MACHINE_NAME: string = 'Podman Machine'; + +let pdRunner: PodmanDesktopRunner; +let page: Page; +let dashboardPage: DashboardPage; +let resourcesPage: ResourcesPage; +let settingsBar: SettingsBar; +let navigationBar: NavigationBar; +let podmanOnboardingPage: PodmanOnboardingPage; + +let notificationPodmanSetup: Locator; + +beforeAll(async () => { + pdRunner = new PodmanDesktopRunner(); + page = await pdRunner.start(); + pdRunner.setVideoAndTraceName('podman-machine-e2e'); + + const welcomePage = new WelcomePage(page); + await welcomePage.handleWelcomePage(true); + navigationBar = new NavigationBar(page); + + // Delete machine if it already exists + if ( + (process.env.TEST_PODMAN_MACHINE !== undefined && process.env.TEST_PODMAN_MACHINE === 'true') || + (process.env.MACHINE_CLEANUP !== undefined && process.env.MACHINE_CLEANUP === 'true') + ) { + await deletePodmanMachine(page, PODMAN_MACHINE_NAME); + } +}); + +afterAll(async () => { + await pdRunner.close(); +}, 120000); + +beforeEach(async ctx => { + ctx.pdRunner = pdRunner; +}); + +describe('Podman Machine verification', async () => { + describe('Podman Machine onboarding workflow', async () => { + test('Setup Podman push notification is present', async () => { + dashboardPage = await navigationBar.openDashboard(); + await playExpect(dashboardPage.mainPage).toBeVisible(); + await playExpect(dashboardPage.notificationsBox).toBeVisible(); + notificationPodmanSetup = dashboardPage.notificationsBox + .getByRole('region', { name: 'id:' }) + .filter({ hasText: 'Podman needs to be set up' }); + await playExpect(notificationPodmanSetup).toBeVisible(); + }); + describe('Onboarding navigation', async () => { + test('Open Podman Machine Onboarding through Setup Notification', async () => { + await notificationPodmanSetup.getByTitle('Set up Podman').click(); + podmanOnboardingPage = await checkPodmanMachineOnboardingPage(page); + }); + test('Return to Dashboard', async () => { + dashboardPage = await navigationBar.openDashboard(); + await playExpect(dashboardPage.mainPage).toBeVisible(); + }); + test('Re-Open Podman Machine Onboarding through Settings Resources page', async () => { + settingsBar = await navigationBar.openSettings(); + await settingsBar.resourcesTab.click(); + resourcesPage = new ResourcesPage(page); + await playExpect(resourcesPage.podmanResources).toBeVisible(); + await resourcesPage.podmanResources.getByLabel('Setup Podman').click(); + podmanOnboardingPage = await checkPodmanMachineOnboardingPage(page); + }); + }); + test('Verify Podman Autostart is enabled and proceed to next page', async () => { + await playExpect(podmanOnboardingPage.podmanAutostartToggle).toBeChecked(); + await podmanOnboardingPage.nextStepButton.click(); + }); + test('Expect no machine created message and proceed to next page', async () => { + await playExpect(podmanOnboardingPage.onboardingStatusMessage).toHaveText( + `We could not find any Podman machine. Let's create one!`, + ); + await podmanOnboardingPage.nextStepButton.click(); + }); + test('Verify default podman machine settings', async () => { + await playExpect(podmanOnboardingPage.createMachinePageTitle).toHaveText(`Create a Podman machine`); + await playExpect(podmanOnboardingPage.podmanMachineConfiguration).toBeVisible(); + await playExpect(podmanOnboardingPage.podmanMachineName).toHaveValue('podman-machine-default'); + await playExpect(podmanOnboardingPage.podmanMachineCPUs).toBeVisible(); + await playExpect(podmanOnboardingPage.podmanMachineMemory).toBeVisible(); + await playExpect(podmanOnboardingPage.podmanMachineDiskSize).toBeVisible(); + await playExpect(podmanOnboardingPage.podmanMachineImage).toHaveValue(''); + await playExpect(podmanOnboardingPage.podmanMachineRootfulCheckbox).toBeChecked(); + await playExpect(podmanOnboardingPage.podmanMachineUserModeNetworkingCheckbox).not.toBeChecked(); + await playExpect(podmanOnboardingPage.podmanMachineStartAfterCreationCheckbox).toBeChecked(); + }); + }); + describe.runIf(process.env.TEST_PODMAN_MACHINE !== undefined && process.env.TEST_PODMAN_MACHINE === 'true')( + 'Podman Machine creation and operations', + async () => { + test('Create a default Podman machine', async () => { + await podmanOnboardingPage.podmanMachineCreateButton.click(); + await playExpect(podmanOnboardingPage.podmanMachineShowLogsButton).toBeVisible(); + await podmanOnboardingPage.podmanMachineShowLogsButton.click(); + await playExpect(podmanOnboardingPage.onboardingStatusMessage).toBeVisible({ + timeout: PODMAN_MACHINE_STARTUP_TIMEOUT, + }); + await playExpect(podmanOnboardingPage.onboardingStatusMessage).toHaveText('Podman successfully setup'); + await podmanOnboardingPage.nextStepButton.click(); + }); + describe('Podman machine operations', async () => { + let podmanMachineDetails: PodmanMachineDetails; + test('Open podman machine details', async () => { + dashboardPage = await navigationBar.openDashboard(); + await playExpect(dashboardPage.mainPage).toBeVisible(); + settingsBar = await navigationBar.openSettings(); + await settingsBar.resourcesTab.click(); + resourcesPage = new ResourcesPage(page); + await playExpect(resourcesPage.podmanResources).toBeVisible(); + const resourcesPodmanConnections = new ResourcesPodmanConnections(page, PODMAN_MACHINE_NAME); + await playExpect(resourcesPodmanConnections.providerConnections).toBeVisible({ timeout: 10_000 }); + await playExpect(resourcesPodmanConnections.podmanMachineElement).toBeVisible(); + await playExpect(resourcesPodmanConnections.machineDetailsButton).toBeVisible(); + await resourcesPodmanConnections.machineDetailsButton.click(); + podmanMachineDetails = new PodmanMachineDetails(page); + await playExpect(podmanMachineDetails.podmanMachineStatus).toBeVisible(); + await playExpect(podmanMachineDetails.podmanMachineConnectionActions).toBeVisible(); + await playExpect(podmanMachineDetails.podmanMachineStartButton).toBeVisible(); + await playExpect(podmanMachineDetails.podmanMachineRestartButton).toBeVisible(); + await playExpect(podmanMachineDetails.podmanMachineStopButton).toBeVisible(); + await playExpect(podmanMachineDetails.podmanMachineDeleteButton).toBeVisible(); + }); + test('Podman machine operations - STOP', async () => { + await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 30_000 }); + await podmanMachineDetails.podmanMachineStopButton.click(); + await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF', { timeout: 30_000 }); + }); + test('Podman machine operations - START', async () => { + await podmanMachineDetails.podmanMachineStartButton.click(); + await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 30_000 }); + }); + test('Podman machine operations - RESTART', async () => { + await podmanMachineDetails.podmanMachineRestartButton.click(); + await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF', { timeout: 30_000 }); + await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 30_000 }); + }); + }); + }, + ); + test.runIf(process.env.MACHINE_CLEANUP !== undefined && process.env.MACHINE_CLEANUP === 'true')( + 'Clean Up Podman Machine', + async () => { + await deletePodmanMachine(page, 'Podman Machine'); + }, + ); +}); + +async function checkPodmanMachineOnboardingPage(page: Page): Promise { + const onboardingPage = new PodmanOnboardingPage(page); + await playExpect(onboardingPage.header).toBeVisible(); + await playExpect(onboardingPage.mainPage).toBeVisible(); + return onboardingPage; +} diff --git a/tests/src/utility/operations.ts b/tests/src/utility/operations.ts index 66c6293445f2c..63099f3f68f57 100644 --- a/tests/src/utility/operations.ts +++ b/tests/src/utility/operations.ts @@ -16,10 +16,13 @@ * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import { type Page } from '@playwright/test'; +import type { Page } from '@playwright/test'; import { NavigationBar } from '../model/workbench/navigation'; import { waitUntil, waitWhile } from './wait'; +import { ResourcesPage } from '../model/pages/resources-page'; import { RegistriesPage } from '../model/pages/registries-page'; +import { expect as playExpect } from '@playwright/test'; +import { ResourcesPodmanConnections } from '../model/pages/resources-podman-connections-page'; /** * Stop and delete container defined by its name @@ -156,3 +159,42 @@ export async function handleConfirmationDialog( const button = confirm ? dialog.getByRole('button', { name: 'Yes' }) : dialog.getByRole('button', { name: 'Cancel' }); await button.click(); } + +/** + * Async function that stops and deletes Podman Machine through Settings -> Resources page + * @param page playwright's page object + * @param machineVisibleName Name of the Podman Machine to delete + */ +export async function deletePodmanMachine(page: Page, machineVisibleName: string): Promise { + const navigationBar = new NavigationBar(page); + const dashboardPage = await navigationBar.openDashboard(); + await playExpect(dashboardPage.mainPage).toBeVisible({ timeout: 3000 }); + const settingsBar = await navigationBar.openSettings(); + const resourcesPage = await settingsBar.openTabPage(ResourcesPage); + await playExpect(resourcesPage.podmanResources).toBeVisible({ timeout: 10_000 }); + const resourcesPodmanConnections = new ResourcesPodmanConnections(page, machineVisibleName); + await playExpect(resourcesPodmanConnections.providerConnections).toBeVisible({ timeout: 10_000 }); + await waitWhile( + async () => { + return (await resourcesPodmanConnections.podmanMachineElement.isVisible()) ? false : true; + }, + 10_000, + 1000, + false, + ); + if (await resourcesPodmanConnections.podmanMachineElement.isVisible()) { + await playExpect(resourcesPodmanConnections.machineConnectionActions).toBeVisible({ timeout: 3000 }); + await playExpect(resourcesPodmanConnections.machineConnectionStatus).toBeVisible({ timeout: 3000 }); + if ((await resourcesPodmanConnections.machineConnectionStatus.innerText()) === 'RUNNING') { + await playExpect(resourcesPodmanConnections.machineStopButton).toBeVisible({ timeout: 3000 }); + await resourcesPodmanConnections.machineStopButton.click(); + await playExpect(resourcesPodmanConnections.machineConnectionStatus).toHaveText('OFF', { timeout: 30_000 }); + } + await playExpect(resourcesPodmanConnections.machineDeleteButton).toBeVisible({ timeout: 3000 }); + await waitWhile(() => resourcesPodmanConnections.machineDeleteButton.isDisabled(), 10_000, 1000, true); + await resourcesPodmanConnections.machineDeleteButton.click(); + await playExpect(resourcesPodmanConnections.podmanMachineElement).toBeHidden({ timeout: 30_000 }); + } else { + console.log(`Podman machine [${machineVisibleName}] not present, skipping deletion.`); + } +}