diff --git a/lib/matchers.ts b/lib/matchers/matchers.ts similarity index 96% rename from lib/matchers.ts rename to lib/matchers/matchers.ts index c872a3032..87477f2c4 100644 --- a/lib/matchers.ts +++ b/lib/matchers/matchers.ts @@ -1,6 +1,6 @@ -import overwriteBigNumberFunction from './matchers/overwriteBigNumberFunction'; +import overwriteBigNumberFunction from './overwriteBigNumberFunction'; import {bigNumberify} from 'ethers/utils'; -import {getBalanceChange, getBalanceChanges} from './utils'; +import {getBalanceChange, getBalanceChanges} from '../utils'; import {Contract, Wallet} from 'ethers'; const solidity = (chai: any, utils: any) => { @@ -38,10 +38,10 @@ const solidity = (chai: any, utils: any) => { ); this.then = derivedPromise.then.bind(derivedPromise); this.catch = derivedPromise.catch.bind(derivedPromise); - return derivedPromise; + return this; }); - Assertion.addMethod('revertedWith', function (revertReason: any) { + Assertion.addMethod('revertedWith', function (revertReason: string) { /* eslint-disable no-underscore-dangle */ const promise = this._obj; const derivedPromise = promise.then( @@ -66,7 +66,7 @@ const solidity = (chai: any, utils: any) => { ); this.then = derivedPromise.then.bind(derivedPromise); this.catch = derivedPromise.catch.bind(derivedPromise); - return derivedPromise; + return this; }); const filterLogsWithTopics = (logs: any[], topic: any) => diff --git a/lib/matchers/matchertypes.ts b/lib/matchers/matchertypes.ts new file mode 100644 index 000000000..2e7aa6af5 --- /dev/null +++ b/lib/matchers/matchertypes.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/// +// I cannot get ethers types to work for some reason + +declare namespace Chai { + interface Assertion extends LanguageChains, NumericComparison, TypeComparison { + reverted: AsyncAssertion; + revertedWith(reason: string): AsyncAssertion; + emit(contract: any, eventName: string): EmitAssertion; + properHex(length: number): void; + properPrivateKey: void; + properAddress: void; + changeBalance(wallet: any, balance: any): AsyncAssertion; + changeBalances(wallets: any[], balances: any[]): AsyncAssertion; + } + + interface NumberComparer { + (value: any, message?: string): Assertion; + } + + interface AsyncAssertion extends Assertion, Promise { + } + + interface EmitAssertion extends AsyncAssertion { + withArgs(...args: any[]): AsyncAssertion; + } +} diff --git a/lib/waffle.ts b/lib/waffle.ts index 705ded604..51461aeca 100644 --- a/lib/waffle.ts +++ b/lib/waffle.ts @@ -1,9 +1,10 @@ import Ganache, { GanacheOpts } from 'ganache-core'; import {ContractFactory, providers, Contract, Wallet} from 'ethers'; -import matchers from './matchers'; +import matchers from './matchers/matchers'; import defaultAccounts from './config/defaultAccounts'; import defaultDeployOptions from './config/defaultDeployOptions'; import {linkSolidity4, linkSolidity5, LinkableContract} from './link'; +import './matchers/matchertypes'; const defaultGanacheOptions = {accounts: defaultAccounts}; diff --git a/test/example/example.js b/test/example/example.ts similarity index 74% rename from test/example/example.js rename to test/example/example.ts index 8513a5a99..6343e5e10 100644 --- a/test/example/example.js +++ b/test/example/example.ts @@ -1,17 +1,23 @@ import chai from 'chai'; -import {createMockProvider, deployContract, getWallets, link} from '../../lib/waffle'; -import BasicTokenMock from './build/BasicTokenMock'; -import MyLibrary from './build/MyLibrary'; -import LibraryConsumer from './build/LibraryConsumer'; -import solidity from '../../lib/matchers'; +import { + createMockProvider, + deployContract, + getWallets, + link, + solidity +} from '../../lib/waffle'; +import BasicTokenMock from './build/BasicTokenMock.json'; +import MyLibrary from './build/MyLibrary.json'; +import LibraryConsumer from './build/LibraryConsumer.json'; +import { Contract } from 'ethers'; chai.use(solidity); const {expect} = chai; describe('INTEGRATION: Example', () => { - let provider = createMockProvider(); - let [wallet, walletTo] = getWallets(provider); - let token; + const provider = createMockProvider(); + const [wallet, walletTo] = getWallets(provider); + let token: Contract; beforeEach(async () => { token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]); @@ -42,7 +48,7 @@ describe('INTEGRATION: Example', () => { .to.be.reverted; }); - it('should use library to add 7', async() => { + it('should use library to add 7', async () => { const myLibrary = await deployContract(wallet, MyLibrary, []); link(LibraryConsumer, 'test/projects/example/MyLibrary.sol:MyLibrary', myLibrary.address); const libraryConsumer = await deployContract(wallet, LibraryConsumer, []); diff --git a/test/example/fixtures-example.js b/test/example/fixtures-example.ts similarity index 78% rename from test/example/fixtures-example.js rename to test/example/fixtures-example.ts index ad34e6fd9..afc16bfc7 100644 --- a/test/example/fixtures-example.js +++ b/test/example/fixtures-example.ts @@ -1,9 +1,10 @@ import {expect} from 'chai'; import {loadFixture, deployContract} from '../../lib/waffle'; -import BasicTokenMock from './build/BasicTokenMock'; +import BasicTokenMock from './build/BasicTokenMock.json'; +import { Wallet, providers } from 'ethers'; describe('INTEGRATION: Fixtures example', () => { - async function fixture(provider, [wallet, other]) { + async function fixture(provider: providers.Provider, [wallet, other]: Wallet[]) { const token = await deployContract(wallet, BasicTokenMock, [ wallet.address, 1000 ]); diff --git a/test/matchers/balance.js b/test/matchers/balance.ts similarity index 78% rename from test/matchers/balance.js rename to test/matchers/balance.ts index 9d8100ce2..f95fa4de0 100644 --- a/test/matchers/balance.js +++ b/test/matchers/balance.ts @@ -1,19 +1,13 @@ import chai, {AssertionError} from 'chai'; import {createMockProvider, getWallets, solidity} from '../../lib/waffle'; -import {utils} from 'ethers'; +import {utils, Wallet} from 'ethers'; chai.use(solidity); const {expect} = chai; describe('INTEGRATION: Balance observers', () => { - let provider; - let sender; - let receiver; - - beforeEach(async () => { - provider = createMockProvider(); - [sender, receiver] = getWallets(provider); - }); + const provider = createMockProvider(); + const [sender, receiver] = getWallets(provider); describe('Change balance, one account', () => { it('Should pass when expected balance change is passed as string and is equal to an actual', async () => { @@ -60,7 +54,10 @@ describe('INTEGRATION: Balance observers', () => { value: 200 })) .to.changeBalance(sender, '-500') - ).to.be.eventually.rejectedWith(AssertionError, `Expected "${sender.address}" to change balance by -500 wei, but it has changed by -200 wei`); + ).to.be.eventually.rejectedWith( + AssertionError, + `Expected "${sender.address}" to change balance by -500 wei, but it has changed by -200 wei` + ); }); it('Should throw in negative case when expected balance change value was equal to an actual', async () => { @@ -74,12 +71,8 @@ describe('INTEGRATION: Balance observers', () => { }); it('Should throw when not a callback is passed to expect', async () => { - expect(() => - expect(sender.sendTransaction({ - to: receiver.address, - gasPrice: 0, - value: 200 - })).to.changeBalance(sender, '-200') + await expect(() => + expect(1).to.changeBalance(sender, '-200') ).to.throw(Error, `Expect subject should be a callback returning the Promise e.g.: await expect(() => wallet.send({to: '0xb', value: 200})).to.changeBalance('0xa', -200)`); }); @@ -95,7 +88,7 @@ describe('INTEGRATION: Balance observers', () => { .to.changeBalances([sender, receiver], ['-200', 200]); }); - it('Should pass on negative case when one of expected balance changes is not equal to an actual value', async () => { + it('Should pass when negated and numbers don\'t match', async () => { await expect(() => sender.sendTransaction({ to: receiver.address, gasPrice: 0, @@ -118,7 +111,11 @@ describe('INTEGRATION: Balance observers', () => { value: 200 })) .to.changeBalances([sender, receiver], [-200, 201]) - ).to.be.eventually.rejectedWith(AssertionError, 'Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 to change balance by -200,201 wei, but it has changed by -200,200 wei'); + ).to.be.eventually.rejectedWith( + AssertionError, + 'Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 ' + + 'to change balance by -200,201 wei, but it has changed by -200,200 wei' + ); await expect( expect(() => sender.sendTransaction({ to: receiver.address, @@ -126,7 +123,11 @@ describe('INTEGRATION: Balance observers', () => { value: 200 })) .to.changeBalances([sender, receiver], [-201, 200]) - ).to.be.eventually.rejectedWith(AssertionError, 'Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 to change balance by -201,200 wei, but it has changed by -200,200 wei'); + ).to.be.eventually.rejectedWith( + AssertionError, + 'Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 ' + + 'to change balance by -201,200 wei, but it has changed by -200,200 wei' + ); }); it('Should throw in negative case when expected balance changes value were equal to an actual', async () => { @@ -136,7 +137,11 @@ describe('INTEGRATION: Balance observers', () => { gasPrice: 0, value: 200 })).to.not.changeBalances([sender, receiver], [-200, 200]) - ).to.be.eventually.rejectedWith(AssertionError, `Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 to not change balance by -200,200 wei`); + ).to.be.eventually.rejectedWith( + AssertionError, + 'Expected 0x17ec8597ff92C3F44523bDc65BF0f1bE632917ff,0x63FC2aD3d021a4D7e64323529a55a9442C444dA0 ' + + 'to not change balance by -200,200 wei' + ); }); it('Should throw when not a callback is passed to expect', async () => { diff --git a/test/matchers/bn.js b/test/matchers/bn.ts similarity index 98% rename from test/matchers/bn.js rename to test/matchers/bn.ts index 6bdac795b..401e9b69f 100644 --- a/test/matchers/bn.js +++ b/test/matchers/bn.ts @@ -1,6 +1,6 @@ import chai, {AssertionError} from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import solidity from '../../lib/matchers'; +import {solidity} from '../../lib/waffle'; import {utils} from 'ethers'; chai.use(solidity); diff --git a/test/matchers/events.js b/test/matchers/events.ts similarity index 62% rename from test/matchers/events.js rename to test/matchers/events.ts index bef4397f5..19ba9a2f4 100644 --- a/test/matchers/events.js +++ b/test/matchers/events.ts @@ -1,8 +1,13 @@ import chai, {AssertionError} from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {createMockProvider, deployContract, getWallets} from '../../lib/waffle'; -import Events from './build/Events'; -import solidity from '../../lib/matchers'; +import { + createMockProvider, + deployContract, + getWallets, + solidity +} from '../../lib/waffle'; +import Events from './build/Events.json'; +import { Contract } from 'ethers'; chai.use(solidity); chai.use(chaiAsPromised); @@ -11,7 +16,7 @@ const {expect} = chai; describe('INTEGRATION: Events', () => { let provider; - let events; + let events: Contract; let wallet; beforeEach(async () => { @@ -41,17 +46,22 @@ describe('INTEGRATION: Events', () => { }); it('Emit both: success (two expects)', async () => { - await expect(events.emitBoth()).to.emit(events, 'One', '0x0000000000000000000000000000000000000000000000000000000000000001'); + await expect(events.emitBoth()) + .to.emit(events, 'One') + .withArgs(1, 'One', '0x0000000000000000000000000000000000000000000000000000000000000001'); await expect(events.emitBoth()).to.emit(events, 'Two'); }); it('Emit both: success (one expect with two to)' , async () => { - await expect(events.emitBoth()).to.emit(events, 'One', '0x0000000000000000000000000000000000000000000000000000000000000001') + await expect(events.emitBoth()) + .to.emit(events, 'One') + .withArgs(1, 'One', '0x0000000000000000000000000000000000000000000000000000000000000001') .and.to.emit(events, 'Two'); }); it('Event with proper args', async () => { - await (expect(events.emitOne()).to.emit(events, 'One')).withArgs(1, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123'); + await (expect(events.emitOne()).to.emit(events, 'One')) + .withArgs(1, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123'); }); it('Event with not enough args', async () => { @@ -68,19 +78,26 @@ describe('INTEGRATION: Events', () => { it('Event with one different arg (integer)', async () => { await expect( - expect(events.emitOne()).to.emit(events, 'One').withArgs(2, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123') + expect(events.emitOne()).to.emit(events, 'One') + .withArgs(2, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123') ).to.be.eventually.rejectedWith(AssertionError, 'Expected "2" to be equal 1'); }); it('Event with one different arg (string)', async () => { await expect( - expect(events.emitOne()).to.emit(events, 'One').withArgs(1, 'Two', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123') + expect(events.emitOne()).to.emit(events, 'One') + .withArgs(1, 'Two', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123') ).to.be.eventually.rejectedWith(AssertionError, 'expected \'Two\' to equal \'One\''); }); it('Event with one different arg (string)', async () => { await expect( - expect(events.emitOne()).to.emit(events, 'One').withArgs(1, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162124') - ).to.be.eventually.rejectedWith(AssertionError, 'expected \'0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162124\' to equal \'0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123\''); + expect(events.emitOne()).to.emit(events, 'One') + .withArgs(1, 'One', '0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162124') + ).to.be.eventually.rejectedWith( + AssertionError, + 'expected \'0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162124\' ' + + 'to equal \'0x00cfbbaf7ddb3a1476767101c12a0162e241fbad2a0162e2410cfbbaf7162123\'' + ); }); }); diff --git a/test/matchers/misc.js b/test/matchers/misc.ts similarity index 90% rename from test/matchers/misc.js rename to test/matchers/misc.ts index afdb4da6a..25b3aa90b 100644 --- a/test/matchers/misc.js +++ b/test/matchers/misc.ts @@ -41,13 +41,19 @@ describe('UNIT: Miscellaneous', () => { it('Expect to throw if invalid private', async () => { expect( () => expect('0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c').to.be.properPrivateKey - ).to.throw(AssertionError, 'Expected "0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c" to be a proper private key'); + ).to.throw( + AssertionError, + 'Expected "0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c" to be a proper private key' + ); }); it('Expect to throw if negation with proper private)', async () => { expect( () => expect('0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5').not.to.be.properPrivateKey - ).to.throw(AssertionError, 'Expected "0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5" not to be a proper private key'); + ).to.throw( + AssertionError, + 'Expected "0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5" not to be a proper private key' + ); }); }); diff --git a/test/matchers/reverted.js b/test/matchers/reverted.ts similarity index 92% rename from test/matchers/reverted.js rename to test/matchers/reverted.ts index b42bf1196..b7785524e 100644 --- a/test/matchers/reverted.js +++ b/test/matchers/reverted.ts @@ -1,8 +1,13 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {createMockProvider, deployContract, getWallets} from '../../lib/waffle'; -import Matchers from './build/Matchers'; -import solidity from '../../lib/matchers'; +import { + createMockProvider, + deployContract, + getWallets, + solidity +} from '../../lib/waffle'; +import Matchers from './build/Matchers.json'; +import { Contract } from 'ethers'; chai.use(solidity); chai.use(chaiAsPromised); @@ -14,9 +19,9 @@ const alwaysReject = new Promise((resolve, reject) => { }); describe('INTEGRATION: Matchers: reverted', () => { - let provider = createMockProvider(); - let [wallet] = getWallets(provider); - let matchers; + const provider = createMockProvider(); + const [wallet] = getWallets(provider); + let matchers: Contract; beforeEach(async () => { matchers = await deployContract(wallet, Matchers); @@ -67,7 +72,7 @@ describe('INTEGRATION: Matchers: reverted', () => { describe('INTEGRATION: Matchers: revertedWith', () => { let provider; - let matchers; + let matchers: Contract; let wallet; beforeEach(async () => { @@ -142,4 +147,3 @@ describe('INTEGRATION: Matchers: revertedWith', () => { ).to.be.eventually.rejected; }); }); - diff --git a/tslint.json b/tslint.json index 4b2dce233..541a97fc2 100644 --- a/tslint.json +++ b/tslint.json @@ -30,6 +30,7 @@ "allow-pascal-case" ], "no-shadowed-variable": false, - "no-empty": [true, "allow-empty-functions"] + "no-empty": [true, "allow-empty-functions"], + "no-unused-expression": false } } \ No newline at end of file