Skip to content

Commit

Permalink
release 0.7.3 (#173)
Browse files Browse the repository at this point in the history
* web3Function tests, bug fix (#172)

* Test contract decoration matches snapshot

* Update yarn.lock

* Improve Contract test coverage

* Classify existing Contract tests as unit tests

* Run contract tests with multiple web3 versions

* Clear localStorage between contract tests

* Improve comment

* Remove redundant comment

* Mock websocket in contract test

* Remove mock-socket from contract tests

* Only snapshot test a subset of decoratedContract

* Remove redundant logic

* Mock the web3 websocket connection

* Cleanup

* Use a complex ABI for contract decoration tests

* Refactor contract delegation for web3 >beta.37

* Improve comments

* Hardcode userAgent in tests

* Setup a ganache instance for use in the test env

* Improve ganache error handling

* Create web3.js test structure

* - Add test for web3Func bigNumber
- Add test for web3Func gasPrice

* Handle restarting ganache when jest is watching

* Add test for web3Funcs.contractGas

* Set ganache account generation to be deterministic

* - Add test for web3Func txGas
- Add test for web3Func balance
- Add test for web3Func accounts
- Add test for web3Func txReceipt

* Create ganacheConfig.js

* Deploy contract to testing ganache chain

* Remove redundant console.log

* Add truffle-contract dependency

* Change the contract deployed to test ganache chain

* Test estimating gas of a truffle method call

* Reduce logic duplication

* Improve comments

* Explicitly end tests once ganache is shutdown

* Fix estimateGas on truffle contract methods

* use latest web3 beta 55 in tests

* update to 0.7.3
  • Loading branch information
cmeisl authored May 13, 2019
1 parent 77afd27 commit de4038f
Show file tree
Hide file tree
Showing 11 changed files with 1,656 additions and 30 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ yarn add bnc-assist
#### Script Tag

The library uses [semantic versioning](https://semver.org/spec/v2.0.0.html).
The current version is 0.7.2.
The current version is 0.7.3.
There are minified and non-minified versions.
Put this script at the top of your `<head>`

```html
<script src="https://assist.blocknative.com/0-7-2/assist.js"></script>
<script src="https://assist.blocknative.com/0-7-3/assist.js"></script>

<!-- OR... -->

<script src="https://assist.blocknative.com/0-7-2/assist.min.js"></script>
<script src="https://assist.blocknative.com/0-7-3/assist.min.js"></script>
```

### Initialize the Library
Expand Down
14 changes: 14 additions & 0 deletions internals/ganacheConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const port = 8546
const accounts = [
'0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1',
'0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0'
]
const args = ['-i 5', `-p ${port}`, '-a 2', '--deterministic']
const convertLibAddress = '0xe78a0f7e598cc8b0bb87894b0f60dd2a88d6a8ab'

module.exports = {
args,
port,
accounts,
convertLibAddress
}
78 changes: 78 additions & 0 deletions internals/jestReporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-console */
/* eslint-disable class-methods-use-this */
const kill = require('kill-port')
const Web3 = require('web3')
const { spawn } = require('child_process')
const convertLib = require('../src/__tests__/res/ConvertLib.json')
const { args, port, accounts } = require('./ganacheConfig.js')

class Reporter {
constructor(globalConfig) {
this._globalConfig = globalConfig
}

// checks if jest was run with --watch or --watchall
watching() {
return this._globalConfig.watch || this._globalConfig.watchAll
}

// start a ganache instance before test run starts
async onRunStart() {
console.log(`Starting Ganache on port ${port}`)
await kill(port)
this.ganacheProcess = spawn('./node_modules/.bin/ganache-cli', args)

this.ganacheProcess.on('close', code => {
if (code !== 0 && code !== 137) {
console.log(`Ganache process closed with code ${code}`)
process.exit(code)
}
!this.watching() && process.exit(code)
})
this.ganacheProcess.on('error', code => {
console.error(`ERROR: Ganache exited with code ${code}`)
process.exit(code)
})
this.ganacheProcess.on('exit', code => {
if (code === 1) {
console.error(`ERROR: Ganache exited with code ${code}`)
console.error(
`Is there already a process already running on port ${port}?`
)
process.exit(code)
}
!this.watching() && process.exit(code)
})

// Wait until ganache is running
await new Promise(resolve => {
this.ganacheProcess.stdout.setEncoding('utf8')
this.ganacheProcess.stdout.on('data', chunk => {
if (chunk.includes('Listening')) {
console.log(`Ganache running on port ${chunk.split(':')[1]}`)
resolve()
}
})
})

// Deploy a contract for truffle testing
this.web3 = new Web3(`ws://localhost:${port}`)
const convertLibWeb3 = await new this.web3.eth.Contract(convertLib.abi)
convertLibWeb3
.deploy({ data: convertLib.bytecode })
.send({ from: accounts[0], gasLimit: 1500000 })

// Ganache setup done, tests will now execute
}

// On completion kill the ganache instance and exit the test run
async onRunComplete() {
this.web3.currentProvider.connection.close()
kill(port)
.then(() => !this.watching() && process.exit(0))
.catch(() => console.error(`Failed to kill ganache on port ${port}`))
}
}

module.exports = Reporter
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ module.exports = {
// projects: null,

// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
reporters: ['default', './internals/jestReporter.js'],

// Automatically reset mock state between every test
// resetMocks: false,
Expand Down
2 changes: 1 addition & 1 deletion multidep.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"path": "multidep_modules",
"versions": {
"web3": [
"1.0.0-beta.54",
"1.0.0-beta.55",
"1.0.0-beta.46",
"1.0.0-beta.37",
"0.20.6"
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bnc-assist",
"version": "0.7.2",
"version": "0.7.3",
"description": "Blocknative Assist js library for Dapp developers",
"main": "lib/assist.min.js",
"scripts": {
Expand Down Expand Up @@ -56,11 +56,13 @@
"eslint-plugin-import": "^2.17.2",
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-prettier": "^3.0.0",
"ganache-cli": "^6.4.3",
"husky": "^1.3.1",
"jest": "^23.6.0",
"jest-cli": "^23.6.0",
"jest-css-modules": "^1.1.0",
"jest-dom": "^3.0.0",
"kill-port": "^1.4.0",
"mock-socket": "^8.0.5",
"mockdate": "^2.0.2",
"multidep": "^2.0.2",
Expand All @@ -74,6 +76,7 @@
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-string": "^2.0.2",
"rollup-plugin-uglify": "^6.0.0",
"truffle-contract": "^4.0.15",
"web3": "^1.0.0-beta.37"
},
"eslintIgnore": [
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/js/contract/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7614,7 +7614,7 @@ Object {
}
`;

exports[`using web3 1.0.0-beta.54 Contract function is called it doesn't fail and returns the expected decorated contract 1`] = `
exports[`using web3 1.0.0-beta.55 Contract function is called it doesn't fail and returns the expected decorated contract 1`] = `
Object {
"BatchRequest": [Function],
"_jsonInterface": undefined,
Expand Down
199 changes: 199 additions & 0 deletions src/__tests__/js/web3.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import truffleContract from 'truffle-contract'
import da from '~/js'
import abi from '~/__tests__/res/dstoken.json'
import { state, initialState, updateState } from '~/js/helpers/state'
import * as websockets from '~/js/helpers/websockets'
import { web3Functions } from '~/js/helpers/web3'
import convertLibJson from '~/__tests__/res/ConvertLib'
import {
accounts,
convertLibAddress,
port
} from '../../../internals/ganacheConfig'

const multidepRequire = require('multidep')('multidep.json')

const Web3v0p20 = multidepRequire('web3', '0.20.6')

const zeroAddress = '0x0000000000000000000000000000000000000000'

const initWeb3 = (simpleVersion, Web3) => {
if (simpleVersion === '1.0') {
return new Web3(`ws://localhost:${port}`)
}
const provider = new Web3.providers.HttpProvider(`http://localhost:${port}`)
return new Web3(provider)
}

describe(`web3.js tests`, () => {
multidepRequire.forEachVersion('web3', (version, Web3) => {
describe(`using web3 ${version}`, () => {
describe('assist is initialised correctly', () => {
let web3
let config
let simpleVersion
beforeEach(() => {
jest
.spyOn(websockets, 'openWebsocketConnection')
.mockImplementation(() => {})
simpleVersion = version.slice(0, 3)
web3 = initWeb3(simpleVersion, Web3)
config = { dappId: '123', web3, networkId: '5' }
da.init(config)
})
afterEach(() => {
// need to close any websocket connection
if (simpleVersion === '1.0') {
web3.currentProvider.connection.close()
}
})
describe('web3Functions', () => {
describe('networkId', () => {
test('should return the expected networkId', async () => {
const networkId = await web3Functions.networkId(simpleVersion)()
if (simpleVersion === '1.0') expect(networkId).toEqual(5)
else expect(networkId).toEqual('5') // 0.20 returns networkId as a string
})
})
describe('bigNumber', () => {
test('should return the expected bigNumber', async () => {
const bigNum1 = await web3Functions.bigNumber(simpleVersion)(5)
const bigNum2 = await web3Functions.bigNumber(simpleVersion)('10')
expect(typeof bigNum1).toEqual('object')
expect(bigNum1.toString()).toEqual('5')
expect(bigNum1.toNumber()).toEqual(5)
expect(bigNum1.add(bigNum2).toString()).toEqual('15')
})
})
describe('gasPrice', () => {
test('should return the expected gasPrice', async () => {
const expected = '20000000000' // recommended gasPrice should be 20000000000
const gasPrice = await web3Functions.gasPrice(simpleVersion)()
expect(gasPrice.toString()).toEqual(expected)
})
})
describe('contractGas', () => {
let contract
describe('from a web3 contract', () => {
beforeEach(() => {
contract = web3.eth.contract
? web3.eth.contract(abi).at(zeroAddress) // web3 0.20
: new web3.eth.Contract(abi, zeroAddress) // web3 1.0
})
test('should return the expected gas cost', async () => {
const expected = 21400 // gas the setOwner call should cost
const contract = web3.eth.contract
? web3.eth.contract(abi).at(zeroAddress) // web3 0.20
: new web3.eth.Contract(abi, zeroAddress) // web3 1.0
const contractMethod = contract.methods
? contract.methods.setOwner // web3 1.0
: contract.setOwner // web3 0.20
const parameters = [zeroAddress]
const contractGas = await web3Functions.contractGas(
simpleVersion
)(contractMethod, parameters, {})
expect(contractGas).toEqual(expected)
})
})
describe('from a truffle contract', () => {
let contractInstance
beforeEach(async () => {
state.config.truffleContract = true
contract = truffleContract(convertLibJson)
contract.setProvider(
new Web3v0p20.providers.HttpProvider(
`http://localhost:${port}`
)
)
contractInstance = await contract.at(convertLibAddress)
})
afterEach(() => {
state.config.truffleContract = false
})
// doesn't seem to work
// see https://github.com/blocknative/assist/issues/171
test('should return the expected gas cost', async () => {
const expected = 21988 // gas the convert call should cost
const contractMethod = contractInstance.convert
const parameters = [5, 10]
const contractGas = await web3Functions.contractGas(
simpleVersion
)(contractMethod, parameters)
expect(contractGas).toEqual(expected)
})
})
})
describe('transactionGas', () => {
test('should return the expected gas cost', async () => {
const expected = 21464 // gas this tx should cost
const estimate = await web3Functions.transactionGas(
simpleVersion
)({
to: '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe',
data:
'0xc6888fa10000000000000000000000000000000000000000000000000000000000000003'
})
expect(estimate).toEqual(expected)
})
})
describe('balance', () => {
test(`should return an address's balance`, async () => {
const expected = '100000000000000000000' // 100 ETH
const balance = await web3Functions.balance(simpleVersion)(
accounts[1]
)
expect(balance.toString()).toEqual(expected)
})
})
describe('accounts', () => {
test(`should return the correct list of accounts`, async () => {
const expected =
simpleVersion === '1.0'
? accounts
: accounts.map(a => a.toLowerCase())
const res = await web3Functions.accounts(simpleVersion)()
expect(res).toEqual(expected)
})
})
describe('txReceipt', () => {
test(`should return the correct receipt`, async () => {
const hash = await new Promise(resolve => {
if (simpleVersion === '1.0') {
web3.eth
.sendTransaction({
from: accounts[0],
to: zeroAddress,
value: 10
})
.on('transactionHash', hash => {
resolve(hash)
})
} else {
web3.eth.sendTransaction(
{
from: accounts[0],
to: zeroAddress,
value: 10
},
(err, hash) => resolve(hash)
)
}
})
const receipt = await web3Functions.txReceipt(hash)
expect(receipt.to).toEqual(zeroAddress)
expect(receipt).toHaveProperty('blockNumber')
expect(receipt).toHaveProperty('transactionHash')
})
})
})
})
})
})
})

afterEach(() => {
document.body.innerHTML = ''
updateState(initialState)
window.localStorage.clear()
jest.clearAllMocks()
})
Loading

0 comments on commit de4038f

Please sign in to comment.