From ceec85209ca30e402b207eda6e7c7a24aba8fc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20V=C3=ADtov=C3=A1?= Date: Tue, 29 Jul 2025 14:00:45 +0200 Subject: [PATCH] Playwright: OSCAP basic test not altering things added by OSCAP --- eslint.config.js | 6 + playwright/Customizations/OpenSCAP.spec.ts | 191 +++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 playwright/Customizations/OpenSCAP.spec.ts diff --git a/eslint.config.js b/eslint.config.js index 269a5115..0f786976 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -151,6 +151,12 @@ module.exports = defineConfig([ ...pluginPlaywright.configs.recommended.rules, 'playwright/no-conditional-in-test': 'off', 'playwright/no-conditional-expect': 'off', + "playwright/no-skipped-test": [ + "error", + { + "allowConditional": true + } + ] }, }, ]); diff --git a/playwright/Customizations/OpenSCAP.spec.ts b/playwright/Customizations/OpenSCAP.spec.ts new file mode 100644 index 00000000..7784cc12 --- /dev/null +++ b/playwright/Customizations/OpenSCAP.spec.ts @@ -0,0 +1,191 @@ +import { expect } from '@playwright/test'; +import { v4 as uuidv4 } from 'uuid'; + +import { test } from '../fixtures/cleanup'; +import { isHosted } from '../helpers/helpers'; +import { ensureAuthenticated } from '../helpers/login'; +import { ibFrame, navigateToLandingPage } from '../helpers/navHelpers'; +import { + createBlueprint, + deleteBlueprint, + exportBlueprint, + fillInDetails, + fillInImageOutputGuest, + importBlueprint, + registerLater, +} from '../helpers/wizardHelpers'; + +test('Create a blueprint with OpenSCAP customization', async ({ + page, + cleanup, +}) => { + const blueprintName = 'test-' + uuidv4(); + test.skip(!isHosted(), 'Exporting is not available in the plugin'); + // Delete the blueprint after the run fixture + await cleanup.add(() => deleteBlueprint(page, blueprintName)); + + await ensureAuthenticated(page); + + // Navigate to IB landing page and get the frame + await navigateToLandingPage(page); + const frame = await ibFrame(page); + + await test.step('Select RHEL 9 and go to optional steps in Wizard', async () => { + await frame.getByRole('button', { name: 'Create image blueprint' }).click(); + await frame.getByTestId('release_select').click(); + await frame + .getByRole('option', { + name: 'Red Hat Enterprise Linux (RHEL) 9 Full support ends: May 2027 | Maintenance', + }) + .click(); + await frame.getByRole('checkbox', { name: 'Virtualization' }).click(); + await frame.getByRole('button', { name: 'Next' }).click(); + await registerLater(frame); + }); + + await test.step('Select only OpenSCAP, and check if dependencies are preselected', async () => { + await frame.getByRole('button', { name: 'Compliance' }).click(); + await frame.getByRole('textbox', { name: 'Type to filter' }).fill('cis'); + await frame + .getByRole('option', { + name: 'CIS Red Hat Enterprise Linux 9 Benchmark for Level 1 - Server This profile', + }) + .click(); + await frame + .getByRole('button', { name: 'File system configuration' }) + .click(); + await expect( + frame + .getByRole('row', { + name: 'Draggable row draggable button /tmp xfs 1 GiB', + }) + .getByRole('button') + .nth(3) + ).toBeVisible(); + await frame.getByRole('button', { name: 'Additional packages' }).click(); + await frame.getByRole('button', { name: 'Selected (9)' }).click(); + await expect(frame.getByRole('gridcell', { name: 'aide' })).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'chrony' })).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'cronie' })).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'firewalld' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'libpwquality' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'libselinux' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'nftables' }) + ).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'sudo' })).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'systemd-journal-remote' }) + ).toBeVisible(); + await frame.getByRole('button', { name: 'Systemd services' }).click(); + await expect( + frame.getByText('Required by OpenSCAPcrondfirewalldsystemd-journald') + ).toBeVisible(); + await frame.getByPlaceholder('Add masked service').fill('nftables'); + await frame.getByPlaceholder('Add masked service').press('Enter'); + await expect( + frame.getByText('Masked service already exists') + ).toBeVisible(); + await expect(frame.getByText('Required by OpenSCAPcupsnfs-')).toBeVisible(); + await expect(frame.getByText('nfs-server')).toBeVisible(); + await expect(frame.getByText('rpcbind')).toBeVisible(); + await expect(frame.getByText('avahi-daemon')).toBeVisible(); + await expect(frame.getByText('autofs')).toBeVisible(); + await expect(frame.getByText('bluetooth')).toBeVisible(); + await expect(frame.getByText('nftables')).toBeVisible(); + await frame.getByRole('button', { name: 'Review and finish' }).click(); + }); + + await test.step('Fill the BP details', async () => { + await fillInDetails(frame, blueprintName); + }); + + await test.step('Create BP', async () => { + await createBlueprint(frame, blueprintName); + }); + + await test.step('Edit BP', async () => { + await frame.getByRole('button', { name: 'Edit blueprint' }).click(); + await frame.getByRole('button', { name: 'Compliance' }).click(); + await expect(frame.getByText('Level 1 - Server')).toBeVisible(); + await frame.getByRole('textbox', { name: 'Type to filter' }).fill('cis'); + await frame + .getByRole('option', { + name: 'CIS Red Hat Enterprise Linux 9 Benchmark for Level 2 - Server This profile', + }) + .click(); + + await frame.getByRole('button', { name: 'Kernel' }).click(); + + await expect( + frame.getByText('Required by OpenSCAPaudit_backlog_limit=8192audit=') + ).toBeVisible(); + await frame.getByRole('button', { name: 'Additional packages' }).click(); + await frame.getByRole('button', { name: 'Selected (11)' }).click(); + await expect(frame.getByRole('gridcell', { name: 'aide' })).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'audit-libs' }) + ).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'chrony' })).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'cronie' })).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'firewalld' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'libpwquality' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'libselinux' }) + ).toBeVisible(); + await expect( + frame.getByRole('gridcell', { name: 'nftables' }) + ).toBeVisible(); + await expect(frame.getByRole('gridcell', { name: 'sudo' })).toBeVisible(); + await frame.getByRole('button', { name: 'Systemd services' }).click(); + await expect( + frame.getByText( + 'Required by OpenSCAPauditdcrondfirewalldsystemd-journald' + ) + ).toBeVisible(); + await frame.getByPlaceholder('Add masked service').fill('nftables'); + await frame.getByPlaceholder('Add masked service').press('Enter'); + await expect( + frame.getByText('Masked service already exists') + ).toBeVisible(); + await expect(frame.getByText('Required by OpenSCAPcupsnfs-')).toBeVisible(); + await expect(frame.getByText('nfs-server')).toBeVisible(); + await expect(frame.getByText('rpcbind')).toBeVisible(); + await expect(frame.getByText('avahi-daemon')).toBeVisible(); + await expect(frame.getByText('autofs')).toBeVisible(); + await expect(frame.getByText('bluetooth')).toBeVisible(); + await expect(frame.getByText('nftables')).toBeVisible(); + await frame.getByRole('button', { name: 'Review and finish' }).click(); + await frame + .getByRole('button', { name: 'Save changes to blueprint' }) + .click(); + }); + + // This is for hosted service only as these features are not available in cockpit plugin + await test.step('Export BP', async () => { + await exportBlueprint(page, blueprintName); + }); + + await test.step('Import BP', async () => { + await importBlueprint(page, blueprintName); + }); + + await test.step('Review imported BP', async () => { + await fillInImageOutputGuest(page); + await page.getByRole('button', { name: 'Compliance' }).click(); + + await expect(frame.getByText('Level 2 - Server')).toBeVisible(); + + await page.getByRole('button', { name: 'Cancel' }).click(); + }); +});