Skip to content

Commit beee656

Browse files
Added automated tests with cypress for Zone form
1 parent 30db374 commit beee656

File tree

1 file changed

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

1 file changed

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

0 commit comments

Comments
 (0)