Skip to content

Commit fe0bdba

Browse files
mgold1234regexowl
authored andcommitted
playwright: Add chip collapse tests for Kernel, Timezone, and Systemd steps
Add Playwright E2E tests for the "show less / more" chip collapse behavior introduced in d97be84. Tests cover: - Kernel arguments - Timezone NTP servers - Systemd services (enabled, disabled, and masked) Each test verifies: - All chips visible when 4 or fewer items - Chips collapse with "X more" button when exceeding threshold - Expanding via "X more" and collapsing via "Show less" - Collapse controls disappear when items drop back below threshold
1 parent b368b23 commit fe0bdba

3 files changed

Lines changed: 265 additions & 4 deletions

File tree

playwright/Customizations/Kernel.spec.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,70 @@ test('Create a blueprint with Kernel customization', async ({
4242
await test.step('Navigate to optional steps in Wizard', async () => {
4343
await fillInImageOutput(frame);
4444
await registerLater(frame);
45+
await frame.getByRole('button', { name: 'Kernel' }).click();
46+
});
47+
48+
await test.step('Shows all chips when 4 or fewer', async () => {
49+
const argInput = frame.getByPlaceholder('Add kernel argument');
50+
for (const arg of ['nosmp', 'rootwait', 'quiet', 'splash']) {
51+
await argInput.fill(arg);
52+
await page.keyboard.press('Enter');
53+
}
54+
55+
await expect(frame.getByText('nosmp')).toBeVisible();
56+
await expect(frame.getByText('rootwait')).toBeVisible();
57+
await expect(frame.getByText('quiet')).toBeVisible();
58+
await expect(frame.getByText('splash')).toBeVisible();
59+
await expect(frame.getByText(/^\d+ more$/)).toBeHidden();
60+
});
61+
62+
await test.step('Collapses and shows "X more" when more than 4', async () => {
63+
const argInput = frame.getByPlaceholder('Add kernel argument');
64+
for (const arg of ['console=tty0', 'debug']) {
65+
await argInput.fill(arg);
66+
await page.keyboard.press('Enter');
67+
}
68+
69+
await expect(frame.getByText('nosmp')).toBeVisible();
70+
await expect(frame.getByText('console=tty0')).toBeHidden();
71+
await expect(frame.getByText('debug')).toBeHidden();
72+
await expect(frame.getByText('2 more')).toBeVisible();
73+
});
74+
75+
await test.step('Expands when clicking "X more" and collapses with "Show less"', async () => {
76+
await frame.getByText('2 more').click();
77+
await expect(frame.getByText('console=tty0')).toBeVisible();
78+
await expect(frame.getByText('debug')).toBeVisible();
79+
await expect(frame.getByText('Show less')).toBeVisible();
80+
81+
await frame.getByText('Show less').click();
82+
await expect(frame.getByText('console=tty0')).toBeHidden();
83+
await expect(frame.getByText('debug')).toBeHidden();
84+
await expect(frame.getByText('2 more')).toBeVisible();
85+
});
86+
87+
await test.step('Collapse controls disappear when items drop below threshold', async () => {
88+
await frame.getByText('2 more').click();
89+
90+
await frame.getByRole('button', { name: 'Close debug' }).click();
91+
await frame.getByRole('button', { name: 'Close console=tty0' }).click();
92+
93+
await expect(frame.getByText(/^\d+ more$/)).toBeHidden();
94+
await expect(frame.getByText('Show less')).toBeHidden();
95+
await expect(frame.getByText('nosmp')).toBeVisible();
96+
await expect(frame.getByText('rootwait')).toBeVisible();
97+
await expect(frame.getByText('quiet')).toBeVisible();
98+
await expect(frame.getByText('splash')).toBeVisible();
99+
});
100+
101+
await test.step('Clean up chip collapse test chips', async () => {
102+
await frame.getByRole('button', { name: 'Close splash' }).click();
103+
await frame.getByRole('button', { name: 'Close quiet' }).click();
104+
await frame.getByRole('button', { name: 'Close nosmp' }).click();
105+
await frame.getByRole('button', { name: 'Close rootwait' }).click();
45106
});
46107

47108
await test.step('Select and fill the Kernel step', async () => {
48-
await frame.getByRole('button', { name: 'Kernel' }).click();
49109
await frame.getByRole('button', { name: 'Menu toggle' }).click();
50110
await frame.getByRole('option', { name: 'kernel', exact: true }).click();
51111
await frame.getByPlaceholder('Add kernel argument').fill('rootwait');

playwright/Customizations/Systemd.spec.ts

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,135 @@ test('Create a blueprint with Systemd customization', async ({
4242
await test.step('Navigate to optional steps in Wizard', async () => {
4343
await fillInImageOutput(frame);
4444
await registerLater(frame);
45+
await frame.getByRole('button', { name: 'Systemd services' }).click();
4546
});
4647

47-
await test.step('Select and correctly fill all of the service fields', async () => {
48-
await frame.getByRole('button', { name: 'Systemd services' }).click();
48+
await test.step('Enabled services: shows all chips when 4 or fewer', async () => {
49+
const enabledInput = frame.getByPlaceholder('Add enabled service');
50+
for (const service of [
51+
'sshd.service',
52+
'httpd.service',
53+
'nginx.service',
54+
'crond.service',
55+
]) {
56+
await enabledInput.fill(service);
57+
await page.keyboard.press('Enter');
58+
}
59+
60+
await expect(frame.getByText('sshd.service')).toBeVisible();
61+
await expect(frame.getByText('httpd.service')).toBeVisible();
62+
await expect(frame.getByText('nginx.service')).toBeVisible();
63+
await expect(frame.getByText('crond.service')).toBeVisible();
64+
await expect(frame.getByText(/^\d+ more$/)).toBeHidden();
65+
});
66+
67+
await test.step('Enabled services: collapses and shows "X more" when more than 4', async () => {
68+
const enabledInput = frame.getByPlaceholder('Add enabled service');
69+
for (const service of ['rsyslog.service', 'chronyd.service']) {
70+
await enabledInput.fill(service);
71+
await page.keyboard.press('Enter');
72+
}
73+
74+
await expect(frame.getByText('sshd.service')).toBeVisible();
75+
await expect(frame.getByText('rsyslog.service')).toBeHidden();
76+
await expect(frame.getByText('chronyd.service')).toBeHidden();
77+
await expect(frame.getByText('2 more').first()).toBeVisible();
78+
});
79+
80+
await test.step('Enabled services: expands and collapses', async () => {
81+
await frame.getByText('2 more').first().click();
82+
await expect(frame.getByText('rsyslog.service')).toBeVisible();
83+
await expect(frame.getByText('chronyd.service')).toBeVisible();
84+
await expect(frame.getByText('Show less').first()).toBeVisible();
85+
86+
await frame.getByText('Show less').first().click();
87+
await expect(frame.getByText('rsyslog.service')).toBeHidden();
88+
await expect(frame.getByText('chronyd.service')).toBeHidden();
89+
await expect(frame.getByText('2 more').first()).toBeVisible();
90+
});
4991

92+
await test.step('Disabled services: collapses and shows "X more" when more than 4', async () => {
93+
const disabledInput = frame.getByPlaceholder('Add disabled service');
94+
for (const service of [
95+
'cups.service',
96+
'avahi-daemon.service',
97+
'bluetooth.service',
98+
'ModemManager.service',
99+
'postfix.service',
100+
]) {
101+
await disabledInput.fill(service);
102+
await page.keyboard.press('Enter');
103+
}
104+
105+
await expect(frame.getByText('cups.service')).toBeVisible();
106+
await expect(frame.getByText('avahi-daemon.service')).toBeVisible();
107+
await expect(frame.getByText('bluetooth.service')).toBeVisible();
108+
await expect(frame.getByText('ModemManager.service')).toBeVisible();
109+
await expect(frame.getByText('postfix.service')).toBeHidden();
110+
await expect(frame.getByText('1 more').first()).toBeVisible();
111+
});
112+
113+
await test.step('Masked services: collapses and shows "X more" when more than 4', async () => {
114+
const maskedInput = frame.getByPlaceholder('Add masked service');
115+
for (const service of [
116+
'firewalld.service',
117+
'iptables.service',
118+
'nftables.service',
119+
'ip6tables.service',
120+
'ebtables.service',
121+
]) {
122+
await maskedInput.fill(service);
123+
await page.keyboard.press('Enter');
124+
}
125+
126+
await expect(frame.getByText('firewalld.service')).toBeVisible();
127+
await expect(frame.getByText('iptables.service')).toBeVisible();
128+
await expect(frame.getByText('nftables.service')).toBeVisible();
129+
await expect(frame.getByText('ip6tables.service')).toBeVisible();
130+
await expect(frame.getByText('ebtables.service')).toBeHidden();
131+
await expect(frame.getByText('1 more').nth(1)).toBeVisible();
132+
});
133+
134+
await test.step('Clean up chip collapse test chips', async () => {
135+
// Clean up enabled services
136+
await frame.getByText('2 more').first().click();
137+
for (const service of [
138+
'chronyd.service',
139+
'rsyslog.service',
140+
'crond.service',
141+
'nginx.service',
142+
'httpd.service',
143+
'sshd.service',
144+
]) {
145+
await frame.getByRole('button', { name: `Close ${service}` }).click();
146+
}
147+
148+
// Clean up disabled services
149+
await frame.getByText('1 more').first().click();
150+
for (const service of [
151+
'postfix.service',
152+
'ModemManager.service',
153+
'bluetooth.service',
154+
'avahi-daemon.service',
155+
'cups.service',
156+
]) {
157+
await frame.getByRole('button', { name: `Close ${service}` }).click();
158+
}
159+
160+
// Clean up masked services
161+
await frame.getByText('1 more').first().click();
162+
for (const service of [
163+
'ebtables.service',
164+
'ip6tables.service',
165+
'nftables.service',
166+
'iptables.service',
167+
'firewalld.service',
168+
]) {
169+
await frame.getByRole('button', { name: `Close ${service}` }).click();
170+
}
171+
});
172+
173+
await test.step('Select and correctly fill all of the service fields', async () => {
50174
await frame
51175
.getByPlaceholder('Add disabled service')
52176
.fill('systemd-dis.service');

playwright/Customizations/Timezone.spec.ts

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,87 @@ test('Create a blueprint with Timezone customization', async ({
4242
await test.step('Navigate to optional steps in Wizard', async () => {
4343
await fillInImageOutput(frame);
4444
await registerLater(frame);
45+
await frame.getByRole('button', { name: 'Timezone' }).click();
46+
});
47+
48+
await test.step('Shows all NTP chips when 4 or fewer', async () => {
49+
const ntpInput = frame.getByPlaceholder('Add NTP servers');
50+
for (const server of [
51+
'0.nl.pool.ntp.org',
52+
'0.cz.pool.ntp.org',
53+
'0.de.pool.ntp.org',
54+
'0.fr.pool.ntp.org',
55+
]) {
56+
await ntpInput.fill(server);
57+
await page.keyboard.press('Enter');
58+
}
59+
60+
await expect(frame.getByText('0.nl.pool.ntp.org')).toBeVisible();
61+
await expect(frame.getByText('0.cz.pool.ntp.org')).toBeVisible();
62+
await expect(frame.getByText('0.de.pool.ntp.org')).toBeVisible();
63+
await expect(frame.getByText('0.fr.pool.ntp.org')).toBeVisible();
64+
await expect(frame.getByText(/^\d+ more$/)).toBeHidden();
65+
});
66+
67+
await test.step('Collapses and shows "X more" when more than 4', async () => {
68+
const ntpInput = frame.getByPlaceholder('Add NTP servers');
69+
for (const server of ['0.us.pool.ntp.org', '0.uk.pool.ntp.org']) {
70+
await ntpInput.fill(server);
71+
await page.keyboard.press('Enter');
72+
}
73+
74+
await expect(frame.getByText('0.nl.pool.ntp.org')).toBeVisible();
75+
await expect(frame.getByText('0.us.pool.ntp.org')).toBeHidden();
76+
await expect(frame.getByText('0.uk.pool.ntp.org')).toBeHidden();
77+
await expect(frame.getByText('2 more')).toBeVisible();
78+
});
79+
80+
await test.step('Expands when clicking "X more" and collapses with "Show less"', async () => {
81+
await frame.getByText('2 more').click();
82+
await expect(frame.getByText('0.us.pool.ntp.org')).toBeVisible();
83+
await expect(frame.getByText('0.uk.pool.ntp.org')).toBeVisible();
84+
await expect(frame.getByText('Show less')).toBeVisible();
85+
86+
await frame.getByText('Show less').click();
87+
await expect(frame.getByText('0.us.pool.ntp.org')).toBeHidden();
88+
await expect(frame.getByText('0.uk.pool.ntp.org')).toBeHidden();
89+
await expect(frame.getByText('2 more')).toBeVisible();
90+
});
91+
92+
await test.step('Collapse controls disappear when items drop below threshold', async () => {
93+
await frame.getByText('2 more').click();
94+
95+
await frame
96+
.getByRole('button', { name: 'Close 0.uk.pool.ntp.org' })
97+
.click();
98+
await frame
99+
.getByRole('button', { name: 'Close 0.us.pool.ntp.org' })
100+
.click();
101+
102+
await expect(frame.getByText(/^\d+ more$/)).toBeHidden();
103+
await expect(frame.getByText('Show less')).toBeHidden();
104+
await expect(frame.getByText('0.nl.pool.ntp.org')).toBeVisible();
105+
await expect(frame.getByText('0.cz.pool.ntp.org')).toBeVisible();
106+
await expect(frame.getByText('0.de.pool.ntp.org')).toBeVisible();
107+
await expect(frame.getByText('0.fr.pool.ntp.org')).toBeVisible();
108+
});
109+
110+
await test.step('Clean up chip collapse test chips', async () => {
111+
await frame
112+
.getByRole('button', { name: 'Close 0.fr.pool.ntp.org' })
113+
.click();
114+
await frame
115+
.getByRole('button', { name: 'Close 0.de.pool.ntp.org' })
116+
.click();
117+
await frame
118+
.getByRole('button', { name: 'Close 0.cz.pool.ntp.org' })
119+
.click();
120+
await frame
121+
.getByRole('button', { name: 'Close 0.nl.pool.ntp.org' })
122+
.click();
45123
});
46124

47125
await test.step('Select and fill the Timezone step', async () => {
48-
await frame.getByRole('button', { name: 'Timezone' }).click();
49126
await frame.getByPlaceholder('Select a timezone').fill('Canada');
50127
await frame.getByRole('option', { name: 'Canada/Saskatchewan' }).click();
51128
await frame.getByPlaceholder('Select a timezone').fill('');

0 commit comments

Comments
 (0)