-
-
Notifications
You must be signed in to change notification settings - Fork 772
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
Refactor sandbox and allow it to stub getters and setters #1416
Conversation
Excellent work @lucasfcosta! I don't have any comments for the code. From reading the PR, I would say that this should be a new |
Thanks @mroderick! You and all the other maintainers have been doing an excellent work as well, it's great to collaborate with such good people. I'd say this is a Since I didn't need to change any test cases in order to make it pass and the API contract is still the same (even though we've got a new deprecation warning) I'd say you're correct. Btw, I always like to think about SemVer as |
I've published |
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 just found this in a pending state. I realize this is already merged. I'm fixing it in a separate ticket.
this.collection.stub(process.env, "HELL", "froze over"); | ||
assert.equals(process.env.HELL, "froze over"); | ||
|
||
deprecated.printWarning = originalPrintWarning; |
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.
Use beforeEach
and afterEach
instead. If the above assertion fails, this line will never be reached and original value of that method will be lost for the remainder of the test run.
@lucasfcosta I'm floored by your work here. I usually don't work with getters a lot, but just now I had a case where this made my test trivial: const stream = new PassThrough();
sandbox.stub(process, 'stdin').get(() => stream); // This failed without your change I wanted to say thank you ❤️ |
@mantoni I'm happy I was able to help. I love contributing to Sinon. All of you are always so kind, active and do great reviews. Actually I'm the one that should be thanking you for making the contribution experience so pleasurable and for taking care of this awesome codebase. ❤️ Whenever you need anything I'll be more than happy to help. |
Purpose (TL;DR)
This aims to fix #1401 and #781 by allowing users to stub
getters
andsetters
while using sandboxes.In order to do this I had to refactor
sandbox.stub
and add newvalue
default behavior for the sake of consistency.Another side-effect of this PR is adding the
value
default behavior to stubs, allowing users to stub thevalue
property on property descriptors.Background (Problem in detail)
As discussed in the two issues linked above, the sandbox API did not allow our users to set
getters
andsetters
for non-function properties they stubbed, because that meant we were going to callstubNonFunctionProperty
and return a raw object with a restore method. Due to this fact, the returned object would not allow us to call theget
andset
default behaviors.Another problem I explained at #781 was that by having
sandbox.stub
to accept a third argument, it was not possible to differentiate this argument from a property descriptor when we wanted to stub non-function-properties, because we would never know whether the user wanted that value to replace that property or if the user wanted that value to be the new property descriptor.GIven the way
sandbox.stub
was working, it presented a bit of duplication and error prone code, because some of the same checks we have insinon.stub
were being made differently insandbox.stub
. This could cause unwantedgetter
triggers when checking property values and therefore inconsistent behavior compared tosinon.stub
.Solution
This is how I solved these problems:
I had to create a separate utility file called
sandbox-stub.js
which does the job of handling calls to the old version of thesandbox.stub
API. The function in this file is called whenever a user passes a third argument tosandbox.stub
. Otherwise, we always call thesinon.stub
function in order to make the behavior ofsandbox.stub
as consistent as we can.This allows us to have all the default stub behaviors available on the stub created by
sandbox.stub
.Then all we have to do is add all the stubbed methods (which are more than one if we're stubbing an entire object) to the current collection.
get
andset
behaviorsSince there is no way to differentiate a descriptor from a desired property value to replace another when we allow three arguments on the
sandbox.stub
API, I added a new default behavior calledvalue
. This makes the API consistent with stubbing other values on property descriptors, such asget
andset
.In order to restore a
stubbed
non-function property a user can just call therestore
method on the created fake.This PR also has:
value
behaviorsandbox.stub
being able to stubgetters
andsetters
stubNonFunctionProperty
sandbox.stub
API to log deprecation warnings to the console. Like this, for example.How to verify - mandatory
npm install
npm test
- This runs both the old tests (proving nothing breaks) and the new ones (proving the new features work properly)As always, any feedbacks will be great, specially given it's a long PR.
Thanks for your time!