-
-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot create a stream then load ESM test modules #575
Comments
I'm a bit confused.
It makes sense to me that your OP won't work, because of the nature of ESM. I'd expect you to have to |
No You're right nextTick(function next() {
var t;
while (t = getNextTest(self)) {
t.run();
if (!t.ended) {
t.once('end', function () { nextTick(next); });
return;
}
}
self.emit('done');
}); The I should have called the method Just try : https://github.com/ydarma/tape/blob/async-load/asyncESMload.mjs, you'll see that it does not work. We need our own test runner with an object stream because we record test results in a database. We recently migrated our code to ESM and ran into this problem with tape. |
no, |
Ah you're right |
ok, thanks for confirming. I wonder if this is just a limitation of streams themselves? Another alternative is some kind of opt-in way to ask the stream to "wait" until a promise resolves? |
It is not a limitation of node streams. Really it comes from the tape implementation which does not wait enough before processing the tests and closes the stream early. The trick I found or the solution I proposed are exactly what you wrote above : waiting until promise resolve. You should try the code on my fork : https://github.com/ydarma/tape/blob/async-load/asyncESMload.mjs with three breakpoints :
I am pretty sure that the right hit order would be Using the trick of encapsulating the module load in a synchronous test, the order is correct. As you wrote above, the synchronous test forces the stream processing (in function Really the problem is that tape processes the stream in a The problem is not new ; look at tape.wait();
var filesPromise = files.reduce(function (promise, file) {
return promise ? promise.then(function () {
return importOrRequire(file);
}) : importOrRequire(file);
}, null);
return filesPromise ? filesPromise.then(function () { tape.run(); }) : tape.run(); There is those In my proposal this code would become : return tape.async(function () {
return files.reduce(function (promise, file) {
return promise.then(function () {
return importOrRequire(file);
});
}, Promise.resolve());
}); Which I find not bad IMHO... |
I really don't like the So let's see if I understand. You're saying that bin/tape solves this problem by waiting until all of the files (passed in via CLI arg) have resolved, which includes any TLA in ESM files, before running What happens if you call |
I tried this too and is does not work.
If you prefer a behavior mutating style, it can be solved by the same kind of test processing lock I have implemented in function createExitHarness(conf, wait) {
//...
run();
if (wait) {
var waiter = new EventEmitter(); // create a lock for the test processing stream
waiter.run = function() {};
harness._results.push(waiter); // push the lock as the first thing to run in the processing stream
harness.run = function() {
waiter.emit("end"); // release the lock, allowing subsequent tests to run
}
} I think that the waiter only needs the I do not know if it breaks something, I can't find other tests invloving |
I have pushed a PR #576 you will choose what you want to do. For now, I will continue to use a synchronous test to lock the processing stream, personally I prefer that to the mutating style |
Hi, the following won't work :
Actually the test in the ESM Module does not run because the stream creates a result queue that is exhausted in the same event loop it is created in (results are consumed in a
setImmediate
callback). The ESM module will be loaded asynchronously, in a subsequent event loop.The
wait
andrun
function used in the cli are not helpful here because the stream will be recreated on therun
method, thus :run
method is called after the test are defined in the test module.For now I am using this trick :
The result processing starts by the synchronously defined test named
'__load_async__'
in the same event loop in which the stream is created. It will then "lock" the stream until all modules are loaded (becauset.end()
is called once they're all loaded). Then the results processing continues with the asynchronously defined tests.I propose something better, which implementation uses the same kind of mechanism as above :
I implemented this here : https://github.com/ydarma/tape/blob/async-load/test/async-test-load.js (I can make a PR).
The text was updated successfully, but these errors were encountered: