-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Fix .only() behaviour when running with watch option, fixes #2429 #2544
Conversation
@davidspinat thanks. can you please sign the CLA? |
@boneskull of course 👍 |
@boneskull may I help you with something else? :) |
@davidspinat Sorry, bandwidth problems. This may not be feasible, but can you provide an integration test? If you're having trouble, I can dig deeper and suggest something. Failing that, maybe you see if you can't re-create the problem via other means... |
@boneskull Sorry haven't managed to provide an integration test. However I would suggest the following: In https://github.com/mochajs/mocha/blob/master/test/integration/helpers.js#L64 we might extend the signature of
Further we would need to modify What's your opinion? |
For the record, I had the same issue as reported in #2429 and just tested this branch locally, it works and fixes issue. Not the same as automated tests, but considering the two changes relatively trivial, maybe its good enough. |
@boneskull how should we proceed here? :) |
@boneskull : just curious if this is being, or has been, integrated yet. My team has been watching this page for months, waiting to update our Mocha version until this issue is fixed, as we found the problem with ".only()" to break behavior we had relied on. This ticket is still listed as open, but if you've integrated this into a recent version, please let us know. Thank you! |
Is this bug getting fixed any time soon? |
Is there any chance this PR will be merged? How might we add a test which covers this fix? I guess everyone would love to see this merged. Please leave some feedback. Greetings |
@davidspinat Can you please revert the change to the root |
A proper harness for testing watch-related behavior would be necessary if we were to make enhancements in this subsystem (or re-implement it). The risk here is that the change involves code that's run regardless of whether |
@@ -795,7 +795,7 @@ Runner.prototype.run = function (fn) { | |||
var rootSuite = this.suite; | |||
|
|||
// If there is an `only` filter | |||
if (this.hasOnly) { | |||
if (hasOnly(rootSuite)) { |
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.
Okay, so it looks like with the addition of --forbid-only
, this may need some changes.
Runner#hasOnly
is set if e.g. a describe.only()
is encountered (see lib/interfaces/common.js
).
The --forbid-only
functionality will check this value. At the point that it's checked, the Runner
may or may not have a suite
property. This means there's likely some weird interactions between --forbid-only
and --watch
.
A solution may be to set Runner#hasOnly
to true
if the result of hasOnly()
is true
. hasOnly()
may also want to check the value of Runner#hasOnly
. When the Runner
's end
event is handled, it may also need to reset Runner#hasOnly
to false
.
I haven't fiddled with this too much, but this is the matrix we're trying to assert is OK:
describe.only()
it.only()
--watch
--forbid-only
For example, run a --watch
with --forbid-only
, then add a describe.only()
, save, then remove it again & save. What happens?
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.
(careful with nested suites here; hasOnly()
looks like it only inspects the innards of any given suite, and not if that suite was itself marked as an "only" suite; that information is stored in the aforemention suite's parent! 😄)
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.
Worth noting that #2874 also touches hasOnly
-using code in addition to the --forbid-only
code already merged doing so.
(I plan on a more detailed review later this week.)
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 should be merged correctly now, I think.
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.
will need further experimentation and/or tests
@@ -795,7 +795,7 @@ Runner.prototype.run = function (fn) { | |||
var rootSuite = this.suite; | |||
|
|||
// If there is an `only` filter | |||
if (this.hasOnly) { | |||
if (hasOnly(rootSuite)) { |
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.
(careful with nested suites here; hasOnly()
looks like it only inspects the innards of any given suite, and not if that suite was itself marked as an "only" suite; that information is stored in the aforemention suite's parent! 😄)
I can't say how long I was running this branch locally, might've been a few weeks though. I never noticed any regressions. Looks like this will requires further changes now - let me know if I can help testing the result. |
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.
(TL;DR? Recommendations at the bottom.)
on design and concerns
(careful with nested suites here; hasOnly() looks like it only inspects the innards of any given suite, and not if that suite was itself marked as an "only" suite; that information is stored in the aforemention suite's parent! 😄)
As long as it's used only on:
- the root suite
- inside the
filterOnly
function
...it should be fine. (And I believe that's the case here.) If we're really paranoid, we could make the existing hasOnly
function only accessible to two other functions: filterOnly
and a runner-level hasOnly
function that calls this existing hasOnly
against the root suite, the new runner-level hasOnly
function being what we would use here and in the forbidding-related code (see also second section). Alternatively, again if we're really paranoid, maybe we could update the hasOnly
function to also check suite.parent._onlySuites.indexOf(suite) >= 0
or something like that? But as long as stuff's tested I don't think either of those is a necessity (see more on that in the rest of this section).
A proper harness for testing watch-related behavior would be necessary if we were to make enhancements in this subsystem (or re-implement it).
If someone had come up with one by now I'd be all for using it, and it would be great to come up with one so we can start in on trying to deal with other watch-related behavior, but for this particular fix I'm not convinced it's worth holding up on something that hard to figure out -- given that the hasOnly
function can be tested to be correct on any given run and merely won't get stale like the hasOnly
property. And speaking of testing for correctness on any given run...
The risk here is that the change involves code that's run regardless of whether --watch is invoked.
...I'm not sure there's much risk involved in this regard since we already have tests for the behavior of only
in general. Surely those cover it?
Of course, if somebody can come up with a test that doesn't use --watch
but does run the tests twice with only
d suites/tests removed the second time, to reproduce the same issue that this fixes, we should incorporate that test into this PR; but (again) I'm fairly confident in the correctness of this particular change without such tests -- as long as we don't break the tests we already have, we at least won't be getting worse than we are now.
on what is required of this PR (including intersection with forbidding)
As far as I can tell, effectively, any place that the hasOnly
property is being used ought to be replaced with calling the hasOnly
function against the root suite. (The hasOnly
property is on the runner, so all such replacements would be equivalent to using the hasOnly
function against the root suite, and are thus safe/correct.) Prior to the addition of the forbid
options, this PR addressed the only use that I'm aware of; however the forbid
options are now using it (and the additional PR #2874 moves that usage to achieve error reporting). That means a few things are going to need to happen:
- This PR should be rebased so it doesn't leave
hasOnly
property usages inmaster
that were added after this was initially devised. (That will also be a good opportunity to drop the changes to the bundledmocha.js
file.) - This PR should additionally remove the place(s) where the
hasOnly
property is being set (lib/reporters/common.js
andlib/mocha.js
, not to be confused with the bundledmocha.js
), so that any future changes to use ofhasOnly
(such as Print failures for pending/only forbidden #2874) will be detected to fail tests if they use the property rather than the function. (Note that I wanted this done sooner or later anyway because, as discussed in --watch option works strangely with.only()
#2429, the root cause of the problem here is needing a single source of truth.) - Either this PR's rebase should wait till Print failures for pending/only forbidden #2874 lands, or Print failures for pending/only forbidden #2874 will have to be updated to use the
hasOnly
function after this PR lands. (I am comfortable personally taking responsibility to handle the update to Print failures for pending/only forbidden #2874 if need be.)
@boneskull Any serious concerns with those recommendations, given the rationale and responses to concerns laid out above?
Waaait a second, I just realized something else: @mochajs/core is
In other words, if (That's not my preferred course of action in principle simply because I'd rather get the root cause corrected now, but backwards compatibility of public interfaces would necessitate it if |
if it's documented or marked I have no problems with a major release. lets fix root causes. |
Quick assessment on that:
Seems like a bit of a side-channel on top of everything else... |
Wow, just failed rebasing that one. Will fix that. |
Changes Unknown when pulling 46e82ed on davidspinat:issue-2429 into ** on mochajs:master**. |
Just updated the PR to include the requested changes. Please let me know if i didn't manage to meet your feedback. I'm happy to help.
Cheers. |
[Editted to add] TL;DR: It doesn't look like this will affect anyone on GitHub if we remove Went through all the GitHub code results (yes, all forty pages) for
I'm marking my prior request for changes as having been satisfied, in any case. |
3182c61
to
6486de0
Compare
Still trying to figure out if I'm merging master into this correctly (which was necessary because conflicts); there's one failing test, looking into that. |
8b81379
to
6486de0
Compare
lib/runner.js
Outdated
@@ -429,7 +429,7 @@ Runner.prototype.runTest = function (fn) { | |||
if (!test) { | |||
return; | |||
} | |||
if (this.forbidOnly && this.hasOnly) { | |||
if (this.forbidOnly && hasOnly(this.parents().reverse()[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.
...Just realized this still isn't right, because it won't work for tests outside of any describe
. Remind me to add a test for that, but first, gonna fix this and merge...
176ca11
to
6486de0
Compare
(mochajs#2544) * Fix .only() behaviour when running with watch option * Remove all occurrences of the hasOnly property
Since version
3.0.0
thewatch
option does not work as expected in combination with.only()
.@fediev already described in detail #2429 the misbehaviour.