2

I want to write a NodeJS chai test which checks that the result of some service-call (which is an array) contains an object which is equal to what I expect. There might be some more fields in the result which I don't want to check.

There are two chai plugins which can solve this problem: chai-things (which allows you to use a syntax like expect(i).to.include.something.that.deep.equals) and chai-like (which allows you to use a syntax like expect(i).to.be.like).

But, in combination they don't work.

See this minimal working example:

const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-things'))
chai.use(require('chai-like'))

describe('the chai setup', function() {
  it('should work', function(done) {
    const i = [{
      name: 'Name A',
      age: 1
    }, {
      name: 'Name B',
      age: 2
    }]

    // Works
    expect(i).to.include.something.that.deep.equals({
      name: 'Name B',
      age: 2
    })

    // Works
    expect(i[1]).to.be.like({
      name: 'Name B'
    })

    // Doesn't work
    expect(i).to.include.something.that.like({
      name: 'Name B'
    })
    done()
  })
})

This doesn't work and throws an error message:

AssertionError: expected { name: 'Name B', age: 2 } to like { name: 'Name B' }

How can this be fixed?

theomega
  • 31,591
  • 21
  • 89
  • 127

2 Answers2

1

Using external plugins not always ends with an expected result. Most probably some of the commands collide as they are not thoroughly tested if at all tested together.

Another approach would be simply use an function and loop your array. Here is a working sample of loop using Mocka and Chai in browser:

function checkNestedObjects(obj){
    expect(obj).is.an('object')
    //expect(obj).to.have.keys(['a','b','c']); //- Fires Error
    expect(obj).to.have.keys(['a','b']);
}
    
var initArray=[{"a":1,"b":1},{"a":2,"b":2}];
for( var i=0; i < initArray.length; i++){
    checkNestedObjects(initArray[i])
}
<!DOCTYPE html>
<html>
<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.min.css" rel="stylesheet"/>
</head>
<body>
  <div id="mocha"></div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.5.3/mocha.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script>
  
  <script>mocha.setup('bdd')</script>
  <script>
    var expect = chai.expect;
    mocha.run();     
  </script>
</body>
</html>

Sometimes asynchronous functions are needed within the loop. Then the looping functions can be called with Promises. How to loop an array with forEach and how to use Promise.all to call "done()" is very good shown here: Node JS Promise.all and forEach

Community
  • 1
  • 1
user2080851
  • 718
  • 6
  • 7
1

Load chai-like before loading chai-things to make them work together:

chai.use(require('chai-like'))
chai.use(require('chai-things'))
Howard Bright
  • 11
  • 1
  • 2