codeceptjs script get stuck when using session inside a Scenario
Hi,
I upgraded my testing platform from codeceptjs v 3.6.10 to v3.7.4 but encounter a strange issue with codeceptjs script get stuck and never get timeout. I used explicitly timeout in config and in scenario but non worked. Stuck may happen on I.grabAttributeFrom, grabTextFrom which could be multi sessions or multi Data Scenarios. I tried to narrow down the issue and found that If a Scenario start and you perform some tasks using grabTextFrom or grabAttributeFrom with same exact locate function and then use the same exact locate function inside a Scenario Session then it get stuck. It could be the locate function cache of the first browser session element which may be behaving differently when called again in a different session in same test case?
Here is the general test case template:
Scenario('issue of multi sessions', async () => { login('abc'); I.amOnPage('mywebsite'); let v = await I.grabTextFrom(locate('#myid')); await session('second', async () => { I.amOnPage(',mywebsite'); let url2 =I.grabCurrentUrl(); let v = await I.grabTextFrom(locate('#myid')); // get stuck never timeout }); }).tag('issue');
similar thing happen when i tried to call the same Scenario with data(array).Scenario and locate function get stuck. I tried few without locate but something again did not let he script to run multiple times when data was passed.
Is the same cache get built for the elements inside codceptjs which never cleared with Scenario run multiple times with data being passed? If i dive such scenario into two then they run fine, any clue?
Also any data being not managed correctly when a session is created inside a Scenario? A reference of element on one session is being shared at a wrong place in a different session, any clue?
My application perform few operations so its hard to write a standalone script with the issue, I hope a review of of such feature by developer may pin point the issue and in the mean while i will try to make a test case which reproduce such issue as stand alone Scenario.
Any help will be highly appreciated. Thanks!
I was able to pin point the issue of hanging nodeJS process while running codeceptjs and not throwing any exception or error message.
- This error is related to the topic of :
- nodejs call to async funciton stuck
- nodejs unhandledRejection logging
- how to print rejected promise in nodejs
- Chaining cycle detected for promise
- https://codecept.io/basics/#multiple-sessions
How I was able to find the issue:
bootstrap.js
I added this line:
`
process.on('unhandledRejection', (reason, promise) => {
console.log('booststrap - unhandledRejection:');
console.log(reason)
console.log(promise)
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});`
What type of test case this unhandledRejection occurred:
When I had a test case with multiple sessions and dynamic data is passed to the test case to run multiple times.
When error message get triggered: first test case run fine. when it run second time it get stuck and nodejs hang on line of login due to some codeceptjs unhandledRejection. It tried to login second attempt and unhandledRejection was recorded.
Test case template:
`
Data([
'a',
'b',
]).Scenario('issue', async({ current })=>{
login('userA');
I.click('Issue');
let options = await I.grabAttributeFromAll('#i', 'value');
I.click('Save');
I.waitForClickable('#btnSave', 10);
await session('sessionB', async ()=>{
login('userB');
// When test case run 2nd time with data 'b'
// It get issue on login funciton
// nhandled Rejection at: Promise {
//
//I am logged in as userB
// userB: I am on page "/"
// › [Url] https://lsite/login
// › [Browser:Verbose]
//[1] <check login> Retrying... Attempt #2
I.click('Issue');
I.assert((await I.grabAttributeFrom('#i', 'disabled')), true);
});
}).tag('@issue'); `
Step file
/* // steps_file.js // loginUser: function(username) { this.amOnPage('/login'); this.fillField('User name', username); this.fillField('Password', 'xyz'); } */
codecept.conf.js file:
`/* //codecept.conf.js auth: { enabled: true, saveToFile: false, inject: 'login', users: { userA: { login: (I) => I.loginUser('guest'), check: (I) => I.checkUser('guest'), }, userB: { login: (I) => I.loginUser('member'), check: (I) => I.checkUser('member'), },
*/`
Temporary work around:
I used loginUser function explcility instead of using calling 'login' `await session('bamanalyst', async ()=>{
I.loginUser('userB'); `
Per doc https://codecept.io/playwright/#multi-session-testing, I guess no async before session
Scenario('I try to open this site as anonymous user', ({ I }) => {
I.amOnPage('/');
I.dontSee('Agree to cookies');
// no async before session
session('anonymous user', () => {
I.amOnPage('/');
I.see('Agree to cookies');
});
})
per doc https://codecept.io/playwright/#multi-session-testing, it does not say that async is not supported. If session function does not support async then how to use this async function inside a sync function? Example: let hint = await I.grabAttributeFrom('#tooltip', 'title'); This will throw an error as await is not allowed inside a sync function!