Skip to content

Commit

Permalink
chore(test): implement podman extensions handling test (#4731)
Browse files Browse the repository at this point in the history
* chore(tests): optimizing commands in package.json

Signed-off-by: Tibor Dancs <tdancs@redhat.com>

* chore(tests): adding settings-extensions test

Signed-off-by: Tibor Dancs <tdancs@redhat.com>
  • Loading branch information
ScrewTSW committed Nov 16, 2023
1 parent 433d2ee commit ab9bbea
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 10 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@
"test": "npm run test:unit && npm run test:e2e",
"test:unit": "npm run test:main && npm run test:preload && npm run test:preload-docker-extension && npm run test:renderer && npm run test:tools && npm run test:extensions",
"test:e2e": "cross-env NODE_ENV=development MODE=development DEBUG=pw:browser npm run build && npm run test:e2e:run",
"test:e2e:build": "cross-env NODE_ENV=development MODE=development DEBUG=pw:browser npm run build",
"test:e2e:run": "xvfb-maybe vitest run tests/src/ --threads false",
"test:e2e:smoke": "cross-env NODE_ENV=development MODE=development DEBUG=pw:browser npm run build && npm run test:e2e:smoke:run",
"test:e2e:smoke": "npm run test:e2e:build && npm run test:e2e:smoke:run",
"test:e2e:smoke:run": "xvfb-maybe vitest run tests/src/*smoke.spec.ts --threads false",
"test:e2e:extension": "cross-env NODE_ENV=development MODE=development DEBUG=pw:browser npm run build && npm run test:e2e:extension:run",
"test:e2e:extension": "npm run test:e2e:build && npm run test:e2e:extension:run",
"test:e2e:extension:run": "xvfb-maybe vitest run tests/src/extension-installation.spec.ts --threads false",
"test:main": "vitest run -r packages/main --passWithNoTests --coverage",
"test:preload": "vitest run -r packages/preload --passWithNoTests --coverage",
Expand Down
12 changes: 8 additions & 4 deletions tests/src/model/pages/dashboard-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,19 @@ export class DashboardPage extends BasePage {

this.openshiftLocalProvider = page.getByLabel('OpenShift Local Provider');
this.openshiftLocalBox = this.featuredExtensions.getByLabel('OpenShift Local');
this.openshiftLocalEnabledStatus = this.getOpenShiftStatusLocator(page);
this.openshiftLocalEnabledStatus = this.getOpenShiftStatusLocator();
}

getOpenShiftStatusLocator(page: Page): Locator {
getOpenShiftStatusLocator(): Locator {
const currentOS = os.platform();
if (currentOS === 'linux') {
return page.getByText('Podman Desktop was not able to find an installation of OpenShift Local.');
return this.content.getByText('Podman Desktop was not able to find an installation of OpenShift Local.');
}
const pattern = new RegExp('OpenShift Local v([0-9.]*) is installed but not ready');
return page.getByText(pattern);
return this.content.getByText(pattern);
}

public getPodmanStatusLocator(): Locator {
return this.content.getByRole('region', { name: 'Podman Provider' });
}
}
8 changes: 6 additions & 2 deletions tests/src/model/pages/settings-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ export class SettingsBar {
this.proxyTab = this.settingsNavBar.getByRole('link', { name: 'Proxy' });
this.registriesTab = this.settingsNavBar.getByRole('link', { name: 'Registries' });
this.authenticationTab = this.settingsNavBar.getByRole('link', { name: 'Authentication' });
this.extensionsTab = this.settingsNavBar.getByRole('link', { name: 'Extensions' });
this.extensionsTab = this.settingsNavBar.getByRole('link', { name: 'Extensions', exact: true });
this.desktopExtensionsTab = this.settingsNavBar.getByRole('link', { name: 'DesktopExtensions' });
this.preferencesTab = this.settingsNavBar.getByRole('link', { name: 'preferences' });
}

async openTabPage<T extends SettingsPage>(type: new (page: Page) => T): Promise<T> {
public async openTabPage<T extends SettingsPage>(type: new (page: Page) => T): Promise<T> {
const desiredPage = new type(this.page);
await (await desiredPage.getTab()).click();
return desiredPage;
}

public getSettingsNavBarTabLocator(name: string): Locator {
return this.settingsNavBar.getByLabel(name);
}
}
20 changes: 19 additions & 1 deletion tests/src/model/pages/settings-extensions-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,30 @@ export class SettingsExtensionsPage extends SettingsPage {
readonly featuredExtensions: Locator;
readonly devSandboxBox: Locator;
readonly openshiftLocalBox: Locator;
readonly extensionsTable: Locator;

constructor(page: Page) {
super(page, 'Extensions');
this.heading = page.getByRole('heading', { name: 'Extensions' });
this.heading = page.getByText('Extensions');
this.featuredExtensions = page.getByLabel('FeaturedExtensions');
this.devSandboxBox = this.featuredExtensions.getByLabel('Developer Sandbox');
this.openshiftLocalBox = this.featuredExtensions.getByLabel('OpenShift Local');
this.extensionsTable = page.getByRole('table');
}

public getExtensionRowFromTable(extensionName: string): Locator {
return this.extensionsTable.getByRole('row').filter({ hasText: extensionName });
}

public getExtensionStopButton(extensionRow: Locator): Locator {
return extensionRow.getByRole('button', { name: 'Stop extension' });
}

public getExtensionStartButton(extensionRow: Locator): Locator {
return extensionRow.getByRole('button', { name: 'Start extension' });
}

public getFeaturedExtension(extensionName: string): Locator {
return this.featuredExtensions.getByLabel(extensionName);
}
}
17 changes: 16 additions & 1 deletion tests/src/model/workbench/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Locator, Page } from 'playwright';
import { ImagesPage } from '../pages/images-page';
import { ContainersPage } from '../pages/containers-page';
import { PodsPage } from '../pages/pods-page';
import { SettingsBar } from '../pages/settings-bar';
import { DashboardPage } from '../pages/dashboard-page';

