Here is my test code for the Dex I made for my cat Dave.
The only extra tests I added were to simply check that the limit orders were being added to the order book. This is because I realized that the tests that check the sort order of the book would pass if the order books remained empty.
const DaveDex = artifacts.require('DaveDex');
const Link = artifacts.require('Link');
const truffleAssert = require('truffle-assertions');
// The buyer mast have ETH deposited such that deposited eth >= buy order value
// the seller must have enough tokens deposited such that token balance > sell order amount
// the first order ([0]) in the BUY order book should have the highest price
// the last order ([0]) in the BUY order book should have the lowest price
contract('DaveDex', accounts => {
let dex, link;
const LINK = web3.utils.fromUtf8('LINK');
const BUY = 0;
const SELL= 1;
before(async ()=> {
dex = await DaveDex.deployed();
link = await Link.deployed();
// Add LINK token to DEX
await dex.addToken(LINK, link.address, { from: accounts[0] });
// Approve LINK deposits
await link.approve(dex.address, 1000, { from: accounts[0] });
});
it('should throw an error if ETH balance is too low when creating a BUY order', async () => {
await truffleAssert.reverts(
// Create BUY order for 5 LINK @ 2 ETH/LINK
dex.createLimitOrder(LINK, BUY, 5, 2, { from: accounts[0] })
);
// Deposit 10 ETH to DEX
await dex.depositEth({ from: accounts[0], value: 10 });
await truffleAssert.passes(
// Create BUY order for 5 LINK @ 2 ETH/LINK
dex.createLimitOrder(LINK, BUY, 5, 2, { from: accounts[0] })
);
});
it('should throw an error if TOKEN balance is too low when creating a SELL order', async () => {
// Create SELL order without any LINK deposited
await truffleAssert.reverts(
dex.createLimitOrder(LINK, SELL, 100, 1)
);
// Deposit 1000 LINK
await dex.deposit(1000, LINK, { from: accounts[0] });
// Create SELL order for 5 LINK @ 2 ETH/LINK
await truffleAssert.passes(
dex.createLimitOrder(LINK, SELL, 5, 2, { from: accounts[0] })
)
});
it('the BUY order book should contain limit orders created by the createLimitOrder function', async () => {
await dex.depositEth({ from: accounts[1], value: 10 })
await truffleAssert.passes(
dex.createLimitOrder(LINK, BUY, 10, 1, { from: accounts[1] })
)
let buyOrderBook = await dex.getOrderBook(LINK, BUY)
await expect(buyOrderBook.length).to.be.at.least(1)
})
it('the SELL order book should contain limit orders created by the createLimitOrder function', async () => {
await truffleAssert.passes(
dex.createLimitOrder(LINK, SELL, 10, 10, { from: accounts[0] })
)
let sellOrderBook = await dex.getOrderBook(LINK, SELL)
await expect(sellOrderBook.length).to.be.at.least(1)
})
it('the BUY order book should be ordered on price from highest to lowest starting at index 0', async () => {
// Deposit ETH to DEX
await dex.depositEth({ from: accounts[0], value: 10 });
await dex.depositEth({ from: accounts[1], value: 10 });
await dex.depositEth({ from: accounts[2], value: 10 });
// Create BUY orders
await dex.createLimitOrder(LINK, BUY, 1, 3, { from: accounts[2] });
await dex.createLimitOrder(LINK, BUY, 1, 1, { from: accounts[0] });
await dex.createLimitOrder(LINK, BUY, 1, 2, { from: accounts[1] });
// BUY order book for LINK
let orderBook = await dex.getOrderBook(LINK, BUY);
for(let i=0; i<orderBook.length-1; i++) {
await expect(Number(orderBook[i].price)).to.be.gte(Number(orderBook[i+1].price))
}
});
it('the SELL order book should be ordered on price from lowest to highest starting at index 0', async () => {
// Create SELL orders
await dex.createLimitOrder(LINK, SELL, 1, 10, { from: accounts[0] });
await dex.createLimitOrder(LINK, SELL, 1, 8, { from: accounts[0] });
await dex.createLimitOrder(LINK, SELL, 1, 9, { from: accounts[0] });
// SELL order book for LINK
let orderBook = await dex.getOrderBook(LINK, SELL);
for(let i=0; i<orderBook.length-1; i++) {
await expect(Number(orderBook[i].price)).to.be.lte(Number(orderBook[i+1].price))
}
});
});