I tried to make this as short as possible and reuse code, while keeping all the tests we had done so far.
As we were creating Bob a lot, I decided it should be a function that we call every time we need to create a person. It takes age, height and amount of ETH as arguments.
Regarding balance, we need to test if the contract is counting it correctly, if correct amount is added upon createPerson() and if it is reset after the owner withdraws all. For that, I defined a balanceTest() function which we call on various moments during one People.deployed instance.
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract ("People", async function (accounts){
let instance;
let age;
let height;
let value;
async function bob(age, height, value){
await instance.createPerson("Bob", age, height, {value: web3.utils.toWei(value.toString(), "ether"), from: accounts [1]});
};
function balanceTest (){
it("counted balance should match the balance on blockchain", async function(){
let countedBalance = await instance.balance();
let chainBalance = await web3.eth.getBalance(People.address);
assert(parseInt(countedBalance) === parseInt(chainBalance));
});
};
before (async function (){
instance = await People.deployed ();
});
balanceTest(); // compares balances at the beginning
it("shouldn't create a person with age over 150", async function(){
await truffleAssert.fails(bob(200, 190, 1), truffleAssert.ErrorType.REVERT);
});
it("shouldn't create a person if payment is less than 1 ETH", async function(){
await truffleAssert.fails(bob(65, 190, 0.1), truffleAssert.ErrorType.REVERT);
});
it("should set age and senior status correctly", async function(){
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});
// bob(65, 190, 1); makes test to fail
// await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether"), from: accounts [1]}); makes test to fail
let result = await instance.getPerson();
assert(result.senior === true && result.age.toNumber() === 65, "Age or senior level not set");
});
balanceTest(); // as this is first time we create person successfully, let's check balance again
it("should allow only owner to delete", async function(){
bob(65, 190, 1);
await truffleAssert.fails(instance.deletePerson(accounts [1], {from: accounts [1]}), truffleAssert.ErrorType.REVERT);
});
it("should allow the owner to delete", async function(){
let instance = await People.new ();
bob(65, 190, 1);
await truffleAssert.passes(instance.deletePerson(accounts [1], {from: accounts [0]}), truffleAssert.ErrorType.REVERT);
});
// cannot be merged with previous test as new instance is needed
it("should allow owner but not others to withdraw all", async function(){
await truffleAssert.fails(instance.withdrawAll({from: accounts [1]}), truffleAssert.ErrorType.REVERT);
await truffleAssert.passes(instance.withdrawAll({from: accounts [0]}), truffleAssert.ErrorType.REVERT);
});
// doesn't need a new instance as withdrawAll() works also if balance is 0
it("withdrawal should drain contract balance on blockchain", async function(){
assert(parseInt(await web3.eth.getBalance(People.address)) === 0);
});
balanceTest(); // to make sure counted balance is reset as well
it("withdrawal should increase owner's balance", async function(){
bob(65, 190, 1);
let ownerBalance = await web3.eth.getBalance(accounts [0]);
await instance.withdrawAll({from: accounts [0]});
let ownerBalanceAfter = await web3.eth.getBalance(accounts [0]);
assert(parseInt(ownerBalanceAfter) > parseInt(ownerBalance));
});
})
With the code above, all the tests pass for me, and also fail if I make a deliberate error.
On it(âshould set age and senior status correctlyâ I am not using the bob() function as it caused the test to fail. I found out that if I add from: accounts [1]}), it also causes the test to fail (like said in the comment). I couldnât figure it out so I left it like that.