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

Arrays passed to `.keys()` assertions are sorted (unexpectedly) by side-effect #359

Merged
merged 1 commit into from Feb 6, 2015

Conversation

Projects
None yet
2 participants
@gregglind
Contributor

gregglind commented Feb 4, 2015

Example

var chai = require("chai");

var orig = ["b", "a"];
var mykeys = ["b","a"];
var O = {
  "b": 1,
  "a": 2
};

chai.expect(mykeys).deep.equal(orig);
chai.expect(O).keys(mykeys);
chai.expect(mykeys).deep.equal(orig);
// AssertionError: expected [ 'a', 'b' ] to deeply equal [ 'b', 'a' ]

This is caused by the .sort() at https://github.com/chaijs/chai/blob/master/lib/chai/core/assertions.js#L1070

Possible Repairs

  1. remove the sort()
  2. clone / copy the expected list earlier in the function.
  3. Something else

Other implications

  • unknown, thus my ask :) I don't know Chai's code base and there may be other sort issues. I didn't see any.

Action Request

If this sounds good, I can write up a PR tomorrow with whichever solution makes the most sense.

gregglind added a commit to gregglind/chai that referenced this pull request Feb 4, 2015

@gregglind gregglind force-pushed the gregglind:b359-unexpected-keys-sort branch from c0f7b76 to ed77323 Feb 4, 2015

gregglind added a commit to gregglind/chai that referenced this pull request Feb 4, 2015

@gregglind

This comment has been minimized.

Contributor

gregglind commented Feb 4, 2015

(updated PR for style. Hard to find prior art on anons/closures in the tests!)

@keithamus

This comment has been minimized.

Member

keithamus commented Feb 5, 2015

Fantastic issue @gregglind! I wish every issue was as detailed as this 😄

expect(obj).keys(expected);
expect(expected).deep.equal(backup);
})()

This comment has been minimized.

@keithamus

keithamus Feb 5, 2015

Member

Stylistically I think these can just be inlined - I dont think there is a need for a closure. If you want to you could create a new it() test instead.

This comment has been minimized.

@gregglind

gregglind Feb 5, 2015

Contributor
  1. Thanks for the compliments! Chai is super useful on my most recent project at Mozilla.
  2. Closure it because
  • it seemed a little gross no matter where I put it.
  • I don't want to leak any of the vars out, and want to
  • make it clear it's part of keys(array) testing.
  1. Nested 'it' isn't called, afaict (so sad!), so tried this:
  it.only("keys(array), array should keep original order (#359)", function () {
    var expected = [ 'b', "a" ];
    var backup = expected.slice(0);
    var obj = { "b": 1, "a" :1 };
    expect(expected).deep.equal(backup);
    expect(obj).keys(expected);
    expect(expected).deep.equal(backup);
  });

It's clearer, but less elegant.

As an inline alternative.

    var issue359 = {
      original:  ['b', 'a'],
      expected: [ 'b', "a" ],
      obj: { "b": 1, "a" : 1 };
    }

    expect(issue359.expected).deep.equal(issue359.original);
    expect(issue359.obj).keys(issue359.expected);
    expect(issue359.expected, "keys should maintain original order").deep.equal(issue359.backup);

Or

    var keys_maintain_original_order_issue359 = function () {
      var expected = [ 'b', 'a' ];
      var original_order = expected.slice(0);
      var obj = { "b": 1, "a" :1 };
      expect(expected).deep.equal(original_order);
      expect(obj).keys(original_order);
      expect(expected, "sorting happened unexpectedly in keys()")
        .deep.equal(original_order);
    }
    keys_maintain_original_order_issue359();

Anyway, this is a weird case. I think I lean toward the last style. And this is probably more time on this than is really needed :) (But fun to consider alternatives!)

(pull updated to reflect last)

@gregglind gregglind force-pushed the gregglind:b359-unexpected-keys-sort branch from ed77323 to d26d39f Feb 5, 2015

gregglind added a commit to gregglind/chai that referenced this pull request Feb 5, 2015

@gregglind

This comment has been minimized.

Contributor

gregglind commented Feb 5, 2015

(updated patch)

.deep.equal(original_order);
}
keys_maintain_original_order_issue359();

This comment has been minimized.

@keithamus

keithamus Feb 5, 2015

Member

Sorry @gregglind, I don't think I made myself clear in the last message. There is no need for these assertions to be made inside a new function scope at all. Line 606, 614 and 615 can be completely removed, so as to keep the code inline with the other assertions - at the same indentation level. Alternatively if you feel like separating the test, it should go in a new it() e.g.

it('keys(array) does not mutate array'. function () {
...
})

If you do a new it() test, it will need to be on the same indentation level as the other it()s.

@gregglind gregglind force-pushed the gregglind:b359-unexpected-keys-sort branch from d26d39f to 68f3c02 Feb 6, 2015

@gregglind

This comment has been minimized.

Contributor

gregglind commented Feb 6, 2015

All right, went with new it test. Coverage is still 100%, all tests pass.

@keithamus

This comment has been minimized.

Member

keithamus commented Feb 6, 2015

Thanks so much @gregglind for sticking with it. Code is perfect now, fantastic job 😄

keithamus added a commit that referenced this pull request Feb 6, 2015

Merge pull request #359 from gregglind/b359-unexpected-keys-sort
Arrays passed to `.keys()` assertions are sorted (unexpectedly) by side-effect

@keithamus keithamus merged commit bd72280 into chaijs:master Feb 6, 2015

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details

gregglind added a commit to gregglind/chai that referenced this pull request Feb 7, 2015

WIP chaijs#359. Questions inside
- *before* didn't throw on too many args for Array.  Claim in bug to do so for Object. So throw on both?  Neither?

gregglind added a commit to gregglind/chai that referenced this pull request Feb 7, 2015

WIP re chaijs#359. Questions inside
- *before* didn't throw on too many args for Array.  Claim in bug to do so for Object. So throw on both?  Neither?

gregglind added a commit to gregglind/chai that referenced this pull request Feb 8, 2015

fix chaijs#359. Add `.keys(object)
- `.keys(object)n => .keys(Object.keys(Object)`
- added exceptions for 'if first arg is non-string, then it must be only
arg.  => `.keys(Array|Object, ...)`

Warning:  `Object.keys` must exist on systems to use this functionality.

gregglind added a commit to gregglind/chai that referenced this pull request Feb 8, 2015

fix chaijs#359. Add `.keys(object)
- `.keys(object)n => .keys(Object.keys(Object)`
- added exceptions for 'if first arg is non-string, then it must be only
arg.  => `.keys(Array|Object, ...)`

Warning:  `Object.keys` must exist on systems to use this functionality.

gregglind added a commit to gregglind/chai that referenced this pull request Feb 9, 2015

fix chaijs#359. Add `.keys(object)
- `.keys(object)n => .keys(Object.keys(Object)`
- added exceptions for 'if first arg is non-string, then it must be only
arg.  => `.keys(Array|Object, ...)`

Warning:  `Object.keys` must exist on systems to use this functionality.

@keithamus keithamus referenced this pull request Feb 12, 2015

Closed

Get a proper changelog #366

@renovate renovate bot referenced this pull request Feb 2, 2018

Open

Update dependency chai to v4 #30

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment