Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(test): migrate tests to pw runner #780

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion tests/playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
"name": "bootc-tests-playwright",
"version": "0.0.1",
"description": "Podman Desktop BootC extension Playwright E2E tests",
"type": "module",
"scripts": {
"test:e2e:setup": "xvfb-maybe --auto-servernum --server-args='-screen 0 1280x960x24' --",
"test:e2e": "npm run test:e2e:setup vitest run src/ --pool=threads --poolOptions.threads.singleThread --poolOptions.threads.isolate --no-file-parallelism"
"test:e2e": "npm run test:e2e:setup npx playwright test src/"
},
"author": "Red Hat",
"license": "Apache-2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/

import { afterEach, onTestFailed } from 'vitest';
import { takeScreenshotHook, type RunnerTestContext } from '@podman-desktop/tests-playwright';
import { defineConfig, devices } from '@playwright/test';

afterEach(async (context: RunnerTestContext) => {
onTestFailed(async () => await takeScreenshotHook(context.pdRunner, context.task.name));
export default defineConfig({
outputDir: 'tests/playwright/output/',
workers: 1,

reporter: [
['list'],
['junit', { outputFile: 'tests/playwright/output/junit-results.xml' }],
['json', { outputFile: 'tests/playwright/output/json-results.json' }],
['html', { open: 'never', outputFolder: 'tests/playwright/output/html-results/' }],
],

projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
],
});
181 changes: 97 additions & 84 deletions tests/playwright/src/bootc-extension.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
***********************************************************************/

import type { Page } from '@playwright/test';
import { afterAll, beforeAll, test, describe, beforeEach } from 'vitest';
import {
NavigationBar,
PodmanDesktopRunner,
Expand All @@ -26,12 +25,12 @@ import {
removeFolderIfExists,
waitForPodmanMachineStartup,
} from '@podman-desktop/tests-playwright';
import { expect as playExpect } from '@playwright/test';
import { RunnerTestContext } from '@podman-desktop/tests-playwright';
import { expect as playExpect, test } from '@playwright/test';
import * as path from 'node:path';
import * as os from 'node:os';
import { BootcPage } from './model/bootc-page';
import { ArchitectureType } from '@podman-desktop/tests-playwright';
import { fileURLToPath } from 'node:url';

let pdRunner: PodmanDesktopRunner;
let page: Page;
Expand All @@ -45,18 +44,16 @@ const extensionLabel = 'redhat.bootc';
const extensionHeading = 'Bootable Container';
const isLinux = os.platform() === 'linux';
const isWindows = os.platform() === 'win32';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const containerFilePath = path.resolve(__dirname, '..', 'resources', 'bootable-containerfile');
const contextDirectory = path.resolve(__dirname, '..', 'resources');
const skipInstallation = process.env.SKIP_INSTALLATION;
const buildISOImage = process.env.BUILD_ISO_IMAGE;
let timeoutForBuild = 900000;
let imageBuildFailed = true;

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

beforeAll(async () => {
test.beforeAll(async () => {
await removeFolderIfExists('tests/output/images');
pdRunner = new PodmanDesktopRunner({ customFolder: 'bootc-tests-pd', autoUpdate: false, autoCheckUpdate: false });
page = await pdRunner.start();
Expand All @@ -68,7 +65,8 @@ beforeAll(async () => {
await waitForPodmanMachineStartup(page);
});

afterAll(async () => {
test.afterAll(async () => {
test.setTimeout(180000);
try {
await deleteImage(page, imageName);
} catch (error) {
Expand All @@ -77,40 +75,40 @@ afterAll(async () => {
await removeFolderIfExists('tests/output/images');
await pdRunner.close();
}
}, 180000);
});

describe('BootC Extension', async () => {
test.describe('BootC Extension', () => {
test('Go to settings and check if extension is already installed', async () => {
const extensionsPage = await navBar.openExtensions();
if (await extensionsPage.extensionIsInstalled(extensionLabel)) extensionInstalled = true;
});

test.runIf(extensionInstalled && !skipInstallation)(
'Uninstalled previous version of bootc extension',
async () => {
console.log('Extension found already installed, trying to remove!');
await ensureBootcIsRemoved();
},
200000,
);

test.runIf(!skipInstallation)(
'Install extension through Extension page',
async () => {
const extensionsPage = await navBar.openExtensions();
await extensionsPage.installExtensionFromOCIImage('ghcr.io/containers/podman-desktop-extension-bootc');

await playExpect
.poll(async () => await extensionsPage.extensionIsInstalled(extensionLabel), { timeout: 30000 })
.toBeTruthy();
},
200000,
);

describe.each([ArchitectureType.ARM64, ArchitectureType.AMD64])(
'Bootc images for architecture: %s',
async architecture => {
test('Build bootc image from containerfile', async () => {
test('Uninstalled previous version of bootc extension', async () => {
test.skip(!extensionInstalled && !!skipInstallation);
test.setTimeout(200000);
console.log('Extension found already installed, trying to remove!');
await ensureBootcIsRemoved();
});

test('Install extension through Extension page', async () => {
test.skip(!!skipInstallation);
test.setTimeout(200000);

const extensionsPage = await navBar.openExtensions();
await extensionsPage.installExtensionFromOCIImage('ghcr.io/containers/podman-desktop-extension-bootc');

await playExpect
.poll(async () => await extensionsPage.extensionIsInstalled(extensionLabel), { timeout: 30000 })
.toBeTruthy();
});

const architectures = [ArchitectureType.AMD64, ArchitectureType.ARM64];

for (const architecture of architectures) {
test.describe.serial(`Bootc images for architecture: ${architecture}`, () => {
test(`Build bootc image from containerfile for architecture: ${architecture}`, async () => {
test.setTimeout(210000);

imageBuildFailed = true;
let imagesPage = await navBar.openImages();
await playExpect(imagesPage.heading).toBeVisible();
Expand All @@ -128,55 +126,70 @@ describe('BootC Extension', async () => {

await playExpect.poll(async () => await imagesPage.waitForImageExists(imageName)).toBeTruthy();
imageBuildFailed = false;
}, 210000);

describe.skipIf(isLinux).each(['QCOW2', 'AMI', 'RAW', 'VMDK', 'ISO'])('Building images ', async type => {
test(`Building bootable image type: ${type}`, async context => {
if (imageBuildFailed) {
console.log('Image build failed, skipping test');
context.skip();
}

if (type === 'ISO') {
if (buildISOImage) {
timeoutForBuild = 1200000;
console.log(`Building ISO image requested, extending timeout to ${timeoutForBuild}`);
});

const types = ['QCOW2', 'AMI', 'RAW', 'VMDK', 'ISO'];

for (const type of types) {
test.describe.serial('Building images ', () => {
test(`Building bootable image type: ${type}`, async () => {
test.skip(isLinux);
test.setTimeout(1250000);

if (imageBuildFailed) {
console.log('Image build failed, skipping test');
test.skip();
}

if (type === 'ISO') {
if (buildISOImage) {
timeoutForBuild = 1200000;
console.log(`Building ISO image requested, extending timeout to ${timeoutForBuild}`);
} else {
console.log(`Building ISO image not requested, skipping test`);
test.skip();
}
}

const imagesPage = await navBar.openImages();
await playExpect(imagesPage.heading).toBeVisible();

const imageDetailPage = await imagesPage.openImageDetails(imageName);
await playExpect(imageDetailPage.heading).toBeVisible();

const pathToStore = path.resolve(
__dirname,
'..',
'tests',
'playwright',
'output',
'images',
`${type}-${architecture}`,
);
[page, webview] = await handleWebview();
const bootcPage = new BootcPage(page, webview);
const result = await bootcPage.buildDiskImage(
`${imageName}:${imageTag}`,
pathToStore,
type,
architecture,
timeoutForBuild,
);
console.log(
`Building disk image for platform ${os.platform()} and architecture ${architecture} and type ${type} is ${result}`,
);
if (isWindows && architecture === ArchitectureType.ARM64) {
console.log('Expected to fail on Windows for ARM64');
playExpect(result).toBeFalsy();
} else {
console.log(`Building ISO image not requested, skipping test`);
context.skip();
console.log('Expected to pass on Linux, Windows and macOS');
playExpect(result).toBeTruthy();
}
}

const imagesPage = await navBar.openImages();
await playExpect(imagesPage.heading).toBeVisible();

const imageDetailPage = await imagesPage.openImageDetails(imageName);
await playExpect(imageDetailPage.heading).toBeVisible();

const pathToStore = path.resolve(__dirname, '..', 'tests', 'output', 'images', `${type}-${architecture}`);
[page, webview] = await handleWebview();
const bootcPage = new BootcPage(page, webview);
const result = await bootcPage.buildDiskImage(
`${imageName}:${imageTag}`,
pathToStore,
type,
architecture,
timeoutForBuild,
);
console.log(
`Building disk image for platform ${os.platform()} and architecture ${architecture} and type ${type} is ${result}`,
);
if (isWindows && architecture === ArchitectureType.ARM64) {
console.log('Expected to fail on Windows for ARM64');
playExpect(result).toBeFalsy();
} else {
console.log('Expected to pass on Linux, Windows and macOS');
playExpect(result).toBeTruthy();
}
}, 1250000);
});
},
);
});
});
}
});
}

test('Remove bootc extension through Settings', async () => {
await ensureBootcIsRemoved();
Expand Down