Search code examples
mocha.jses6-promisechaisolidity

Array destructuring returned from promises not working as expected


I am using Mocha and Chai for writing tests for a smart contract deployed on the development blockchain with truffle.

I have a contract named Election which contains two candidates.

The test code is as follows:

it("Checking the properties for candidates", () => {
    return Election.deployed().then((app) => {
      return [app.candidates(1), app];
    }).then(params => {
      const [candidate1, app] = params;
      assert.equal(candidate1.id, 0);
      return [app.candidates(1), app];
    }).then(params => {
      const [candidate2, app] = params;
      assert.equal(candidate2.id, 1);
    });
  });

The test cases pass when I am not using the array destructuring to return app.candidates() and an instance of the app. In that case I had to declare a global variable, assign it to app and use it in every scope. But I want to avoid defining a global variable. I came across this post on SO which suggests using ES6 destructuring.

But here I am getting candidate1.id and candidate2.id both as undefined.

What am I doing wrong here?


Solution

  • Why are you returning from an it? It's not needed, they should only throw.

    I strongly recommend avoiding this .then syntax and npm i chai-as-promised --save-dev then install it like this:

    const chai = require('chai');
    const chaiAsPromised = require('chai-as-promised');
    
    // Must install Chai as Promised last - https://github.com/domenic/chai-as-promised/#node
    chai.use(chaiAsPromised);
    
    // Disable object truncating - https://stackoverflow.com/a/23378037/1828637
    chai.config.truncateThreshold = 0;
    
    global.expect = chai.expect;
    

    Then you would do:

    it("Checking the properties for candidates", async () => {
        expect(Election.deployed()).to.eventually.satisfy(app => app.candidates(1).id === 0)
            and.satisfy(app => app.candidates(2).id === 1);
    });
    

    If app.candidates returns a promise, maybe can even do this, I'm not sure about async function to argument of satisfy though.

    it("Checking the properties for candidates", async () => {
        expect(Election.deployed()).to.eventually.satisfy(async app => {
            await expect(app.candidates(1)).to.eventually.be.an('object').that.has.property('id', 0);
            await expect(app.candidates(2)).to.eventually.be.an('object').has.property('id', 1);
        });
    });