Skip to content

Commit c321365

Browse files
authored
Merge pull request #9560 from asirvadAbrahamVarghese/enhance-intercept-api-command
Enhance intercept api command
2 parents 0fa3a7a + a7b4733 commit c321365

File tree

4 files changed

+110
-27
lines changed

4 files changed

+110
-27
lines changed

cypress/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ ManageIQ implements the following cypress extensions:
5757
* `cy.toolbarItems(toolbarButton)` - returns an array of objects {text: String, disabled: Boolean} for the toolbar dropdown buttons for when a toolbar button is clicked. `toolbarButton` is the string for the text of the toolbar button that you want to click on.
5858
* `cy.toolbar(toolbarButton, toolbarOption)` - click on the toolbar button specified by the user. Can also then click on a specified dropdown option as well. `toolbarButton` is the string for the text of the toolbar button that you want to click on. `toolbarOption` is the string for the text of the toolbar dropdown option that you want to click on.
5959

60+
##### api_commands
61+
62+
* `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); } });`
63+
* `cy.getInterceptedApiAliases()` - returns the intercepted API aliases stored in Cypress environment variables.
64+
* `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');`
65+
* `cy.resetInterceptedApiAliases()` - resets the intercepted API aliases stored in Cypress environment variables.
66+
6067
##### custom_logging_commands
6168

6269
* `cy.logAndThrowError(messageToLog, messageToThrow)` - Logs a custom error message to Cypress log and then throws an error. `messageToLog` is the message to display in the Cypress command log. `messageToThrow` is the optional error message to throw, defaults to `messageToLog`. e.g. `cy.logAndThrowError('This is the logged message', 'This is the thrown error message');`, `cy.logAndThrowError('This is the message that gets logged and thrown');`

cypress/e2e/ui/validate-intercept-api-command.cy.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ describe('Validate intercept command', () => {
88
cy.menu('Settings', 'Application Settings');
99
});
1010

11-
it('Should register the alias, intercept & wait when API fired', () => {
11+
it('Should register the alias, intercept, wait & validate response status code when an API is fired', () => {
1212
cy.accordion('Diagnostics');
1313
cy.interceptApi({
1414
alias: 'treeSelectApi',
1515
urlPattern: /\/ops\/tree_select\?id=.*&text=.*/,
1616
triggerFn: () => cy.selectAccordionItem([/^ManageIQ Region:/, /^Zone:/]),
17+
onApiResponse: (interception) => {
18+
expect(interception.response.statusCode).to.equal(200);
19+
},
1720
}).then(() => {
1821
// verifies that the alias is set and the request is intercepted & awaited
19-
expect(Cypress.env('interceptedAliases')).to.have.property(
20-
'treeSelectApi'
21-
);
22+
cy.getInterceptedApiAliases().then((interceptedAliasesObject) => {
23+
expect(interceptedAliasesObject).to.have.property('treeSelectApi');
24+
});
2225
});
2326
});
2427

@@ -36,10 +39,12 @@ describe('Validate intercept command', () => {
3639
triggerFn: () => cy.selectAccordionItem([/^ManageIQ Region:/, /^Zone:/]),
3740
}).then(() => {
3841
// verifies that both the aliases are set and the request is intercepted & awaited
39-
expect(Cypress.env('interceptedAliases')).to.include.all.keys(
40-
'accordionSelectApi',
41-
'treeSelectApi'
42-
);
42+
cy.getInterceptedApiAliases().then((interceptedAliasesObject) => {
43+
expect(interceptedAliasesObject).to.include.all.keys(
44+
'accordionSelectApi',
45+
'treeSelectApi'
46+
);
47+
});
4348
});
4449
});
4550

@@ -50,15 +55,19 @@ describe('Validate intercept command', () => {
5055
urlPattern: /\/ops\/accordion_select\?id=.*/,
5156
triggerFn: () => cy.accordion('Diagnostics'),
5257
}).then(() => {
53-
expect(Object.keys(Cypress.env('interceptedAliases')).length).to.equal(1);
58+
cy.getInterceptedApiAliases().then((interceptedAliasesObject) => {
59+
expect(Object.keys(interceptedAliasesObject).length).to.equal(1);
60+
});
5461
});
5562
// second first api with alias 'treeSelectApi'
5663
cy.interceptApi({
5764
alias: 'treeSelectApi',
5865
urlPattern: /\/ops\/tree_select\?id=.*&text=.*/,
5966
triggerFn: () => cy.selectAccordionItem([/^ManageIQ Region:/, /^Zone:/]),
6067
}).then(() => {
61-
expect(Object.keys(Cypress.env('interceptedAliases')).length).to.equal(2);
68+
cy.getInterceptedApiAliases().then((interceptedAliasesObject) => {
69+
expect(Object.keys(interceptedAliasesObject).length).to.equal(2);
70+
});
6271
});
6372
// third api with a duplicate alias as above 'accordionSelectApi'
6473
cy.interceptApi({
@@ -67,7 +76,9 @@ describe('Validate intercept command', () => {
6776
triggerFn: () => cy.accordion('Access Control'),
6877
}).then(() => {
6978
// assert that the alias is not overwritten
70-
expect(Object.keys(Cypress.env('interceptedAliases')).length).to.equal(2);
79+
cy.getInterceptedApiAliases().then((interceptedAliasesObject) => {
80+
expect(Object.keys(interceptedAliasesObject).length).to.equal(2);
81+
});
7182
});
7283
});
7384
});
Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,58 @@
11
/* eslint-disable no-undef */
22

