serenity icon indicating copy to clipboard operation
serenity copied to clipboard

LibWeb/Tests: Support running text tests containing async

Open shannonbooth opened this issue 1 year ago • 1 comments

I have been trying to implement tests for the Web::Blob::stream implementation.

Due to the async nature of streams, it seems to currently be not possible to add text tests for this (or I am messing something up here!) - as the async code will finish running after the document has loaded where the documents' text is dumped.

Below is a simple example test that I was trying to write:

<script src="../include.js"></script>
<script>
    async function readFromBlobStream() {
        let blob = new Blob(["Hello friends!"], {
            type: "text/plain"
        });
        const readableStream = blob.stream();
        const stream = readableStream.getReader();
        let result = "";
        while (true) {
            let { done, value } = await stream.read();
            if (done)
                break;
            result += value;
        }
        return result;
    }

    test(async () => {
        const result = await readFromBlobStream();
        println(result);
    });
</script>

It would be nice if we could figure out a way of adding tests for this type of thing. Hopefully the fix is as simple as changing the implementation of my above attempt of a test.

shannonbooth avatar Jun 12 '23 02:06 shannonbooth

If you restructure your code a bit, this seems to work for me.

First, you have a bug in that you will end up with a list of code points, and not a string, in result. But that's not the issue.

If you queue up your promise inside your script block, without attaching it to the DOMContentLoaded event by using test(), the browser will try to finish your script before firing the event. And since it's a quick and simple async function, it will succeed.

This works for me:

<script src="./include.js"></script>
<script>
    let blob = new Blob(["Hello friends!"], {
            type: "text/plain"
    });

    async function readFromBlobStream() {
        const stream = blob.stream().getReader();
        let result = "";
        while (true) {
            let { done, value } = await stream.read();
            if (done)
                break;
            result += String.fromCodePoint(...value);
        }
        return result;
    }
    // Enqueue the promise inside the script block, and attach only
    // the printing to the DOMContentLoaded event
    readFromBlobStream().then(result => test(() => println(result)));
</script>

slahn avatar Jul 09 '23 14:07 slahn

First, you have a bug in that you will end up with a list of code points, and not a string, in result. But that's not the issue.

Yeah, that was me being lazy and not tidying up :laughing: I knew I was getting a list of code points, just didn't tidy it up at the time. Thanks though!

shannonbooth avatar Jul 13 '23 10:07 shannonbooth