Skip to content

Commit

Permalink
Updated example; getWallets has no async now; delete contractWithWall…
Browse files Browse the repository at this point in the history
…et (TrueFiEng#55)
  • Loading branch information
marekkirejczyk authored Jan 15, 2019
1 parent 74c4442 commit d84ecc5
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 69 deletions.
54 changes: 33 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ Sweeter, simpler, faster than Truffle.
* __Faster__: Strong focus on the speed of tests execution.

## Features:
* Sweet set of chai matchers
* Easy contract importing from npm modules
* Fast compilation with native and dockerized solc
* Typescript compatible
* Fixtures that help write fast and maintainable test suites
* Well [documented](https://ethereum-waffle.readthedocs.io/en/latest/)
* Sweet set of chai matchers, e.g.:
* `expect(...).to.be.revertedWith('Error message')`
* `expect(...).to.emitEvent(contract, 'EventName).withArgs(...)`)
* Importing contracts from npm modules working out of the box, e.g.:
* `import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";`
* Fixtures that help write fast and maintainable test suites, e.g.:
* `const {token} = await loadFixture(standardTokenWithBalance);`
* Sub-second compilation with native and dockerized solc
* Support for TypeScript
* [Documentation](https://ethereum-waffle.readthedocs.io/en/latest/)


## Documentation
Expand All @@ -36,21 +40,27 @@ yarn add ethereum-waffle

## Step by step guide

### Add external dependency:
To add external library add npm to your project:

```sh
npm i open-zeppelin
```

### Example contract
Below is example contract written in Solidity. Place it in `contracts` directory of your project:

```solidity
pragma solidity ^0.5.1;
import "../BasicToken.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
contract BasicTokenMock is BasicToken {
// Example class - a mock class using delivering from ERC20
contract BasicTokenMock is ERC20 {
constructor(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
super._mint(initialAccount, initialBalance);
}
}
```

Expand All @@ -61,20 +71,18 @@ Belows is example test written for the contract above written with Waffle. Place
import chai from 'chai';
import {createMockProvider, deployContract, getWallets, solidity} from 'ethereum-waffle';
import BasicTokenMock from './build/BasicTokenMock';
import MyLibrary from './build/MyLibrary';
import LibraryConsumer from './build/LibraryConsumer';

chai.use(solidity);

const {expect} = chai;

describe('Example', () => {
let provider;
describe('INTEGRATION: Example', () => {
let provider = createMockProvider();
let [wallet, walletTo] = getWallets(provider);
let token;
let wallet;
let walletTo;

beforeEach(async () => {
provider = createMockProvider();
[wallet, walletTo] = await getWallets(provider);
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
});

Expand All @@ -84,7 +92,6 @@ describe('Example', () => {

it('Transfer adds amount to destination account', async () => {
await token.transfer(walletTo.address, 7);
expect(await token.balanceOf(wallet.address)).to.eq(993);
expect(await token.balanceOf(walletTo.address)).to.eq(7);
});

Expand All @@ -94,11 +101,16 @@ describe('Example', () => {
.withArgs(wallet.address, walletTo.address, 7);
});

it('Can not transfer above the amount', async () => {
await expect(token.transfer(walletTo.address, 1007)).to.be.reverted;
});

it('Can not transfer from empty account', async () => {
const tokenFromOtherWallet = contractWithWallet(token, walletTo);
const tokenFromOtherWallet = token.connect(walletTo);
await expect(tokenFromOtherWallet.transfer(wallet.address, 1))
.to.be.revertedWith('Not enough balance on sender account');
.to.be.reverted;
});

});
```

Expand Down
2 changes: 1 addition & 1 deletion docs/source/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Get example wallets
Get wallets you can use to sign transactions:
::

[wallet, walletTo] = await getWallets(provider);
[wallet, walletTo] = getWallets(provider);

You can get up to ten wallets.

Expand Down
32 changes: 16 additions & 16 deletions docs/source/start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,16 @@ Below is example contract written in Solidity. Place it in ``contracts`` directo

pragma solidity ^0.5.1;

import "../BasicToken.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract BasicTokenMock is BasicToken {

// Example class - a mock class using delivering from ERC20
contract BasicTokenMock is ERC20 {
constructor(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
super._mint(initialAccount, initialBalance);
}

}


Writing first tests
-------------------
Belows is example test written for the contract above written with Waffle. Place it in ``test`` directory of your project:
Expand All @@ -45,20 +43,18 @@ Belows is example test written for the contract above written with Waffle. Place
import chai from 'chai';
import {createMockProvider, deployContract, getWallets, solidity} from 'ethereum-waffle';
import BasicTokenMock from './build/BasicTokenMock';
import MyLibrary from './build/MyLibrary';
import LibraryConsumer from './build/LibraryConsumer';

chai.use(solidity);

const {expect} = chai;

describe('Example', () => {
let provider;
describe('INTEGRATION: Example', () => {
let provider = createMockProvider();
let [wallet, walletTo] = getWallets(provider);
let token;
let wallet;
let walletTo;

beforeEach(async () => {
provider = createMockProvider();
[wallet, walletTo] = await getWallets(provider);
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
});

Expand All @@ -68,7 +64,6 @@ Belows is example test written for the contract above written with Waffle. Place

it('Transfer adds amount to destination account', async () => {
await token.transfer(walletTo.address, 7);
expect(await token.balanceOf(wallet.address)).to.eq(993);
expect(await token.balanceOf(walletTo.address)).to.eq(7);
});

Expand All @@ -78,11 +73,16 @@ Belows is example test written for the contract above written with Waffle. Place
.withArgs(wallet.address, walletTo.address, 7);
});

it('Can not transfer above the amount', async () => {
await expect(token.transfer(walletTo.address, 1007)).to.be.reverted;
});

it('Can not transfer from empty account', async () => {
const tokenFromOtherWallet = contractWithWallet(token, walletTo);
const tokenFromOtherWallet = token.connect(walletTo);
await expect(tokenFromOtherWallet.transfer(wallet.address, 1))
.to.be.revertedWith('Not enough balance on sender account');
.to.be.reverted;
});

});


Expand Down
7 changes: 2 additions & 5 deletions lib/waffle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function createMockProvider(ganacheOptions: GanacheOpts = {}) {
return new providers.Web3Provider(Ganache.provider(options));
}

export async function getWallets(provider: providers.Provider) {
export function getWallets(provider: providers.Provider) {
return defaultAccounts.map((account) => new Wallet(account.secretKey, provider));
}

Expand Down Expand Up @@ -40,9 +40,6 @@ export async function deployContract(
return new Contract(receipt.contractAddress, abi, wallet);
}

export const contractWithWallet = (contract: Contract, wallet: Wallet) =>
new Contract(contract.address, contract.interface.abi, wallet);

export const link = (contract: LinkableContract, libraryName: string, libraryAddress: string) => {
const {object} = contract.evm.bytecode;
if (object.indexOf('$') >= 0) {
Expand Down Expand Up @@ -73,7 +70,7 @@ export function createFixtureLoader(provider = createMockProvider(), wallets?: W
await provider.send('evm_snapshot', []);
return matchingSnapshot.data;
}
const data = await fixture(provider, wallets || await getWallets(provider));
const data = await fixture(provider, wallets || getWallets(provider));
const id = await provider.send('evm_snapshot', []);
snapshots.push({fixture, data, id});
return data;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"chai-string": "~1.4.0",
"fs-extra": "^7.0.0",
"mocha": "^5.1.1",
"openzeppelin-solidity": "^1.11.0",
"openzeppelin-solidity": "^2.1.1",
"sinon": "^6.1.5",
"sinon-chai": "^3.2.0",
"solium": "^1.1.8",
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('E2E: Compiler integration', () => {

it('links library', async () => {
const provider = createMockProvider();
const [wallet] = await getWallets(provider);
const [wallet] = getWallets(provider);
const libraryPath = resolve(join(configuration.targetPath, 'MyLibrary.json'));
const MyLibrary = require(libraryPath);
const LibraryConsumer = deepCopy(require(resolve(join(configuration.targetPath, 'Two.json'))));
Expand Down
13 changes: 5 additions & 8 deletions test/example/example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import chai from 'chai';
import {createMockProvider, deployContract, getWallets, contractWithWallet, link} from '../../lib/waffle';
import {createMockProvider, deployContract, getWallets, link} from '../../lib/waffle';
import BasicTokenMock from './build/BasicTokenMock';
import MyLibrary from './build/MyLibrary';
import LibraryConsumer from './build/LibraryConsumer';
Expand All @@ -9,14 +9,11 @@ chai.use(solidity);
const {expect} = chai;

describe('INTEGRATION: Example', () => {
let provider;
let provider = createMockProvider();
let [wallet, walletTo] = getWallets(provider);
let token;
let wallet;
let walletTo;

beforeEach(async () => {
provider = createMockProvider();
[wallet, walletTo] = await getWallets(provider);
token = await deployContract(wallet, BasicTokenMock, [wallet.address, 1000]);
});

Expand All @@ -40,9 +37,9 @@ describe('INTEGRATION: Example', () => {
});

it('Can not transfer from empty account', async () => {
const tokenFromOtherWallet = contractWithWallet(token, walletTo);
const tokenFromOtherWallet = token.connect(walletTo);
await expect(tokenFromOtherWallet.transfer(wallet.address, 1))
.to.be.revertedWith('Not enough balance on sender account');
.to.be.reverted;
});

it('should use library to add 7', async() => {
Expand Down
2 changes: 1 addition & 1 deletion test/matchers/balance.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('INTEGRATION: Balance observers', () => {

beforeEach(async () => {
provider = createMockProvider();
[sender, receiver] = await getWallets(provider);
[sender, receiver] = getWallets(provider);
});

describe('Change balance, one account', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/matchers/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('INTEGRATION: Events', () => {

beforeEach(async () => {
provider = createMockProvider();
[wallet] = await getWallets(provider);
[wallet] = getWallets(provider);
events = await deployContract(wallet, Events);
});

Expand Down
6 changes: 2 additions & 4 deletions test/matchers/reverted.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ const alwaysReject = new Promise((resolve, reject) => {
});

describe('INTEGRATION: Matchers: reverted', () => {
let provider;
let provider = createMockProvider();
let [wallet] = getWallets(provider);
let matchers;
let wallet;

beforeEach(async () => {
provider = createMockProvider();
[wallet] = await getWallets(provider);
matchers = await deployContract(wallet, Matchers);
});

Expand Down
11 changes: 4 additions & 7 deletions test/projects/example/mock/BasicTokenMock.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
pragma solidity ^0.5.1;

import "../BasicToken.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";


// mock class using BasicToken
contract BasicTokenMock is BasicToken {

// Example class - a mock class using delivering from ERC20
contract BasicTokenMock is ERC20 {
constructor(address initialAccount, uint256 initialBalance) public {
balances[initialAccount] = initialBalance;
totalSupply_ = initialBalance;
super._mint(initialAccount, initialBalance);
}

}
7 changes: 4 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3842,9 +3842,10 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"

openzeppelin-solidity@^1.11.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz#7b9c55975e73370d4541e3442b30cb3d91ac973a"
openzeppelin-solidity@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.1.1.tgz#a929b63f30846ff429354a510a719624d7f4abc2"
integrity sha512-kvVI/2n3oYfVYP53rUw+q6QNPlorwYRFaGu/Zs+TWFw2tKlnrz7UXh0UTWYd3Sfbq6eOo4XXnGv4bgcKguOrWg==

os-homedir@^1.0.0:
version "1.0.2"
Expand Down

0 comments on commit d84ecc5

Please sign in to comment.