I want cypress to wait until a kubernetes resources has the correct status.
There for i created the task k8n_xy_status
that get the status of the custom resource.
My only problem is to get cypress to wait for the status to have the expected status.
In both of the following examples cypress is execution the task only once and that waits 30sec on the same not changing stauts to be SYNCED
.
What is want cypress to do:
k8n_xy_status
every 10secSYNCED
or the timeout of 15 minutes are reached.My cypress configuration:
setupNodeEvents(on, config) {
on('task', {
k8n_xy_status({namespace, xy_name}): Promise<XyStatus> {
return k8n_xy_status(
config.env.OC_CLUSTER_URL,
config.env.OC_ACCESS_TOKEN,
namespace,
xy_name,
);
},
}
}
export interface XyStatus {
status: string;
statusMsg: string;
}
My test case looks like:
it('#' + step++ + ' The xy in namespace e2e-a is up and running', () => {
cy.waitUntil(() =>
cy.task('k8n_xy_status', {
namespace: 'e2e-a',
xy_name: 'e2e',
})
.then((xyStatus) => {
cy.log(`XY status at e2e-a: ${xyStatus.status} ${xyStatus.statusMsg} `);
return cy.wrap(xyStatus.status);
})
.should('equal', 'SYNCED'),
{
errorMsg: 'Xy in e2e-b is not running',
timeout: (15 * 60 * 1000),
interval: 10_000,
});
});
it('#' + step++ + ' The xy in namespace e2e-b is up and running', () => {
function checkStatus() {
const startTime = Date.now();
const timeout = 15 * 60 * 1000;
return cy.task('k8n_xy_status', {
namespace: 'e2e-b',
xy_name: 'e2e',
}, {
timeout,
})
.then((xyStatus) => {
cy.log(`XY status at e2e-b: ${xyStatus.status} ${xyStatus.statusMsg} `);
if (xyStatus.status === 'SYNCED') {
return true;
}
const elapsed = Date.now() - startTime;
if (elapsed < timeout) {
return cy.wait(10_000).then(checkStatus); // Wait 10 seconds before retrying
} else {
throw new Error('Timed out waiting for xy e2e-b to be SYNCED');
}
});
}
checkStatus();
});
My dependencys:
"devDependencies": {
"@types/mocha": "^9.1.1",
"@types/node": "^18.0.0",
"cypress": "^14.3.1",
"cypress-multi-reporters": "2.0.5",
"cypress-terminal-report": "7.1.0",
"cypress-wait-until": "3.0.2",
"eslint": "9.20.1",
"eslint-plugin-cypress": "4.1.0",
"eslint-plugin-jsonc": "2.19.1",
"eslint-plugin-mocha": "10.5.0",
"mocha": "11.1.0",
"mocha-junit-reporter": "2.2.1",
"ts-loader": "^9.3.0",
"typescript": "^4.7.3",
"yaml-lint": "1.7.0"
},
"dependencies": {
"@kubernetes/client-node": "^1.1.2",
"js-yaml": "^4.1.0",
"uuid": "^11.1.0"
},
You get better results by converting your recursive function into a Custom Command.
I ran you function version of checkStatus
and got the same result - only one call to the cy.task()
. Which is strange, because it's very similar to the example given at Request Polling.
To check out the Custom Command version, I simulated your XYStatus
task with a simple function that returns SYNCED
status on the 3rd call.
cypress.config.js
const { defineConfig } = require("cypress");
let calls = 0
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
resetCalls() { // this is just so I can init the call counter
calls = 0
return null
},
getXYStatus({namespace, xy_name}) {
calls++
return calls === 3 ? {status: 'SYNCED', statusMsg: 'OK'}
: {status: 'PENDING', statusMsg: 'not yet'};
}
})
},
},
});
recursive-task-call.cy.js
Cypress.Commands.add('checkStatus', ({expireTime}) => {
cy.task('getXYStatus', {namespace: 'e2e-b', xy_name: 'e2e'})
.then((xyStatus) => {
Cypress.log({name: 'XY status at e2e-b', message: `${xyStatus.status}: ${xyStatus.statusMsg}`});
if (xyStatus.status === 'SYNCED') {
return
}
if (Date.now() > expireTime) {
throw new Error('Timed out waiting for xy e2e-b to be SYNCED');
}
cy.wait(1000, {log:false}).then(() => {
cy.checkStatus({expireTime})
})
});
})
cy.task('resetCalls')
const timeout = 3000;
cy.checkStatus({expireTime: Date.now() + timeout})