How to test for events that are dispatched in a nested operation?

Use openzeppelin-test-helpers expectEvent.inTransaction to test for events from other contracts

https://github.com/OpenZeppelin/openzeppelin-test-helpers#async-intransaction-txhash-emitter-eventname-eventargs--

async inTransaction (txHash, emitter, eventName, eventArgs = {})

Same as inLogs , but for events emitted in an arbitrary transaction (of hash txHash ), by an arbitrary contract ( emitter ), even if it was indirectly called (i.e. if it was called by another smart contract and not an externally owned account).


I put together the following sample code to illustrate

B.test.js

const { expectEvent } = require('openzeppelin-test-helpers');

const A = artifacts.require('A');
const B = artifacts.require('B');

contract('B', function () {
  beforeEach(async function () {
    this.a = await A.new();
    this.b = await B.new(this.a.address);
  });

  it('does stuff', async function () {
    const receipt = await this.b.doBStuff();

    // Log-checking will not only look at the event name, but also the values, which can be addresses, strings, numbers, etc.
    await expectEvent.inLogs(receipt.logs, 'DidBStuff', { message: "B" });
    await expectEvent.inTransaction(receipt.tx, A, 'DidAStuff', { message: "A" });
  });
});

A.sol

pragma solidity ^0.5.0;

contract A {

    function doAStuff() public {
        emit DidAStuff("A");
    }

    event DidAStuff(string message);
}

B.sol

pragma solidity ^0.5.0;

import "./A.sol";

contract B {

    A _a;

    constructor(A a) public {
        _a = a;
    }

    function doBStuff() public {
        _a.doAStuff();
        emit DidBStuff("B");
    }

    event DidBStuff(string message);
}
2 Likes