Skip to content

Commit 6473364

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

File tree

1 file changed

+310
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)