Value Assignment
Click to Reveal Code (LONG)
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
// The STATE of the contract is preserved through each test
contract("People", async function(accounts){
let instance;
// before function runs ONCE ONLY, before ANY and ALL tests
before(async function(){
instance = await People.deployed();
});
// after();
// afterEach();
it("shouldn't create a person with age over 150 years", async function(){
// beforeEach function executes here for EVERY test
await truffleAssert.fails(instance.createPerson("Bob", 200, 175, {value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
});
it("shouldn't create a person without payment", async function(){
await truffleAssert.fails(instance.createPerson("Bob", 200, 175, {value: 1000}), truffleAssert.ErrorType.REVERT);
});
it("should set senior status correctly", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
let result = await instance.getPerson();
assert(result.senior === true, "Senior level not set");
});
it("should set age correctly", async function(){
let result = await instance.getPerson();
assert(result.age.toNumber() === 65, "Age not set correctly");
});
// To test the owner, we need to test functions in the People contract that
// only the owner should be able to do.
it("should only let the owner of the contract delete people from the contract", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}));
});
it("shouldn't let anyone except the owner of the contract delete people from the contract", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it("should only let the owner of the contract retrieve the contract owner's address", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.passes(instance.getCreator([0], {from: accounts[0]}));
});
it("shouldn't let anyone except the owner of the contract retrieve the contract owner's address", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.getCreator([0], {from: accounts[1]}));
});
it("should have the balance increase when a new person is created", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
let blockchainBalance = await web3.eth.getBalance(instance.address);
let contractBalance = await instance.balance();
assert(contractBalance == blockchainBalance, "The contract balance differs from the blockchain balance");
});
it("should only let the owner of the contract spend its balance", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
let oldContractBalance = parseInt(await instance.balance());
let oldOwnerBalance = parseInt(await web3.eth.getBalance(accounts[0]));
let withdrawal = await instance.withdrawAll({from: accounts[0]});
let newOwnerBalance = parseInt(await web3.eth.getBalance(accounts[0]));
let blockchainBalance = parseInt(await web3.eth.getBalance(instance.address));
let newContractBalance = parseInt(await instance.balance());
assert(newContractBalance == blockchainBalance, "The contract balance differs from the blockchain balance");
assert(blockchainBalance == 0, "The balance on the blockchain is not zero");
// See https://www.trufflesuite.com/docs/truffle/getting-started/interacting-with-your-contracts
// and/or https://web3js.readthedocs.io/en/v1.2.7/web3-eth.html
// for more info on commands & syntax
const gasWithdrawal = withdrawal.receipt.gasUsed;
const withdrawalTx = await web3.eth.getTransaction(withdrawal.tx);
const gasWithdrawalPrice = withdrawalTx.gasPrice;
const totalGasCost = gasWithdrawal * gasWithdrawalPrice
// Inputs - Outputs = Fees
// --> Inputs - Fees = Outputs
assert.equal(oldOwnerBalance + oldContractBalance - totalGasCost, newOwnerBalance, "The contract balance has not been withdrawn correctly")
});
it("shouldn't let anyone except the owner of the contract spend its balance", async function(){
await instance.createPerson("Bob", 65, 175, {value: web3.utils.toWei("1", "ether")});
await instance.createPerson("Carol", 39, 155, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
})
Definitely the most tricky assignment so far. The penultimate ‘it’ statement regarding only letting the owner of the contract withdraw its balance was coded quite thoroughly. I saw some much shorter solutions throughout the forum, but I wanted to encapsulate everything that Filip mentioned in the assignment video into the test function.
I learnt that the getBalance
function returns a string rather than a number (couldn’t think of a reason why, maybe strings take less memory?), so I found out about the parseInt
function to change strings into integers.
I also learnt about the functions receipt
, gasUsed
, getTransaction
and gasPrice
. When I initially ran the tests, I was finding small discrepancies between the owner’s before and after balances. Then I realised I forgot about the gas fees!
Peopletest.js Final Result