openzeppelin-test-helpers icon indicating copy to clipboard operation
openzeppelin-test-helpers copied to clipboard

Support expectEvent testing for multiple emits of the same event in a transaction

Open abcoathup opened this issue 4 years ago • 9 comments

Support expectEvent testing for multiple emits.

Currently expectEvent will pass for 1 or more emits of the event.

Raised by a community member in Telegram: https://forum.openzeppelin.com/t/test-for-multiple-emits-of-the-same-event-with-expectevent/4106

abcoathup avatar Oct 26 '20 00:10 abcoathup

Also looking for support for this feature. Thanks

fabdarice avatar Apr 08 '21 05:04 fabdarice

Would something like the following work, with a new options argument specifying the times the event should show up.

expectEvent(receipt, 'Foo', { arg1: 'bar' }, { times: 2 });

And this function would return the array of found events.

frangio avatar Apr 09 '21 14:04 frangio

Not really, events could be emitted many times but with different values

fab-spring avatar Apr 09 '21 14:04 fab-spring

In that case you can use subsequent calls to expectEvent.

expectEvent(receipt, 'Foo', { arg1: 'bar' });
expectEvent(receipt, 'Foo', { arg1: 'quux' });

Otherwise I'm not sure I'm understanding the request. Can someone provide an example of what they would like to write and how they would want it to behave?

frangio avatar Apr 09 '21 20:04 frangio

For example: my contract loops through the conditions, and each time generates the same event, but for example the result changes

SSharshunov avatar Aug 14 '21 11:08 SSharshunov

if (x == 1 || x == 2) {
    uint y = doCalc(some1, some0);
    emit yCalculated(x, y); // Triggering event
    if (x == 2) {
        uint y2 = doCalc(some0, some1);
        emit yCalculated(x, y2); // Triggering event
    }
}

SSharshunov avatar Aug 14 '21 11:08 SSharshunov

@SSharshunov In this you would also want to check that the events are emitted in the correct order?

frangio avatar Aug 17 '21 23:08 frangio

if (x == 1 || x == 2) {
    uint y = doCalc(some1, some0);
    emit yCalculated(x, y); // Triggering event
    if (x == 2) {
        uint y2 = doCalc(some0, some1);
        emit yCalculated(x, y2); // Triggering event
    }
}

Just call the expectEvent and pass the right event name and the values of said events

If you are expecting 3 events of Transfer

expecteEvent(tx, 'Transfer', {from:0x.., to:0x.., value:value}
expecteEvent(tx, 'Transfer', {from:0x.., to:0x.., value:value}
expecteEvent(tx, 'Transfer', {from:0x.., to:0x.., value:value}

The value MUST be of type BigNumber or a String, else expectEvent would give you a misleading error expected {expected} but got {actual} cause it only throws the very first error in the error array, which isn't the actual error. expectEvent Source I had to go into the library function to find this.

zikyfranky avatar Feb 12 '22 12:02 zikyfranky

Does anyone know how to use it for multiple events in one function?

RUIRUI-ashui avatar Jun 26 '22 08:06 RUIRUI-ashui