Skip to content

Commit d28ad6c

Browse files
authored
chore: extension functionality verification e2e tests (#70)
* chore: extension verification e2e tests Signed-off-by: Rostislav Lán <[email protected]> * Refactored, renamed test cases to better match their content Signed-off-by: Rostislav Lán <[email protected]> --------- Signed-off-by: Rostislav Lán <[email protected]>
1 parent 447191b commit d28ad6c

File tree

2 files changed

+116
-10
lines changed

2 files changed

+116
-10
lines changed

podman-desktop-extension/tests/src/image-checker.spec.ts

Lines changed: 88 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
ExtensionCardPage,
2323
RunnerOptions,
2424
test,
25+
deleteImage,
2526
} from '@podman-desktop/tests-playwright';
2627
import { ImageCheckerExtensionPage } from './pages/image-checker-extension-page';
2728
import { ImageCheckerImageDetailsPage } from './pages/image-checker-image-details-page';
@@ -33,7 +34,11 @@ const extensionLabel = 'redhat.openshift-checker';
3334
const extensionLabelName = 'openshift-checker';
3435
const activeExtensionStatus = 'ACTIVE';
3536
const disabledExtensionStatus = 'DISABLED';
36-
const imageToCheck = 'ghcr.io/linuxcontainers/alpine';
37+
const imageToCheck = 'docker.io/library/httpd';
38+
const isLinux = process.platform === 'linux';
39+
const providerName = 'Red Hat OpenShift Checker';
40+
const extensionName = 'Red Hat OpenShift Checker extension';
41+
3742
test.use({
3843
runnerOptions: new RunnerOptions({ customFolder: 'image-checker-tests-pd', autoUpdate: false, autoCheckUpdates: false }),
3944
});
@@ -43,8 +48,13 @@ test.beforeAll(async ({ runner, page, welcomePage }) => {
4348
extensionCard = new ExtensionCardPage(page, extensionLabelName, extensionLabel);
4449
});
4550

