@ethereum-waffle/chai
Version:
A sweet set of chai matchers for your blockchain testing needs.
81 lines • 4.14 kB
JavaScript
import { utils } from 'ethers';
import { keccak256, toUtf8Bytes } from 'ethers/lib/utils';
import { callPromise } from '../call-promise';
import { waitForPendingTransaction } from './misc/transaction';
import { supportWithArgs } from './withArgs';
import { supportWithNamedArgs } from './withNamedArgs';
export function supportEmit(Assertion) {
const filterLogsWithTopics = (logs, topic, contractAddress) => logs.filter((log) => log.topics.includes(topic))
.filter((log) => log.address &&
(contractAddress === undefined || log.address.toLowerCase() === contractAddress.toLowerCase()));
const assertEmit = (assertion, frag, isNegated, from) => {
const topic = keccak256(toUtf8Bytes(frag.format()));
const receipt = assertion.txReceipt;
assertion.args = filterLogsWithTopics(receipt.logs, topic, from);
const isCurrentlyNegated = assertion.__flags.negate === true;
assertion.__flags.negate = isNegated;
assertion.assert(assertion.args.length > 0, `Expected event "${frag.name}" to be emitted, but it wasn't`, `Expected event "${frag.name}" NOT to be emitted, but it was`);
assertion.__flags.negate = isCurrentlyNegated;
};
Assertion.addMethod('emit', function (contractOrEventSig, eventName) {
if (typeof this._obj === 'string') {
if (typeof contractOrEventSig === 'string') {
throw new Error('The emit by event signature matcher must be called on a transaction');
}
// Handle specific case of using transaction hash to specify transaction. Done for backwards compatibility.
this.callPromise = waitForPendingTransaction(this._obj, contractOrEventSig.provider)
.then(txReceipt => {
this.txReceipt = txReceipt;
});
}
else {
callPromise(this);
}
const isNegated = this.__flags.negate === true;
this.callPromise = this.callPromise.then(() => {
if (!('txReceipt' in this)) {
throw new Error('The emit matcher must be called on a transaction');
}
let eventFragment;
if (typeof contractOrEventSig === 'string') {
try {
eventFragment = utils.EventFragment.from(contractOrEventSig);
}
catch (e) {
throw new Error(`Invalid event signature: "${contractOrEventSig}"`);
}
assertEmit(this, eventFragment, isNegated);
}
else if (eventName) {
try {
eventFragment = contractOrEventSig.interface.getEvent(eventName);
}
catch (e) {
// ignore error
}
if (eventFragment === undefined) {
this.assert(this.__flags.negate, `Expected event "${eventName}" to be emitted, but it doesn't` +
' exist in the contract. Please make sure you\'ve compiled' +
' its latest version before running the test.', `WARNING: Expected event "${eventName}" NOT to be emitted.` +
' The event wasn\'t emitted because it doesn\'t' +
' exist in the contract. Please make sure you\'ve compiled' +
' its latest version before running the test.', eventName, '');
return;
}
assertEmit(this, eventFragment, isNegated, contractOrEventSig.address);
this.contract = contractOrEventSig;
}
else {
throw new Error('The emit matcher must be called with a contract and an event name or an event signature');
}
});
this.then = this.callPromise.then.bind(this.callPromise);
this.catch = this.callPromise.catch.bind(this.callPromise);
this.eventName = eventName;
this.txMatcher = 'emit';
return this;
});
supportWithArgs(Assertion);
supportWithNamedArgs(Assertion);
}
//# sourceMappingURL=emit.js.map