Skip to content

Commit 5d91ad3

Browse files
committed
test: added image checker extension verification tests
Signed-off-by: Rostislav Lán <[email protected]>
1 parent 82cd5a3 commit 5d91ad3

File tree

5 files changed

+201
-0
lines changed

5 files changed

+201
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
.vscode
22
node_modules
3+
test-results
4+
output
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import type { NavigationBar } from '@podman-desktop/tests-playwright';
20+
import {
21+
expect as playExpect,
22+
ExtensionCardPage,
23+
RunnerOptions,
24+
test,
25+
} from '@podman-desktop/tests-playwright';
26+
import { ImageCheckerExtensionPage } from './pages/image-checker-extension-page';
27+
import { ImageCheckerImageDetailsPage } from './pages/image-checker-image-details-page';
28+
29+
let extensionInstalled = false;
30+
let extensionCard: ExtensionCardPage;
31+
const imageName = 'ghcr.io/redhat-developer/podman-desktop-image-checker-openshift-ext:latest';
32+
const extensionLabel = 'redhat.openshift-checker';
33+
const extensionLabelName = 'openshift-checker';
34+
const activeExtensionStatus = 'ACTIVE';
35+
const disabledExtensionStatus = 'DISABLED';
36+
const imageToCheck = 'ghcr.io/linuxcontainers/alpine';
37+
test.use({
38+
runnerOptions: new RunnerOptions({ customFolder: 'image-checker-tests-pd', autoUpdate: false, autoCheckUpdates: false }),
39+
});
40+
test.beforeAll(async ({ runner, page, welcomePage }) => {
41+
runner.setVideoAndTraceName('image-checker-e2e');
42+
await welcomePage.handleWelcomePage(true);
43+
extensionCard = new ExtensionCardPage(page, extensionLabelName, extensionLabel);
44+
});
45+
46+
test.afterAll(async ({ runner }) => {
47+
await runner.close();
48+
});
49+
50+
test.describe.serial('Red Hat Image Checker extension installation', () => {
51+
test('Check if extension is already installed', async ({ navigationBar }) => {
52+
const extensions = await navigationBar.openExtensions();
53+
if (await extensions.extensionIsInstalled(extensionLabel)) {
54+
extensionInstalled = true;
55+
}
56+
});
57+
58+
test('Remove old version of the extension', async ({ navigationBar }) => {
59+
test.skip(!extensionInstalled);
60+
await removeExtension(navigationBar);
61+
});
62+
63+
test('Extension can be installed from an OCI image', async ({ navigationBar }) => {
64+
test.setTimeout(180000);
65+
const extensions = await navigationBar.openExtensions();
66+
await extensions.installExtensionFromOCIImage(imageName);
67+
await playExpect(extensionCard.card).toBeVisible();
68+
});
69+
70+
test('Extension is installed and active, extension card is present', async ({ navigationBar }) => {
71+
const extensions = await navigationBar.openExtensions();
72+
await playExpect
73+
.poll(async () => await extensions.extensionIsInstalled(extensionLabel), { timeout: 60000 })
74+
.toBeTruthy();
75+
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
76+
await playExpect(extensionCard.status, `Extension status is: ${extensionCard.status}`).toHaveText(activeExtensionStatus);
77+
});
78+
79+
test("Extension details show correct status, no error", async ({ page, navigationBar }) => {
80+
const extensions = await navigationBar.openExtensions();
81+
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
82+
await extensionCard.openExtensionDetails('Red Hat OpenShift Checker extension');
83+
const detailsPage = new ImageCheckerExtensionPage(page);
84+
await playExpect(detailsPage.heading).toBeVisible();
85+
await playExpect(detailsPage.status).toHaveText(activeExtensionStatus);
86+
const errorTab = detailsPage.tabs.getByRole('button', { name: 'Error' });
87+
// we would like to propagate the error's stack trace into test failure message
88+
let stackTrace = '';
89+
if ((await errorTab.count()) > 0) {
90+
await detailsPage.activateTab('Error');
91+
stackTrace = await detailsPage.errorStackTrace.innerText();
92+
}
93+
await playExpect(errorTab, `Error Tab was present with stackTrace: ${stackTrace}`).not.toBeVisible();
94+
});
95+
96+
test('Image Checker tab is present in Image Details Page', async ({ navigationBar }) => {
97+
await imageCheckerTabPresent(navigationBar);
98+
});
99+
100+
test('Extension can be removed', async ({ navigationBar }) => {
101+
await removeExtension(navigationBar);
102+
});
103+
});
104+
105+
async function removeExtension(navigationBar: NavigationBar): Promise<void> {
106+
const extensions = await navigationBar.openExtensions();
107+
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
108+
await extensionCard.disableExtension();
109+
await extensionCard.removeExtension();
110+
await playExpect
111+
.poll(async () => await extensions.extensionIsInstalled(extensionLabel), { timeout: 15000 })
112+
.toBeFalsy();
113+
}
114+
115+
async function imageCheckerTabPresent(navigationBar: NavigationBar) {
116+
const imagesPage = await navigationBar.openImages();
117+
await playExpect(imagesPage.heading).toBeVisible();
118+
119+
const pullImagePage = await imagesPage.openPullImage();
120+
const updatedImages = await pullImagePage.pullImage(imageToCheck);
121+
122+
const exists = await updatedImages.waitForImageExists(imageToCheck);
123+
playExpect(exists, `${imageToCheck} image not found in the image list`).toBeTruthy();
124+
125+
const imageDetailPage = await imagesPage.openImageDetails(imageToCheck);
126+
const imageDetailsPage = new ImageCheckerImageDetailsPage(imageDetailPage.page, imageToCheck);
127+
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
128+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import type { Page } from '@playwright/test';
20+
import { ExtensionDetailsPage } from '@podman-desktop/tests-playwright';
21+
22+
export class ImageCheckerExtensionPage extends ExtensionDetailsPage {
23+
constructor(page: Page) {
24+
super(page, 'Red Hat OpenShift Checker extension');
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import type { Locator, Page } from '@playwright/test';
20+
import { DetailsPage } from '@podman-desktop/tests-playwright';
21+
22+
export class ImageCheckerImageDetailsPage extends DetailsPage {
23+
readonly imageCheckerTab: Locator;
24+
25+
constructor(page: Page, name: string) {
26+
super(page, name);
27+
this.imageCheckerTab = this.tabs.getByText('Check');
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"strictNullChecks": true,
4+
"lib": [ "ES2020", "webworker" ],
5+
"module": "esnext",
6+
"target": "esnext",
7+
"sourceMap": true,
8+
"rootDir": "src",
9+
"outDir": "dist",
10+
"skipLibCheck": true,
11+
"types": [ "node" ],
12+
"allowSyntheticDefaultImports": true,
13+
"moduleResolution": "Node",
14+
"esModuleInterop": true
15+
}
16+
}

0 commit comments

Comments
 (0)