Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cypress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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()});`
31 changes: 11 additions & 20 deletions cypress/e2e/ui/Settings/Application-Settings/schedule.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-undef */
import { flashClassMap } from '../../../../support/assertions/assertion_constants';

const textConstants = {
// List items
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -107,10 +102,6 @@ const {
deleteScheduleConfigOption,
schedulesAccordionItem,
configToolbarButton,
flashTypeSuccess,
flashTypeWarning,
flashTypeError,
flashTypeInfo,
flashMessageScheduleQueued,
flashMessageOperationCanceled,
flashMessageScheduleDisabled,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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 ===== */
});
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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', () => {
Expand All @@ -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(() => {
Expand Down
7 changes: 7 additions & 0 deletions cypress/support/assertions/assertion_constants.js
Original file line number Diff line number Diff line change
@@ -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',
Expand Down
35 changes: 24 additions & 11 deletions cypress/support/assertions/expect_alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.`
);
}
);

Expand Down