setup() methods are called prematurely when tests are loaded asynchronously #320
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I believe this might be an example of this problem in the wild.
If tests are loaded asynchronously, the document is loaded before they are read, which changes the values of
config.autorun
andconfig.blocking
and eventually causes the callbacks queued in Test.queue() to be run out-of-sequence.This pull request contains a separate test HTML file with accompanying JS tests that exemplify the problem.
The exact sequence of problematic events goes like this:
QUnit.load()
completes, and callsQUnit.start()
QUnit.start()
setsconfig.blocking
tofalse
, then callsprocess()
process()
callsdone()
done()
setsconfig.autorun
totrue
init()
, which is autorun bysynchronize()
run()
, which is autorunsetup()
, which is autorunrun()
, which is autorun; now we're blocking.teardown()
andfinish()
. queue is now [A.teardown, A.finish]init()
and innerrun()
. queue is now [A.teardown, A.finish, B.init, B.run]init()
and innerrun()
. queue is now [A.teardown, A.finish, B.init, B.run, C.init, C.run]teardown()
andfinish()
are run; no more blocking. queue is now [B.init, B.run, C.init, C.run]init()
and innerrun()
are run. queue is now [C.init, C.run]setup()
. queue is now [C.init, C.run, B.setup]synchronize()
queues Test B'ssetup()
and kicks offprocess()
process()
runs the next functions in the queue, which are Test C'sinit()
andrun()
.setup()
. queue is now [B.setup, C.setup]And now you're thinking with portals.