Skip to content

Commit f47d71d

Browse files
Added automated tests with cypress for Namespace form
1 parent 2729d56 commit f47d71d

File tree

1 file changed

+317
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)