Skip to content

Commit 13eb407

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

File tree

1 file changed

+308
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)