1

I'm testing an api with the wonderful Mocha and Should.js.

I do a GET and receive an array of objects, for example:

[{
  username: 'boris',
  something: 123
},
{ 
  username: 'jeremy',
  something: 456
},
{ 
  username: 'steven',
  something: 789
},
{ ... },
{ ... },
{ ... }]

For each object, I want to make sure that the username value matches a property in a different object:

mockUsernames = {
    a  : 'bill',
    b  : 'ben',
    c  : 'boris'
};

How can you achieve this? As an example I want something like this:

.get()
...

  var someData = res.body;

  someData.forEach(function (e){
    e.username.should.equal(mockUsernames.a || mockUsernames.b || mockUsernames.c);
  });

...

As expected this doesn't work as I want because should.equal uses equal comparison operator.

Any recommended should.js methods would be v.appreciated. I can't seem to find what I want, or maybe this should be approached differently.

Tony Barnes
  • 2,625
  • 1
  • 18
  • 29

2 Answers2

1

Assuming that mockUserNames (or the names contained therein) can also be an array, you have a few options:

// Check one by one
someData.forEach(function(e) {
  mockUsernames.should.containEql(e.username);
});

// Check all in one go
mockUsernames.should.containDeep(someData.map(function(d) {
  return d.username;
}));

// If someData contains the same name multiple times, the previous method fails.
// Using `lodash` we can generate a list of unique names.
var _     = require('lodash');
var names = _.uniq(_.pluck(someData, 'username'));

mockUsernames.should.containDeep(names);

Documentation:

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks Robert, pretty perfect! I was aware of `containEql` and `containDeep` - think i've been looking at this for too long and wanting to use an object rather than an array. – Tony Barnes Aug 28 '15 at 13:26
  • The `map` approach is really nice, however `containDeep`/map ordering doesn't seem to work well with more items. Eg: `expected Array [ 'bill', 'ben', 'boris' ] to contain Array [ 'bill', 'boris', 'ben', 'bill', 'bill']`. (I haven't really used map yet). Do you know if there is a way to have map 'check' without order? Because `containDeep` doesn't check order. – Tony Barnes Aug 28 '15 at 13:34
  • 1
    @TonyBarnes I added an additional solution that uses `lodash` to make sure that the list of username is unique. – robertklep Aug 28 '15 at 13:44
  • There is .containDeepOrdered of order matter – den bardadym Aug 28 '15 at 16:46
0

I could suggest such way:

var should = require('should');

var res = [{
   username: 'boris',
   something: 123
 },
 { 
   username: 'jeremy',
   something: 456
 },
 { 
   username: 'steven',
   something: 789
}];

var mockUsernames = [ 'bill', 'ben', 'boris'];

res.should.matchEvery(function(it) { return mockUsernames.indexOf(it.username) >= 0 });
/* throws
AssertionError: expected Array [
  Object { something: 123, username: 'boris' },
  Object { something: 456, username: 'jeremy' },
  Object { something: 789, username: 'steven' }
] to match each Function { name: '' }
    expected Object { something: 456, username: 'jeremy' } to match Function { name: '' }
    at Assertion.fail (/Users/den/Projects/shouldjs/should.js/lib/assertion.js:180:17)
    at Assertion.prop.value (/Users/den/Projects/shouldjs/should.js/lib/assertion.js:65:17)
...
*/

mockUsernames = ['boris', 'steven', 'jeremy'];
res.should.matchEvery(function(it) { return mockUsernames.indexOf(it.username) >= 0 });//not throws
den bardadym
  • 2,747
  • 3
  • 25
  • 27