diff --git a/cypress/README.md b/cypress/README.md index 25c311b5cc6..e71c506074e 100644 --- a/cypress/README.md +++ b/cypress/README.md @@ -76,5 +76,5 @@ ManageIQ implements the following cypress extensions: * `cy.expect_show_list_title(title)` - check the title on a show\_list screen matches the provided title. `title`: String for the title. * `cy.expect_search_box()` - check if searchbox is present on the screen. * `cy.expect_text(element, text)` - check if the text in the element found by doing cy.get on the element String matches the provided text. `element`: String for the Cypress selector to get a specific element on the screen. `text`: String for the text that should be found within the selected element. -* `cy.expect_flash(flashType, containsText)` - command to validate flash messages. `flashType` is the type of flash (success, warning, error, info). `containsText` is the optional text that the flash-message should contain. e.g. `expect_flash('warning', 'cancelled');` +* `cy.expect_flash(flashType, containsText)` - command to validate flash messages. `flashType` is the type of flash. It is recommended to use values from `flashClassMap`.`containsText` is the optional text that the flash-message should contain. e.g. `expect_flash(flashClassMap.warning, 'cancelled');` * `cy.expect_browser_confirm_with_text({ confirmTriggerFn, containsText, proceed })` - command to validate browser confirm alerts. `confirmTriggerFn` is the function that triggers the confirm dialog. This function **must return a Cypress.Chainable**, like `cy.get(...).click()` so that Cypress can properly wait and chain .then() afterward. `containsText` is the optional text that the confirm alert should contain. `proceed` is the flag to determine whether to proceed with the confirm (true = OK, false = Cancel). e.g. `cy.expect_browser_confirm_with_text({containsText: 'sure to proceed?', proceed: true, confirmTriggerFn: () => { return cy.get('[data-testid="delete"]').click()}});`, `cy.expect_browser_confirm_with_text({ confirmTriggerFn: () => cy.contains('deleted').click()});` \ No newline at end of file diff --git a/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js b/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js index 2503af6b5de..ae7a932e724 100644 --- a/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js +++ b/cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js @@ -1,4 +1,5 @@ /* eslint-disable no-undef */ +import { flashClassMap } from '../../../../support/assertions/assertion_constants'; const textConstants = { // List items @@ -49,12 +50,6 @@ const textConstants = { settingsMenuOption: 'Settings', appSettingsMenuOption: 'Application Settings', - // Flash message types - flashTypeSuccess: 'success', - flashTypeWarning: 'warning', - flashTypeError: 'error', - flashTypeInfo: 'info', - // Flash message text snippets flashMessageScheduleQueued: 'queued to run', flashMessageOperationCanceled: 'cancelled', @@ -107,10 +102,6 @@ const { deleteScheduleConfigOption, schedulesAccordionItem, configToolbarButton, - flashTypeSuccess, - flashTypeWarning, - flashTypeError, - flashTypeInfo, flashMessageScheduleQueued, flashMessageOperationCanceled, flashMessageScheduleDisabled, @@ -171,7 +162,7 @@ function deleteSchedule(scheduleName = initialScheduleName) { confirmTriggerFn: () => selectConfigMenu(deleteScheduleConfigOption), containsText: browserAlertDeleteConfirmText, }); - cy.expect_flash(flashTypeSuccess, flashMessageScheduleDeleted); + cy.expect_flash(flashClassMap.success, flashMessageScheduleDeleted); } function interceptGetScheduleDetailsApi(scheduleName = initialScheduleName) { @@ -387,13 +378,13 @@ describe('Automate Schedule form operations: Settings > Application Settings > S ) .should('be.enabled') .click(); - cy.expect_flash(flashTypeSuccess, flashMessageOperationCanceled); + cy.expect_flash(flashClassMap.success, flashMessageOperationCanceled); }); it('Checking whether add, edit & delete schedule works', () => { /* ===== Adding a schedule ===== */ addSchedule(); - cy.expect_flash(flashTypeSuccess, flashMessageScheduleSaved); + cy.expect_flash(flashClassMap.success, flashMessageScheduleSaved); /* ===== Editing a schedule ===== */ // Selecting the schedule and intercepting the API call to get schedule details @@ -406,7 +397,7 @@ describe('Automate Schedule form operations: Settings > Application Settings > S cy.contains('#main-content .bx--btn-set button[type="submit"]', saveButton) .should('be.enabled') .click(); - cy.expect_flash(flashTypeSuccess, flashMessageScheduleSaved); + cy.expect_flash(flashClassMap.success, flashMessageScheduleSaved); /* ===== Delete is already handled from afterEach hook ===== */ }); @@ -425,7 +416,7 @@ describe('Automate Schedule form operations: Settings > Application Settings > S ) .should('be.enabled') .click(); - cy.expect_flash(flashTypeSuccess, flashMessageOperationCanceled); + cy.expect_flash(flashClassMap.success, flashMessageOperationCanceled); /* ===== Checking whether Reset button works ===== */ // Selecting the schedule and intercepting the API call to get schedule details @@ -437,7 +428,7 @@ describe('Automate Schedule form operations: Settings > Application Settings > S cy.contains('#main-content .bx--btn-set button[type="button"]', resetButton) .should('be.enabled') .click(); - cy.expect_flash(flashTypeWarning, flashMessageResetSchedule); + 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); @@ -452,7 +443,7 @@ describe('Automate Schedule form operations: Settings > Application Settings > S /* ===== Trying to add the same schedule again ===== */ addSchedule(); - cy.expect_flash(flashTypeError, flashMessageFailedToAddSchedule); + cy.expect_flash(flashClassMap.error, flashMessageFailedToAddSchedule); }); it('Checking whether Disabling, Enabling & Queueing up the schedule works', () => { @@ -463,15 +454,15 @@ describe('Automate Schedule form operations: Settings > Application Settings > S /* ===== Disabling the schedule ===== */ selectConfigMenu(disableScheduleConfigOption); - cy.expect_flash(flashTypeInfo, flashMessageScheduleDisabled); + cy.expect_flash(flashClassMap.info, flashMessageScheduleDisabled); /* ===== Enabling the schedule ===== */ selectConfigMenu(enableScheduleConfigOption); - cy.expect_flash(flashTypeInfo, flashMessageScheduleEnabled); + cy.expect_flash(flashClassMap.info, flashMessageScheduleEnabled); /* ===== Queueing-up the schedule ===== */ selectConfigMenu(queueScheduleConfigOption); - cy.expect_flash(flashTypeSuccess, flashMessageScheduleQueued); + cy.expect_flash(flashClassMap.success, flashMessageScheduleQueued); }); afterEach(() => { diff --git a/cypress/support/assertions/assertion_constants.js b/cypress/support/assertions/assertion_constants.js index f55e7fe77c7..cda0959c082 100644 --- a/cypress/support/assertions/assertion_constants.js +++ b/cypress/support/assertions/assertion_constants.js @@ -1,3 +1,10 @@ +/** + * Map of flash message types to their corresponding CSS class names. + * Used by the expect_flash command to validate flash messages. + * @example + * cy.expect_flash(flashClassMap.success); + * cy.expect_flash(flashClassMap.error, 'failed'); + */ export const flashClassMap = { warning: 'warning', error: 'danger', diff --git a/cypress/support/assertions/expect_alerts.js b/cypress/support/assertions/expect_alerts.js index ea73136a002..c5668ce8596 100644 --- a/cypress/support/assertions/expect_alerts.js +++ b/cypress/support/assertions/expect_alerts.js @@ -3,26 +3,39 @@ import { flashClassMap } from './assertion_constants'; /** * Custom Cypress command to validate flash messages. - * @param {string} flashType - Type of flash (success, warning, error, info). + * @param {string} flashType - Type of flash. Use values from flashClassMap (e.g., flashClassMap.success, flashClassMap.error). * @param {string} [containsText] - Optional text that the flash-message should contain. * @returns {Cypress.Chainable} - The flash-message element if found, or an assertion failure. + * @example + * cy.expect_flash(flashClassMap.success); + * cy.expect_flash(flashClassMap.error, 'failed'); */ Cypress.Commands.add( 'expect_flash', (flashType = flashClassMap.success, containsText) => { - const flashMessageClassName = flashClassMap[flashType] || flashClassMap.success; - const flashMessageElement = cy - .get(`#main_div #flash_msg_div .alert-${flashMessageClassName}`) - .should('be.visible'); + if (Object.values(flashClassMap).includes(flashType)) { + const flashMessageElement = cy + .get(`#main_div #flash_msg_div .alert-${flashType}`) + .should('be.visible'); - if (containsText) { - return flashMessageElement.should(($el) => { - const actualText = $el.text().toLowerCase(); - expect(actualText).to.include(containsText.toLowerCase()); - }); + if (containsText) { + return flashMessageElement.should((flash) => { + const actualText = flash.text().toLowerCase(); + expect(actualText).to.include(containsText.toLowerCase()); + }); + } + + return flashMessageElement; } - return flashMessageElement; + // If an invalid flash type is passed, throw an error + cy.logAndThrowError( + `Invalid flash type: "${flashType}". Valid flash types are: ${Object.values( + flashClassMap + ).join( + ', ' + )}. It is recommended to use flashClassMap values (e.g., flashClassMap.error, flashClassMap.success) to pass flash types.` + ); } );