-
Notifications
You must be signed in to change notification settings - Fork 782
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
Core: Adding promise handling on qunit callbacks: begin, moduleStart, testStart, testDone, moduleDone #1307
Conversation
Looks like 2 cli tests is failing, will be looking into it. Update: Two CLI test failed Both failures are due to
For the test
VS the expected output :
For the test
VS the expected output :
Not sure how to move forward, any thoughts? |
a6c0add
to
6711d27
Compare
23b9f10
to
2537115
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just leaving a few questions-- not seeing anything that stands out as a red flag, however.
38ce4e3
to
da24318
Compare
@platinumazure about the parentheses being escaped, eslint throws |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this is looking good. I have a couple comments about order-of-execution though. Thanks for working on this!
12c6b62
to
3044ca2
Compare
@platinumazure @trentmwillis addressed the feedbacks, would you be able to give it another go to see if there's any other sticking point? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, looks good. I think we just need to address the Promise
support issue and then we can ship. Thanks for the hard work! :)
Edit: As a quick note, I'd be inclined to drop IE 9/10 from support, but even IE 11 doesn't have Promises.
After talking a bit with @step2yeung about the various options here, we came up with two different paths forward:
I personally think option 2 above is better for the longer term project health and generally leaves things better off for future iteration, but am pretty confident that we can make either option work if including a fallback promise lib isn't acceptable. @stefanpenner / @trentmwillis - What do you think? |
@rwjblue / @step2yeung, in general, I'm not too concerned with the file size of QUnit given that it is a development tool. I agree with your opinion that option 2 is the better approach for the long-run, but would be fine with option 1 as well as I don't think it'll negatively affect the code base much if it is factored well (likely a function or two that can be swapped out with native Promise functions later). I originally suggested an approach like option 1 as I thought it would be quicker to get landed. Introducing an extra library that has fallback behavior will require modifications to the build system and some special testing. With that said, I leave the choice up to the implementer! |
3044ca2
to
0f148ce
Compare
@step2yeung - Looks like you need to rebase against master and resolve a |
58edfb5
to
b59ba6f
Compare
@rwjblue rebased! |
Since we don't have appyoyer or browser stack tests turned on, I tested the above on a windows machine by running |
b59ba6f
to
71d4810
Compare
71d4810
to
671f528
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 looks good @step2yeung
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! One last tiny request: can we update the relevant docs to note that callbacks can return Promises (other than the Log callback)?
Also, two asides (not to keep this PR from landing):
- We need to improve our code coverage reporting. The polyfill and rollup/babel make it seem like our code coverage is much worse than it actually is.
- I can't wait for us to hit a support policy where async/await is available (I know we could polyfill it, but don't really want to).
Also, we should definitely add support for this to |
755682d
to
73fbe52
Compare
Created #1329 to keep track of the two issues you raised. |
Thank you! I know that was a lot of work, but it's appreciated; I'm excited to see how y'all use it. I'll try to do a new minor release tomorrow morning (unlikely to get to it today). |
Way to go, @step2yeung !!!! This is awesome stuff! |
Three issues came up when trying to use QUnit in an embedded mozjs context. 1. console.warn is undefined. This regressed in a recent release where we started to assume that if 'console' is defined, that 'console.warn' is as well. This is not true in SpiderMonkey (checked mozjs 68). 2. setTimeout is undefined. QUnit has historically made sure not to rely on setTimeout, but this broke when es6-promise was added in gh-1307, which assumed presence of setTimeout. The funny part is, mozjs 68 actually has native Promise support, but the polyfill is written in a way (and built in a way, with Rollup) that unconditionally builds and imports the fallback, even when it decides not to use it. It seems Rollup does not support importing files in a way that only executes the imported files conditionally (it always hoists imported files and executes imports before any other code). So, to fix this, I'm switching the polyfil library to a lighter alternative, and patching it with a conditional check on the inside rather than on the outside, so that it can be unconditionally imported by Rollup, but still only conditionally build its setTimeout-based fallback. 3. QUnit is not exported. I believe we used to have an export to the global object if no module loader was detected, but this morphed over time and we now hardcode global exports specifically for DOM global (window) and Web Worker global (self), which means it no longer worked in SpiderMonkey. Our current structure of the internal export.js file, is to provide any and all exports we can detect, which is rather unusual in the JS ecosystem, but it would also be a breaking change to stop doing this, so I'll reserve that for QUnit 3. This patch introduces a realm-agnostic global export if and only if no other export methods were applied. I suggest that in QUnit 3 we restructure this to simply always export on the global this, and then optionally also export to one module loader, trying only one after the other (mutually exclusive), which is more in line with how UMD work etc. I won't do this now yet, because I found at least one test case that breaks if we unconditionally add a global on Node.js in QUnit 2, which is our Grunt task that assumes it has control over setting the QUnit global itself. I think that's easy to fix and fine to break soon, but not until QUnit 3.
Three issues came up when trying to use QUnit in an embedded mozjs context. 1. console.warn is undefined. This regressed in a recent release where we started to assume that if 'console' is defined, that 'console.warn' is as well. This is not true in SpiderMonkey (checked mozjs 68). 2. setTimeout is undefined. QUnit has historically made sure not to rely on setTimeout, but this broke when es6-promise was added in gh-1307, which assumed presence of setTimeout. The funny part is, mozjs 68 actually has native Promise support, but the polyfill is written in a way (and built in a way, with Rollup) that unconditionally builds and imports the fallback, even when it decides not to use it. It seems Rollup does not support importing files in a way that only executes the imported files conditionally (it always hoists imported files and executes imports before any other code). So, to fix this, I'm switching the polyfil library to a lighter alternative, and patching it with a conditional check on the inside rather than on the outside, so that it can be unconditionally imported by Rollup, but still only conditionally build its setTimeout-based fallback. 3. QUnit is not exported. I believe we used to have an export to the global object if no module loader was detected, but this morphed over time and we now hardcode global exports specifically for DOM global (window) and Web Worker global (self), which means it no longer worked in SpiderMonkey. Our current structure of the internal export.js file, is to provide any and all exports we can detect, which is rather unusual in the JS ecosystem, but it would also be a breaking change to stop doing this, so I'll reserve that for QUnit 3. This patch introduces a realm-agnostic global export if and only if no other export methods were applied. I suggest that in QUnit 3 we restructure this to simply always export on the global this, and then optionally also export to one module loader, trying only one after the other (mutually exclusive), which is more in line with how UMD work etc. I won't do this now yet, because I found at least one test case that breaks if we unconditionally add a global on Node.js in QUnit 2, which is our Grunt task that assumes it has control over setting the QUnit global itself. I think that's easy to fix and fine to break soon, but not until QUnit 3.
Three issues came up when trying to use QUnit in an embedded mozjs context. 1. console.warn is undefined. This regressed in a recent release where we started to assume that if 'console' is defined, that 'console.warn' is as well. This is not true in SpiderMonkey (checked mozjs 68). 2. setTimeout is undefined. QUnit has historically made sure not to rely on setTimeout, but this broke when es6-promise was added in gh-1307, which assumed presence of setTimeout. The funny part is, mozjs 68 actually has native Promise support, but the polyfill is written in a way (and built in a way, with Rollup) that unconditionally builds and imports the fallback, even when it decides not to use it. It seems Rollup does not support importing files in a way that only executes the imported files conditionally (it always hoists imported files and executes imports before any other code). So, to fix this, I'm switching the polyfil library to a lighter alternative, and patching it with a conditional check on the inside rather than on the outside, so that it can be unconditionally imported by Rollup, but still only conditionally build its setTimeout-based fallback. 3. QUnit is not exported. I believe we used to have an export to the global object if no module loader was detected, but this morphed over time and we now hardcode global exports specifically for DOM global (window) and Web Worker global (self), which means it no longer worked in SpiderMonkey. Our current structure of the internal export.js file, is to provide any and all exports we can detect, which is rather unusual in the JS ecosystem, but it would also be a breaking change to stop doing this, so I'll reserve that for QUnit 3. This patch introduces a realm-agnostic global export if and only if no other export methods were applied. I suggest that in QUnit 3 we restructure this to simply always export on the global this, and then optionally also export to one module loader, trying only one after the other (mutually exclusive), which is more in line with how UMD work etc. I won't do this now yet, because I found at least one test case that breaks if we unconditionally add a global on Node.js in QUnit 2, which is our Grunt task that assumes it has control over setting the QUnit global itself. I think that's easy to fix and fine to break soon, but not until QUnit 3.
Addresses #1228
This change consist of several parts to enable QUnit callbacks to handle promises like:
Make advanceTaskQueue handle promises returned from each task
Each QUnit Test consist of multiple tasks, which handles setup, test execution, teardown and reporting of test results.
"advanceTaskQueue" is the function that controls the execution flow of tasks from each test. Hence, this needs to be able to handle promises that are returned by tasks.
'runLoggingCallbacks' returning a promise
'runLoggingCallbacks' is the function used to execute callback (eg. begin, moduleStart, testStart, testDone, moduleDone, done) function that is registered. This will now return a promise of the callbacks.
Note: since we are returning Promise.all(callbackPromises), it does not resolve promises in sequential order. Open to make it handle sequentially.
Since 'runLoggingCallbacks' returns a promise,
begin()
andfinish()
will have to return that promise chain. The promise will end up being waited on by 'advanceTaskQueue', and will move forward when the promise is resolved.Note2: Have not enabled this for QUnit.on(), QUnit.log() and QUnit.done().
TODOs: