Skip to content

Commit be18344

Browse files
Added e2e test cases for firewall selection changes and validations
1 parent aee586d commit be18344

6 files changed

Lines changed: 153 additions & 26 deletions

File tree

packages/manager/cypress/e2e/core/linodes/create-linode-with-firewall.spec.ts

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,150 @@ describe('Create Linode with Firewall (Linode Interfaces)', () => {
903903
ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`);
904904
});
905905

906+
/*
907+
* Legacy Configuration Profile Interfaces
908+
* - Confirms UI flow to create a Linode with "No firewall" option.
909+
* - Confirms that no firewall is reflected in create summary section.
910+
* - Confirms that outgoing Linode Create API request specifies no Firewall to be attached.
911+
*/
912+
it('can assign "No firewall" option during Linode Create flow (legacy)', () => {
913+
const mockLinode = linodeFactory.build({
914+
id: randomNumber(),
915+
label: randomLabel(),
916+
region: linodeRegion.id,
917+
});
918+
919+
mockCreateLinode(mockLinode).as('createLinode');
920+
mockGetLinodeDetails(mockLinode.id, mockLinode);
921+
922+
cy.visitWithLogin('/linodes/create');
923+
924+
linodeCreatePage.setLabel(mockLinode.label);
925+
linodeCreatePage.selectImage('Debian 12');
926+
linodeCreatePage.selectRegionById(linodeRegion.id);
927+
linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB');
928+
linodeCreatePage.setRootPassword(randomString(32));
929+
930+
// Confirm the Linode Interfaces section is shown.
931+
assertNewLinodeInterfacesIsAvailable();
932+
933+
// Switch to legacy Config Interfaces
934+
linodeCreatePage.selectLegacyConfigInterfacesType();
935+
936+
// Select a firewall
937+
linodeCreatePage.selectFirewall(
938+
'No firewall - traffic is unprotected (not recommended)',
939+
'Firewall'
940+
);
941+
942+
// Create Linode and confirm contents of outgoing API request payload.
943+
ui.button
944+
.findByTitle('Create Linode')
945+
.should('be.visible')
946+
.should('be.enabled')
947+
.click();
948+
949+
cy.wait('@createLinode').then((xhr) => {
950+
const requestPayload = xhr.request.body;
951+
const firewallId = requestPayload['firewall_id'];
952+
expect(firewallId).to.equal(-1);
953+
});
954+
955+
// Confirm redirect to new Linode.
956+
cy.url().should('endWith', `/linodes/${mockLinode.id}`);
957+
// Confirm toast notification should appear on Linode create.
958+
ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`);
959+
});
960+
961+
/*
962+
* Linode Interfaces
963+
* - Confirms UI flow to create a Linode with "No firewall" option.
964+
* - Confirms that no firewall is reflected in create summary section.
965+
* - Confirms that outgoing Linode Create API request specifies no Firewall to be attached.
966+
*/
967+
it('can assign "No firewall" option during Linode Create flow (Linode Interfaces)', () => {
968+
const mockLinode = linodeFactory.build({
969+
id: randomNumber(),
970+
label: randomLabel(),
971+
region: linodeRegion.id,
972+
});
973+
974+
mockCreateLinode(mockLinode).as('createLinode');
975+
mockGetLinodeDetails(mockLinode.id, mockLinode);
976+
977+
cy.visitWithLogin('/linodes/create');
978+
979+
linodeCreatePage.setLabel(mockLinode.label);
980+
linodeCreatePage.selectImage('Debian 12');
981+
linodeCreatePage.selectRegionById(linodeRegion.id);
982+
linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB');
983+
linodeCreatePage.setRootPassword(randomString(32));
984+
985+
// Confirm the Linode Interfaces section is shown.
986+
assertNewLinodeInterfacesIsAvailable();
987+
988+
linodeCreatePage.selectFirewall(
989+
'No firewall - traffic is unprotected (not recommended)',
990+
'Public Interface Firewall'
991+
);
992+
993+
// Create Linode and confirm contents of outgoing API request payload.
994+
ui.button
995+
.findByTitle('Create Linode')
996+
.should('be.visible')
997+
.should('be.enabled')
998+
.click();
999+
1000+
cy.wait('@createLinode').then((xhr) => {
1001+
const requestPayload = xhr.request.body;
1002+
const firewallId = requestPayload['interfaces'][0]['firewall_id'];
1003+
expect(firewallId).to.equal(-1);
1004+
});
1005+
1006+
// Confirm redirect to new Linode.
1007+
cy.url().should('endWith', `/linodes/${mockLinode.id}`);
1008+
// Confirm toast notification should appear on Linode create.
1009+
ui.toast.assertMessage(`Your Linode ${mockLinode.label} is being created.`);
1010+
});
1011+
1012+
/*
1013+
* Mocks no selection made in firewall dropdown.
1014+
* Confirms that correct validation error message is shown on the page when attempting to create a Linode.
1015+
*/
1016+
it('displays validation error related to firewall if no selection made in firewall dropdown', () => {
1017+
const mockLinode = linodeFactory.build({
1018+
id: randomNumber(),
1019+
label: randomLabel(),
1020+
region: linodeRegion.id,
1021+
});
1022+
1023+
mockCreateLinode(mockLinode).as('createLinode');
1024+
mockGetLinodeDetails(mockLinode.id, mockLinode);
1025+
1026+
cy.visitWithLogin('/linodes/create');
1027+
1028+
linodeCreatePage.setLabel(mockLinode.label);
1029+
linodeCreatePage.selectImage('Debian 12');
1030+
linodeCreatePage.selectRegionById(linodeRegion.id);
1031+
linodeCreatePage.selectPlan('Shared CPU', 'Nanode 1 GB');
1032+
linodeCreatePage.setRootPassword(randomString(32));
1033+
1034+
// Confirm the Linode Interfaces section is shown.
1035+
assertNewLinodeInterfacesIsAvailable();
1036+
1037+
// Create Linode and confirm contents of outgoing API request payload.
1038+
ui.button
1039+
.findByTitle('Create Linode')
1040+
.should('be.visible')
1041+
.should('be.enabled')
1042+
.click();
1043+
1044+
// Confirm the correct validation error related to firewall show up on the page.
1045+
cy.findByText('Select an option or create a new Firewall.').should(
1046+
'be.visible'
1047+
);
1048+
});
1049+
9061050
/*
9071051
* - Mocks the internal header to enable the Generate Compliant Firewall banner.
9081052
* - Mocks an error response to the Create Firewall call.

packages/manager/cypress/e2e/core/stackscripts/smoke-community-stackscripts.spec.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { getProfile } from '@linode/api-v4';
22
import { authenticate } from 'support/api/authentication';
3-
import { mockGetFirewalls } from 'support/intercepts/firewalls';
43
import { interceptCreateLinode } from 'support/intercepts/linodes';
54
import { mockGetUserPreferences } from 'support/intercepts/profile';
65
import {
@@ -11,10 +10,10 @@ import {
1110
import { ui } from 'support/ui';
1211
import { linodeCreatePage } from 'support/ui/pages';
1312
import { cleanUp } from 'support/util/cleanup';
14-
import { randomLabel, randomNumber, randomString } from 'support/util/random';
13+
import { randomLabel, randomString } from 'support/util/random';
1514
import { chooseRegion } from 'support/util/regions';
1615

17-
import { firewallFactory, stackScriptFactory } from 'src/factories';
16+
import { stackScriptFactory } from 'src/factories';
1817
import { formatDate } from 'src/utilities/formatDate';
1918

2019
import type { Profile, StackScript } from '@linode/api-v4';
@@ -286,16 +285,11 @@ describe('Community Stackscripts integration tests', () => {
286285
const image = 'AlmaLinux 9';
287286
const region = chooseRegion({ capabilities: ['Linodes', 'Vlans'] });
288287
const linodeLabel = randomLabel();
289-
const mockFirewall = firewallFactory.build({
290-
id: randomNumber(),
291-
label: randomLabel(),
292-
});
293288

294289
// Ensure that the Primary Nav is open
295290
mockGetUserPreferences({ desktop_sidebar_open: false }).as(
296291
'getPreferences'
297292
);
298-
mockGetFirewalls([mockFirewall]).as('getFirewalls');
299293
interceptGetStackScripts().as('getStackScripts');
300294
cy.visitWithLogin('/stackscripts/community');
301295
cy.wait(['@getStackScripts', '@getPreferences']);

packages/manager/src/features/Firewalls/components/FirewallSelect.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { FirewallSelectOption } from './FirewallSelectOption';
1010
import type { Firewall } from '@linode/api-v4';
1111
import type { EnhancedAutocompleteProps } from '@linode/ui';
1212

13+
// -1 is used as the value for the "firewall_id" if user doesn't want to use a firewall.
14+
// If null or undefined were used instead, the API would default to using the default firewall, which is not the intended behavior when a user explicitly selects "No firewall".
1315
const NO_FIREWALL_ID = -1;
1416

1517
const noFirewallOption = {

packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceGeneration.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ export const InterfaceGeneration = () => {
8585
label={
8686
<Stack mt={1.25} spacing={0.5}>
8787
<Stack direction="row">
88-
<Typography sx={(theme) => ({ font: theme.font.bold })}>
89-
Linode Interfaces (Recommended)
90-
</Typography>
88+
<Typography>Linode Interfaces (Recommended)</Typography>
9189
<LinodeInterfaceFeatureStatusChip />
9290
<TooltipIcon
9391
status="info"
@@ -126,9 +124,7 @@ export const InterfaceGeneration = () => {
126124
disabled={disabled}
127125
label={
128126
<Stack direction="row" mt={1.25} spacing={0.5}>
129-
<Typography sx={(theme) => ({ font: theme.font.bold })}>
130-
Configuration Profile Interfaces (Legacy)
131-
</Typography>
127+
<Typography>Configuration Profile Interfaces (Legacy)</Typography>
132128
<TooltipIcon
133129
status="info"
134130
sxTooltipIcon={{

packages/manager/src/features/Linodes/LinodeCreate/Networking/InterfaceType.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,7 @@ export const InterfaceType = ({ index }: Props) => {
136136
key={interfaceType.purpose}
137137
label={
138138
<Stack direction="row" mt={1.25} spacing={0.5}>
139-
<Typography sx={(theme) => ({ font: theme.font.bold })}>
140-
{interfaceType.label}
141-
</Typography>
139+
<Typography>{interfaceType.label}</Typography>
142140
<TooltipIcon
143141
status="info"
144142
sxTooltipIcon={{ p: 0, ml: 0.5 }}

packages/manager/src/features/Linodes/LinodesDetail/LinodeNetworking/LinodeInterfaces/AddInterfaceDrawer/AddInterfaceForm.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,11 @@ export const AddInterfaceForm = (props: Props) => {
5858
async resolver(rawValues, context, options) {
5959
const valuesWithOnlySelectedInterface = getCleanedLinodeInterfaceValues(
6060
structuredClone(rawValues)
61-
);
61+
) as CreateInterfaceFormValues;
6262

6363
const { errors, values } = await yupResolver(
6464
CreateLinodeInterfaceFormSchema
65-
)(
66-
{
67-
...valuesWithOnlySelectedInterface,
68-
firewall_id: valuesWithOnlySelectedInterface.firewall_id!,
69-
},
70-
context,
71-
options
72-
);
65+
)(valuesWithOnlySelectedInterface, context, options);
7366

7467
if (errors) {
7568
return { errors, values };

0 commit comments

Comments
 (0)