46-
test.afterAll(async ({ runner }) => {
47-
await runner.close();
51+
test.afterAll(async ({ runner, page }) => {
52+
test.setTimeout(60000);
53+
try {
54+
deleteImage(page, imageToCheck);
55+
} finally {
56+
await runner.close();
57+
}
4858
});
4959

5060
test.describe.serial('Red Hat Image Checker extension installation', () => {
@@ -67,7 +77,7 @@ test.describe.serial('Red Hat Image Checker extension installation', () => {
6777
await playExpect(extensionCard.card).toBeVisible();
6878
});
6979

70-
test('Extension is installed and active, extension card is present', async ({ navigationBar }) => {
80+
test('Extension card is present in extension list, extension is active', async ({ navigationBar }) => {
7181
const extensions = await navigationBar.openExtensions();
7282
await playExpect
7383
.poll(async () => await extensions.extensionIsInstalled(extensionLabel), { timeout: 60000 })
@@ -79,7 +89,7 @@ test.describe.serial('Red Hat Image Checker extension installation', () => {
7989
test("Extension details show correct status, no error", async ({ page, navigationBar }) => {
8090
const extensions = await navigationBar.openExtensions();
8191
const extensionCard = await extensions.getInstalledExtension(extensionLabelName, extensionLabel);
82-
await extensionCard.openExtensionDetails('Red Hat OpenShift Checker extension');
92+
await extensionCard.openExtensionDetails(extensionName);
8393
const detailsPage = new ImageCheckerExtensionPage(page);
8494
await playExpect(detailsPage.heading).toBeVisible();
8595
await playExpect(detailsPage.status).toHaveText(activeExtensionStatus);
@@ -92,10 +102,81 @@ test.describe.serial('Red Hat Image Checker extension installation', () => {
92102
}
93103
await playExpect(errorTab, `Error Tab was present with stackTrace: ${stackTrace}`).not.toBeVisible();
94104
});
105+
});
106+
107+
test.describe.serial('Red Hat Image Checker extension functionality', () => {
108+
test('Pull testing image, check tab is present in image details page', async ({ navigationBar }) => {
109+
let imagesPage = await navigationBar.openImages();
110+
await playExpect(imagesPage.heading).toBeVisible();
111+
112+
const pullImagePage = await imagesPage.openPullImage();
113+
await playExpect(pullImagePage.heading).toBeVisible();
114+
imagesPage = await pullImagePage.pullImage(imageToCheck);
115+
const imageDetailsPage = await getImageDetailsPage(navigationBar);
116+
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
117+
118+
await imageDetailsPage.imageCheckerTab.click();
119+
await playExpect(imageDetailsPage.imageCheckerTabContent).toBeVisible();
120+
});
121+
122+
test('Image checker can be turned off and on in image details page', async ({ navigationBar }) => {
123+
const imageDetailsPage = await getImageDetailsPage(navigationBar);
124+
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
125+
await imageDetailsPage.imageCheckerTab.click();
126+
127+
const provider = await imageDetailsPage.getProvider(providerName);
128+
await playExpect(provider).toBeVisible();
129+
const analysisResults = imageDetailsPage.analysisTable;
130+
await playExpect(analysisResults).toBeVisible();
131+
132+
await imageDetailsPage.setProviderCheckbox(providerName, false);
133+
await playExpect(await imageDetailsPage.getProviderCheckbox(providerName)).not.toBeChecked();
134+
await playExpect(analysisResults.getByRole("row")).not.toBeVisible();
135+
136+
await imageDetailsPage.setProviderCheckbox(providerName, true);
137+
await playExpect(await imageDetailsPage.getProviderCheckbox(providerName)).toBeChecked();
138+
await playExpect(analysisResults.getByRole("row")).toBeVisible();
139+
});
140+
141+
test('Verify analysis status, analysis providers and results are visible', async ({ navigationBar }) => {
142+
const imageDetailsPage = await getImageDetailsPage(navigationBar);
143+
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
144+
await imageDetailsPage.imageCheckerTab.click();
145+
await playExpect(imageDetailsPage.imageCheckerTabContent).toBeVisible();
146+
147+
// wait for the analysis to be complete
148+
const analysisStatus = await imageDetailsPage.getAnalysisStatus();
149+
await playExpect(analysisStatus).toBeVisible();
150+
await playExpect
151+
.poll(async () => await analysisStatus.innerText(), { timeout: 60000 })
152+
.toContain('Image analysis complete');
153+
154+
await playExpect(imageDetailsPage.providersTable).toBeVisible();
155+
156+
const redhatCheckerProvider = await imageDetailsPage.getProvider(providerName);
157+
await playExpect(redhatCheckerProvider).toBeVisible();
158+
159+
await playExpect(imageDetailsPage.analysisTable).toBeVisible();
160+
});
95161

96-
test('Image Checker tab is present in Image Details Page', async ({ navigationBar }) => {
162+
test('Verify analysis results', async ({ navigationBar }) => {
97163
const imageDetailsPage = await getImageDetailsPage(navigationBar);
98164
await playExpect(imageDetailsPage.imageCheckerTab).toBeVisible();
165+
await imageDetailsPage.imageCheckerTab.click();
166+
167+
if (isLinux) {
168+
const resultError = await imageDetailsPage.getAnalysisResult('Analyze error');
169+
await playExpect(resultError, 'Tests assume analysis not implemented on linux').toBeVisible();
170+
}
171+
else {
172+
const checkExpose = await imageDetailsPage.getAnalysisResult('Privileged port exposed');
173+
await playExpect(checkExpose).toBeVisible();
174+
const checkChown = await imageDetailsPage.getAnalysisResult('Owner set');
175+
await playExpect(checkChown).toBeVisible();
176+
const checkUser = await imageDetailsPage.getAnalysisResult('User set to root');
177+
await playExpect(checkUser).toBeVisible();
178+
// TODO: create custom image to test specific directives, instead of using httpd
179+
}
99180
});
100181
});
101182

@@ -139,10 +220,7 @@ async function getImageDetailsPage(navigationBar: NavigationBar): Promise<ImageC
139220
const imagesPage = await navigationBar.openImages();
140221
await playExpect(imagesPage.heading).toBeVisible();
141222

142-
const pullImagePage = await imagesPage.openPullImage();
143-
const updatedImages = await pullImagePage.pullImage(imageToCheck);
144-
145-
const exists = await updatedImages.waitForImageExists(imageToCheck);
223+
const exists = await imagesPage.waitForImageExists(imageToCheck);
146224
playExpect(exists, `${imageToCheck} image not found in the image list`).toBeTruthy();
147225

148226
const imageDetailPage = await imagesPage.openImageDetails(imageToCheck);

podman-desktop-extension/tests/src/pages/image-checker-image-details-page.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,37 @@ import { DetailsPage } from '@podman-desktop/tests-playwright';
2121

2222
export class ImageCheckerImageDetailsPage extends DetailsPage {
2323
readonly imageCheckerTab: Locator;
24+
readonly imageCheckerTabContent: Locator;
25+
readonly providersTable: Locator;
26+
readonly analysisTable: Locator;
27+
readonly analysisStatus: Locator;
2428

2529
constructor(page: Page, name: string) {
2630
super(page, name);
2731
this.imageCheckerTab = this.tabs.getByText('Check');
32+
this.imageCheckerTabContent = this.page.getByRole('region', { name: 'Tab Content' });
33+
this.providersTable = this.imageCheckerTabContent.getByLabel('Providers', { exact: true });
34+
this.analysisTable = this.imageCheckerTabContent.getByLabel('Analysis Results', { exact: true });
35+
this.analysisStatus = this.imageCheckerTabContent.getByRole('status', { name: 'Analysis Status' });
36+
}
37+
38+
async getProvider(providerName: string): Promise<Locator> {
39+
return this.providersTable.getByRole('row', {name: providerName});
40+
}
41+
42+
async getAnalysisResult(analysisName: string): Promise<Locator> {
43+
return this.analysisTable.getByRole('row', {name: analysisName});
44+
}
45+
46+
async getProviderCheckbox(providerName: string): Promise<Locator> {
47+
const provider = await this.getProvider(providerName);
48+
return provider.getByRole('checkbox').locator('..'); // parent element of checkbox
49+
}
50+
51+
async setProviderCheckbox(providerName: string, checked: boolean): Promise<void> {
52+
const providerCheckbox = await this.getProviderCheckbox(providerName);
53+
if (await providerCheckbox.isChecked() !== checked) {
54+
await providerCheckbox.click();
55+
}
2856
}
2957
}

0 commit comments

Comments
 (0)