How to do fs.existsSync(path) with Timeout

时光毁灭记忆、已成空白 提交于 2020-01-02 09:41:00

问题


I'm writing an automated test script using TestCafe and Node.JS. One of the tests is to download a file and validate that the download is complete. I don't want to write a hard coded

await t.wait(4000);

because since my test is based on a data driven framework I can feed it lots of data with lots of different files and file types. So the file size could vary by extreme amounts from a few Kilobytes to Gigabytes.

So writing

await t.wait(4000);

might work for one test case but will almost certainly fail for other test cases.

I'm using dependency 'downloads-folder' to discover the path to the downloads folder on the local system. From there I look for the specific file that I expect to be there. It works for small text files and small zip files that download fast. But as soon as I try to download a really large zip file with lots of data it fails

if (fs.existsSync(zipFileNameAndPath)) {
    await t.expect(true).eql(true); // Report it as a success.
} else {
    console.log('file does NOT exist: ' + zipFileNameAndPath);
  await t.expect(false).eql(true); // Report it as a failure!
}

So my question is:

Is there a way to do something like

if (fs.existsSync(zipFileNameAndPath){[ timeout: 50000000]}) {...} else {...}

Where the resulting timeout would work as a dynamic timeout, waiting to see when the file is found, and if it is found before the timeout expired then it would return true, and only after the timeout period has passed would it return false?

I'm looking for a Synchronous answer that doesn't have any dependencies on things like Lodash or JQuery and works fine in ES6.


回答1:


I wrote a function:

async function CheckFileExistsWithTimeDelay(t, timeDelay, fileNameAndPath) {
    for (var i = 0; i < timeDelay; i++) {
        console.log('Waited for a total of ' + i.toString() + ' microseconds');
        await t.wait(1);
        if (fs.existsSync(fileNameAndPath)) {
            // break;
            return;
        }
    }
};

Then the caller of that function looks like:

await Common.CheckFileExistsWithTimeDelay(t, 500000, zipFileNameAndPath);

Of course you could comment out the console.log(...), I just left it in there so I could watch it as it waited for debugging purposes.

When I ran it, it waited for 7996 microseconds while downloading a 59mb zip file before breaking out and continuing script execution successfully.

Could just as easily be Break; or Return; depending if you wanted to keep it as a function or use it directly in-line with your script code.




回答2:


const filepath = 'YOUR_FILE.pdf';
const verifyDownload = async () => new Promise((resolve, reject) => {
    fs.watchFile(filepath, (curr, prev) => {
        if (fs.existsSync(filepath)) {
            fs.unwatchFile(filepath);
            resolve(true);
        }
     });
});

await t.expect(await verifyDownload()).ok("Could not download", { timeout: 30000 });



回答3:


The problem is you are checking for the file to exist without waiting for the download to complete. The code you posted is fine - you need to make sure it's not invoked until after the download completes (or fails).

How to do that is dependent on how you are doing the download. It could be as simple as dropping an 'await' on the line of code that does the download.



来源:https://stackoverflow.com/questions/48910111/how-to-do-fs-existssyncpath-with-timeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!