Skip to content

Commit

Permalink
test: added image checker extension verification tests
Browse files Browse the repository at this point in the history
Signed-off-by: Rostislav Lán <[email protected]>
  • Loading branch information
rostalan committed Dec 2, 2024
1 parent 037f90b commit 6742ec3
Show file tree
Hide file tree
Showing 7 changed files with 2,798 additions and 326 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.vscode
node_modules
test-results
output
15 changes: 12 additions & 3 deletions podman-desktop-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
"icon": "icon.png",
"publisher": "redhat",
"license": "Apache-2.0",
"type": "module",
"engines": {
"podman-desktop": "^1.6.3"
"podman-desktop": "^1.14.0"
},
"main": "./dist/extension.js",
"contributes": {
Expand All @@ -16,16 +17,24 @@
"scripts": {
"build": "vite build",
"test": "vitest run --coverage --passWithNoTests",
"test:e2e:setup": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' --",
"test:e2e": "cross-env npm run test:e2e:setup npx playwright test ./tests/src",
"test:watch": "vitest watch --coverage --passWithNoTests",
"watch": "tsc -w"
},
"dependencies": {},
"devDependencies": {
"@playwright/test": "^1.49.0",
"@podman-desktop/api": "^1.6.3",
"@podman-desktop/tests-playwright": "next",
"@types/node": "^18",
"cross-env": "^7.0.3",
"electron": "^33.2.1",
"mkdirp": "^3.0.1",
"typescript": "5.3.3",
"vite": "^5.0.9",
"vitest": "^2.1.8",
"xvfb-maybe": "^0.2.1",
"zip-local": "^0.3.5"
}
},
"packageManager": "[email protected]+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
}
128 changes: 128 additions & 0 deletions podman-desktop-extension/tests/src/image-checker.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**********************************************************************
* 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 { NavigationBar } from '@podman-desktop/tests-playwright';
import {
expect as playExpect,
ExtensionCardPage,
RunnerOptions,
test,
} from '@podman-desktop/tests-playwright';
import { ImageCheckerExtensionPage } from './pages/image-checker-extension-page';
import { ImageCheckerImageDetailsPage } from './pages/image-checker-image-details-page';

let extensionInstalled = false;
let extensionCard: ExtensionCardPage;
const imageName = 'ghcr.io/redhat-developer/podman-desktop-image-checker-openshift-ext:latest';
const extensionLabel = 'redhat.openshift-checker';
const extensionLabelName = 'openshift-checker';
const activeExtensionStatus = 'ACTIVE';
const disabledExtensionStatus = 'DISABLED';
const imageToCheck = 'ghcr.io/linuxcontainers/alpine';
test.use({
runnerOptions: new RunnerOptions({ customFolder: 'image-checker-tests-pd', autoUpdate: false, autoCheckUpdates: false }),
});
test.beforeAll(async ({ runner, page, welcomePage }) => {
runner.setVideoAndTraceName('image-checker-e2e');
await welcomePage.handleWelcomePage(true);
extensionCard = new ExtensionCardPage(page, extensionLabelName, extensionLabel);
});

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

test.describe.serial('Red Hat Image Checker extension installation', () => {
test('Check if extension is already installed', async ({ navigationBar }) => {
const extensions = await navigationBar.openExtensions();
if (await extensions.extensionIsInstalled(extensionLabel)) {
extensionInstalled = true;
}
});

test('Remove old version of the extension', async ({ navigationBar }) => {
test.skip(!extensionInstalled);
await removeExtension(navigationBar);
});

test('Extension can be installed from an OCI image', async ({ navigationBar }) => {
test.setTimeout(180000);
const extensions = await navigationBar.openExtensions();
await extensions.installExtensionFromOCIImage(imageName);
await playExpect(extensionCard.card).toBeVisible();
});

test('Extension is installed and active, extension card is present', async ({ navigationBar }) => {
const extensions = await navigationBar.openExtensions();
await playExpect
.poll(async () => await extensions.extensionIsInstalled(extensionLabel), { timeout: 60000 })
.toBeTruthy();
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
await playExpect(extensionCard.status, `Extension status is: ${extensionCard.status}`).toHaveText(activeExtensionStatus);
});

test("Extension details show correct status, no error", async ({ page, navigationBar }) => {
const extensions = await navigationBar.openExtensions();
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
await extensionCard.openExtensionDetails('Red Hat OpenShift Checker extension');
const detailsPage = new ImageCheckerExtensionPage(page);
await playExpect(detailsPage.heading).toBeVisible();
await playExpect(detailsPage.status).toHaveText(activeExtensionStatus);
const errorTab = detailsPage.tabs.getByRole('button', { name: 'Error' });
// we would like to propagate the error's stack trace into test failure message
let stackTrace = '';
if ((await errorTab.count()) > 0) {
await detailsPage.activateTab('Error');
stackTrace = await detailsPage.errorStackTrace.innerText();
}
await playExpect(errorTab, `Error Tab was present with stackTrace: ${stackTrace}`).not.toBeVisible();
});

test('Image Checker tab is present in Image Details Page', async ({ navigationBar }) => {
await imageCheckerTabPresent(navigationBar);
});

test('Extension can be removed', async ({ navigationBar }) => {
await removeExtension(navigationBar);
});
});

async function removeExtension(navigationBar: NavigationBar): Promise<void> {
const extensions = await navigationBar.openExtensions();
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
await extensionCard.disableExtension();
await extensionCard.removeExtension();
await playExpect
.poll(async () => await extensions.extensionIsInstalled(extensionLabel), { timeout: 15000 })
.toBeFalsy();
}

async function imageCheckerTabPresent(navigationBar: NavigationBar) {
const imagesPage = await navigationBar.openImages();
await playExpect(imagesPage.heading).toBeVisible();

const pullImagePage = await imagesPage.openPullImage();
const updatedImages = await pullImagePage.pullImage(imageToCheck);

const exists = await updatedImages.waitForImageExists(imageToCheck);
playExpect(exists, `${imageToCheck} image not found in the image list`).toBeTruthy();

const imageDetailPage = await imagesPage.openImageDetails(imageToCheck);
const imageDetailsPage = new ImageCheckerImageDetailsPage(imageDetailPage.page, imageToCheck);
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**********************************************************************
* 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/test';
import { ExtensionDetailsPage } from '@podman-desktop/tests-playwright';

export class ImageCheckerExtensionPage extends ExtensionDetailsPage {
constructor(page: Page) {
super(page, 'Red Hat OpenShift Checker extension');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**********************************************************************
* 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 { DetailsPage } from '@podman-desktop/tests-playwright';

export class ImageCheckerImageDetailsPage extends DetailsPage {
readonly imageCheckerTab: Locator;

constructor(page: Page, name: string) {
super(page, name);
this.imageCheckerTab = this.tabs.getByText('Check');
}
}
16 changes: 16 additions & 0 deletions podman-desktop-extension/tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"strictNullChecks": true,
"lib": [ "ES2020", "webworker" ],
"module": "esnext",
"target": "esnext",
"sourceMap": true,
"rootDir": "src",
"outDir": "dist",
"skipLibCheck": true,
"types": [ "node" ],
"allowSyntheticDefaultImports": true,
"moduleResolution": "Node",
"esModuleInterop": true
}
}
Loading

0 comments on commit 6742ec3

Please sign in to comment.