diff --git a/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js b/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js index ae7a932e724..3da98f4894c 100644 --- a/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js +++ b/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js @@ -1,480 +1,569 @@ /* eslint-disable no-undef */ import { flashClassMap } from '../../../../support/assertions/assertion_constants'; -const textConstants = { - // List items - schedulesAccordionItem: 'Schedules', - - // Field values - initialScheduleName: 'Test-name', - editedScheduleName: 'Dummy-name', - initialDescription: 'Test description', - editedDescription: 'Dummy description', - actionTypeVmAnalysis: 'vm', - actionTypeTemplateAnalysis: 'miq_template', - actionTypeHostAnalysis: 'host', - actionTypeContainerAnalysis: 'container_image', - actionTypeClusterAnalysis: 'emscluster', - actionTypeDataStoreAnalysis: 'storage', - actionTypeVmCompilanceCheck: 'vm_check_compliance', - actionTypeHostCompilanceCheck: 'host_check_compliance', - actionTypeContainerCompilanceCheck: 'container_image_check_compliance', - actionTypeAutomationTasks: 'automation_request', - filterTypeVmCluster: 'cluster', - timerTypeOnce: 'Once', - timerTypeHourly: 'Hourly', - timerTypeDaily: 'Daily', - timerTypeWeekly: 'Weekly', - timerTypeMonthly: 'Monthly', - frequencyTypeHour: '1 Hour', - timezoneTypeHawaii: '(GMT-10:00) Hawaii', - initialStartDate: '06/30/2025', - editedStartDate: '07/21/2025', - startTime: '11:23', - - // Buttons - saveButton: 'Save', - cancelButton: 'Cancel', - resetButton: 'Reset', - - // Config options - configToolbarButton: 'Configuration', - addScheduleConfigOption: 'Add a new Schedule', - deleteScheduleConfigOption: 'Delete this Schedule from the Database', - editScheduleConfigOption: 'Edit this Schedule', - disableScheduleConfigOption: 'Disable this Schedule', - enableScheduleConfigOption: 'Enable this Schedule', - queueScheduleConfigOption: 'Queue up this Schedule to run now', - - // Menu options - settingsMenuOption: 'Settings', - appSettingsMenuOption: 'Application Settings', - - // Flash message text snippets - flashMessageScheduleQueued: 'queued to run', - flashMessageOperationCanceled: 'cancelled', - flashMessageScheduleDisabled: 'disabled', - flashMessageScheduleEnabled: 'enabled', - flashMessageScheduleSaved: 'saved', - flashMessageResetSchedule: 'reset', - flashMessageScheduleDeleted: 'delete successful', - flashMessageFailedToAddSchedule: 'failed', - - // Browser alert text snippets - browserAlertDeleteConfirmText: 'will be permanently removed', -}; - -const { - settingsMenuOption, - appSettingsMenuOption, - actionTypeVmAnalysis, - actionTypeTemplateAnalysis, - actionTypeHostAnalysis, - actionTypeContainerAnalysis, - actionTypeClusterAnalysis, - actionTypeDataStoreAnalysis, - actionTypeVmCompilanceCheck, - actionTypeHostCompilanceCheck, - actionTypeContainerCompilanceCheck, - actionTypeAutomationTasks, - timerTypeOnce, - timerTypeHourly, - timerTypeDaily, - timerTypeWeekly, - timerTypeMonthly, - cancelButton, - saveButton, - initialScheduleName, - editScheduleConfigOption, - editedScheduleName, - editedDescription, - editedStartDate, - resetButton, - initialDescription, - initialStartDate, - disableScheduleConfigOption, - enableScheduleConfigOption, - queueScheduleConfigOption, - addScheduleConfigOption, - frequencyTypeHour, - timezoneTypeHawaii, - startTime, - deleteScheduleConfigOption, - schedulesAccordionItem, - configToolbarButton, - flashMessageScheduleQueued, - flashMessageOperationCanceled, - flashMessageScheduleDisabled, - flashMessageScheduleEnabled, - flashMessageScheduleSaved, - flashMessageResetSchedule, - flashMessageScheduleDeleted, - flashMessageFailedToAddSchedule, - browserAlertDeleteConfirmText, -} = textConstants; - -function selectConfigMenu(menuOption = addScheduleConfigOption) { - return cy.toolbar(configToolbarButton, menuOption); +// Component route url +const COMPONENT_ROUTE_URL = '/ops/explorer'; + +// List items +const SCHEDULES_ACCORDION_ITEM = 'Schedules'; +const MANAGEIQ_REGION_ACCORDION_ITEM = /^ManageIQ Region:/; + +// Field values +const BASIC_INFO_SUB_HEADER = 'Basic Information'; +const NAME_FIELD_LABEL = 'Name'; +const DESCRIPTION_FIELD_LABEL = 'Description'; +const ACTIVE_CHECKBOX_FIELD_LABEL = 'Active'; +const ACTION_TYPE_FIELD_LABEL = 'Action'; +const FILTER_TYPE_FIELD_LABEL = 'Filter'; +const ZONE_FIELD_LABEL = 'Zone'; +const OBJECT_DETAILS_SUB_HEADER = 'Object Details'; +const SYSTEM_FIELD_LABEL = 'System/Process'; +const MESSAGE_FIELD_LABEL = 'Message'; +const REQUEST_FIELD_LABEL = 'Request'; +const OBJECT_LABEL_TEXT = 'Object'; +const OBJECT_TYPE_FIELD_LABEL = 'Type'; +const OBJECT_TYPE_CLOUD_NETWORK = 'Cloud Network'; +const ATTRIBUTE_PAIRS_SUB_HEADER = 'Attribute/Value Pairs'; +const TIMER_TYPE_FIELD_LABEL = 'Run'; +const TIMER_VALUE_FIELD_LABEL = 'Every'; +const TIME_ZONE_FIELD_LABEL = 'Time Zone'; +const START_DATE_FIELD_LABEL = 'Starting Date'; +const START_TIME_FIELD_LABEL = 'Starting Time'; +const INITIAL_SCHEDULE_NAME = 'Test-name'; +const EDITED_SCHEDULE_NAME = 'Dummy-name'; +const INITIAL_DESCRIPTION = 'Test description'; +const EDITED_DESCRIPTION = 'Dummy description'; +const ACTION_TYPE_VM_ANALYSIS = 'vm'; +const ACTION_TYPE_TEMPLATE_ANALYSIS = 'miq_template'; +const ACTION_TYPE_HOST_ANALYSIS = 'host'; +const ACTION_TYPE_CONTAINER_ANALYSIS = 'container_image'; +const ACTION_TYPE_CLUSTER_ANALYSIS = 'emscluster'; +const ACTION_TYPE_DATA_STORE_ANALYSIS = 'storage'; +const ACTION_TYPE_VM_COMPILANCE_CHECK = 'vm_check_compliance'; +const ACTION_TYPE_HOST_COMPILANCE_CHECK = 'host_check_compliance'; +const ACTION_TYPE_CONTAINER_COMPILANCE_CHECK = + 'container_image_check_compliance'; +const ACTION_TYPE_AUTOMATION_TASKS = 'automation_request'; +const TIMER_TYPE_ONCE = 'Once'; +const TIMER_TYPE_HOURLY = 'Hourly'; +const TIMER_TYPE_DAILY = 'Daily'; +const TIMER_TYPE_WEEKLY = 'Weekly'; +const TIMER_TYPE_MONTHLY = 'Monthly'; +const FREQUENCY_TYPE_HOUR = '1 Hour'; +const TIME_ZONE_TYPE_HAWAII = '(GMT-10:00) Hawaii'; +const INITIAL_START_DATE = '06/30/2025'; +const EDITED_START_DATE = '07/21/2025'; +const START_TIME = '11:23'; + +// Buttons +const SAVE_BUTTON_TEXT = 'Save'; +const CANCEL_BUTTON_TEXT = 'Cancel'; +const RESET_BUTTON_TEXT = 'Reset'; + +// Config options +const CONFIG_TOOLBAR_BUTTON = 'Configuration'; +const ADD_SCHEDULE_CONFIG_OPTION = 'Add a new Schedule'; +const DELETE_SCHEDULE_CONFIG_OPTION = 'Delete this Schedule from the Database'; +const EDIT_SCHEDULE_CONFIG_OPTION = 'Edit this Schedule'; +const DISABLE_SCHEDULE_CONFIG_OPTION = 'Disable this Schedule'; +const ENABLE_SCHEDULE_CONFIG_OPTION = 'Enable this Schedule'; +const QUEUE_SCHEDULE_CONFIG_OPTION = 'Queue up this Schedule to run now'; + +// Menu options +const SETTINGS_OPTION = 'Settings'; +const APP_SETTINGS_OPTION = 'Application Settings'; + +// Flash message text snippets +const FLASH_MESSAGE_SCHEDULE_QUEUED = 'queued'; +const FLASH_MESSAGE_OPERATION_CANCELED = 'cancel'; +const FLASH_MESSAGE_SCHEDULE_DISABLED = 'disabled'; +const FLASH_MESSAGE_SCHEDULE_ENABLED = 'enabled'; +const FLASH_MESSAGE_SCHEDULE_SAVED = 'saved'; +const FLASH_MESSAGE_RESET_SCHEDULE = 'reset'; +const FLASH_MESSAGE_SCHEDULE_DELETED = 'delete'; +const FLASH_MESSAGE_FAILED_TO_ADD_SCHEDULE = 'failed'; + +// Browser alert text snippets +const BROWSER_ALERT_DELETE_CONFIRM_TEXT = 'removed'; + +function selectConfigMenu(menuOption) { + return cy.toolbar(CONFIG_TOOLBAR_BUTTON, menuOption); } function addSchedule() { - selectConfigMenu(); - // Checks if Save button is disabled initially - cy.contains( - '#main-content .bx--btn-set button[type="submit"]', - saveButton - ).should('be.disabled'); - // Adding data - cy.get('input#name').type(initialScheduleName); - cy.get('input#description').type(initialDescription); - cy.get('input[type="checkbox"]#enabled').check({ force: true }); - // Select Action type option: 'VM Analysis' - cy.get('select#action_typ').select(actionTypeVmAnalysis); - // Select Filter type option: 'A Single VM' - cy.get('select#filter_typ').select(actionTypeVmAnalysis); - // Select Run option: 'Hours' - cy.get('select#timer_typ').select(timerTypeHourly); - // Select Every option: '1 Hour' - cy.get('select#timer_value').select(frequencyTypeHour); - // Select Time zone option: '(GMT-10:00) Hawaii' - cy.get('input[role="combobox"]#time_zone').click(); - cy.contains('[role="option"]', timezoneTypeHawaii) - .should('be.visible') - .click(); - cy.get('input#start_date').type(initialStartDate); - cy.get('input#start_time').type(startTime); - // Intercepting the API call for adding a new schedule - cy.intercept('POST', '/ops/schedule_edit/new?button=save').as( - 'addScheduleApi' + selectConfigMenu(ADD_SCHEDULE_CONFIG_OPTION); + cy.getFormFooterButtonByTypeWithText({ + buttonText: SAVE_BUTTON_TEXT, + buttonType: 'submit', + }).should('be.disabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'name' }).type( + INITIAL_SCHEDULE_NAME ); - cy.contains('#main-content .bx--btn-set button[type="submit"]', saveButton) - .should('be.enabled') // Checks if Save button is enabled once all required fields are filled - .click(); - // Wait for the API call to complete - cy.wait('@addScheduleApi'); -} - -function deleteSchedule(scheduleName = initialScheduleName) { - // Selecting the schedule and intercepting the API call to get schedule details - interceptGetScheduleDetailsApi(scheduleName); - // Listening for the browser confirm alert and confirming deletion - cy.expect_browser_confirm_with_text({ - confirmTriggerFn: () => selectConfigMenu(deleteScheduleConfigOption), - containsText: browserAlertDeleteConfirmText, - }); - cy.expect_flash(flashClassMap.success, flashMessageScheduleDeleted); -} - -function interceptGetScheduleDetailsApi(scheduleName = initialScheduleName) { - // Flag to check if the request is fired - let requestFired = false; - // Intercepting the API call - cy.intercept( - { - method: 'POST', - pathname: '/ops/tree_select', - query: { text: scheduleName }, - }, - // This callback function will be called when the request is fired, - // from which the requestFired flag will be set to true - () => (requestFired = true) - ).as('getCreatedScheduleApi'); - // Triggering the action that will fire the API call, - // which is selecting the created schedule - cy.accordionItem(scheduleName); - // Wait for the API call to complete if it was fired - // This is to ensure that the test does not fail if the request was not fired - cy.then(() => { - // If the request was fired, wait for the alias - if (requestFired) { - cy.wait('@getCreatedScheduleApi'); - } + cy.getFormInputFieldByIdAndType({ inputId: 'description' }).type( + INITIAL_DESCRIPTION + ); + cy.getFormLabelByForAttribute({ forValue: 'enabled' }).click(); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_VM_ANALYSIS + ); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }).select( + ACTION_TYPE_VM_ANALYSIS + ); + cy.getFormSelectFieldById({ selectId: 'timer_typ' }).select( + TIMER_TYPE_HOURLY + ); + cy.getFormSelectFieldById({ selectId: 'timer_value' }).select( + FREQUENCY_TYPE_HOUR + ); + cy.getFormInputFieldByIdAndType({ inputId: 'time_zone' }).click(); + cy.contains('[role="option"]', TIME_ZONE_TYPE_HAWAII).click(); + cy.getFormInputFieldByIdAndType({ inputId: 'start_date' }).type( + INITIAL_START_DATE + ); + cy.getFormInputFieldByIdAndType({ inputId: 'start_time' }).type(START_TIME); + cy.interceptApi({ + alias: 'addScheduleApi', + urlPattern: '/ops/schedule_edit/new?button=save', + triggerFn: () => + cy + .getFormFooterButtonByTypeWithText({ + buttonText: SAVE_BUTTON_TEXT, + buttonType: 'submit', + }) + .should('be.enabled') // Checks if Save button is enabled once all required fields are filled + .click(), }); -} - -function invokeCleanupDeletion() { - // Iterate and clean up any leftover schedules created during the test - cy.get('li.list-group-item').each(($el) => { - const text = $el?.text()?.trim(); - if (text === initialScheduleName) { - deleteSchedule(); - return false; - } - if (text === editedScheduleName) { - deleteSchedule(editedScheduleName); - return false; - } - return true; + return cy.then(() => { + return INITIAL_SCHEDULE_NAME; }); } -function verifyFilterTypeDropdownExists() { - cy.get('label[for="filter_typ"]').should('exist'); - cy.get('select#filter_typ').should('exist'); +function clickScheduleItem(scheduleName) { + cy.selectAccordionItem([ + MANAGEIQ_REGION_ACCORDION_ITEM, + SCHEDULES_ACCORDION_ITEM, + scheduleName, + ]); } -function verifyTimerDropdownExists() { - cy.get('label[for="timer_value"]').should('exist'); - cy.get('select#timer_value').should('exist'); +function deleteSchedule(scheduleName) { + clickScheduleItem(scheduleName); + cy.expect_browser_confirm_with_text({ + confirmTriggerFn: () => selectConfigMenu(DELETE_SCHEDULE_CONFIG_OPTION), + containsText: BROWSER_ALERT_DELETE_CONFIRM_TEXT, + }); + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_SCHEDULE_DELETED); } describe('Automate Schedule form operations: Settings > Application Settings > Settings > Schedules > Configuration > Add a new schedule', () => { beforeEach(() => { cy.login(); - cy.menu(settingsMenuOption, appSettingsMenuOption); - cy.intercept( - { - method: 'POST', - pathname: '/ops/tree_select', - query: { text: schedulesAccordionItem }, - }, - ).as('getSchedules'); - cy.accordionItem(schedulesAccordionItem); - cy.wait('@getSchedules'); + cy.menu(SETTINGS_OPTION, APP_SETTINGS_OPTION); + cy.accordion(SETTINGS_OPTION); + cy.selectAccordionItem([ + MANAGEIQ_REGION_ACCORDION_ITEM, + SCHEDULES_ACCORDION_ITEM, + ]); }); - it('Validate visibility of elements based on dropdown selections', () => { - selectConfigMenu(); + it('Validate visibility of elements and dynamic rendering based on dropdown changes', () => { + selectConfigMenu(ADD_SCHEDULE_CONFIG_OPTION); + cy.contains('h3', BASIC_INFO_SUB_HEADER).should('be.visible'); + cy.getFormLabelByForAttribute({ forValue: 'name' }) + .should('be.visible') + .and('contain.text', NAME_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'name' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'description' }) + .should('be.visible') + .and('contain.text', DESCRIPTION_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'description' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'enabled' }) + .should('be.visible') + .and('contain.text', ACTIVE_CHECKBOX_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ + inputId: 'enabled', + inputType: 'checkbox', + }) + .should('be.visible') + .and('be.enabled'); /* ===== Selecting any option other than "Automation Tasks" from "Action" dropdown does not hide the Filter dropdown ===== */ - - cy.get('select#action_typ').select(actionTypeVmAnalysis); - cy.get('select#action_typ').should('have.value', actionTypeVmAnalysis); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeTemplateAnalysis); - cy.get('select#action_typ').should( - 'have.value', - actionTypeTemplateAnalysis + cy.getFormLabelByForAttribute({ forValue: 'action_typ' }) + .should('be.visible') + .and('contain.text', ACTION_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'action_typ' }) + .should('be.visible') + .and('be.enabled') + .select(ACTION_TYPE_VM_ANALYSIS); + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_TEMPLATE_ANALYSIS ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeHostAnalysis); - cy.get('select#action_typ').should('have.value', actionTypeHostAnalysis); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeContainerAnalysis); - cy.get('select#action_typ').should( - 'have.value', - actionTypeContainerAnalysis + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_HOST_ANALYSIS ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeClusterAnalysis); - cy.get('select#action_typ').should('have.value', actionTypeClusterAnalysis); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeDataStoreAnalysis); - cy.get('select#action_typ').should( - 'have.value', - actionTypeDataStoreAnalysis + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_CONTAINER_ANALYSIS ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeVmCompilanceCheck); - cy.get('select#action_typ').should( - 'have.value', - actionTypeVmCompilanceCheck + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_CLUSTER_ANALYSIS ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - cy.get('select#action_typ').select(actionTypeHostCompilanceCheck); - cy.get('select#action_typ').should( - 'have.value', - actionTypeHostCompilanceCheck + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_DATA_STORE_ANALYSIS + ); + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_VM_COMPILANCE_CHECK + ); + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_HOST_COMPILANCE_CHECK + ); + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_CONTAINER_COMPILANCE_CHECK + ); + cy.getFormLabelByForAttribute({ forValue: 'filter_typ' }) + .should('be.visible') + .and('contain.text', FILTER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'filter_typ' }) + .should('be.visible') + .and('be.enabled'); + + /* ===== Selecting "Automation Tasks" option from "Action" dropdown should show Zone, Object details & Object fields ===== */ + cy.getFormSelectFieldById({ selectId: 'action_typ' }).select( + ACTION_TYPE_AUTOMATION_TASKS + ); + cy.getFormLabelByForAttribute({ forValue: 'zone_id' }) + .should('be.visible') + .and('contain.text', ZONE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'zone_id' }) + .should('be.visible') + .and('be.enabled'); + + // Verifying Object Details fields + cy.contains('h3[name="object_details"]', OBJECT_DETAILS_SUB_HEADER).should( + 'be.visible' + ); + cy.getFormLabelByForAttribute({ forValue: 'instance_name' }) + .should('be.visible') + .and('contain.text', SYSTEM_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'instance_name' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'message' }) + .should('be.visible') + .and('contain.text', MESSAGE_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'message' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'request' }) + .should('be.visible') + .and('contain.text', REQUEST_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'request' }) + .should('be.visible') + .and('be.enabled'); + + // Verifying Object fields + cy.contains('h3[name="object_attributes"]', OBJECT_LABEL_TEXT).should( + 'be.visible' + ); + cy.getFormLabelByForAttribute({ forValue: 'target_class' }) + .should('be.visible') + .and('contain.text', OBJECT_TYPE_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'target_class' }) + .should('be.visible') + .and('be.enabled') + .click(); + cy.contains('[role="option"]', OBJECT_TYPE_CLOUD_NETWORK).click(); + cy.getFormLabelByForAttribute({ forValue: 'target_id' }) + .should('be.visible') + .and('contain.text', OBJECT_LABEL_TEXT); + cy.getFormInputFieldByIdAndType({ inputId: 'target_id' }) + .should('be.visible') + .and('be.enabled'); + + // Verifying Attribute/Value pairs fields + cy.contains('h3', ATTRIBUTE_PAIRS_SUB_HEADER).should('be.visible'); + cy.getFormInputFieldByIdAndType({ inputId: 'attribute_1' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'value_1' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'attribute_2' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'value_2' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'attribute_3' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'value_3' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'attribute_4' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'value_4' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'attribute_5' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormInputFieldByIdAndType({ inputId: 'value_5' }) + .should('be.visible') + .and('be.enabled'); + + /* ===== Selecting "Once" option from "Run" dropdown should not show "Every" dropdown ===== */ + cy.getFormLabelByForAttribute({ forValue: 'timer_typ' }) + .should('be.visible') + .and('contain.text', TIMER_TYPE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'timer_typ' }) + .should('be.visible') + .and('be.enabled') + .select(TIMER_TYPE_ONCE); + cy.getFormInputFieldByIdAndType({ inputId: 'timer_value' }).should( + 'not.exist' ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - cy.get('select#action_typ').select(actionTypeContainerCompilanceCheck); - cy.get('select#action_typ').should( - 'have.value', - actionTypeContainerCompilanceCheck + /* ===== Selecting any other option other than "Once" from "Run" dropdown should show "Every" dropdown ===== */ + cy.getFormSelectFieldById({ selectId: 'timer_typ' }).select( + TIMER_TYPE_HOURLY ); - // Checking for Filter type dropdown - verifyFilterTypeDropdownExists(); - - /* ===== Selecting "Automation Tasks" option from "Action" dropdown shows Zone, Object details & Object fields ===== */ - - cy.get('select#action_typ').select(actionTypeAutomationTasks); - cy.get('select#action_typ').should('have.value', actionTypeAutomationTasks); - - // Checking for Zone dropdown - cy.get('label[for="zone_id"]').should('exist'); - cy.get('select#zone_id').should('exist'); - - // Checking for Object Details - cy.get('h3[name="object_details"]').should('exist'); - // Checking for System/Process dropdown - cy.get('label[for="instance_name"]').should('exist'); - cy.get('select#instance_name').should('exist'); - // Checking for Messsage textfield - cy.get('label[for="message"]').should('exist'); - cy.get('input#message').should('exist'); - // Checking for Request textfield - cy.get('label[for="request"]').should('exist'); - cy.get('input#request').should('exist'); - - // Checking for Object - cy.get('h3[name="object_attributes"]').should('exist'); - // Checking for Type Combobox - cy.get('label[for="target_class"]').should('exist'); - cy.get('input[role="combobox"]#target_class').should('exist'); - // Checking for Object Combobox - cy.get('label[for="target_id"]').should('exist'); - cy.get('input[role="combobox"]#target_id').should('exist'); - - // Checking for Attribute/Value pairs - cy.contains('h3', 'Attribute/Value Pairs').should('exist'); - // Checking for 5 attribute-value pairs text fields - cy.get('input#attribute_1').should('exist'); - cy.get('input#value_1').should('exist'); - cy.get('input#attribute_2').should('exist'); - cy.get('input#value_2').should('exist'); - cy.get('input#attribute_3').should('exist'); - cy.get('input#value_3').should('exist'); - cy.get('input#attribute_4').should('exist'); - cy.get('input#value_4').should('exist'); - cy.get('input#attribute_5').should('exist'); - cy.get('input#value_5').should('exist'); - - /* ===== Selecting "Once" option from "Run" dropdown does not show the "Every" dropdown ===== */ - - cy.get('select#timer_typ').select(timerTypeOnce); - // Checking whether the Every dropdown is hidden - cy.get('input#timer_value').should('not.exist'); - - /* ===== Selecting any other option other than "Once" from "Run" dropdown shows the "Every" dropdown ===== */ - - cy.get('select#timer_typ').select(timerTypeHourly); - // Checking whether the "Every" dropdown exist - verifyTimerDropdownExists(); - - cy.get('select#timer_typ').select(timerTypeDaily); - // Checking whether the "Every" dropdown exist - verifyTimerDropdownExists(); - - cy.get('select#timer_typ').select(timerTypeWeekly); - // Checking whether the "Every" dropdown exist - verifyTimerDropdownExists(); - - cy.get('select#timer_typ').select(timerTypeMonthly); - // Checking whether the "Every" dropdown exist - verifyTimerDropdownExists(); + cy.getFormLabelByForAttribute({ forValue: 'timer_value' }) + .should('be.visible') + .and('contain.text', TIMER_VALUE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'timer_value' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'timer_typ' }).select( + TIMER_TYPE_DAILY + ); + cy.getFormLabelByForAttribute({ forValue: 'timer_value' }) + .should('be.visible') + .and('contain.text', TIMER_VALUE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'timer_value' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'timer_typ' }).select( + TIMER_TYPE_WEEKLY + ); + cy.getFormLabelByForAttribute({ forValue: 'timer_value' }) + .should('be.visible') + .and('contain.text', TIMER_VALUE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'timer_value' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormSelectFieldById({ selectId: 'timer_typ' }).select( + TIMER_TYPE_MONTHLY + ); + cy.getFormLabelByForAttribute({ forValue: 'timer_value' }) + .should('be.visible') + .and('contain.text', TIMER_VALUE_FIELD_LABEL); + cy.getFormSelectFieldById({ selectId: 'timer_value' }) + .should('be.visible') + .and('be.enabled'); + + cy.getFormLabelByForAttribute({ forValue: 'time_zone' }) + .should('be.visible') + .and('contain.text', TIME_ZONE_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'time_zone' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'start_date' }) + .should('be.visible') + .and('contain.text', START_DATE_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'start_date' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormLabelByForAttribute({ forValue: 'start_time' }) + .should('be.visible') + .and('contain.text', START_TIME_FIELD_LABEL); + cy.getFormInputFieldByIdAndType({ inputId: 'start_time' }) + .should('be.visible') + .and('be.enabled'); + cy.getFormFooterButtonByTypeWithText({ + buttonText: SAVE_BUTTON_TEXT, + buttonType: 'submit', + }) + .should('be.visible') + .and('be.disabled'); + cy.getFormFooterButtonByTypeWithText({ buttonText: CANCEL_BUTTON_TEXT }) + .should('be.visible') + .and('be.enabled'); }); it('Checking whether Cancel button works on the Add form', () => { - selectConfigMenu(); - cy.contains( - '#main-content .bx--btn-set button[type="button"]', - cancelButton - ) - .should('be.enabled') - .click(); - cy.expect_flash(flashClassMap.success, flashMessageOperationCanceled); + selectConfigMenu(ADD_SCHEDULE_CONFIG_OPTION); + cy.getFormFooterButtonByTypeWithText({ + buttonText: CANCEL_BUTTON_TEXT, + }).click(); + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_OPERATION_CANCELED); }); it('Checking whether add, edit & delete schedule works', () => { - /* ===== Adding a schedule ===== */ - addSchedule(); - cy.expect_flash(flashClassMap.success, flashMessageScheduleSaved); - - /* ===== Editing a schedule ===== */ - // Selecting the schedule and intercepting the API call to get schedule details - interceptGetScheduleDetailsApi(); - selectConfigMenu(editScheduleConfigOption); - // Editing name and description - cy.get('input#name').clear().type(editedScheduleName); - cy.get('input#description').clear().type(editedDescription); - // Confirms Save button is enabled after making edits - cy.contains('#main-content .bx--btn-set button[type="submit"]', saveButton) + addSchedule().then((createdScheduleName) => { + // createdScheduleName value will be "Test-name" + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_SCHEDULE_SAVED); + clickScheduleItem(createdScheduleName); + }); + + selectConfigMenu(EDIT_SCHEDULE_CONFIG_OPTION); + cy.getFormInputFieldByIdAndType({ inputId: 'name' }) + .clear() + .type(EDITED_SCHEDULE_NAME); + cy.getFormInputFieldByIdAndType({ inputId: 'description' }) + .clear() + .type(EDITED_DESCRIPTION); + cy.getFormFooterButtonByTypeWithText({ + buttonText: SAVE_BUTTON_TEXT, + buttonType: 'submit', + }) .should('be.enabled') .click(); - cy.expect_flash(flashClassMap.success, flashMessageScheduleSaved); + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_SCHEDULE_SAVED); /* ===== Delete is already handled from afterEach hook ===== */ }); it('Checking whether Cancel & Reset buttons work fine in the Edit form', () => { - /* ===== Adding a schedule ===== */ - addSchedule(); - - /* ===== Checking whether Cancel button works ===== */ - // Selecting the schedule and intercepting the API call to get schedule details - interceptGetScheduleDetailsApi(); - selectConfigMenu(editScheduleConfigOption); - cy.contains( - '#main-content .bx--btn-set button[type="button"]', - cancelButton - ) - .should('be.enabled') - .click(); - cy.expect_flash(flashClassMap.success, flashMessageOperationCanceled); + addSchedule().then((createdScheduleName) => { + // createdScheduleName value will be "Test-name" + clickScheduleItem(createdScheduleName); + }); /* ===== Checking whether Reset button works ===== */ - // Selecting the schedule and intercepting the API call to get schedule details - interceptGetScheduleDetailsApi(); - selectConfigMenu(editScheduleConfigOption); - // Editing description and start date - cy.get('input#description').clear().type(editedDescription); - cy.get('input#start_date').clear().type(editedStartDate); - cy.contains('#main-content .bx--btn-set button[type="button"]', resetButton) + selectConfigMenu(EDIT_SCHEDULE_CONFIG_OPTION); + cy.getFormInputFieldByIdAndType({ inputId: 'description' }) + .clear() + .type(EDITED_DESCRIPTION); + cy.getFormInputFieldByIdAndType({ inputId: 'start_date' }) + .clear() + .type(EDITED_START_DATE); + cy.getFormFooterButtonByTypeWithText({ buttonText: RESET_BUTTON_TEXT }) .should('be.enabled') .click(); - cy.expect_flash(flashClassMap.warning, flashMessageResetSchedule); - // Confirming the edited fields contain the old values after resetting - cy.get('input#description').should('have.value', initialDescription); - cy.get('input#start_date').should('have.value', initialStartDate); + cy.expect_flash(flashClassMap.warning, FLASH_MESSAGE_RESET_SCHEDULE); + cy.getFormInputFieldByIdAndType({ inputId: 'description' }).should( + 'have.value', + INITIAL_DESCRIPTION + ); + cy.getFormInputFieldByIdAndType({ inputId: 'start_date' }).should( + 'have.value', + INITIAL_START_DATE + ); - // Selecting Schedules menu item to bypass a bug, can be removed once #9505 is merged - cy.accordionItem(schedulesAccordionItem); + /* ===== Checking whether Cancel button works ===== */ + cy.getFormFooterButtonByTypeWithText({ + buttonText: CANCEL_BUTTON_TEXT, + }).click(); + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_OPERATION_CANCELED); }); it('Checking whether creating a duplicate record is restricted', () => { - /* ===== Adding schedule ===== */ addSchedule(); - - /* ===== Trying to add the same schedule again ===== */ addSchedule(); - cy.expect_flash(flashClassMap.error, flashMessageFailedToAddSchedule); + cy.expect_flash(flashClassMap.error, FLASH_MESSAGE_FAILED_TO_ADD_SCHEDULE); }); it('Checking whether Disabling, Enabling & Queueing up the schedule works', () => { - /* ===== Adding a schedule ===== */ addSchedule(); - // Selecting the schedule and intercepting the API call to get schedule details - interceptGetScheduleDetailsApi(); + clickScheduleItem(INITIAL_SCHEDULE_NAME); /* ===== Disabling the schedule ===== */ - selectConfigMenu(disableScheduleConfigOption); - cy.expect_flash(flashClassMap.info, flashMessageScheduleDisabled); + selectConfigMenu(DISABLE_SCHEDULE_CONFIG_OPTION); + cy.expect_flash(flashClassMap.info, FLASH_MESSAGE_SCHEDULE_DISABLED); /* ===== Enabling the schedule ===== */ - selectConfigMenu(enableScheduleConfigOption); - cy.expect_flash(flashClassMap.info, flashMessageScheduleEnabled); + selectConfigMenu(ENABLE_SCHEDULE_CONFIG_OPTION); + cy.expect_flash(flashClassMap.info, FLASH_MESSAGE_SCHEDULE_ENABLED); /* ===== Queueing-up the schedule ===== */ - selectConfigMenu(queueScheduleConfigOption); - cy.expect_flash(flashClassMap.success, flashMessageScheduleQueued); + selectConfigMenu(QUEUE_SCHEDULE_CONFIG_OPTION); + cy.expect_flash(flashClassMap.success, FLASH_MESSAGE_SCHEDULE_QUEUED); }); afterEach(() => { - cy?.url()?.then((url) => { - // Ensures navigation to Settings -> Application-Settings in the UI - if (url?.includes('/ops/explorer')) { - invokeCleanupDeletion(); - } else { - // Navigate to Settings -> Application-Settings before looking out for Schedules created during test - cy.menu(settingsMenuOption, appSettingsMenuOption); - invokeCleanupDeletion(); - } - }); + cy.url() + .then((url) => { + // Ensures navigation to Settings -> Application-Settings in the UI + if (!url.endsWith(COMPONENT_ROUTE_URL)) { + cy.visit(COMPONENT_ROUTE_URL); + } + cy.accordion(SETTINGS_OPTION); + }) + .then(() => { + // Iterate and clean up any leftover schedules created during the test + cy.get('div.panel-collapse.collapse.in li.list-group-item').each( + (item) => { + const text = item.text().trim(); + if ( + text === INITIAL_SCHEDULE_NAME || + text === EDITED_SCHEDULE_NAME + ) { + if (!item.hasClass('node-selected')) { + cy.wrap(item).click(); + } + cy.expect_browser_confirm_with_text({ + confirmTriggerFn: () => + selectConfigMenu(DELETE_SCHEDULE_CONFIG_OPTION), + containsText: BROWSER_ALERT_DELETE_CONFIRM_TEXT, + }); + return false; // exit iteration + } + return null; // has no impact, just to get rid of eslint warning + } + ); + }); }); });