diff --git a/cypress/README.md b/cypress/README.md index 2246e8bc63f..33b4a2bdb48 100644 --- a/cypress/README.md +++ b/cypress/README.md @@ -59,7 +59,7 @@ ManageIQ implements the following cypress extensions: ##### api_commands -* `cy.interceptApi({ alias, method = 'POST', urlPattern, triggerFn, onApiResponse })` - intercepts API calls and waits for them to complete. This command will: 1) Register an intercept for the given alias and URL pattern if not already registered, 2) Execute the trigger function that makes the API call, 3) Wait for the intercepted request to complete. `alias` is the string for a unique alias for this interception. `method` is the string for the HTTP method (default: 'POST'). `urlPattern` is the string or RegExp for the URL pattern to intercept. `triggerFn` is the function that triggers the API call. `onApiResponse` is an optional callback function that receives the interception object after the API call completes. Use this to perform assertions on the response, extract data, or perform additional actions based on the API result. Default is a no-op function. e.g. `cy.interceptApi({ alias: 'getUsers', method: 'GET', urlPattern: '/api/users', triggerFn: () => cy.get('#load-users').click(), onApiResponse: (interception) => { expect(interception.response.statusCode).to.equal(200); } });` +* `cy.interceptApi({ alias, method = 'POST', urlPattern, triggerFn, onApiResponse })` - intercepts API calls and waits for them to complete. This command will: 1) Register an intercept(in method-alias format e.g. post-myApiAlias) for the given alias & URL pattern if not already registered, 2) Execute the trigger function that makes the API call, 3) Wait for the intercepted request to complete. `alias` is the string for a unique alias for this interception. `method` is the string for the HTTP method (default: 'POST'). `urlPattern` is the string or RegExp for the URL pattern to intercept. `triggerFn` is the function that triggers the API call. `onApiResponse` is an optional callback function that receives the interception object after the API call completes. Use this to perform assertions on the response, extract data, or perform additional actions based on the API result. Default is a no-op function. e.g. `cy.interceptApi({ alias: 'getUsers', method: 'GET', urlPattern: '/api/users', triggerFn: () => cy.get('#load-users').click(), onApiResponse: (interception) => { expect(interception.response.statusCode).to.equal(200); } });` * `cy.getInterceptedApiAliases()` - returns the intercepted API aliases stored in Cypress environment variables. * `cy.setInterceptedApiAlias(aliasKey, aliasValue)` - sets an intercepted API alias in the Cypress environment variables. `aliasKey` is the string for the key/name of the alias to set. `aliasValue` is an optional string for the value to store for the alias (defaults to the same as the key). e.g. `cy.setInterceptedApiAlias('getUsersApi');`, `cy.setInterceptedApiAlias('getUsersApi', 'customValue');` * `cy.resetInterceptedApiAliases()` - resets the intercepted API aliases stored in Cypress environment variables. diff --git a/cypress/e2e/ui/validate-intercept-api-command.cy.js b/cypress/e2e/ui/validate-intercept-api-command.cy.js index 5e62ede5287..1c09ef177e6 100644 --- a/cypress/e2e/ui/validate-intercept-api-command.cy.js +++ b/cypress/e2e/ui/validate-intercept-api-command.cy.js @@ -20,7 +20,7 @@ describe('Validate intercept command', () => { }).then(() => { // verifies that the alias is set and the request is intercepted & awaited cy.getInterceptedApiAliases().then((interceptedAliasesObject) => { - expect(interceptedAliasesObject).to.have.property('treeSelectApi'); + expect(interceptedAliasesObject).to.have.property('post-treeSelectApi'); }); }); }); @@ -41,8 +41,8 @@ describe('Validate intercept command', () => { // verifies that both the aliases are set and the request is intercepted & awaited cy.getInterceptedApiAliases().then((interceptedAliasesObject) => { expect(interceptedAliasesObject).to.include.all.keys( - 'accordionSelectApi', - 'treeSelectApi' + 'post-accordionSelectApi', + 'post-treeSelectApi' ); }); }); diff --git a/cypress/support/commands/api_commands.js b/cypress/support/commands/api_commands.js index 1ed72f89160..87e942b6c69 100644 --- a/cypress/support/commands/api_commands.js +++ b/cypress/support/commands/api_commands.js @@ -4,11 +4,11 @@ * Custom command to get the intercepted API aliases stored in Cypress environment variables. * This command returns the object containing all registered API interception aliases. * - * @returns {Object} An object where keys are the alias names and values are typically the same alias names + * @returns {Object} An object where keys are in format method-alias(e.g. post-myApiAlias) and values are typically the same alias names * @example * cy.getInterceptedApiAliases().then((aliases) => { * Check if a specific alias exists - * expect(aliases).to.have.property('myApiAlias'); + * expect(aliases).to.have.property('post-myApiAlias'); * * Get the number of registered aliases * const aliasCount = Object.keys(aliases).length; @@ -53,6 +53,28 @@ Cypress.Commands.add('resetInterceptedApiAliases', () => Cypress.env('interceptedAliases', {}) ); +/** + * Sets the request interception flag in Cypress environment. + * This flag is used to track whether a request matching an intercept pattern was detected. + * + * @param {boolean} value - The value to set for the flag (true if request was intercepted, false otherwise) + * @example + * // Mark a request as intercepted + * setRequestIntercepted(true); + * + * // Reset the interception flag + * setRequestIntercepted(false); + */ +const setRequestIntercepted = (value) => + Cypress.env('wasRequestIntercepted', value); + +/** + * Gets the current value of the request interception flag from Cypress environment. + * This flag indicates whether a request matching an intercept pattern was detected. + * @returns {boolean} The current value of the request interception flag + */ +const getRequestIntercepted = () => Cypress.env('wasRequestIntercepted'); + /** * Custom command to intercept API calls and wait for them to complete. * This command will: @@ -88,21 +110,29 @@ Cypress.Commands.add( // Check if this request is already registered cy.getInterceptedApiAliases().then((interceptedAliasesMap) => { + const aliasObjectKey = `${method.toLowerCase()}-${alias}`; // Check if this request is already registered - const isAlreadyRegistered = !!interceptedAliasesMap[alias]; - + const isAlreadyRegistered = !!interceptedAliasesMap[aliasObjectKey]; + // Setting wasRequestIntercepted flag to false initially + setRequestIntercepted(false); // Register the intercept if not already done if (!isAlreadyRegistered) { - cy.intercept(method, urlPattern).as(alias); - cy.setInterceptedApiAlias(alias); + cy.intercept(method, urlPattern, () => { + // Setting wasRequestIntercepted flag to true after request is intercepted + setRequestIntercepted(true); + }).as(alias); + cy.setInterceptedApiAlias(aliasObjectKey, alias); } // Execute the function that triggers the API call triggerFn(); // Wait for the intercepted request to complete - cy.wait(`@${alias}`).then((interception) => { - onApiResponse(interception); + cy.then(() => { + const isRequestIntercepted = getRequestIntercepted(); + if (isRequestIntercepted) { + cy.wait(`@${alias}`).then(onApiResponse); + } }); }); }