[Ethereum] Watching events with truffle test

eventstestingtruffle

Given following solidity code:

pragma solidity ^0.5.1;

contract Foo {

    event FooInc(uint256 _a);
    uint256 a;

    constructor() public {
        a = 42;
    }

    function inc() public returns(bool) {
        a += 1;
        emit FooInc(a);
        return true;
    }
}

and following test javascript code:

let Foo = artifacts.require('Foo');

contract("foocontract", async accounts => {
    it("testing inc", async (done) => {
        let foo = await Foo.deployed();
        foo.allEvents().on('data', function(e) {
            console.log('allevents', e);
            done();
        });
        foo.inc().then(r => {
            console.log('done', r);         
            foo.getPastEvents('allEvents', undefined, (e, l) => {
                console.log("pastevents", e, l);
                done();
            });

        });
    });
});

The receipt from the foo.inc() promise gets logged. Neither of the event listener accessors for the contract events fire, although the receipt object shows the event was triggered.

$ truffle test
Using network 'test'.


Compiling your contracts...
===========================
> Compiling ./contracts/Foo.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-2020127-266345-9s8aje.7jzss
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



  Contract: foocontract
done {
  tx: '0x158109501fa0cecffa6c7887d05c255cb5e76002c25881f5e684ab199a75cdff',
  receipt: {
    transactionHash: '0x158109501fa0cecffa6c7887d05c255cb5e76002c25881f5e684ab199a75cdff',
    transactionIndex: 0,
    blockHash: '0x55e2fce5a0257fad6d851ba35e03885509f98a6641e3e92a146e2fbaad9e3a18',
    blockNumber: 5,
    from: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
    to: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
    gasUsed: 28961,
    cumulativeGasUsed: 28961,
    contractAddress: null,
    logs: [ [Object] ],
    status: true,
    logsBloom: '0x00000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000010000000000000',
    rawLogs: [ [Object] ]
  },
  logs: [
    {
      logIndex: 0,
      transactionIndex: 0,
      transactionHash: '0x158109501fa0cecffa6c7887d05c255cb5e76002c25881f5e684ab199a75cdff',
      blockHash: '0x55e2fce5a0257fad6d851ba35e03885509f98a6641e3e92a146e2fbaad9e3a18',
      blockNumber: 5,
      address: '0x345cA3e014Aaf5dcA488057592ee47305D9B3e10',
      type: 'mined',
      id: 'log_8dfd46f8',
      event: 'FooInc',
      args: [Result]
    }
  ]
}

I am using truffle@v5.1.14 and the docs for it suggest that it should merely be a matter of listening for javascript events data and error. What am I missing here?

Best Answer

This works for me on Truffle v4.1.16:

const Foo = artifacts.require('Foo');

contract("foocontract", async accounts => {
    it("testing inc", async (done) => {
        const foo = await Foo.deployed();
        const receipt = await foo.inc();
        printLogs("receipt", receipt.logs);
        foo.allEvents().get(function(error, logs) {
            assert.equal(error, null);
            printLogs("listened", logs);
        });
    });
});

function printLogs(title, logs) {
    for (let i = 0; i < logs.length; i++) {
        console.log();
        console.log(`${title} event #${i + 1}:`);
        console.log(JSON.stringify(logs[i], null, 4));
    }
}

You may want to try something similar on your version of Truffle.

Keep in mind that Truffle v4.x relies on web3.js v0.x, while Truffle v5.x relies on web3.js v1.x.

So there might be a few differences in how events are listened to.

Related Topic