CreateImageWizard: Implement user-friendly error messages
Puts the error messages in one place - LabelInput.tsx
This commit is contained in:
parent
3f35101f68
commit
ccfdb49db2
11 changed files with 156 additions and 97 deletions
|
|
@ -63,19 +63,29 @@ test('Create a blueprint with Firewall customization', async ({
|
||||||
await test.step('Select and incorrectly fill the ports in Firewall step', async () => {
|
await test.step('Select and incorrectly fill the ports in Firewall step', async () => {
|
||||||
await frame.getByPlaceholder('Add ports').fill('x');
|
await frame.getByPlaceholder('Add ports').fill('x');
|
||||||
await frame.getByRole('button', { name: 'Add ports' }).click();
|
await frame.getByRole('button', { name: 'Add ports' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(0)).toBeVisible();
|
await expect(
|
||||||
|
frame
|
||||||
|
.getByText(
|
||||||
|
'Expected format: <port/port-name>:<protocol>. Example: 8080:tcp, ssh:tcp'
|
||||||
|
)
|
||||||
|
.nth(0)
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Select and incorrectly fill the disabled services in Firewall step', async () => {
|
await test.step('Select and incorrectly fill the disabled services in Firewall step', async () => {
|
||||||
await frame.getByPlaceholder('Add disabled service').fill('1');
|
await frame.getByPlaceholder('Add disabled service').fill('1');
|
||||||
await frame.getByRole('button', { name: 'Add disabled service' }).click();
|
await frame.getByRole('button', { name: 'Add disabled service' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(1)).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText('Expected format: <service-name>. Example: sshd').nth(0)
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Select and incorrectly fill the enabled services in Firewall step', async () => {
|
await test.step('Select and incorrectly fill the enabled services in Firewall step', async () => {
|
||||||
await frame.getByPlaceholder('Add enabled service').fill('ťčš');
|
await frame.getByPlaceholder('Add enabled service').fill('ťčš');
|
||||||
await frame.getByRole('button', { name: 'Add enabled service' }).click();
|
await frame.getByRole('button', { name: 'Add enabled service' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(2)).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText('Expected format: <service-name>. Example: sshd').nth(1)
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Fill the BP details', async () => {
|
await test.step('Fill the BP details', async () => {
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,11 @@ test('Create a blueprint with Kernel customization', async ({
|
||||||
.getByPlaceholder('Add kernel argument')
|
.getByPlaceholder('Add kernel argument')
|
||||||
.fill('invalid/argument');
|
.fill('invalid/argument');
|
||||||
await frame.getByRole('button', { name: 'Add kernel argument' }).click();
|
await frame.getByRole('button', { name: 'Add kernel argument' }).click();
|
||||||
await expect(frame.getByText('Invalid format.')).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText(
|
||||||
|
'Expected format: <kernel-argument>. Example: console=tty0'
|
||||||
|
)
|
||||||
|
).toBeVisible();
|
||||||
await frame.getByPlaceholder('Select kernel package').fill('new-package');
|
await frame.getByPlaceholder('Select kernel package').fill('new-package');
|
||||||
await frame
|
await frame
|
||||||
.getByRole('option', { name: 'Custom kernel package "new-' })
|
.getByRole('option', { name: 'Custom kernel package "new-' })
|
||||||
|
|
|
||||||
|
|
@ -64,15 +64,21 @@ test('Create a blueprint with Systemd customization', async ({
|
||||||
await test.step('Select and incorrectly fill all of the service fields', async () => {
|
await test.step('Select and incorrectly fill all of the service fields', async () => {
|
||||||
await frame.getByPlaceholder('Add disabled service').fill('&&');
|
await frame.getByPlaceholder('Add disabled service').fill('&&');
|
||||||
await frame.getByRole('button', { name: 'Add disabled service' }).click();
|
await frame.getByRole('button', { name: 'Add disabled service' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(0)).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText('Expected format: <service-name>. Example: sshd').nth(0)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
await frame.getByPlaceholder('Add enabled service').fill('áá');
|
await frame.getByPlaceholder('Add enabled service').fill('áá');
|
||||||
await frame.getByRole('button', { name: 'Add enabled service' }).click();
|
await frame.getByRole('button', { name: 'Add enabled service' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(1)).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText('Expected format: <service-name>. Example: sshd').nth(1)
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
await frame.getByPlaceholder('Add masked service').fill('78');
|
await frame.getByPlaceholder('Add masked service').fill('78');
|
||||||
await frame.getByRole('button', { name: 'Add masked service' }).click();
|
await frame.getByRole('button', { name: 'Add masked service' }).click();
|
||||||
await expect(frame.getByText('Invalid format.').nth(2)).toBeVisible();
|
await expect(
|
||||||
|
frame.getByText('Expected format: <service-name>. Example: sshd').nth(2)
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Fill the BP details', async () => {
|
await test.step('Fill the BP details', async () => {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,11 @@ test('Create a blueprint with Timezone customization', async ({
|
||||||
await expect(frame.getByText('NTP server already exists.')).toBeVisible();
|
await expect(frame.getByText('NTP server already exists.')).toBeVisible();
|
||||||
await frame.getByPlaceholder('Add NTP servers').fill('xxxx');
|
await frame.getByPlaceholder('Add NTP servers').fill('xxxx');
|
||||||
await frame.getByRole('button', { name: 'Add NTP server' }).click();
|
await frame.getByRole('button', { name: 'Add NTP server' }).click();
|
||||||
await expect(frame.getByText('Invalid format.')).toBeVisible();
|
await expect(
|
||||||
|
frame
|
||||||
|
.getByText('Expected format: <ntp-server>. Example: time.redhat.com')
|
||||||
|
.nth(0)
|
||||||
|
).toBeVisible();
|
||||||
await frame.getByPlaceholder('Add NTP servers').fill('0.cz.pool.ntp.org');
|
await frame.getByPlaceholder('Add NTP servers').fill('0.cz.pool.ntp.org');
|
||||||
await frame.getByRole('button', { name: 'Add NTP server' }).click();
|
await frame.getByRole('button', { name: 'Add NTP server' }).click();
|
||||||
await expect(frame.getByText('0.cz.pool.ntp.org')).toBeVisible();
|
await expect(frame.getByText('0.cz.pool.ntp.org')).toBeVisible();
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,44 @@ const LabelInput = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validator(value)) {
|
if (!validator(value)) {
|
||||||
setOnStepInputErrorText('Invalid format.');
|
switch (fieldName) {
|
||||||
|
case 'ports':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <port/port-name>:<protocol>. Example: 8080:tcp, ssh:tcp'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'kernelAppend':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <kernel-argument>. Example: console=tty0'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'kernelName':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <kernel-name>. Example: kernel-5.14.0-284.11.1.el9_2.x86_64'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'groups':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <group-name>. Example: admin'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'ntpServers':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <ntp-server>. Example: time.redhat.com'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'enabledSystemdServices':
|
||||||
|
case 'disabledSystemdServices':
|
||||||
|
case 'maskedSystemdServices':
|
||||||
|
case 'disabledServices':
|
||||||
|
case 'enabledServices':
|
||||||
|
setOnStepInputErrorText(
|
||||||
|
'Expected format: <service-name>. Example: sshd'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setOnStepInputErrorText('Invalid format.');
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { CheckCircleIcon } from '@patternfly/react-icons';
|
import { CheckCircleIcon } from '@patternfly/react-icons';
|
||||||
import { jwtDecode, JwtPayload } from 'jwt-decode';
|
import { jwtDecode } from 'jwt-decode';
|
||||||
|
|
||||||
import { getListOfDuplicates } from './getListOfDuplicates';
|
import { getListOfDuplicates } from './getListOfDuplicates';
|
||||||
|
|
||||||
|
|
@ -30,6 +30,7 @@ import {
|
||||||
selectLanguages,
|
selectLanguages,
|
||||||
selectKeyboard,
|
selectKeyboard,
|
||||||
selectTimezone,
|
selectTimezone,
|
||||||
|
selectSatelliteCaCertificate,
|
||||||
selectSatelliteRegistrationCommand,
|
selectSatelliteRegistrationCommand,
|
||||||
selectImageTypes,
|
selectImageTypes,
|
||||||
UserWithAdditionalInfo,
|
UserWithAdditionalInfo,
|
||||||
|
|
@ -45,11 +46,11 @@ import {
|
||||||
isMountpointMinSizeValid,
|
isMountpointMinSizeValid,
|
||||||
isSnapshotValid,
|
isSnapshotValid,
|
||||||
isHostnameValid,
|
isHostnameValid,
|
||||||
isKernelNameValid,
|
|
||||||
isUserNameValid,
|
isUserNameValid,
|
||||||
isSshKeyValid,
|
isSshKeyValid,
|
||||||
isNtpServerValid,
|
isNtpServerValid,
|
||||||
isKernelArgumentValid,
|
isKernelArgumentValid,
|
||||||
|
isKernelNameValid,
|
||||||
isPortValid,
|
isPortValid,
|
||||||
isServiceValid,
|
isServiceValid,
|
||||||
isUserGroupValid,
|
isUserGroupValid,
|
||||||
|
|
@ -113,74 +114,13 @@ type ValidationState = {
|
||||||
ruleCharacters: HelperTextVariant;
|
ruleCharacters: HelperTextVariant;
|
||||||
};
|
};
|
||||||
|
|
||||||
function tokenValidityRemaining(expireTimeInSeconds: number): number {
|
|
||||||
const currentTimeSeconds = Math.floor(Date.now() / 1000);
|
|
||||||
return expireTimeInSeconds - currentTimeSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decodeToken(token: string): JwtPayload | undefined {
|
|
||||||
try {
|
|
||||||
const decoded = jwtDecode(token) as { exp?: number };
|
|
||||||
return decoded;
|
|
||||||
} catch {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getExpirationString(totalSeconds: number): string | undefined {
|
|
||||||
const hours = Math.floor(totalSeconds / 3600);
|
|
||||||
|
|
||||||
if (hours > 25) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hours > 0) {
|
|
||||||
return `${hours} hour${hours > 1 ? 's' : ''}`;
|
|
||||||
}
|
|
||||||
return 'less than an hour';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function validateSatelliteToken(
|
|
||||||
registrationCommand: string | undefined
|
|
||||||
) {
|
|
||||||
const errors: Record<string, string> = {};
|
|
||||||
if (registrationCommand === '') {
|
|
||||||
errors.command = 'No registration command for Satellite registration';
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = registrationCommand?.match(/Bearer\s+([\w-]+\.[\w-]+\.[\w-]+)/);
|
|
||||||
if (!match || match.length < 2) {
|
|
||||||
errors.command = 'Invalid or missing token';
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
const satelliteToken = decodeToken(match[1]);
|
|
||||||
if (satelliteToken === undefined) {
|
|
||||||
errors.command = 'Invalid or missing token';
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (satelliteToken.exp) {
|
|
||||||
const tokenRemainingS = tokenValidityRemaining(satelliteToken.exp);
|
|
||||||
if (tokenRemainingS <= 0) {
|
|
||||||
errors.command = `The token is expired. Check out the Satellite documentation to extend the token lifetime.`;
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
const expirationString = getExpirationString(tokenRemainingS);
|
|
||||||
if (expirationString !== undefined) {
|
|
||||||
errors.expired = `The token expires in ${expirationString}. Check out the Satellite documentation to extend the token lifetime.`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useRegistrationValidation(): StepValidation {
|
export function useRegistrationValidation(): StepValidation {
|
||||||
const registrationType = useAppSelector(selectRegistrationType);
|
const registrationType = useAppSelector(selectRegistrationType);
|
||||||
const activationKey = useAppSelector(selectActivationKey);
|
const activationKey = useAppSelector(selectActivationKey);
|
||||||
const registrationCommand = useAppSelector(
|
const registrationCommand = useAppSelector(
|
||||||
selectSatelliteRegistrationCommand
|
selectSatelliteRegistrationCommand
|
||||||
);
|
);
|
||||||
|
const caCertificate = useAppSelector(selectSatelliteCaCertificate);
|
||||||
|
|
||||||
const { isFetching: isFetchingKeyInfo, isError: isErrorKeyInfo } =
|
const { isFetching: isFetchingKeyInfo, isError: isErrorKeyInfo } =
|
||||||
useShowActivationKeyQuery(
|
useShowActivationKeyQuery(
|
||||||
|
|
@ -190,11 +130,7 @@ export function useRegistrationValidation(): StepValidation {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (registrationType !== 'register-later' && !activationKey) {
|
||||||
registrationType !== 'register-later' &&
|
|
||||||
registrationType !== 'register-satellite' &&
|
|
||||||
!activationKey
|
|
||||||
) {
|
|
||||||
return {
|
return {
|
||||||
errors: { activationKey: 'No activation key selected' },
|
errors: { activationKey: 'No activation key selected' },
|
||||||
disabledNext: true,
|
disabledNext: true,
|
||||||
|
|
@ -203,7 +139,6 @@ export function useRegistrationValidation(): StepValidation {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
registrationType !== 'register-later' &&
|
registrationType !== 'register-later' &&
|
||||||
registrationType !== 'register-satellite' &&
|
|
||||||
activationKey &&
|
activationKey &&
|
||||||
(isFetchingKeyInfo || isErrorKeyInfo)
|
(isFetchingKeyInfo || isErrorKeyInfo)
|
||||||
) {
|
) {
|
||||||
|
|
@ -215,14 +150,50 @@ export function useRegistrationValidation(): StepValidation {
|
||||||
|
|
||||||
if (registrationType === 'register-satellite') {
|
if (registrationType === 'register-satellite') {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
const tokenErrors = validateSatelliteToken(registrationCommand);
|
if (caCertificate === '') {
|
||||||
Object.assign(errors, tokenErrors);
|
Object.assign(errors, {
|
||||||
|
certificate:
|
||||||
|
'Valid certificate must be present if you are registering Satellite.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (registrationCommand === '' || !registrationCommand) {
|
||||||
|
Object.assign(errors, {
|
||||||
|
command: 'No registration command for Satellite registration',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const match = registrationCommand?.match(
|
||||||
|
/Bearer\s+([\w-]+\.[\w-]+\.[\w-]+)/
|
||||||
|
);
|
||||||
|
if (!match) {
|
||||||
|
Object.assign(errors, { command: 'Invalid or missing token' });
|
||||||
|
} else {
|
||||||
|
const token = match[1];
|
||||||
|
const decoded = jwtDecode(token);
|
||||||
|
if (decoded.exp) {
|
||||||
|
const currentTimeSeconds = Date.now() / 1000;
|
||||||
|
const dayInSeconds = 86400;
|
||||||
|
if (decoded.exp < currentTimeSeconds + dayInSeconds) {
|
||||||
|
const expirationDate = new Date(decoded.exp * 1000);
|
||||||
|
Object.assign(errors, {
|
||||||
|
expired:
|
||||||
|
'The token is already expired or will expire by next day. Expiration date: ' +
|
||||||
|
expirationDate,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
errors: errors,
|
||||||
|
disabledNext: caCertificate === undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Object.assign(errors, { command: 'Invalid or missing token' });
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
errors: errors,
|
errors: errors,
|
||||||
disabledNext:
|
disabledNext:
|
||||||
Object.keys(errors).some((key) => key !== 'expired') ||
|
Object.keys(errors).length > 0 || caCertificate === undefined,
|
||||||
!registrationCommand,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -555,9 +555,6 @@ describe('Import modal', () => {
|
||||||
await screen.findByPlaceholderText('Paste your public SSH key')
|
await screen.findByPlaceholderText('Paste your public SSH key')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
expect(
|
|
||||||
await screen.findByText(/Invalid user groups: 0000/)
|
|
||||||
).toBeInTheDocument();
|
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
user.click(screen.getByRole('button', { name: /close 0000/i }))
|
user.click(screen.getByRole('button', { name: /close 0000/i }))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -120,17 +120,27 @@ describe('Step Firewall', () => {
|
||||||
test('port in an invalid format cannot be added', async () => {
|
test('port in an invalid format cannot be added', async () => {
|
||||||
await renderCreateMode();
|
await renderCreateMode();
|
||||||
await goToFirewallStep();
|
await goToFirewallStep();
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(
|
||||||
|
screen.queryByText(
|
||||||
|
'Expected format: <port/port-name>:<protocol>. Example: 8080:tcp, ssh:tcp'
|
||||||
|
)
|
||||||
|
).not.toBeInTheDocument();
|
||||||
await addPort('00:wrongFormat');
|
await addPort('00:wrongFormat');
|
||||||
await screen.findByText('Invalid format.');
|
await screen.findByText(
|
||||||
|
'Expected format: <port/port-name>:<protocol>. Example: 8080:tcp, ssh:tcp'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('service in an invalid format cannot be added', async () => {
|
test('service in an invalid format cannot be added', async () => {
|
||||||
await renderCreateMode();
|
await renderCreateMode();
|
||||||
await goToFirewallStep();
|
await goToFirewallStep();
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(
|
||||||
|
screen.queryByText('Expected format: <service-name>. Example: sshd')
|
||||||
|
).not.toBeInTheDocument();
|
||||||
await addPort('wrong--service');
|
await addPort('wrong--service');
|
||||||
await screen.findByText('Invalid format.');
|
await screen.findByText(
|
||||||
|
'Expected format: <port/port-name>:<protocol>. Example: 8080:tcp, ssh:tcp'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('revisit step button on Review works', async () => {
|
test('revisit step button on Review works', async () => {
|
||||||
|
|
|
||||||
|
|
@ -438,7 +438,7 @@ describe('Registration request generated correctly', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const expiredTokenHelper = await screen.findByText(
|
const expiredTokenHelper = await screen.findByText(
|
||||||
/The token is expired./i
|
/The token is already expired or will expire by next day./i
|
||||||
);
|
);
|
||||||
await waitFor(() => expect(expiredTokenHelper).toBeInTheDocument());
|
await waitFor(() => expect(expiredTokenHelper).toBeInTheDocument());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,20 +179,34 @@ describe('Step Services', () => {
|
||||||
// Enabled services input
|
// Enabled services input
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
||||||
await addEnabledService('-------');
|
await addEnabledService('-------');
|
||||||
expect(await screen.findByText('Invalid format.')).toBeInTheDocument();
|
expect(
|
||||||
|
await screen.findByText('Expected format: <service-name>. Example: sshd')
|
||||||
|
).toBeInTheDocument();
|
||||||
await waitFor(() => user.click(clearInputButtons[0]));
|
await waitFor(() => user.click(clearInputButtons[0]));
|
||||||
|
|
||||||
// Disabled services input
|
// Disabled services input
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
||||||
await addDisabledService('-------');
|
await addDisabledService('-------');
|
||||||
expect(await screen.findByText('Invalid format.')).toBeInTheDocument();
|
expect(
|
||||||
|
await screen.findByText('Expected format: <service-name>. Example: sshd')
|
||||||
|
).toBeInTheDocument();
|
||||||
await waitFor(() => user.click(clearInputButtons[1]));
|
await waitFor(() => user.click(clearInputButtons[1]));
|
||||||
|
|
||||||
// Masked services input
|
// Masked services input
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
||||||
await addMaskedService('-------');
|
await addMaskedService('-------');
|
||||||
expect(await screen.findByText('Invalid format.')).toBeInTheDocument();
|
expect(
|
||||||
|
await screen.findByText('Expected format: <service-name>. Example: sshd')
|
||||||
|
).toBeInTheDocument();
|
||||||
await waitFor(() => user.click(clearInputButtons[2]));
|
await waitFor(() => user.click(clearInputButtons[2]));
|
||||||
|
|
||||||
|
// Enabled services input
|
||||||
|
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
||||||
|
await addEnabledService('-------');
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Expected format: <service-name>. Example: sshd')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
await waitFor(() => user.click(clearInputButtons[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('services from OpenSCAP get added correctly and cannot be removed', async () => {
|
test('services from OpenSCAP get added correctly and cannot be removed', async () => {
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,15 @@ describe('Step Timezone', () => {
|
||||||
test('NTP server in an invalid format cannot be added', async () => {
|
test('NTP server in an invalid format cannot be added', async () => {
|
||||||
await renderCreateMode();
|
await renderCreateMode();
|
||||||
await goToTimezoneStep();
|
await goToTimezoneStep();
|
||||||
expect(screen.queryByText('Invalid format.')).not.toBeInTheDocument();
|
expect(
|
||||||
|
screen.queryByText(
|
||||||
|
'Expected format: <ntp-server>. Example: time.redhat.com'
|
||||||
|
)
|
||||||
|
).not.toBeInTheDocument();
|
||||||
await addNtpServerViaKeyDown('this is not NTP server');
|
await addNtpServerViaKeyDown('this is not NTP server');
|
||||||
await screen.findByText('Invalid format.');
|
await screen.findByText(
|
||||||
|
'Expected format: <ntp-server>. Example: time.redhat.com'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('revisit step button on Review works', async () => {
|
test('revisit step button on Review works', async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue