import { screen, waitFor, within } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; import { CREATE_BLUEPRINT, EDIT_BLUEPRINT } from '../../../../../constants'; import { CreateBlueprintRequest } from '../../../../../store/imageBuilderApi'; import { mockBlueprintIds } from '../../../../fixtures/blueprints'; import { baseCreateBlueprintRequest, expectedFilesystemCisL2, expectedKernelCisL2, expectedOpenscapCisL2, expectedPackagesCisL2, expectedServicesCisL2, oscapCreateBlueprintRequest, } from '../../../../fixtures/editMode'; import { clickNext, clickReviewAndFinish, goToOscapStep, goToReview, interceptBlueprintRequest, interceptEditBlueprintRequest, openAndDismissSaveAndBuildModal, renderCreateMode, renderEditMode, selectGuestImageTarget, selectRhel9, } from '../../wizardTestUtils'; const selectRhel8 = async () => { const user = userEvent.setup(); await waitFor(async () => user.click(screen.getByTestId('release_select'))); const rhel8 = await screen.findByRole('option', { name: /red hat enterprise linux \(rhel\) 8/i, }); await waitFor(async () => user.click(rhel8)); }; const selectImageInstallerTarget = async () => { const user = userEvent.setup(); const imageInstallerCheckbox = await screen.findByRole('checkbox', { name: /Bare metal installer/i, }); await waitFor(() => user.click(imageInstallerCheckbox)); }; const selectWslTarget = async () => { const user = userEvent.setup(); const wslCheckBox = await screen.findByRole('checkbox', { name: /windows subsystem for linux/i, }); await waitFor(() => user.click(wslCheckBox)); }; const selectProfile = async () => { const user = userEvent.setup(); const selectProfileDropdown = await screen.findByPlaceholderText(/none/i); await waitFor(() => user.click(selectProfileDropdown)); const cis1Profile = await screen.findByText( /cis red hat enterprise linux 8 benchmark for level 1 - workstation/i, ); await waitFor(() => user.click(cis1Profile)); }; const selectDifferentProfile = async () => { const user = userEvent.setup(); const selectProfileDropdown = await screen.findByPlaceholderText(/none/i); await waitFor(() => user.click(selectProfileDropdown)); const cis2Profile = await screen.findByText( /cis red hat enterprise linux 8 benchmark for level 2 - workstation/i, ); await waitFor(() => user.click(cis2Profile)); }; const selectNone = async () => { const user = userEvent.setup(); const selectProfileDropdown = await screen.findByPlaceholderText(/none/i); await waitFor(() => user.click(selectProfileDropdown)); await waitFor(async () => user.click(await screen.findByText(/none/i))); }; const clickRevisitButton = async () => { const user = userEvent.setup(); const expandable = await screen.findByTestId('oscap-detail-expandable'); const revisitButton = await within(expandable).findByTestId('revisit-openscap'); await waitFor(() => user.click(revisitButton)); }; describe('Step OpenSCAP', () => { beforeEach(() => { vi.clearAllMocks(); }); const user = userEvent.setup(); test('create an image with None OpenSCAP profile', async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectNone(); // check that the FSC does not contain a /tmp partition await clickNext(); await screen.findByRole('heading', { name: /File system configuration/i }); expect( screen.queryByRole('cell', { name: /tmp/i, }), ).not.toBeInTheDocument(); await clickNext(); // skip Snapshots await clickNext(); // skip Repositories // check that there are no Packages contained when selecting the "None" profile option await clickNext(); await screen.findByRole('heading', { name: /Additional packages/i, }); await screen.findByText( /Search above to add additionalpackages to your image/, ); }); test('create an image with an OpenSCAP profile', async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await screen.findByText(/Packages/); await screen.findByText(/aide, neovim/i); await screen.findByText(/Kernel arguments/); await screen.findByText(/audit_backlog_limit=8192 audit=1/i); await screen.findByText(/Enabled services/); await screen.findByText(/crond/i); await screen.findByText(/Disabled services/); await screen.findByText( /rpcbind autofs nftables nfs-server emacs-service/i, ); // check that the FSC contains a /tmp partition await clickNext(); await screen.findByRole('heading', { name: /File system configuration/i }); await screen.findByText(/tmp/i); await clickNext(); // skip Snapshots await clickNext(); // skip Repositories // check that the Packages contains correct packages await clickNext(); await screen.findByRole('heading', { name: /Additional packages/i, }); const selected = await screen.findByText(/Selected/); user.click(selected); await screen.findByText(/aide/i); await screen.findByText(/neovim/i); }); test('dropdown is disabled for WSL targets only', async () => { await renderCreateMode(); await selectRhel8(); await selectWslTarget(); await goToOscapStep(); await screen.findByText( /OpenSCAP profiles are not compatible with WSL images/i, ); expect(await screen.findByTestId('profileSelect')).toHaveClass( 'pf-m-disabled', ); }); test('alert displayed and OpenSCAP dropdown enabled when targets include WSL', async () => { await renderCreateMode(); await selectRhel8(); await selectImageInstallerTarget(); await selectWslTarget(); await goToOscapStep(); await screen.findByText( /OpenSCAP profiles are not compatible with WSL images/i, ); await waitFor(() => { expect(screen.getByPlaceholderText(/none/i)).toBeEnabled(); }); }); test('clicking Review and finish leads to Review', async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await clickReviewAndFinish(); await screen.findByRole('heading', { name: /Review/i, }); }); }); describe('OpenSCAP request generated correctly', () => { beforeEach(() => { vi.clearAllMocks(); }); test('add a profile', async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await goToReview('Oscap test'); // informational modal pops up in the first test only as it's tied // to a 'imageBuilder.saveAndBuildModalSeen' variable in localStorage await openAndDismissSaveAndBuildModal(); const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT); const expectedRequest: CreateBlueprintRequest = { ...oscapCreateBlueprintRequest, name: 'Oscap test', }; await waitFor(() => { expect(receivedRequest).toEqual(expectedRequest); }); }); test('remove a profile', { timeout: 20000 }, async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await selectNone(); await goToReview('Oscap test'); const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT); const expectedRequest: CreateBlueprintRequest = { ...baseCreateBlueprintRequest, name: 'Oscap test', }; await waitFor(() => { expect(receivedRequest).toEqual(expectedRequest); }); }); test('change profile', { timeout: 20000 }, async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await selectDifferentProfile(); await goToReview('Oscap test'); const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT); const expectedRequest: CreateBlueprintRequest = { ...baseCreateBlueprintRequest, customizations: { packages: expectedPackagesCisL2, openscap: expectedOpenscapCisL2, services: expectedServicesCisL2, kernel: expectedKernelCisL2, filesystem: expectedFilesystemCisL2, }, name: 'Oscap test', }; await waitFor(() => { expect(receivedRequest).toEqual(expectedRequest); }); }); test('revisit step button on Review works', async () => { await renderCreateMode(); await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await goToReview('Oscap test'); await clickRevisitButton(); await screen.findByRole('heading', { name: /OpenSCAP/ }); }); }); describe('OpenSCAP edit mode', () => { beforeEach(() => { vi.clearAllMocks(); }); const user = userEvent.setup(); test('edit mode works', async () => { const id = mockBlueprintIds['oscap']; await renderEditMode(id); // starts on review step const receivedRequest = await interceptEditBlueprintRequest( `${EDIT_BLUEPRINT}/${id}`, ); const expectedRequest = oscapCreateBlueprintRequest; expect(receivedRequest).toEqual(expectedRequest); }); test('fsc and packages get populated on edit', async () => { const id = mockBlueprintIds['oscap']; await renderEditMode(id); // check that the FSC contains a /tmp partition const fscBtns = await screen.findAllByRole('button', { name: /file system configuration/i, }); user.click(fscBtns[0]); await screen.findByRole('heading', { name: /file system configuration/i }); await screen.findByText('/tmp'); // check that the Packages contain neovim package const packagesNavBtn = await screen.findByRole('button', { name: /additional packages/i, }); user.click(packagesNavBtn); await screen.findByRole('heading', { name: /Additional packages/i, }); const selectedBtn = await screen.findByRole('button', { name: /Selected/i, }); user.click(selectedBtn); await screen.findByText('neovim'); }); test('customized policy shows only non-removed rules', async () => { const { oscapCustomizations, oscapCustomizationsPolicy } = await import( '../../../../fixtures/oscap' ); const profileId = 'xccdf_org.ssgproject.content_profile_cis_workstation_l1'; const normalProfile = oscapCustomizations(profileId); expect(normalProfile.packages).toEqual(['aide', 'neovim']); const customPolicy = oscapCustomizationsPolicy('custom-policy-123'); expect(customPolicy.packages).toEqual(['neovim']); await renderCreateMode(); await selectRhel9(); await selectGuestImageTarget(); await goToOscapStep(); await selectProfile(); await waitFor(() => { expect(screen.getByText(/aide, neovim/i)).toBeInTheDocument(); }); expect(customPolicy.packages).not.toContain('aide'); expect(customPolicy.packages).toContain('neovim'); expect(normalProfile.packages).toContain('aide'); expect(normalProfile.packages).toContain('neovim'); }); });