chore(test): initial draft for podman machine tests (#8785)

* chore(test): initial draft for podman machine tests
Signed-off-by: Vladimir Lazar <vlazar@redhat.com>
This commit is contained in:
Vladimir Lazar 2024-09-16 09:00:04 +02:00 committed by GitHub
parent 2c363e700c
commit dcba187c9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 204 additions and 11 deletions

View file

@ -44,7 +44,7 @@
"test:e2e:extension": "npm run test:e2e:build && npm run test:e2e:extension:run",
"test:e2e:extension:run": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' -- npx playwright test tests/playwright/src/specs/extension-installation.spec.ts",
"test:e2e:pw": "npm run test:e2e:build && npm run test:e2e:pw:run",
"test:e2e:pw:run": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' -- npx playwright test tests/playwright/src/specs/pod-smoke.spec.ts",
"test:e2e:pw:run": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' -- npx playwright test tests/playwright/src/specs/podman-machine-tests.spec.ts",
"test:e2e:update": "npm run test:e2e:build && npm run test:e2e:update:run",
"test:e2e:update:run": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' -- npx playwright test tests/playwright/src/specs/installation/ -g @update-install",
"test:main": "vitest run -r packages/main --passWithNoTests --coverage",

View file

@ -29,9 +29,9 @@ export class PodmanMachineDetails extends ResourcesPage {
readonly podmanMachineStopButton: Locator;
readonly podmanMachineDeleteButton: Locator;
constructor(page: Page) {
constructor(page: Page, podmanMachineName: string) {
super(page);
this.podmanMachineName = this.getPage().getByRole('heading', { name: 'Podman Machine' });
this.podmanMachineName = this.getPage().getByRole('heading', { name: podmanMachineName });
this.podmanMachineStatus = this.getPage().getByLabel('Connection Status Label');
this.podmanMachineConnectionActions = this.getPage().getByRole('group', { name: 'Connection Actions' });
this.podmanMachineStartButton = this.podmanMachineConnectionActions.getByRole('button', {

View file

@ -34,6 +34,7 @@ export class PodmanOnboardingPage extends OnboardingPage {
readonly podmanMachineStartAfterCreationCheckbox: Locator;
readonly podmanMachineCreateButton: Locator;
readonly podmanMachineShowLogsButton: Locator;
readonly goBackButton: Locator;
constructor(page: Page) {
super(page);
@ -41,7 +42,7 @@ export class PodmanOnboardingPage extends OnboardingPage {
name: 'Autostart Podman engine when launching Podman Desktop',
});
this.createMachinePageTitle = this.onboardingComponent.getByLabel('title');
this.podmanMachineConfiguration = this.mainPage.getByRole('form', { name: 'Properties Information' });
this.podmanMachineConfiguration = this.page.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' });
@ -59,5 +60,6 @@ export class PodmanOnboardingPage extends OnboardingPage {
});
this.podmanMachineCreateButton = this.podmanMachineConfiguration.getByRole('button', { name: 'Create' });
this.podmanMachineShowLogsButton = this.mainPage.getByRole('button', { name: 'Show Logs' });
this.goBackButton = this.page.getByRole('button', { name: 'Go back to resources' });
}
}

View file

@ -31,7 +31,20 @@ export class ResourcesPage extends SettingsPage {
}
public async resourceCardIsVisible(resourceLabel: string): Promise<boolean> {
const resourceCard = this.content.getByRole('region', { name: resourceLabel });
return (await resourceCard.count()) > 0;
return (await this.resourceCardLocatorGenerator(resourceLabel).count()) > 0;
}
public async goToCreateNewResourcePage(resourceLabel: string): Promise<void> {
if (!(await this.resourceCardIsVisible(resourceLabel))) {
throw new Error(`Resource card with label ${resourceLabel} is not available`);
}
await this.resourceCardLocatorGenerator(resourceLabel)
.getByRole('button', { name: `Create new ${resourceLabel}` })
.click();
}
private resourceCardLocatorGenerator(resourceLabel: string): Locator {
return this.content.getByRole('region', { name: resourceLabel, exact: true });
}
}

View file

@ -153,7 +153,7 @@ test.describe.serial('Podman Machine verification', () => {
await playExpect(resourcesPodmanConnections.resourceElement).toBeVisible({ timeout: 20_000 });
await playExpect(resourcesPodmanConnections.resourceElementDetailsButton).toBeVisible();
await resourcesPodmanConnections.resourceElementDetailsButton.click();
const podmanMachineDetails = new PodmanMachineDetails(page);
const podmanMachineDetails = new PodmanMachineDetails(page, PODMAN_MACHINE_NAME);
await playExpect(podmanMachineDetails.podmanMachineStatus).toBeVisible();
await playExpect(podmanMachineDetails.podmanMachineConnectionActions).toBeVisible();
await playExpect(podmanMachineDetails.podmanMachineStartButton).toBeVisible();
@ -163,7 +163,7 @@ test.describe.serial('Podman Machine verification', () => {
});
test('Podman machine operations - STOP', async ({ page }) => {
const podmanMachineDetails = new PodmanMachineDetails(page);
const podmanMachineDetails = new PodmanMachineDetails(page, PODMAN_MACHINE_NAME);
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 50_000 });
await playExpect(podmanMachineDetails.podmanMachineStopButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStopButton.click();
@ -171,14 +171,14 @@ test.describe.serial('Podman Machine verification', () => {
});
test('Podman machine operations - START', async ({ page }) => {
const podmanMachineDetails = new PodmanMachineDetails(page);
const podmanMachineDetails = new PodmanMachineDetails(page, PODMAN_MACHINE_NAME);
await playExpect(podmanMachineDetails.podmanMachineStartButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStartButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 50_000 });
});
test('Podman machine operations - RESTART', async ({ page }) => {
const podmanMachineDetails = new PodmanMachineDetails(page);
const podmanMachineDetails = new PodmanMachineDetails(page, PODMAN_MACHINE_NAME);
await playExpect(podmanMachineDetails.podmanMachineRestartButton).toBeEnabled();
await podmanMachineDetails.podmanMachineRestartButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF', { timeout: 50_000 });

View file

@ -0,0 +1,178 @@
/**********************************************************************
* 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 * as os from 'node:os';
import type { Page } from '@playwright/test';
import { PodmanMachineDetails } from '../model/pages/podman-machine-details-page';
import { PodmanOnboardingPage } from '../model/pages/podman-onboarding-page';
import { ResourceConnectionCardPage } from '../model/pages/resource-connection-card-page';
import { ResourcesPage } from '../model/pages/resources-page';
import { expect as playExpect, test } from '../utility/fixtures';
import { deletePodmanMachine } from '../utility/operations';
import { waitForPodmanMachineStartup } from '../utility/wait';
const DEFAULT_PODMAN_MACHINE = 'Podman Machine';
const DEFAULT_PODMAN_MACHINE_VISIBLE = 'podman-machine-default';
const ROOTLESS_PODMAN_MACHINE_VISIBLE = 'podman-machine-rootless';
const ROOTLESS_PODMAN_MACHINE = 'Podman Machine rootless';
const RESOURCE_NAME = 'podman';
test.skip(os.platform() === 'linux', 'Tests suite should not run on Linux platform');
test.beforeAll(async ({ runner, welcomePage, page }) => {
runner.setVideoAndTraceName('podman-machine-tests');
await welcomePage.handleWelcomePage(true);
await waitForPodmanMachineStartup(page);
});
test.afterAll(async ({ runner }) => {
await runner.close();
});
test.describe.serial(`Podman machine switching validation `, () => {
test('Check data for available Podman Machine and stop machine', async ({ page, navigationBar }) => {
const settingsBar = await navigationBar.openSettings();
await settingsBar.resourcesTab.click();
const resourcesPage = new ResourcesPage(page);
await playExpect(resourcesPage.heading).toBeVisible();
await playExpect.poll(async () => await resourcesPage.resourceCardIsVisible(RESOURCE_NAME)).toBeTruthy();
const resourcesPodmanConnections = new ResourceConnectionCardPage(
page,
RESOURCE_NAME,
DEFAULT_PODMAN_MACHINE_VISIBLE,
);
await playExpect(resourcesPodmanConnections.providerConnections).toBeVisible({ timeout: 10_000 });
await playExpect(resourcesPodmanConnections.resourceElement).toBeVisible({ timeout: 20_000 });
await playExpect(resourcesPodmanConnections.resourceElementDetailsButton).toBeVisible();
await resourcesPodmanConnections.resourceElementDetailsButton.click();
const podmanMachineDetails = new PodmanMachineDetails(page, DEFAULT_PODMAN_MACHINE);
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();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 50_000 });
await playExpect(podmanMachineDetails.podmanMachineStopButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStopButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF', { timeout: 50_000 });
});
test('Create rootless podman machine', async ({ page, navigationBar }) => {
test.setTimeout(120000);
const dashboard = await navigationBar.openDashboard();
await playExpect(dashboard.heading).toBeVisible();
const settingsBar = await navigationBar.openSettings();
await settingsBar.resourcesTab.click();
const resourcesPage = new ResourcesPage(page);
await playExpect(resourcesPage.heading).toBeVisible();
await playExpect.poll(async () => await resourcesPage.resourceCardIsVisible(RESOURCE_NAME)).toBeTruthy();
await resourcesPage.goToCreateNewResourcePage(RESOURCE_NAME);
const podmanMachineCreatePage = new PodmanOnboardingPage(page);
await playExpect(podmanMachineCreatePage.podmanMachineName).toBeVisible();
await podmanMachineCreatePage.podmanMachineName.clear();
await podmanMachineCreatePage.podmanMachineName.fill(ROOTLESS_PODMAN_MACHINE_VISIBLE);
await playExpect(podmanMachineCreatePage.podmanMachineRootfulCheckbox).toBeChecked();
await podmanMachineCreatePage.podmanMachineRootfulCheckbox.locator('..').click();
await playExpect(podmanMachineCreatePage.podmanMachineRootfulCheckbox).not.toBeChecked();
await playExpect(podmanMachineCreatePage.podmanMachineStartAfterCreationCheckbox).toBeChecked();
await podmanMachineCreatePage.podmanMachineStartAfterCreationCheckbox.locator('..').click();
await playExpect(podmanMachineCreatePage.podmanMachineStartAfterCreationCheckbox).not.toBeChecked();
await podmanMachineCreatePage.podmanMachineCreateButton.click();
await playExpect(podmanMachineCreatePage.goBackButton).toBeEnabled({ timeout: 100000 });
await podmanMachineCreatePage.goBackButton.click();
await playExpect(resourcesPage.heading).toBeVisible();
});
test('Switch to rootless podman machine', async ({ page }) => {
const resourcesPodmanConnections = new ResourceConnectionCardPage(
page,
RESOURCE_NAME,
ROOTLESS_PODMAN_MACHINE_VISIBLE,
);
await playExpect(resourcesPodmanConnections.resourceElementDetailsButton).toBeVisible();
await resourcesPodmanConnections.resourceElementDetailsButton.click();
const podmanMachineDetails = new PodmanMachineDetails(page, ROOTLESS_PODMAN_MACHINE);
await playExpect(podmanMachineDetails.podmanMachineName).toBeVisible();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF');
await playExpect(podmanMachineDetails.podmanMachineStartButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStartButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 50_000 });
await handlePopupDialog(page, 'Yes');
await handlePopupDialog(page, 'OK');
});
test('Stop rootless podman machine', async ({ page }) => {
const podmanMachineDetails = new PodmanMachineDetails(page, ROOTLESS_PODMAN_MACHINE);
await playExpect(podmanMachineDetails.podmanMachineName).toBeVisible();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING');
await playExpect(podmanMachineDetails.podmanMachineStopButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStopButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('OFF', { timeout: 50_000 });
});
test('Restart default podman machine', async ({ page, navigationBar }) => {
const dashboard = await navigationBar.openDashboard();
await playExpect(dashboard.heading).toBeVisible();
const settingsBar = await navigationBar.openSettings();
await settingsBar.resourcesTab.click();
const resourcesPage = new ResourcesPage(page);
await playExpect(resourcesPage.heading).toBeVisible();
await playExpect.poll(async () => await resourcesPage.resourceCardIsVisible(RESOURCE_NAME)).toBeTruthy();
const resourcesPodmanConnections = new ResourceConnectionCardPage(
page,
RESOURCE_NAME,
DEFAULT_PODMAN_MACHINE_VISIBLE,
);
await playExpect(resourcesPodmanConnections.resourceElementDetailsButton).toBeVisible();
await resourcesPodmanConnections.resourceElementDetailsButton.click();
const podmanMachineDetails = new PodmanMachineDetails(page, DEFAULT_PODMAN_MACHINE);
await playExpect(podmanMachineDetails.podmanMachineStartButton).toBeEnabled();
await podmanMachineDetails.podmanMachineStartButton.click();
await playExpect(podmanMachineDetails.podmanMachineStatus).toHaveText('RUNNING', { timeout: 50_000 });
await handlePopupDialog(page, 'Yes');
await handlePopupDialog(page, 'OK');
});
test('Clean up rootless podman machine', async ({ page }) => {
await deletePodmanMachine(page, ROOTLESS_PODMAN_MACHINE_VISIBLE);
});
async function handlePopupDialog(page: Page, action: string): Promise<void> {
const dialog = page.getByRole('dialog', { name: 'Podman', exact: true });
await playExpect(dialog).toBeVisible();
const clickOnButton = dialog.getByRole('button', { name: action, exact: true });
await playExpect(clickOnButton).toBeEnabled();
await clickOnButton.click();
}
});

View file

@ -177,7 +177,7 @@ export async function deletePodmanMachine(page: Page, machineVisibleName: string
const RESOURCE_NAME: string = 'podman';
const navigationBar = new NavigationBar(page);
const dashboardPage = await navigationBar.openDashboard();
await playExpect(dashboardPage.mainPage).toBeVisible({ timeout: 3000 });
await playExpect(dashboardPage.heading).toBeVisible();
const settingsBar = await navigationBar.openSettings();
const resourcesPage = await settingsBar.openTabPage(ResourcesPage);
await playExpect