Skip to content

Commit 3fb1448

Browse files
Added automated tests with cypress for Zone form
1 parent ab2ae8c commit 3fb1448

File tree

1 file changed

+335
-0
lines changed
  • cypress/e2e/ui/Settings/Application-Settings

1 file changed

+335
-0
lines changed
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/* eslint-disable no-undef */
2+
3+
const textConstants = {
4+
// Component route url
5+
componentRouteUrl: '/ops/explorer',
6+
7+
// Menu options
8+
settingsOption: 'Settings',
9+
appSettingsMenuOption: 'Application Settings',
10+
11+
// Accordion items
12+
manageIQRegionAccordItem: /^ManageIQ Region:/,
13+
zonesAccordItem: 'Zones',
14+
15+
// Config options
16+
configToolbarButton: 'Configuration',
17+
addZoneConfigOption: 'Add a new Zone',
18+
editZoneConfigOption: 'Edit this Zone',
19+
deleteZoneConfigOption: 'Delete this Zone',
20+
21+
// Field values
22+
formHeaderFragment: 'Zone',
23+
infoSubHeader: 'Info',
24+
settingsSubHeader: 'Settings',
25+
zoneName: 'Test-Zone-Name',
26+
initialZoneDescription: 'Test-Zone-Description',
27+
updatedZoneDescription: 'Test-Zone-Description-Updated',
28+
initialServerIp: '0.0.0.0',
29+
updatedServerIp: '1.1.1.1',
30+
initialMaxScanLimit: 5,
31+
updatedMaxScanLimit: 10,
32+
33+
// Element ids
34+
nameInputFieldId: 'name',
35+
descriptionInputFieldId: 'description',
36+
ipInputFieldId: 'settings\\.proxy_server_ip',
37+
maxScanSelectFieldId: 'settings\\.concurrent_vm_scans',
38+
39+
// Common selectors
40+
inputFieldLabelSelector: (forValue) =>
41+
`#main-content .bx--form label[for="${forValue}"]`,
42+
inputFieldSelector: (inputId) => `#main-content .bx--form input#${inputId}`,
43+
selectFieldSelector: (selectId) => `#main-content .bx--form select#${selectId}`,
44+
buttonSelector: (type) => `#main-content .bx--btn-set button[type="${type}"]`,
45+
46+
// Buttons
47+
saveButton: 'Save',
48+
cancelButton: 'Cancel',
49+
addButton: 'Add',
50+
resetButton: 'Reset',
51+
52+
// Flash message types
53+
flashTypeSuccess: 'success',
54+
flashTypeWarning: 'warning',
55+
56+
// Flash message text snippets
57+
flashMessageOperationCanceled: 'cancel',
58+
flashMessageZoneUpdated: 'queued',
59+
flashMessageOperationReset: 'reset',
60+
deleteConfirmText: 'delete',
61+
};
62+
63+
const {
64+
componentRouteUrl,
65+
settingsOption,
66+
appSettingsMenuOption,
67+
manageIQRegionAccordItem,
68+
zonesAccordItem,
69+
configToolbarButton,
70+
addZoneConfigOption,
71+
editZoneConfigOption,
72+
deleteZoneConfigOption,
73+
selectFieldSelector,
74+
buttonSelector,
75+
inputFieldSelector,
76+
inputFieldLabelSelector,
77+
cancelButton,
78+
addButton,
79+
saveButton,
80+
resetButton,
81+
flashTypeSuccess,
82+
flashTypeWarning,
83+
deleteConfirmText,
84+
flashMessageOperationCanceled,
85+
flashMessageOperationReset,
86+
flashMessageZoneUpdated,
87+
formHeaderFragment,
88+
infoSubHeader,
89+
settingsSubHeader,
90+
zoneName,
91+
initialZoneDescription,
92+
updatedZoneDescription,
93+
initialServerIp,
94+
updatedServerIp,
95+
initialMaxScanLimit,
96+
updatedMaxScanLimit,
97+
nameInputFieldId,
98+
descriptionInputFieldId,
99+
ipInputFieldId,
100+
maxScanSelectFieldId,
101+
} = textConstants;
102+
103+
function addZone() {
104+
// Open add form
105+
cy.toolbar(configToolbarButton, addZoneConfigOption);
106+
// Adding name, description, ip and scan limit
107+
cy.get(inputFieldSelector(nameInputFieldId)).type(zoneName);
108+
cy.get(inputFieldSelector(descriptionInputFieldId)).type(
109+
initialZoneDescription
110+
);
111+
cy.get(inputFieldSelector(ipInputFieldId)).type(initialServerIp);
112+
cy.get(selectFieldSelector(maxScanSelectFieldId)).select(initialMaxScanLimit);
113+
cy.intercept('POST', '/api/zones').as('createZone');
114+
cy.getFormFooterButtonByType(addButton, 'submit')
115+
.should('be.enabled')
116+
.click();
117+
cy.wait('@createZone');
118+
}
119+
120+
function validateFormElements(isEditForm = false) {
121+
// Assert form header is visible
122+
cy.expect_explorer_title(formHeaderFragment);
123+
// Assert Info sub header is visible
124+
cy.get('#main-content .bx--form h3').contains(infoSubHeader);
125+
// Assert name field label is visible
126+
cy.get(inputFieldLabelSelector(nameInputFieldId)).should('be.visible');
127+
// Assert name field is visible and enabled
128+
cy.get(inputFieldSelector(nameInputFieldId))
129+
.should('be.visible')
130+
.then((nameField) => {
131+
if (isEditForm) {
132+
expect(nameField).to.be.disabled;
133+
} else {
134+
expect(nameField).to.not.be.disabled;
135+
}
136+
});
137+
// Assert description field label is visible
138+
cy.get(inputFieldLabelSelector(descriptionInputFieldId)).should('be.visible');
139+
// Assert description field is visible and enabled
140+
cy.get(inputFieldSelector(descriptionInputFieldId))
141+
.should('be.visible')
142+
.and('be.enabled');
143+
// Assert IP field label is visible
144+
cy.get(inputFieldLabelSelector(ipInputFieldId)).should('be.visible');
145+
// Assert IP field is visible and enabled
146+
cy.get(inputFieldSelector(ipInputFieldId))
147+
.should('be.visible')
148+
.and('be.enabled');
149+
// Assert Settings sub header is visible
150+
cy.get('#main-content .bx--form h3').contains(settingsSubHeader);
151+
// Assert max scan field label is visible
152+
cy.get(inputFieldLabelSelector(maxScanSelectFieldId)).should('be.visible');
153+
// Assert max scan field is visible and enabled
154+
cy.get(selectFieldSelector(maxScanSelectFieldId))
155+
.should('be.visible')
156+
.and('be.enabled');
157+
// Assert cancel button is visible and enabled
158+
cy.contains(buttonSelector(normalButtonType), cancelButton)
159+
.should('be.visible')
160+
.and('be.enabled');
161+
if (isEditForm) {
162+
// Assert reset button is visible and disabled
163+
cy.contains(buttonSelector(normalButtonType), resetButton)
164+
.should('be.visible')
165+
.and('be.disabled');
166+
}
167+
// Assert add/save button is visible and disabled
168+
cy.getFormFooterButtonByType(isEditForm ? saveButton : addButton, 'submit')
169+
.should('be.visible')
170+
.and('be.disabled');
171+
}
172+
173+
function cleanUp() {
174+
cy.get('li.list-group-item').each((item) => {
175+
const text = item?.text()?.trim();
176+
if (text.includes(initialZoneDescription)) {
177+
// Select the zone node if it hasn’t been selected yet
178+
if (!item.hasClass('node-selected')) {
179+
cy.wrap(item).click();
180+
cy.wait('@treeSelectApi');
181+
}
182+
// Deleting the zone
183+
cy.expect_browser_confirm_with_text({
184+
confirmTriggerFn: () =>
185+
cy.toolbar(configToolbarButton, deleteZoneConfigOption),
186+
});
187+
return false; // exit the iteration
188+
}
189+
return null; // has no impact - just to get rid of eslint warning
190+
});
191+
}
192+
193+
describe('Automate Schedule form operations: Settings > Application Settings > Settings > Zones > Configuration > Add a new Zone', () => {
194+
beforeEach(() => {
195+
cy.login();
196+
// Navigate to Application-Settings
197+
cy.menu(settingsOption, appSettingsMenuOption);
198+
// Expand Settings accordion panel if not already expanded
199+
cy.accordion(settingsOption);
200+
// Select "Zones" accordion item
201+
cy.intercept('POST', /\/ops\/tree_select\?id=.*&text=.*/).as(
202+
'treeSelectApi'
203+
);
204+
cy.selectAccordionItem([manageIQRegionAccordItem, zonesAccordItem]);
205+
cy.wait('@treeSelectApi');
206+
});
207+
208+
it('Validate the visibility and state of add form elements', () => {
209+
// Open add form
210+
cy.toolbar(configToolbarButton, addZoneConfigOption);
211+
// Validate fields
212+
validateFormElements();
213+
});
214+
215+
it('Checking whether cancel button works on the add form', () => {
216+
// Open add form
217+
cy.toolbar(configToolbarButton, addZoneConfigOption);
218+
// Cancelling the form
219+
cy.contains(buttonSelector(normalButtonType), cancelButton).click();
220+
cy.expect_flash(flashTypeWarning, flashMessageOperationCanceled);
221+
});
222+
223+
it('Checking whether add, edit & delete zone works', () => {
224+
/* ===== Add ===== */
225+
// Adding zone
226+
addZone();
227+
cy.expect_flash(flashTypeSuccess, flashMessageZoneUpdated);
228+
// Expand Settings accordion panel if not expanded
229+
cy.accordion(settingsOption);
230+
/* ===== Edit ===== */
231+
// Select the created zone
232+
cy.selectAccordionItem([
233+
manageIQRegionAccordItem,
234+
zonesAccordItem,
235+
`Zone: ${initialZoneDescription}`,
236+
]);
237+
cy.wait('@treeSelectApi');
238+
// Open edit form
239+
cy.toolbar(configToolbarButton, editZoneConfigOption);
240+
// Update IP & scan limit
241+
cy.get(inputFieldSelector(descriptionInputFieldId))
242+
.clear()
243+
.type(updatedServerIp);
244+
cy.get(selectFieldSelector(maxScanSelectFieldId)).select(
245+
updatedMaxScanLimit
246+
);
247+
// Save the form
248+
cy.getFormFooterButtonByType(saveButton, 'submit')
249+
.should('be.enabled')
250+
.click();
251+
cy.expect_flash(flashTypeSuccess, flashMessageZoneUpdated);
252+
/* ===== Delete ===== */
253+
// Deleting the zone
254+
cy.expect_browser_confirm_with_text({
255+
confirmTriggerFn: () =>
256+
cy.toolbar(configToolbarButton, deleteZoneConfigOption),
257+
containsText: deleteConfirmText,
258+
});
259+
cy.expect_flash(flashTypeSuccess, deleteConfirmText);
260+
});
261+
262+
it('Validate the visibility and state of edit form elements', () => {
263+
// Adding zone
264+
addZone();
265+
// Expand Settings accordion panel if not expanded
266+
cy.accordion(settingsOption);
267+
// Select the created zone
268+
cy.selectAccordionItem([
269+
manageIQRegionAccordItem,
270+
zonesAccordItem,
271+
`Zone: ${initialZoneDescription}`,
272+
]);
273+
cy.wait('@treeSelectApi');
274+
// Open edit form
275+
cy.toolbar(configToolbarButton, editZoneConfigOption);
276+
// Validate fields
277+
validateFormElements(true);
278+
// Cancelling the form
279+
cy.contains(buttonSelector(normalButtonType), cancelButton).click();
280+
});
281+
282+
it('Checking whether cancel & reset buttons work on the edit form', () => {
283+
// Adding zone
284+
addZone();
285+
// Expand Settings accordion panel if not expanded
286+
cy.accordion(settingsOption);
287+
// Select the created zone
288+
cy.selectAccordionItem([
289+
manageIQRegionAccordItem,
290+
zonesAccordItem,
291+
`Zone: ${initialZoneDescription}`,
292+
]);
293+
cy.wait('@treeSelectApi');
294+
// Open edit form
295+
cy.toolbar(configToolbarButton, editZoneConfigOption);
296+
/* ===== Reset ===== */
297+
// Update description & IP
298+
cy.get(inputFieldSelector(descriptionInputFieldId))
299+
.clear()
300+
.type(updatedZoneDescription);
301+
cy.get(inputFieldSelector(ipInputFieldId)).clear().type(updatedServerIp);
302+
// Resetting the form
303+
cy.contains(buttonSelector(normalButtonType), resetButton)
304+
.should('be.enabled')
305+
.click();
306+
cy.expect_flash(flashTypeWarning, flashMessageOperationReset);
307+
// Confirming the edited fields contain the old values after resetting
308+
cy.get(inputFieldSelector(descriptionInputFieldId)).should(
309+
'have.value',
310+
initialZoneDescription
311+
);
312+
cy.get(inputFieldSelector(ipInputFieldId)).should(
313+
'have.value',
314+
initialServerIp
315+
);
316+
/* ===== Cancel ===== */
317+
// Cancelling the form
318+
cy.contains(buttonSelector(normalButtonType), cancelButton).click();
319+
cy.expect_flash(flashTypeWarning, flashMessageOperationCanceled);
320+
});
321+
322+
afterEach(() => {
323+
cy.url()
324+
?.then((url) => {
325+
// Ensures navigation to Settings -> Application-Settings in the UI
326+
if (!url?.includes(componentRouteUrl)) {
327+
// Navigate to Settings -> Application-Settings before cleanup
328+
cy.menu(settingsOption, appSettingsMenuOption);
329+
}
330+
})
331+
.then(() => {
332+
cleanUp();
333+
});
334+
});
335+
});

0 commit comments

Comments
 (0)