Skip to content

Commit 210d1aa

Browse files
committed
test: Add validation test for import
This adds a test to check whether validation messages get rendered on import. Each step is checked for the correctly rendered error messages and then all invalid values are cleared so Next button re-enables and it's possible to continue.
1 parent c9a5611 commit 210d1aa

File tree

1 file changed

+245
-0
lines changed

1 file changed

+245
-0
lines changed

src/test/Components/Blueprints/ImportBlueprintModal.test.tsx

+245
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,83 @@ enabled = ["ftp", "ntp"]
198198
disabled = ["telnet"]
199199
`;
200200

201+
const ONPREM_BLUEPRINT_TOML_WITH_INVALID_VALUES = `
202+
name = "tmux"
203+
description = "tmux image with openssh"
204+
version = "1.2.16"
205+
distro = "rhel-93"
206+
207+
[[packages]]
208+
name = "tmux"
209+
version = "*"
210+
211+
[[packages]]
212+
name = "openssh-server"
213+
version = "*"
214+
215+
[[groups]]
216+
name = "anaconda-tools"
217+
218+
[customizations]
219+
hostname = "--invalid-hostname--"
220+
fips = true
221+
222+
[[customizations.sshkey]]
223+
user = "root"
224+
key = "ssh-rsa d"
225+
226+
[[customizations.user]]
227+
name = "admin"
228+
password = "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L..."
229+
key = "ssh-rsa d"
230+
groups = ["widget", "users", "wheel"]
231+
232+
[customizations.services]
233+
enabled = ["--invalid-enabled-service"]
234+
disabled = ["--invalid-disabled-service"]
235+
masked = ["--invalid-masked-service"]
236+
237+
[[customizations.files]]
238+
data = "W1VuaXRdCkRlc2NyaXB0aW9uPVJ1biBmaXJzdCBib290IHNjcmlwdApDb25kaXRpb25QYXRoRXhpc3RzPS91c3IvbG9jYWwvc2Jpbi9jdXN0b20tZmlyc3QtYm9vdApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CkFmdGVyPW9zYnVpbGQtZmlyc3QtYm9vdC5zZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2xvY2FsL3NiaW4vY3VzdG9tLWZpcnN0LWJvb3QKRXhlY1N0YXJ0UG9zdD1tdiAvdXNyL2xvY2FsL3NiaW4vY3VzdG9tLWZpcnN0LWJvb3QgL3Vzci9sb2NhbC9zYmluL2N1c3RvbS1maXJzdC1ib290LmRvbmUKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldAo="
239+
data_encoding = "base64"
240+
ensure_parents = true
241+
path = "/etc/systemd/system/custom-first-boot.service"
242+
243+
[[customizations.files]]
244+
data = "IyEvYmluL2Jhc2gKZmlyc3Rib290IHNjcmlwdCB0byB0ZXN0IGltcG9ydA=="
245+
data_encoding = "base64"
246+
ensure_parents = true
247+
mode = "0774"
248+
path = "/usr/local/sbin/custom-first-boot"
249+
250+
[[customizations.filesystem]]
251+
mountpoint = "/var"
252+
minsize = 1000000
253+
254+
[customizations.installer]
255+
unattended = true
256+
sudo-nopasswd = ["user", "%wheel"]
257+
258+
[customizations.timezone]
259+
timezone = "invalid-timezone"
260+
ntpservers = ["0.north-america.pool.ntp.org", "1.north-america.pool.ntp.org", "invalid-ntp-server"]
261+
262+
[customizations.locale]
263+
languages = ["invalid-language"]
264+
keyboard = "invalid-keyboard"
265+
266+
[customizations.kernel]
267+
name = "--invalid-kernel-name--"
268+
append = "invalid-kernel-argument"
269+
270+
[customizations.firewall]
271+
ports = ["invalid-port"]
272+
273+
[customizations.firewall.services]
274+
enabled = ["--invalid-enabled-service"]
275+
disabled = ["--invalid-disabled-service"]
276+
`;
277+
201278
const uploadFile = async (filename: string, content: string): Promise<void> => {
202279
const user = userEvent.setup();
203280
const fileInput: HTMLElement | null =
@@ -437,4 +514,172 @@ describe('Import modal', () => {
437514
await screen.findByText('telnetd');
438515
await screen.findByText('rpcbind');
439516
}, 20000);
517+
518+
test('should render errors for invalid values', async () => {
519+
await setUp();
520+
await uploadFile(
521+
`blueprints.toml`,
522+
ONPREM_BLUEPRINT_TOML_WITH_INVALID_VALUES
523+
);
524+
const reviewButton = screen.getByTestId('import-blueprint-finish');
525+
await waitFor(() => expect(reviewButton).not.toHaveClass('pf-m-disabled'));
526+
user.click(reviewButton);
527+
528+
// Image output
529+
const guestImageCheckBox = await screen.findByRole('checkbox', {
530+
name: /virtualization guest image checkbox/i,
531+
});
532+
await waitFor(() => user.click(guestImageCheckBox));
533+
534+
await clickNext(); // Registration
535+
await clickNext(); // OpenScap
536+
537+
// File system configuration
538+
await clickNext();
539+
expect(
540+
await screen.findByText(/The Wizard only supports KiB, MiB, or GiB/)
541+
).toBeInTheDocument();
542+
543+
await clickNext(); // Repository snapshot
544+
await clickNext(); // Custom Repos step
545+
await clickNext(); // Packages step
546+
await clickNext(); // Users
547+
548+
// Timezone
549+
await clickNext();
550+
expect(await screen.findByText('Unknown timezone')).toBeInTheDocument();
551+
expect(
552+
await screen.findByText('Invalid NTP servers: invalid-ntp-server')
553+
).toBeInTheDocument();
554+
const clearButtons = await screen.findAllByRole('button', {
555+
name: /clear input/i,
556+
});
557+
await waitFor(async () => user.click(clearButtons[0]));
558+
await waitFor(async () =>
559+
user.click(
560+
await screen.findByRole('button', {
561+
name: /close invalid-ntp-server/i,
562+
})
563+
)
564+
);
565+
566+
// Locale
567+
await clickNext();
568+
expect(
569+
await screen.findByText('Unknown languages: invalid-language')
570+
).toBeInTheDocument();
571+
expect(await screen.findByText('Unknown keyboard')).toBeInTheDocument();
572+
await waitFor(async () =>
573+
user.click(
574+
await screen.findByRole('button', {
575+
name: /close invalid-language/i,
576+
})
577+
)
578+
);
579+
await waitFor(async () =>
580+
user.click(
581+
await screen.findByRole('button', {
582+
name: /clear input/i,
583+
})
584+
)
585+
);
586+
587+
// Hostname
588+
await clickNext();
589+
expect(await screen.findByText(/Invalid hostname/)).toBeInTheDocument();
590+
await waitFor(() =>
591+
user.clear(
592+
screen.getByRole('textbox', {
593+
name: /hostname input/i,
594+
})
595+
)
596+
);
597+
598+
// Kernel
599+
await clickNext();
600+
expect(await screen.findByText(/Invalid format/)).toBeInTheDocument();
601+
expect(
602+
await screen.findByText(/Invalid kernel arguments/)
603+
).toBeInTheDocument();
604+
await waitFor(() =>
605+
user.click(screen.getAllByRole('button', { name: /clear input/i })[0])
606+
);
607+
await waitFor(() =>
608+
user.click(
609+
screen.getByRole('button', { name: /close invalid-kernel-argument/i })
610+
)
611+
);
612+
613+
// Firewall
614+
await clickNext();
615+
expect(
616+
await screen.findByText(/Invalid ports: invalid-port/)
617+
).toBeInTheDocument();
618+
expect(
619+
await screen.findByText(
620+
/Invalid disabled services: --invalid-disabled-service/
621+
)
622+
).toBeInTheDocument();
623+
expect(
624+
await screen.findByText(
625+
/Invalid enabled services: --invalid-enabled-service/
626+
)
627+
).toBeInTheDocument();
628+
await waitFor(() =>
629+
user.click(screen.getByRole('button', { name: /close invalid-port/i }))
630+
);
631+
await waitFor(() =>
632+
user.click(
633+
screen.getByRole('button', {
634+
name: /close --invalid-disabled-service/i,
635+
})
636+
)
637+
);
638+
await waitFor(() =>
639+
user.click(
640+
screen.getByRole('button', { name: /close --invalid-enabled-service/i })
641+
)
642+
);
643+
644+
// Services
645+
await clickNext();
646+
expect(
647+
await screen.findByText(
648+
/Invalid enabled services: --invalid-enabled-service/
649+
)
650+
).toBeInTheDocument();
651+
expect(
652+
await screen.findByText(
653+
/Invalid disabled services: --invalid-disabled-service/
654+
)
655+
).toBeInTheDocument();
656+
expect(
657+
await screen.findByText(
658+
/Invalid masked services: --invalid-masked-service/
659+
)
660+
).toBeInTheDocument();
661+
await waitFor(() =>
662+
user.click(
663+
screen.getByRole('button', { name: /close --invalid-enabled-service/i })
664+
)
665+
);
666+
await waitFor(() =>
667+
user.click(
668+
screen.getByRole('button', {
669+
name: /close --invalid-disabled-service/i,
670+
})
671+
)
672+
);
673+
await waitFor(() =>
674+
user.click(
675+
screen.getByRole('button', { name: /close --invalid-masked-service/i })
676+
)
677+
);
678+
679+
// Firstboot
680+
await clickNext();
681+
expect(
682+
await screen.findByRole('heading', { name: /First boot configuration/i })
683+
).toBeInTheDocument();
684+
}, 20000);
440685
});

0 commit comments

Comments
 (0)