Skip to content

Commit 3f7777e

Browse files
Added automated tests with cypress for Zone form
1 parent ef8fb4c commit 3f7777e

File tree

1 file changed

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

1 file changed

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

0 commit comments

Comments
 (0)