3+
/**
4+
* Custom command to get the intercepted API aliases stored in Cypress environment variables.
5+
* This command returns the object containing all registered API interception aliases.
6+
*
7+
* @returns {Object} An object where keys are the alias names and values are typically the same alias names
8+
* @example
9+
* cy.getInterceptedApiAliases().then((aliases) => {
10+
* Check if a specific alias exists
11+
* expect(aliases).to.have.property('myApiAlias');
12+
*
13+
* Get the number of registered aliases
14+
* const aliasCount = Object.keys(aliases).length;
15+
* });
16+
*/
17+
Cypress.Commands.add('getInterceptedApiAliases', () =>
18+
Cypress.env('interceptedAliases')
19+
);
20+
21+
/**
22+
* Custom command to set an intercepted API alias in the Cypress environment variables.
23+
* This command adds an alias in the intercepted aliases tracking object.
24+
*
25+
* @param {string} aliasKey - The key/name of the alias to set
26+
* @param {string} [aliasValue=aliasKey] - The value to store for the alias (defaults to the same as the key)
27+
* @example
28+
* Set a new alias
29+
* cy.setInterceptedApiAlias('getUsersApi');
30+
*
31+
* Set an alias with a custom value
32+
* cy.setInterceptedApiAlias('getUsersApi', 'customValue');
33+
*/
34+
Cypress.Commands.add(
35+
'setInterceptedApiAlias',
36+
(aliasKey, aliasValue = aliasKey) => {
37+
cy.getInterceptedApiAliases().then((interceptedAliasesMap) => {
38+
interceptedAliasesMap[aliasKey] = aliasValue;
39+
Cypress.env('interceptedAliases', interceptedAliasesMap);
40+
});
41+
}
42+
);
43+
44+
/**
45+
* Custom command to reset all intercepted API aliases stored in Cypress environment variables.
46+
* This command clears the tracking object by setting it to an empty object.
47+
* Useful for cleaning up between tests or test suites.
48+
* @example
49+
* Reset all intercepted API aliases
50+
* cy.resetInterceptedApiAliases();
51+
*/
52+
Cypress.Commands.add('resetInterceptedApiAliases', () =>
53+
Cypress.env('interceptedAliases', {})
54+
);
55+
356
/**
457
* Custom command to intercept API calls and wait for them to complete.
558
* This command will:
@@ -12,33 +65,45 @@
1265
* @param {string} options.method - HTTP method (default: 'POST')
1366
* @param {string|RegExp} options.urlPattern - URL pattern to intercept
1467
* @param {Function} options.triggerFn - Function that triggers the API call
68+
* @param {Function} [options.onApiResponse] - Optional callback function that receives the interception object after the API call completes.
69+
* Use this to perform assertions on the response, extract data, or perform additional actions based on the API result.
70+
* Default is a no-op function. e.g. { onApiResponse: (interception) => { expect(interception.response.statusCode).to.equal(200); } }
1571
*/
1672
Cypress.Commands.add(
1773
'interceptApi',
18-
({ alias, method = 'POST', urlPattern, triggerFn }) => {
74+
({
75+
alias,
76+
method = 'POST',
77+
urlPattern,
78+
triggerFn,
79+
onApiResponse = () => {
80+
/* default implementation */
81+
},
82+
}) => {
1983
/* ===== TODO: Remove this block once interceptApi command becomes stable ===== */
2084
const envVars = Cypress.env();
2185
cy.log('Cypress Environment Variables:');
2286
cy.log(JSON.stringify(envVars, null, 2));
2387
/* ======================================================= */
2488

2589
// Check if this request is already registered
26-
const isAlreadyRegistered = !!Cypress.env('interceptedAliases')[alias];
27-
28-
// Register the intercept if not already done
29-
if (!isAlreadyRegistered) {
30-
cy.intercept(method, urlPattern).as(alias);
90+
cy.getInterceptedApiAliases().then((interceptedAliasesMap) => {
91+
// Check if this request is already registered
92+
const isAlreadyRegistered = !!interceptedAliasesMap[alias];
3193

32-
// Store the alias in the tracking object
33-
const interceptedAliases = Cypress.env('interceptedAliases');
34-
interceptedAliases[alias] = alias;
35-
Cypress.env('interceptedAliases', interceptedAliases);
36-
}
94+
// Register the intercept if not already done
95+
if (!isAlreadyRegistered) {
96+
cy.intercept(method, urlPattern).as(alias);
97+
cy.setInterceptedApiAlias(alias);
98+
}
3799

38-
// Execute the function that triggers the API call
39-
triggerFn();
100+
// Execute the function that triggers the API call
101+
triggerFn();
40102

41-
// Wait for the intercepted request to complete
42-
cy.wait(`@${alias}`);
103+
// Wait for the intercepted request to complete
104+
cy.wait(`@${alias}`).then((interception) => {
105+
onApiResponse(interception);
106+
});
107+
});
43108
}
44109
);

cypress/support/e2e.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ beforeEach(() => {
7979
// cy.stub_notifications();
8080

8181
// Reset the intercepted aliases tracking object
82-
Cypress.env('interceptedAliases', {});
82+
cy.resetInterceptedApiAliases();
8383
})

0 commit comments

Comments
 (0)