I actually randomly wrote my own TAP producing test runner in TypeScript recently for no reason other than I wanted something to do while I was stuck at home during the pandemic. The protocol is pretty simple to follow although I do agree that you have to have something to orchestrate the whole thing up front. I actually wrote it for an example script for an asynchronous utilities library that had the equivalent of low level primitives like an async version of locks and barriers. The barriers were useful for orchestrating when the different tests ran so that I could make sure that build up and tear down happened at the right time before and after the tests. The locks insured that each tests logs didn’t print over each other as I proxies the console and ran the tests all at the same time and then I did the logging sequentially. I got most of it working but I haven’t touched it in about a month or two. I feel like it might not be a good thing to have those lower level paradigms in JavaScript just because it seems a bit like a foot gun. I’m also pretty certain it wouldn’t work in parallel programming situations just in async situations. I based my TAP producing test runner off a previous work I did in modifying a testing framework that Ryan Florence made in the size of a tweet. I modified it to support async functions [1]. I had to use the async lock in that one too.
[1]: https://gist.github.com/johnsonjo4531/d751d7b63576a50878c977...