-
-
Notifications
You must be signed in to change notification settings - Fork 769
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
Maps matchers #1215
Maps matchers #1215
Conversation
Damn, you're productive around XMas! I am busy having holidays so will need to check back. |
AFAICT, Map wasn't implemented in IE until IE11. Will the saucelabs tests error out in IE10 when merged into I would suggest using https://github.com/medikoo/es6-map in the test file, to ensure that the tests can run, even when |
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.
Thank you for the PR @lucasfcosta.
I only have a few comments.
var arrayToString = Array.prototype.toString; | ||
|
||
// This is an `every` implementation that works for all iterables | ||
var every = function (obj, fn) { |
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.
Would you mind extracting this to it's own file in lib/sinon/util/core/
, and sprinkle a few tests?
return pass; | ||
}; | ||
|
||
var iterableToString = function (obj) { |
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.
Would you mind extracting this to it's own file in lib/sinon/util/core/
, and sprinkle a few tests?
Thanks for the feedback @mroderick, that's a great idea indeed! It will be a lot better to test these functions individually just to make sure they're working whenever we need to make changes on methods that use them. It makes the whole code a lot safer to change. Regarding the IE10 tests, they (hopefully) won't fail on Let me know if I misunderstood what you've said or if you disagree. I can do whatever you think it's better. 😄 @fatso83 hahahaha I'm a bit lonely this during this year's holidays so I'm having a lot of time to work on Open Source and study things. Don't worry about reviewing this fast, I'm already very grateful for you all to be reading these PRs and giving me feedback. Make sure you spend quality time with your friends and loved ones on these holidays 😄 |
eed4caf
to
c2a8bd7
Compare
ea30483
to
6e3a677
Compare
I have just move those methods to the core and added tests for them. EDIT: I have just noticed the coverage decreased because the |
Adding code that patches the run system in Sinon is not a good idea. It will lead to false negatives: running tests using Sinon will then give the impression that code works on platforms that does not support those features. But as soon as one removes Sinon the code starts breaking. That reminds me that I made a mistake in accepting the I don't mind adding a polyfill in the test code, mind you. |
"use strict"; | ||
var typeOf = require("../../typeOf"); | ||
|
||
module.exports = function (obj) { |
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.
To aid in debugging, especially in less capable JavaScript engines, it is a good practice to name essential functions. I would suggest naming this one iterableToString
.
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 totally agree, I always name my functions whether they get assigned to a variable or are used only once, I just thought you prefer these functions to not have names due to what I've seen in other files.
Thanks for the feedback!
return typeof item === "string" ? "'" + item + "'" : String(item); | ||
} | ||
|
||
if (typeOf(obj) === "map") { |
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 my eyes iterableToString
is a higher abstraction function that covers two input scenarios, Map
or generic input.
I would suggest de-structuring the iterableToString
function to call lower abstraction functions, perhaps something like this.
"use strict";
var typeOf = require("../../typeOf");
function stringify(item) {
return typeof item === "string" ? "'" + item + "'" : String(item);
}
function mapToString(map) {
var representation = "";
map.forEach(function (value, key) {
representation += "[" + stringify(key) + "," + stringify(value) + "],";
});
representation = representation.slice(0, -1);
return representation;
}
function genericIterableToString(obj) {
var representation = "";
obj.forEach(function (value) {
representation += stringify(value) + ",";
});
representation = representation.slice(0, -1);
return representation;
}
module.exports = function iterableToString(obj) {
if (typeOf(obj) === "map") {
return mapToString(obj);
}
return genericIterableToString(obj);
};
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.
Excellent idea, it really looks better.
Thanks for the help!
}); | ||
|
||
it("returns an String representation of Map objects", function () { | ||
if (typeof Map === "function") { |
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.
Wouldn't it be better to wrap the it
statement with the conditional, like you did in match-test.js
?
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 it would be better since then this test would not count as passed, it would just be ignored.
Well noticed, thanks!
}); | ||
|
||
it("returns an String representation of Set objects", function () { | ||
if (typeof Set === "function") { |
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.
Same question as above regarding wrapping the it
statement with the conditional
Thanks everyone for your feedback, I've just learned a lot by reading your considerations! 😄 |
The ramifications of letting the Promise polyfill enter the main Sinon code escaped me at the time I reviewed sinonjs#1211, but it struck me when reviewing sinonjs#1215 that had similar issues. In short: having the polyfill bundled with Sinon will lead to false negatives: running tests using Sinon will then give the impression that code works on platforms that does not support the features that were polyfilled. This reverts the introduction of `native-promise-only` in the main code and moves it to its proper place: the test code.
The ramifications of letting the Promise polyfill enter the main Sinon code escaped me at the time I reviewed #1211, but it struck me when reviewing #1215 that had similar issues. In short: having the polyfill bundled with Sinon will lead to false negatives: running tests using Sinon will then give the impression that code works on platforms that does not support the features that were polyfilled. This reverts the introduction of `native-promise-only` in the main code and moves it to its proper place: the test code.
6e3a677
to
cc92daa
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.
All looks great, but just to improve on the general standard would you mind naming the anonymous functions?
"use strict"; | ||
|
||
// This is an `every` implementation that works for all iterables | ||
module.exports = function (obj, fn) { |
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.
Name anonymous function to aid debugging (ref previous review).
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.
Yup, I'm doing this right now, I'm a bit of an anxious guy so I have this bad habit of pushing commits as soon as I do any rebase.
|
||
match.map = match.typeOf("map"); | ||
|
||
match.map.deepEquals = function (expectation) { |
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.
Name anonymous function to aid debugging (ref previous review).
"use strict"; | ||
var typeOf = require("../../typeOf"); | ||
|
||
module.exports = function iterableToString(obj) { |
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.
Name anonymous function to aid debugging (ref previous review).
cc92daa
to
c0f9856
Compare
1 similar comment
I've just finished this, here are all the changes 😄 I definitely gotta stop doing multiple pushes to my fork while working, I always forget about this coveralls bot 😅 I've named all the anonymous functions added in this PR and I've also improved As for the Anyway, would you like to add it? What do you think its better? Also, thanks for the feedback, it was really valuable. |
@lucasfcosta, sorry for jumping the gun. I just got the email about it being updated, so jumped on it. Please do add the polyfills if you can find some decent ones, but add it to the test suites, not the main library. See 942fc53 for why and how. |
@fatso83 Don't worry, actually it's me that should not do a push everytime I rebase something. I've been trying to use some symbol Polyfills but none of them seem to reimplement |
@lucasfcosta Well, we could fix the polyfills, submit a PR, and use a github branch reference while we might for it to be merged upstream? Might be a bit of a detour of course ... On the other hand, if I understand you correctly, the polyfill for Symbol at polyfill.io seems to implement |
@fatso83 Yeah, I thought about that, but it would definitely be a detour, however, if that's the only way to fix this, we've gotta do it. I tried a couple more possibilities including the service you listed and none of them seemed to work. Apparently I also tried to use core-js and the only way to override All the other individual polyfills I've tried didn't address this too. I'm running out of ideas, I guess I'll just have to implement it somewhere. |
You know what, let's just leave it for now. I will merge this, as the tests have been implemented and are being run and that is the main thing. Upping the coverage report is not "up there" on the priority list IMHO. Any objections? Otherwise I'll merge this ASAP as every other item has been checked off the review list. |
The changes have been implemented.
@fatso83 I'll work on another PR for If I can't find a way to fix it in that PR I'll just reimplement For now, I'd just like to thank everyone for the feedback and for your work, it helped a lot. 😄 |
|
It seems like these tests are failing because In Chai we've got this awesome module for type-detection and it works pretty well. Maybe we could start using it instead of this I have substituted var type = require('type-detect');
module.exports = function typeOf(value) {
return type(value).toLowerCase();
}; And every test is still passing. However, I need to set up karma in order to test properly in IE11. Edit: My speculation was wrong. Apparently this is a problem regarding how the Map and Set objects were created. I'm still investigating it. |
I managed to discover the reason of this error:
This happens because the it("returns an String representation of Set objects", function () {
var set = new Set();
set.add(1);
set.add("one");
set.add(true);
set.add(undefined);
set.add(null);
var expected = "1,'one',true,undefined,null";
assert.equals(iterableToString(set), expected);
}); However, when running the other tests in that stack trace on my IE11 VM they didn't fail.
|
Hmm weird. I still think your type library is interesting. We are not doing this because we like maintaining code, so if it is better and well maintained; all the better. Maybe a later PR ;) |
Purpose (TL;DR) - mandatory
As discussed on #1210, this adds the following matchers for the
Map
type:sinon.match.map(map)
- Requires an object to be aMap
sinon.match.map.deepEquals(map)
- Requires aMap
to be deep equal another onesinon.match.map.contains(map)
- Requires aMap
to contain each one of the items the given map has.This also adds tests for each matcher and updates the docs.
Background (Problem in detail)
Due to the fact that the
order
of elements should not mean anything in aMap
(and we can't really have any item's index), I didn't include thestartsWith
andendsWith
matchers for Maps.Since the old matchers should work for
Array
objects only, the new ones forMap
andSet
objects will be strict as well.This PR adds matchers for Maps only, I'll be working on the Sets matchers as soon as this gets merged. I'm submitting this one first because I want to make sure we all agree on the spec before going further.
How to verify - mandatory
npm install
npm run test
- This will run the newly created testsLet me know if I missed something or if there's anything to improve and I'll happily update this PR. It's always great to hear your feedback.
Thanks for reading this 😄