export class NavigationBar {
readonly page: Page;
Expand All @@ -24,6 +26,12 @@ export class NavigationBar {
this.settingsLink = this.page.getByRole('link', { name: 'Settings' });
}

async openDashboard(): Promise<DashboardPage> {
await this.dashboardLink.waitFor({ state: 'visible', timeout: 3000 });
await this.dashboardLink.click({ timeout: 5000 });
return new DashboardPage(this.page);
}

async openImages(): Promise<ImagesPage> {
await this.imagesLink.waitFor({ state: 'visible', timeout: 3000 });
await this.imagesLink.click({ timeout: 5000 });
Expand All @@ -37,7 +45,14 @@ export class NavigationBar {
}

async openPods(): Promise<PodsPage> {
await this.podsLink.click();
await this.podsLink.waitFor({ state: 'visible', timeout: 3000 });
await this.podsLink.click({ timeout: 5000 });
return new PodsPage(this.page);
}

async openSettings(): Promise<SettingsBar> {
await this.settingsLink.waitFor({ state: 'visible', timeout: 3000 });
await this.settingsLink.click({ timeout: 5000 });
return new SettingsBar(this.page);
}
}
151 changes: 151 additions & 0 deletions tests/src/podman-extension-smoke.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**********************************************************************
* Copyright (C) 2023 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 { expect as playExpect } from '@playwright/test';
import { NavigationBar } from './model/workbench/navigation';
import type { SettingsBar } from './model/pages/settings-bar';
import { SettingsExtensionsPage } from './model/pages/settings-extensions-page';
import { ExtensionPage } from './model/pages/extension-page';

const SETTINGS_EXTENSIONS_TABLE_PODMAN_TITLE: string = 'Podman (default extension)';
const SETTINGS_EXTENSIONS_TABLE_EXTENSION_STATUS_LABEL: string = 'connection-status-label';
const PODMAN_EXTENSION_STATUS_RUNNING: string = 'RUNNING';
const PODMAN_EXTENSION_STATUS_OFF: string = 'OFF';
const SETTINGS_NAVBAR_PREFERENCES_PODMAN_EXTENSION: string = 'Extension: Podman';
const SETTINGS_NAVBAR_EXTENSIONS_PODMAN: string = 'Podman';
const PODMAN_EXTENSION_PAGE_HEADING: string = 'Podman Extension';
const PODMAN_EXTENSION_PAGE_STATUS_ENABLED: string = 'ENABLED';
const PODMAN_EXTENSION_PAGE_STATUS_DISABLED: string = 'DISABLED';

let pdRunner: PodmanDesktopRunner;
let page: Page;
let dashboardPage: DashboardPage;
let settingsBar: SettingsBar;
let navigationBar: NavigationBar;

beforeAll(async () => {
pdRunner = new PodmanDesktopRunner();
page = await pdRunner.start();
pdRunner.setVideoName('settings-extensions-e2e');

const welcomePage = new WelcomePage(page);
await welcomePage.handleWelcomePage(true);
navigationBar = new NavigationBar(page);
});

afterAll(async () => {
await pdRunner.close();
});

beforeEach<RunnerTestContext>(async ctx => {
ctx.pdRunner = pdRunner;
});

describe('Verification of Podman extension', async () => {
test('Podman is enabled and present', async () => {
await verifyPodmanExtensionStatus(true);
});
test('Disable Podman extension from Settings -> Extensions -> Podman page and verify status', async () => {
await openSettingsExtensionsPage();
const podmanExtensionPage = await openSettingsExtensionsPodmanPage();
await podmanExtensionPage.disableButton.click();
await verifyPodmanExtensionStatus(false);
});
test('Re-Enable Podman extension from Settings -> Extensions page and verify podman status', async () => {
const settingsExtensionsPage = await openSettingsExtensionsPage();
const podmanExtensionRowLocator = settingsExtensionsPage.getExtensionRowFromTable(
SETTINGS_EXTENSIONS_TABLE_PODMAN_TITLE,
);
await settingsExtensionsPage.getExtensionStartButton(podmanExtensionRowLocator).click();
await verifyPodmanExtensionStatus(true);
});
});

async function verifyPodmanExtensionStatus(enabled: boolean) {
dashboardPage = await navigationBar.openDashboard();
const podmanProviderLocator = dashboardPage.getPodmanStatusLocator();
enabled
? await playExpect(podmanProviderLocator).toBeVisible()
: await playExpect(podmanProviderLocator).not.toBeVisible();
// always present and visible
const settingsExtensionsPage = await openSettingsExtensionsPage();
const settingsExtensionsPodmanLocator = settingsExtensionsPage.getFeaturedExtension(
SETTINGS_NAVBAR_EXTENSIONS_PODMAN,
);
await playExpect(settingsExtensionsPodmanLocator).toBeVisible();
const podmanExtensionRowLocator = settingsExtensionsPage.getExtensionRowFromTable(
SETTINGS_EXTENSIONS_TABLE_PODMAN_TITLE,
);
await playExpect(podmanExtensionRowLocator).toBeVisible();
const connectionStatusLabel = podmanExtensionRowLocator.getByLabel(SETTINGS_EXTENSIONS_TABLE_EXTENSION_STATUS_LABEL);
await playExpect(connectionStatusLabel).toBeVisible();
const connectionStatusLocatorText = await connectionStatusLabel.innerText({ timeout: 3000 });
// --------------------------
await playExpect(
enabled
? settingsExtensionsPage.getExtensionStopButton(podmanExtensionRowLocator)
: settingsExtensionsPage.getExtensionStartButton(podmanExtensionRowLocator),
).toBeVisible();
playExpect(
enabled
? connectionStatusLocatorText === PODMAN_EXTENSION_STATUS_RUNNING
: connectionStatusLocatorText === PODMAN_EXTENSION_STATUS_OFF,
).toBeTruthy();
// always present and visible
const podmanExtensionPage = await openSettingsExtensionsPodmanPage();
await playExpect(podmanExtensionPage.heading).toBeVisible();
// --------------------------
if (enabled) {
await playExpect(podmanExtensionPage.enableButton).toBeDisabled({ timeout: 10000 });
await playExpect(podmanExtensionPage.disableButton).toBeEnabled({ timeout: 10000 });
await playExpect(podmanExtensionPage.status.getByText(PODMAN_EXTENSION_PAGE_STATUS_ENABLED)).toBeVisible();
} else {
await playExpect(podmanExtensionPage.enableButton).toBeEnabled({ timeout: 10000 });
await playExpect(podmanExtensionPage.disableButton).toBeDisabled({ timeout: 10000 });
await playExpect(podmanExtensionPage.status.getByText(PODMAN_EXTENSION_PAGE_STATUS_DISABLED)).toBeVisible();
}
// expand Settings -> Preferences menu
await settingsBar.preferencesTab.click();
enabled
? await playExpect(
settingsBar.getSettingsNavBarTabLocator(SETTINGS_NAVBAR_PREFERENCES_PODMAN_EXTENSION),
).toBeVisible()
: await playExpect(
settingsBar.getSettingsNavBarTabLocator(SETTINGS_NAVBAR_PREFERENCES_PODMAN_EXTENSION),
).not.toBeVisible();
// collapse Settings -> Preferences menu
await settingsBar.preferencesTab.click();
}

async function openSettingsExtensionsPage(): Promise<SettingsExtensionsPage> {
await navigationBar.openDashboard();
settingsBar = await navigationBar.openSettings();
return settingsBar.openTabPage(SettingsExtensionsPage);
}

async function openSettingsExtensionsPodmanPage(): Promise<ExtensionPage> {
const podmanExtensionNavBarLocator = settingsBar.getSettingsNavBarTabLocator(SETTINGS_NAVBAR_EXTENSIONS_PODMAN);
await podmanExtensionNavBarLocator.click();
return new ExtensionPage(page, SETTINGS_NAVBAR_EXTENSIONS_PODMAN, PODMAN_EXTENSION_PAGE_HEADING);
}

0 comments on commit ab9bbea

Please sign in to comment.