Mock fixtures for RHEL 10 were missing, meaning the tests were unable to fetch mocked data and failed.
377 lines
11 KiB
TypeScript
377 lines
11 KiB
TypeScript
import type { Router as RemixRouter } from '@remix-run/router';
|
|
import { screen, waitFor, within } from '@testing-library/react';
|
|
import { userEvent } from '@testing-library/user-event';
|
|
|
|
import {
|
|
CREATE_BLUEPRINT,
|
|
EDIT_BLUEPRINT,
|
|
RHEL_9,
|
|
} from '../../../../../constants';
|
|
import { mockBlueprintIds } from '../../../../fixtures/blueprints';
|
|
import { kernelCreateBlueprintRequest } from '../../../../fixtures/editMode';
|
|
import {
|
|
blueprintRequest,
|
|
clickBack,
|
|
clickNext,
|
|
enterBlueprintName,
|
|
interceptBlueprintRequest,
|
|
interceptEditBlueprintRequest,
|
|
openAndDismissSaveAndBuildModal,
|
|
renderEditMode,
|
|
selectRhel9,
|
|
verifyCancelButton,
|
|
} from '../../wizardTestUtils';
|
|
import { clickRegisterLater, renderCreateMode } from '../../wizardTestUtils';
|
|
|
|
let router: RemixRouter | undefined = undefined;
|
|
|
|
const CUSTOM_NAME = 'custom-kernel-name';
|
|
|
|
const goToKernelStep = async () => {
|
|
const user = userEvent.setup();
|
|
const guestImageCheckBox = await screen.findByRole('checkbox', {
|
|
name: /virtualization guest image checkbox/i,
|
|
});
|
|
await waitFor(() => user.click(guestImageCheckBox));
|
|
await clickNext(); // Registration
|
|
await clickRegisterLater();
|
|
await clickNext(); // OpenSCAP
|
|
await clickNext(); // File system configuration
|
|
await clickNext(); // Snapshots
|
|
await clickNext(); // Custom repositories
|
|
await clickNext(); // Additional packages
|
|
await clickNext(); // Users
|
|
await clickNext(); // Timezone
|
|
await clickNext(); // Locale
|
|
await clickNext(); // Hostname
|
|
await clickNext(); // Kernel
|
|
};
|
|
|
|
const goToOpenSCAPStep = async () => {
|
|
const user = userEvent.setup();
|
|
const guestImageCheckBox = await screen.findByRole('checkbox', {
|
|
name: /virtualization guest image checkbox/i,
|
|
});
|
|
await waitFor(() => user.click(guestImageCheckBox));
|
|
await clickNext(); // Registration
|
|
await clickRegisterLater();
|
|
await clickNext(); // OpenSCAP
|
|
};
|
|
|
|
const goFromOpenSCAPToKernel = async () => {
|
|
await clickNext(); // File system configuration
|
|
await clickNext(); // Snapshots
|
|
await clickNext(); // Custom repositories
|
|
await clickNext(); // Additional packages
|
|
await clickNext(); // Users
|
|
await clickNext(); // Timezone
|
|
await clickNext(); // Locale
|
|
await clickNext(); // Hostname
|
|
await clickNext(); // Kernel
|
|
};
|
|
|
|
const goToReviewStep = async () => {
|
|
await clickNext(); // Firewall
|
|
await clickNext(); // Services
|
|
await clickNext(); // First boot script
|
|
await clickNext(); // Details
|
|
await enterBlueprintName();
|
|
await clickNext(); // Review
|
|
};
|
|
|
|
const getKernelNameOptions = async () => {
|
|
return await screen.findByPlaceholderText(/Select kernel package/i);
|
|
};
|
|
|
|
const openKernelNameOptions = async (dropdown: Element) => {
|
|
const user = userEvent.setup();
|
|
await waitFor(() => user.click(dropdown));
|
|
};
|
|
|
|
const selectKernelName = async (kernelName: string) => {
|
|
const user = userEvent.setup();
|
|
const kernelNameDropdown = await getKernelNameOptions();
|
|
await openKernelNameOptions(kernelNameDropdown);
|
|
|
|
const kernelOption = await screen.findByText(kernelName);
|
|
await waitFor(() => user.click(kernelOption));
|
|
};
|
|
|
|
const selectCustomKernelName = async (kernelName: string) => {
|
|
const user = userEvent.setup();
|
|
const kernelNameDropdown = await getKernelNameOptions();
|
|
await waitFor(() => user.type(kernelNameDropdown, kernelName));
|
|
|
|
const customOption = await screen.findByText(/custom kernel package/i);
|
|
await waitFor(() => user.click(customOption));
|
|
};
|
|
|
|
const clearKernelName = async () => {
|
|
const user = userEvent.setup();
|
|
const kernelNameClearBtn = await screen.findAllByRole('button', {
|
|
name: /clear input/i,
|
|
});
|
|
await waitFor(() => user.click(kernelNameClearBtn[0]));
|
|
};
|
|
|
|
const addKernelAppend = async (kernelArg: string) => {
|
|
const user = userEvent.setup();
|
|
const kernelAppendInput = await screen.findByPlaceholderText(
|
|
'Add kernel argument'
|
|
);
|
|
await waitFor(() => user.click(kernelAppendInput));
|
|
await waitFor(() => user.type(kernelAppendInput, kernelArg));
|
|
|
|
const addKernelArg = await screen.findByRole('button', {
|
|
name: /Add kernel argument/,
|
|
});
|
|
await waitFor(() => user.click(addKernelArg));
|
|
};
|
|
|
|
const removeKernelArg = async (kernelArg: string) => {
|
|
const user = userEvent.setup();
|
|
|
|
const removeNosmtArgButton = await screen.findByRole('button', {
|
|
name: `Close ${kernelArg}`,
|
|
});
|
|
await waitFor(() => user.click(removeNosmtArgButton));
|
|
};
|
|
|
|
const selectProfile = async () => {
|
|
const user = userEvent.setup();
|
|
const selectProfileDropdown = await screen.findByPlaceholderText(/none/i);
|
|
await waitFor(() => user.click(selectProfileDropdown));
|
|
|
|
const cis1Profile = await screen.findByText(/Kernel append only profile/i);
|
|
await waitFor(() => user.click(cis1Profile));
|
|
};
|
|
|
|
const clickRevisitButton = async () => {
|
|
const user = userEvent.setup();
|
|
const expandable = await screen.findByTestId('kernel-expandable');
|
|
const revisitButton = await within(expandable).findByTestId('revisit-kernel');
|
|
await waitFor(() => user.click(revisitButton));
|
|
};
|
|
|
|
describe('Step Kernel', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
router = undefined;
|
|
});
|
|
|
|
test('clicking Next loads Firewall', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await clickNext();
|
|
await screen.findByRole('heading', {
|
|
name: 'Firewall',
|
|
});
|
|
});
|
|
|
|
test('clicking Back loads Hostname', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await clickBack();
|
|
await screen.findByRole('heading', { name: 'Hostname' });
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await verifyCancelButton(router);
|
|
});
|
|
|
|
test('adds custom kernel package to options', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
|
|
const kernelNameDropdown = await getKernelNameOptions();
|
|
await openKernelNameOptions(kernelNameDropdown);
|
|
expect(screen.queryByText(CUSTOM_NAME)).not.toBeInTheDocument();
|
|
|
|
await selectCustomKernelName(CUSTOM_NAME);
|
|
await openKernelNameOptions(kernelNameDropdown);
|
|
await screen.findByText(CUSTOM_NAME);
|
|
});
|
|
|
|
test('disable Next with invalid custom kernel name', async () => {
|
|
const user = userEvent.setup();
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
|
|
const kernelNameDropdown = await getKernelNameOptions();
|
|
await openKernelNameOptions(kernelNameDropdown);
|
|
|
|
await waitFor(() => user.type(kernelNameDropdown, '-----------'));
|
|
await screen.findByText(/"-----------" is not a valid kernel package name/);
|
|
|
|
await clearKernelName();
|
|
expect(screen.queryByText(/Invalid format/)).not.toBeInTheDocument();
|
|
});
|
|
|
|
test('kernel argument can be added and removed', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await addKernelAppend('nosmt=force');
|
|
await addKernelAppend('page_poison=1');
|
|
await removeKernelArg('nosmt=force');
|
|
expect(screen.queryByText('nosmt=force')).not.toBeInTheDocument();
|
|
});
|
|
|
|
test('kernel append from OpenSCAP gets added correctly and cannot be removed', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9();
|
|
await goToOpenSCAPStep();
|
|
await selectProfile();
|
|
await goFromOpenSCAPToKernel();
|
|
await screen.findByText('Required by OpenSCAP');
|
|
await screen.findByText('audit_backlog_limit=8192');
|
|
await screen.findByText('audit=1');
|
|
expect(
|
|
screen.queryByRole('button', { name: /close audit_backlog_limit=8192/i })
|
|
).not.toBeInTheDocument();
|
|
expect(
|
|
screen.queryByRole('button', { name: /close audit=1/i })
|
|
).not.toBeInTheDocument();
|
|
});
|
|
|
|
test('revisit step button on Review works', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await selectKernelName('kernel');
|
|
await goToReviewStep();
|
|
await clickRevisitButton();
|
|
await screen.findByRole('heading', { name: /Kernel/ });
|
|
});
|
|
});
|
|
|
|
describe('Kernel request generated correctly', () => {
|
|
beforeEach(async () => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
test('with kernel name', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await selectKernelName('kernel-debug');
|
|
await goToReviewStep();
|
|
// 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 = {
|
|
...blueprintRequest,
|
|
customizations: {
|
|
kernel: {
|
|
name: 'kernel-debug',
|
|
},
|
|
},
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('when unselecting kernel name', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await selectKernelName('kernel-debug');
|
|
await clearKernelName();
|
|
await goToReviewStep();
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest = {
|
|
...blueprintRequest,
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('with kernel arg added and removed', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await addKernelAppend('nosmt=force');
|
|
await removeKernelArg('nosmt=force');
|
|
await goToReviewStep();
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest = {
|
|
...blueprintRequest,
|
|
customizations: {},
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('with kernel append', async () => {
|
|
await renderCreateMode();
|
|
await goToKernelStep();
|
|
await addKernelAppend('nosmt=force');
|
|
await goToReviewStep();
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest = {
|
|
...blueprintRequest,
|
|
customizations: {
|
|
kernel: {
|
|
append: 'nosmt=force',
|
|
},
|
|
},
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('with OpenSCAP profile that includes kernel append', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9();
|
|
await goToOpenSCAPStep();
|
|
await selectProfile();
|
|
await goFromOpenSCAPToKernel();
|
|
await goToReviewStep();
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest = {
|
|
...blueprintRequest,
|
|
distribution: RHEL_9, // overrides default RHEL 10 to make OpenSCAP available
|
|
customizations: {
|
|
openscap: {
|
|
profile_id: 'xccdf_org.ssgproject.content_profile_ccn_basic',
|
|
},
|
|
kernel: {
|
|
append: 'audit_backlog_limit=8192 audit=1',
|
|
},
|
|
},
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Kernel edit mode', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
test('edit mode works', async () => {
|
|
const id = mockBlueprintIds['kernel'];
|
|
await renderEditMode(id);
|
|
|
|
// starts on review step
|
|
const receivedRequest = await interceptEditBlueprintRequest(
|
|
`${EDIT_BLUEPRINT}/${id}`
|
|
);
|
|
const expectedRequest = kernelCreateBlueprintRequest;
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|