-
Notifications
You must be signed in to change notification settings - Fork 779
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: Introduce before/after hooks for modules #919
Conversation
a46c1b9
to
64b93ea
Compare
@leobalter I think this is ready for review. Tried my best to keep the implementation within existing constructs, but required a few new properties to get all the features/behavior this should support. |
@@ -56,11 +58,14 @@ extend( QUnit, { | |||
var module = { | |||
name: moduleName, | |||
parentModule: parentModule, | |||
tests: [] | |||
tests: [], | |||
testsRun: 0 |
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.
this might be my only concern on this PR. Exposing a new detail on the API conflicts with the plans for the EventEmitter changes (#882).
Although, the tests
array will still prevail and I wonder if we can set an equivalent property on the reference object for the test on that array. Doing that, we would have the tradeoff to filter the array, but it would save us a new API exposure.
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.
Looking at the "events details types" issue, I think we would be able to replace module.testsRun
with module.status.total
when it is implemented since it looks like it will be similar.
I would also be fine with setting an equivalent property on the tests
array, though it feels a little less correct.
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.
Looking at the "events details types" issue, I think we would be able to replace module.testsRun with module.status.total when it is implemented since it looks like it will be similar.
👍 that would be great!
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.
In the interim, should we proceed with this current implementation? (After I clean up the style issues, of course.)
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.
Yes, sure.
We will need to have the API docs on http://github.com/jquery/api.qunitjs.com to be able to land it, would you mind to help on that part too?
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.
I'll open a PR documenting the new before
/after
hooks for module
. Is there anything else I should document?
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.
I believe they'll be enough for now, QUnit docs will probably face a whole logging details review on a near future.
The tests look great and I like the implementation. My concerns remained only on the API as in #919 (comment) Other noticed minor style issues for missing spaces between parenthesis, which are not blockers. |
64b93ea
to
9bdb29f
Compare
Updated the PR (think I got all the style issues). |
test.preserveEnvironment = true; | ||
} | ||
|
||
if ( hookName === "after" && hookOwner.testsRun !== numberOfTests(hookOwner) - 1 ) { |
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.
a small style issue here numberOfTests(hookOwner)
=> numberOfTests( hookOwner )
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.
Ah, missed one.
9bdb29f
to
6049d78
Compare
delete this.module.testEnvironment.beforeEach; | ||
delete this.module.testEnvironment.afterEach; | ||
delete this.module.testEnvironment.after; |
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.
This may require treating the change as breaking. @leobalter?
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.
I don't think so. We have this delete statement only because we're introducing new properties to the modules' hook: before
and after
. Anyone previously extending that module with these keywords would get their tests affected.
That same could happen when we moved setup
and teardown
to beforeEach
and afterEach
. Similarly we could mention the introduction of QUnit.skip
to the API that could interfere with any other use of custom made methods.
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.
Anyone previously extending that module with these keywords would get their tests affected.
Exactly. Code like QUnit.module( name, { after: new Date(2016, 0, 1) }, … )
, which is currently supported, will be broken. This is why I abhor the conflation of module options and test context in a single parameter, but there it is. And it's different from adding QUnit.skip
because QUnit
is our object, but that parameter is explicitly wide open for users, minus our exceptions.
Anyway, while maybe not a huge deal, this is technically breaking.
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.
This is why I abhor the conflation of module options and test context in a single parameter
We should discuss a way to solve this before 2.0. Maybe we need to isolate the hooks from the environment or event remove the possibility to define env values on this object (let this
do its job).
I wonder if this should cover edge cases like delaying the definition of a test. They're a bit pathological, but it would still be bad to run an |
@gibson042 is that a real use case? If so, I don't really see a realistic way to handle it other than making an explicit declaration of the number of tests your module should have, since we need advanced knowledge of whether or not another test is expected to run. |
That example reflects tests added through async files loading, as in AMD. A dirty check could use a global variable to tell they are added. Anyway, I also believe it's a developer responsibility to organize well tests introduced asynchronously. An update to the example - where I only added a single line: reveals a structure antipattern: https://jsfiddle.net/obuj0czg/1/ |
Okay, makes sense. Should I attempt to cover that use case? Based on the example you gave, it probably doesn't make much sense without guaranteeing what module a test belongs to |
I believe a simple timeout example is enough to cover it up, testing it works properly on async operations and it does not leak anywhere else. AMD cases will be the responsibility for those who implements it. |
Right, pathological. 😄 |
Sorry about the noise. But my point was that we should add documentation and assertions that lock down how |
Sorry if I'm missing something obvious, but going back to my earlier point, if a test definition is delayed, then it may not get added to the module's test queue until after the module has already emptied it's test queue. How do we notify the module that even though it has ran all of it's tests, it should not run the |
We don't. We just document and assert our behavior, which will take one of two forms:
I'm just forcing the above as an explicit choice, rather than an accident of implementation. |
Okay, cleared that all up. Currently the implementation means your second option is true (it will result in successive invocations), though I think the first option makes more sense. This is because I imagine If that makes sense, I'll add a test for that here and document it in the documentation PR. |
@trentmwillis ++. do you mind? It would be great to have it tested and documented. |
d4e3c5d
to
b4694d6
Compare
@leobalter updated with a test and updated the doc PR as well. Travis failed but it looks like it's for the same reason the master build is failing currently. |
I'm sick of browserstack-runner timeouts. |
@leobalter @gibson042 is the only remaining question whether or not we should consider this breaking? If so, I'd be fine with feature-flagging this somehow or delaying merge until 2.0. |
@trentmwillis, I really want to merge and release a new version with it, but I might need to release a major version. I'm running on other necessary changes (the warning api) to release the next major, so releasing this feature won't be a problem. |
@leobalter a major version sounds good. Will let this sit until ready then. |
@trentmwillis good work! |
b4694d6
to
45874fa
Compare
@leobalter this has been rebased and should be good to go. Care to do a once over since it's been awhile? |
As discussed in #893. Included tests for the following in support of this feature:
before
runs beforebeforeEach
after
runs afterafterEach
after
only runs after last test in modulebefore
only runs before first test in modulebefore
with a promiseafter
with a promisebefore
with an assert.asyncafter
with an assert.asyncbefore
hooksafter
hooksbefore
are applied to all tests