Skip to content

Commit 1901a74

Browse files
Added automated tests with cypress for Namespace form
1 parent 8e71ce6 commit 1901a74

File tree

1 file changed

+339
-0
lines changed

1 file changed

+339
-0
lines changed
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
/* eslint-disable no-undef */
2+
import { flashClassMap } from '../../../../../support/assertions/assertion_constants';
3+
4+
// Component route url
5+
const COMPONENT_ROUTE_URL = 'miq_ae_class/explorer#/';
6+
7+
// Menu options
8+
const AUTOMATION_MENU_OPTION = 'Automation';
9+
const EMBEDDED_AUTOMATION_MENU_OPTION = 'Embedded Automate';
10+
const EXPLORER_MENU_OPTION = 'Explorer';
11+
12+
// Toolbar options
13+
const TOOLBAR_CONFIGURATION = 'Configuration';
14+
const TOOLBAR_ADD_NEW_DOMAIN = 'Add a New Domain';
15+
const TOOLBAR_REMOVE_DOMAIN = 'Remove this Domain';
16+
const TOOLBAR_ADD_NEW_NAMESPACE = 'Add a New Namespace';
17+
const TOOLBAR_EDIT_NAMESPACE = 'Edit this Namespace';
18+
const TOOLBAR_REMOVE_NAMESPACE = 'Remove this Namespace';
19+
20+
// Field values
21+
const NAME_SAPCE_PATH_FIELD_LABEL = 'Fully Qualified Name';
22+
const NAME_FIELD_LABEL = 'Name';
23+
const DESCRIPTION_FIELD_LABEL = 'Description';
24+
const DOMAIN_NAME = 'Test_Domain';
25+
const DESCRIPTION = 'Test description';
26+
const NAMESPACE_NAME = 'Test_Namespace';
27+
const EDITED_NAMESPACE_NAME = 'Test_Namespace_Edited';
28+
const EDITED_DESCRIPTION = 'Test description edited';
29+
const INVALID_NAMESPACE_NAME = 'Test Namespace';
30+
const NAMESPACE_FORM_HEADER = 'Automate Namespace';
31+
const NAMESPACE_FORM_SUB_HEADER = 'Info';
32+
33+
// List items
34+
const DATA_STORE_ACCORDION_LABEL = 'Datastore';
35+
36+
// Buttons
37+
const ADD_BUTTON_TEXT = 'Add';
38+
const CANCEL_BUTTON_TEXT = 'Cancel';
39+
const SAVE_BUTTON_TEXT = 'Save';
40+
const RESET_BUTTON_TEXT = 'Reset';
41+
42+
// Flash message text snippets
43+
const FLASH_MESSAGE_ADD_SUCCESS = 'added';
44+
const FLASH_MESSAGE_SAVE_SUCCESS = 'saved';
45+
const FLASH_MESSAGE_CANCELLED = 'cancel';
46+
const FLASH_MESSAGE_INVALID_NAMESPACE = 'contain only alphanumeric';
47+
const FLASH_MESSAGE_NAMESPACE_REMOVED = 'delete successful';
48+
const FLASH_MESSAGE_NAME_ALREADY_EXISTS = 'taken';
49+
const FLASH_MESSAGE_RESET_NAMESPACE = 'reset';
50+
const BROWSER_CONFIRM_REMOVE_MESSAGE = 'remove';
51+
52+
function addDomainOrNamespace({ nameFieldValue }) {
53+
// Adding name & description
54+
cy.getFormInputFieldByIdAndType({ inputId: 'name' }).type(nameFieldValue);
55+
cy.getFormInputFieldByIdAndType({ inputId: 'description' }).type(DESCRIPTION);
56+
// Submitting the form
57+
cy.interceptApi({
58+
alias: 'addDomainOrNamespaceApi',
59+
urlPattern: '/miq_ae_class/create_namespace/new?button=add',
60+
triggerFn: () =>
61+
cy
62+
.getFormFooterButtonByTypeWithText({
63+
buttonText: ADD_BUTTON_TEXT,
64+
buttonType: 'submit',
65+
})
66+
.click(),
67+
});
68+
}
69+
70+
function selectAccordionElement(selectNamespace) {
71+
const pathToTargetNode = selectNamespace
72+
? [DOMAIN_NAME, NAMESPACE_NAME]
73+
: [DOMAIN_NAME];
74+
cy.selectAccordionItem([DATA_STORE_ACCORDION_LABEL, ...pathToTargetNode]);
75+
}
76+
77+
function validateNamespaceFormFields(isEditForm = false) {
78+
// Assert form header is visible
79+
cy.expect_explorer_title(NAMESPACE_FORM_HEADER);
80+
// Assert sub header is visible
81+
cy.get('#main-content #datastore-form-wrapper h3').contains(
82+
NAMESPACE_FORM_SUB_HEADER
83+
);
84+
// Assert name-space path field label is visible
85+
cy.getFormLabelByForAttribute({ forValue: 'namespacePath' })
86+
.should('be.visible')
87+
.and('contain.text', NAME_SAPCE_PATH_FIELD_LABEL);
88+
// Assert name-space path field is visible and disabled
89+
cy.getFormInputFieldByIdAndType({ inputId: 'namespacePath' })
90+
.should('be.visible')
91+
.and('be.disabled')
92+
.invoke('val')
93+
.should('include', DOMAIN_NAME);
94+
// Assert name field label is visible
95+
cy.getFormLabelByForAttribute({ forValue: 'name' })
96+
.should('be.visible')
97+
.and('contain.text', NAME_FIELD_LABEL);
98+
// Assert name field is visible and enabled
99+
cy.getFormInputFieldByIdAndType({ inputId: 'name' })
100+
.should('be.visible')
101+
.and('be.enabled');
102+
// Assert description field label is visible
103+
cy.getFormLabelByForAttribute({ forValue: 'description' })
104+
.should('be.visible')
105+
.and('contain.text', DESCRIPTION_FIELD_LABEL);
106+
// Assert description field is visible and enabled
107+
cy.getFormInputFieldByIdAndType({ inputId: 'description' })
108+
.should('be.visible')
109+
.and('be.enabled');
110+
// Assert cancel button is visible and enabled
111+
cy.getFormFooterButtonByTypeWithText({ buttonText: CANCEL_BUTTON_TEXT })
112+
.should('be.visible')
113+
.and('be.enabled');
114+
// Assert add/save button is visible and disabled
115+
cy.getFormFooterButtonByTypeWithText({
116+
buttonText: isEditForm ? SAVE_BUTTON_TEXT : ADD_BUTTON_TEXT,
117+
buttonType: 'submit',
118+
})
119+
.should('be.visible')
120+
.and('be.disabled');
121+
if (isEditForm) {
122+
// Assert reset button is visible and disabled
123+
cy.getFormFooterButtonByTypeWithText({ buttonText: RESET_BUTTON_TEXT })
124+
.should('be.visible')
125+
.and('be.disabled');
126+
}
127+
}
128+
129+
function createNamespaceAndOpenEditForm() {
130+
/* TODO: DATA_SETUP - Use API for namespace setup, excluding the test meant to validate functionality via UI */
131+
// Navigating to the Add Namespace form
132+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
133+
// Adding a new namespace
134+
addDomainOrNamespace({ nameFieldValue: NAMESPACE_NAME });
135+
// Selecting the created namespace from the accordion list items
136+
selectAccordionElement(true);
137+
// Opening the edit form
138+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_EDIT_NAMESPACE);
139+
}
140+
141+
describe('Automate operations on Namespaces: Automation -> Embedded Automate -> Explorer -> {Any-created-domain} -> Namespace form', () => {
142+
beforeEach(() => {
143+
cy.login();
144+
// Navigate to Explorer under Automation -> Embedded Automate
145+
cy.menu(
146+
AUTOMATION_MENU_OPTION,
147+
EMBEDDED_AUTOMATION_MENU_OPTION,
148+
EXPLORER_MENU_OPTION
149+
);
150+
// Expand "Datastore" accordion if not already expanded
151+
cy.accordion(DATA_STORE_ACCORDION_LABEL);
152+
/* TODO: DATA_SETUP - Refactor to use API for domain data setup */
153+
// Navigating to the Add Domain form
154+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_DOMAIN);
155+
// Creating a domain to validate namespace operations
156+
addDomainOrNamespace({
157+
nameFieldValue: DOMAIN_NAME,
158+
});
159+
cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_ADD_SUCCESS);
160+
// Selecting the created domain from the accordion list items
161+
selectAccordionElement(false);
162+
});
163+
164+
it('Validate Add Namespace form fields', () => {
165+
// Navigating to the Add Namespace form
166+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
167+
168+
// Validating the form fields
169+
validateNamespaceFormFields();
170+
171+
// Cancelling the form
172+
cy.getFormFooterButtonByTypeWithText({
173+
buttonText: CANCEL_BUTTON_TEXT,
174+
}).click();
175+
});
176+
177+
it('Validate Cancel button', () => {
178+
// Navigating to the Add Namespace form
179+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
180+
181+
// Cancelling the form
182+
cy.getFormFooterButtonByTypeWithText({ buttonText: CANCEL_BUTTON_TEXT })
183+
.should('be.enabled')
184+
.click();
185+
cy.expect_flash(flashClassMap.warning, FLASH_MESSAGE_CANCELLED);
186+
});
187+
188+
it('Validate Name field allows only alphanumeric and _ . - $ characters', () => {
189+
// Navigating to the Add Namespace form
190+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
191+
// Trying to add a namespace with invalid characters
192+
addDomainOrNamespace({ nameFieldValue: INVALID_NAMESPACE_NAME });
193+
cy.expect_flash(flashClassMap.error, FLASH_MESSAGE_INVALID_NAMESPACE);
194+
195+
// Cancelling the form
196+
cy.getFormFooterButtonByTypeWithText({
197+
buttonText: CANCEL_BUTTON_TEXT,
198+
}).click();
199+
});
200+
201+
it('Validate Edit Namespace form fields', () => {
202+
// Create a namespace and open the edit form
203+
createNamespaceAndOpenEditForm();
204+
205+
// Validating the form fields
206+
validateNamespaceFormFields(true);
207+
208+
// Cancelling the form
209+
cy.getFormFooterButtonByTypeWithText({
210+
buttonText: CANCEL_BUTTON_TEXT,
211+
}).click();
212+
});
213+
214+
it('Checking whether add, edit & delete namespace works', () => {
215+
// Navigating to the Add Namespace form
216+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
217+
// Adding a new namespace
218+
addDomainOrNamespace({ nameFieldValue: NAMESPACE_NAME });
219+
cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_ADD_SUCCESS);
220+
221+
// Selecting the created namespace from the accordion list items
222+
selectAccordionElement(true);
223+
// Editing the namespace
224+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_EDIT_NAMESPACE);
225+
// Checking if the Save button is disabled initially
226+
cy.getFormFooterButtonByTypeWithText({
227+
buttonText: SAVE_BUTTON_TEXT,
228+
buttonType: 'submit',
229+
}).should('be.disabled');
230+
cy.getFormInputFieldByIdAndType({ inputId: 'description' })
231+
.clear()
232+
.type(EDITED_DESCRIPTION);
233+
cy.getFormFooterButtonByTypeWithText({
234+
buttonText: SAVE_BUTTON_TEXT,
235+
buttonType: 'submit',
236+
})
237+
.should('be.enabled')
238+
.click();
239+
cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_SAVE_SUCCESS);
240+
241+
// Deleting the namespace
242+
cy.expect_browser_confirm_with_text({
243+
confirmTriggerFn: () =>
244+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_REMOVE_NAMESPACE),
245+
containsText: BROWSER_CONFIRM_REMOVE_MESSAGE,
246+
});
247+
cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_NAMESPACE_REMOVED);
248+
});
249+
250+
it('Checking whether creating a duplicate namespace is restricted', () => {
251+
/* TODO: DATA_SETUP - Use API for namespace setup, excluding the test meant to validate functionality via UI */
252+
// Navigating to the Add Namespace form
253+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
254+
// Adding a new namespace
255+
addDomainOrNamespace({ nameFieldValue: NAMESPACE_NAME });
256+
// Navigating to the Add Namespace form again
257+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_ADD_NEW_NAMESPACE);
258+
// Trying to add duplicate namespace
259+
addDomainOrNamespace({ nameFieldValue: NAMESPACE_NAME });
260+
cy.expect_flash(flashClassMap.error, FLASH_MESSAGE_NAME_ALREADY_EXISTS);
261+
262+
// Cancelling the form
263+
cy.getFormFooterButtonByTypeWithText({
264+
buttonText: CANCEL_BUTTON_TEXT,
265+
}).click();
266+
});
267+
268+
it('Checking whether Cancel & Reset buttons work fine in the Edit form', () => {
269+
// Create a namespace and open the edit form
270+
createNamespaceAndOpenEditForm();
271+
272+
/* Validating Reset button */
273+
// Checking if the Reset button is disabled initially
274+
cy.getFormFooterButtonByTypeWithText({
275+
buttonText: RESET_BUTTON_TEXT,
276+
}).should('be.disabled');
277+
// Editing name and description fields
278+
cy.getFormInputFieldByIdAndType({ inputId: 'name' })
279+
.clear()
280+
.type(EDITED_NAMESPACE_NAME);
281+
cy.getFormInputFieldByIdAndType({ inputId: 'description' })
282+
.clear()
283+
.type(EDITED_DESCRIPTION);
284+
// Resetting
285+
cy.getFormFooterButtonByTypeWithText({ buttonText: RESET_BUTTON_TEXT })
286+
.should('be.enabled')
287+
.click();
288+
cy.expect_flash(flashClassMap.warning, FLASH_MESSAGE_RESET_NAMESPACE);
289+
// Confirming the edited fields contain the old values after resetting
290+
cy.getFormInputFieldByIdAndType({ inputId: 'name' }).should(
291+
'have.value',
292+
NAMESPACE_NAME
293+
);
294+
cy.getFormInputFieldByIdAndType({ inputId: 'description' }).should(
295+
'have.value',
296+
DESCRIPTION
297+
);
298+
299+
/* Validating Cancel button */
300+
cy.getFormFooterButtonByTypeWithText({
301+
buttonText: CANCEL_BUTTON_TEXT,
302+
}).click();
303+
cy.expect_flash(flashClassMap.warning, FLASH_MESSAGE_CANCELLED);
304+
});
305+
306+
afterEach(() => {
307+
cy.url()
308+
?.then((url) => {
309+
// Ensures navigation to Automation -> Embedded Automate -> Explorer in the UI
310+
if (!url.endsWith(COMPONENT_ROUTE_URL)) {
311+
// Navigate to Automation -> Embedded Automate -> Explorer before cleanup
312+
cy.visit(COMPONENT_ROUTE_URL);
313+
}
314+
// Expand "Datastore" accordion if not already expanded
315+
cy.accordion(DATA_STORE_ACCORDION_LABEL);
316+
})
317+
.then(() => {
318+
cy.get('div.panel-collapse.collapse.in li.list-group-item').each(
319+
(item) => {
320+
const text = item?.text()?.trim();
321+
if (text === DOMAIN_NAME) {
322+
// Select the domain node if it hasn't been selected yet
323+
if (!item.hasClass('node-selected')) {
324+
cy.wrap(item).click();
325+
return false;
326+
}
327+
// Deleting the domain
328+
cy.expect_browser_confirm_with_text({
329+
confirmTriggerFn: () =>
330+
cy.toolbar(TOOLBAR_CONFIGURATION, TOOLBAR_REMOVE_DOMAIN),
331+
containsText: BROWSER_CONFIRM_REMOVE_MESSAGE,
332+
});
333+
}
334+
return null; // has no impact, just to get rid of eslint warning
335+
}
336+
);
337+
});
338+
});
339+
});

0 commit comments

Comments
 (0)