Reputation: 1879
Problem:
Trying to call tests within an array of items returned from a Cypress custom command.
Approaches attempted using npm package mocha-each and another test using the forEach
function.
Custom Command:
I created a custom Cypress command that returns an array of AppParamsType
:
/// <reference types="Cypress" />
import { AppParamsType } from 'support';
declare global {
namespace Cypress {
interface Chainable {
cmdGetAppsParams: () => Chainable<AppParamsType[]>;
}
}
}
export function cmdGetAppsParams() {
const paramsApps: AppParamsType[] = [];
cy.cmdAppKeys()
.then(($appKeys: string[]) => {
cy.wrap($appKeys).each(($appKey: string) => {
cy.cmdProviderAppParams($appKey).then((paramApp: AppParamsType) => {
paramsApps.push(paramApp);
});
});
})
.then(() => {
return cy.wrap(paramsApps);
});
}
Cypress.Commands.add('cmdGetAppsParams', cmdGetAppsParams);
Test using Custom Command:
The following Cypress test calls the custom command cmdGetAppsParams()
to return an array of items.
The array is being iterated with one test using npm package mocha-each and another test using Array forEach. Neither approach calls the tests within the loops.
import * as forEach from 'mocha-each';
let apps: AppParamsType[];
describe('DESCRIBE Apps Add Apps Spec', () => {
before('BEFORE', () => {
cy.cmdGetAppsParams().then(($apps: AppParamsType[]) => {
expect($apps).to.be.an('array').not.empty;
apps = $apps;
});
});
it('TEST Apps Params Array', () => {
cy.task('log', { line: 'A', data: apps });
expect(apps).to.be.an('array').not.empty;
});
it('TEST each item mocha forEach', () => {
cy.task('log', { line: 'B', data: apps });
forEach(apps).it('item', (item: AppParamsType) => {
cy.task('log', { line: 'B.1', data: item });
expect(item).to.be.an('object').not.null;
});
});
it('TEST each item array forEach', () => {
cy.task('log', { line:'C', data: apps });
expect(apps).to.be.an('array').not.empty;
apps.forEach((item: AppParamsType) => {
it('TEST App Param', () => {
cy.task('log', { line: 'C.1', data: item });
expect(item).to.be.an('object').not.null;
});
});
});
The results I am seeing is that the outer tests, indicated by labels 'A', 'B' and 'C', are getting called. But, not the inner tests, which would be indicated by labels 'B.1' and 'C.1':
{
"line": "A",
"data": [
***
]
}
{
"line": "B",
"data": [
***
]
}
{
"line": "C",
"data": [
***
]
}
Upvotes: 0
Views: 887
Reputation:
Nesting an it()
inside an it()
looks novel. I'm surprised you are not getting an error from it.
The basic problem when generating tests dynamically is that the Cypress runner needs to know exactly how many tests will be generated before it starts running them. But any Cypress commands (including custom commands) will not run until the entire test script has finished running (excluding callback code), so you can't get the apps
list from a custom command.
The best way to proceed is to convert cy.cmdAppKeys()
, cy.cmdGetAppsParams()
, and cy.cmdProviderAppParams()
from custom commands to a plain javascript function, and then run that function at the top of the script, e.g
const apps = getMyApps(); // synchronous JS function,
// will run as soon as the test starts
apps.forEach((item: AppParamsType) => {
const titleForTest = `Test App Param ${item.name}`; // Construct an informative title
it(titleForTest, () => {
...
})
})
If you can provide details of the custom commands cy.cmdAppKeys()
and cy.cmdProviderAppParams()
, may be able to help convert to the synchronous function.
Upvotes: 1