How to add recursive function checking xhr response in testcafe script?
Asked Answered
E

1

6

I'm trying to write a test download works, which requires to check if xhr response has status READY. I created a client function in TestCafe, using promises, but it's failing in case of recursion.

How should I fix my code to handle this situation?

P.S. many apologies for newbies questions, I have just started my journey in automation testing.


fixture`Download report works`


test
    .requestHooks(logger)//connected a request hook, will wait for logger request 
    ('I should be able to download PDF report from header of the page', async t => {
        //recursively check if response status is READY, and then go to assertions

        const waitForDownloadResponseStatus = ClientFunction((log) => {
            return new Promise((resolve,rejects)=>{
                const waitForStatus=()=>{

                        const arrayFromResponse = JSON.parse(log.response.body);
                        const responseStatus = arrayFromResponse.status;
                        if (responseStatus == 'READY')
                        {
                            resolve(responseStatus);
                        } 
                        else {
                            waitForStatus();
                        }
                    }
                waitForStatus();
                })
        });
        //page objects
        const reportTableRaw = Selector('div.contentcontainer').find('a').withText('April 2019').nth(0);
        const downloadPdfButton = Selector('a.sr-button.sr-methodbutton.btn-export').withText('PDF');
        //actions.

        await t
                .navigateTo(url)
                .useRole(admin)       
                .click(reportTableRaw)//went to customise your report layout
                .click(downloadPdfButton)
                .expect(logger.contains(record => record.response.statusCode === 200))
                .ok();//checked if there is something in logger
        const logResponse = logger.requests[0];

                // const arrayFromResponse = JSON.parse(logResponse.response.body);
                // const responseStatus = arrayFromResponse.status;

        console.log(logger.requests);
        await waitForDownloadResponseStatus(logResponse).then((resp)=>{
            console.log(resp);
            t.expect(resp).eql('READY');
        });     


    });
Electropositive answered 9/5, 2019 at 2:36 Comment(0)
T
5

When you pass an object as an argument or a dependency to a client function, it will receive a copy of the passed object. Thus it won't be able to detect any changes made by external code. In this particular case, the waitForStatus function won't reach its termination condition because it can't detect changes in the log object made by an external request hook. It means that this function will run indefinitely until it consumes the all available stack memory. After that, it will fail with a stack overflow error.

To avoid this situation, you can check out that response has status READY if you change the predicate argument of the contains function. Take a look at the following code:

.expect(logger.contains(record => record.response.statusCode === 200 &&
                                  JSON.parse(record.response.body).status === 'READY'))
.ok({ timeout: 5000 });

Also, you can use the timeout option. It's the time (in milliseconds) an assertion can take to pass before the test fails.

Tripe answered 13/5, 2019 at 17:17 Comment(2)
Now I understood. And the code you suggested works! no need to write long functions. Thank you for the answer, Andrey!Electropositive
We are happy to hear that this code was helpful. May I ask you to mark our answer as a "solution", to make it more discoverable for other users?Brackett

© 2022 - 2024 — McMap. All rights reserved.