UNPKG

10.9 kBPlain TextView Raw
1import 'mocha'
2import * as async from 'async'
3import Web3 from 'web3';
4import * as assert from 'assert'
5import { Provider } from 'remix-simulator'
6
7import { compileFileOrFiles } from '../dist/compiler'
8import { deployAll } from '../dist/deployer'
9import { runTest, compilationInterface } from '../dist/index'
10import { ResultsInterface, TestCbInterface, ResultCbInterface } from '../dist/index'
11
12// deepEqualExcluding allows us to exclude specific keys whose values vary.
13// In this specific test, we'll use this helper to exclude `time` keys.
14// Assertions for the existance of these will be made at the correct places.
15function deepEqualExcluding(a: any, b: any, excludedKeys: string[]) {
16 function removeKeysFromObject(obj: any, excludedKeys: string[]) {
17 if (obj !== Object(obj)) {
18 return obj
19 }
20
21 if(Object.prototype.toString.call(obj) !== '[object Array]') {
22 obj = Object.assign({}, obj)
23 for (const key of excludedKeys) {
24 delete obj[key]
25 }
26
27 return obj
28 }
29
30 let newObj = []
31 for (const idx in obj) {
32 newObj[idx] = removeKeysFromObject(obj[idx], excludedKeys);
33 }
34
35 return newObj
36 }
37
38 let aStripped: any = removeKeysFromObject(a, excludedKeys);
39 let bStripped: any = removeKeysFromObject(b, excludedKeys);
40 assert.deepEqual(aStripped, bStripped)
41}
42
43let accounts: string[]
44let provider = new Provider()
45
46async function compileAndDeploy(filename: string, callback: Function) {
47 let web3: Web3 = new Web3()
48 let sourceASTs: any = {}
49 await provider.init()
50 web3.setProvider(provider)
51 let compilationData: object
52 async.waterfall([
53 function getAccountList(next: Function): void {
54 web3.eth.getAccounts((_err: Error | null | undefined, _accounts: string[]) => {
55 accounts = _accounts
56 web3.eth.defaultAccount = accounts[0]
57 next(_err)
58 })
59 },
60 function compile(next: Function): void {
61 compileFileOrFiles(filename, false, { accounts }, next)
62 },
63 function deployAllContracts(compilationResult: compilationInterface, asts, next: Function): void {
64 for(const filename in asts) {
65 if(filename.endsWith('_test.sol'))
66 sourceASTs[filename] = asts[filename].ast
67 }
68 try {
69 compilationData = compilationResult
70 deployAll(compilationResult, web3, false, next)
71 } catch (e) {
72 throw e
73 }
74 }
75 ], function (_err: Error | null | undefined, contracts: any): void {
76 callback(null, compilationData, contracts, sourceASTs, accounts)
77 })
78}
79
80
81describe('testRunner', () => {
82 let tests: any[] = [], results: ResultsInterface;
83
84 const testCallback: TestCbInterface = (err, test) => {
85 if (err) { throw err }
86
87 if (test.type === 'testPass' || test.type === 'testFailure') {
88 assert.ok(test.time, 'test time not reported')
89 assert.ok(!Number.isInteger(test.time || 0), 'test time should not be an integer')
90 }
91
92 tests.push(test)
93 }
94
95 const resultsCallback: Function = (done) => {
96 return (err, _results) => {
97 if (err) { throw err }
98 results = _results
99 done()
100 }
101 }
102
103 describe('#runTest', () => {
104 describe('test with beforeAll', () => {
105 const filename: string = 'tests/examples_1/simple_storage_test.sol'
106
107 before((done) => {
108 compileAndDeploy(filename, (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) => {
109 runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
110 })
111 })
112
113 after(() => { tests = [] })
114
115 it('should have 3 passing test', function () {
116 assert.equal(results.passingNum, 3)
117 })
118
119 it('should have 1 failing test', function () {
120 assert.equal(results.failureNum, 1)
121 })
122
123 it('should return 6 messages', function () {
124 deepEqualExcluding(tests, [
125 { type: 'accountList', value: accounts },
126 { type: 'contract', value: 'MyTest', filename: 'tests/examples_1/simple_storage_test.sol' },
127 { type: 'testPass', value: 'Initial value should be100', context: 'MyTest' },
128 { type: 'testPass', value: 'Initial value should not be200', context: 'MyTest' },
129 { type: 'testFailure', value: 'Should trigger one fail', errMsg: 'uint test 1 fails', context: 'MyTest' },
130 { type: 'testPass', value: 'Should trigger one pass', context: 'MyTest' }
131 ], ['time'])
132 })
133 })
134
135 describe('test with beforeEach', function () {
136 const filename: string = 'tests/examples_2/simple_storage_test.sol'
137
138 before(function (done) {
139 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
140 runTest('MyTest', contracts.MyTest, compilationData[filename]['MyTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
141 })
142 })
143
144 after(() => { tests = [] })
145
146 it('should have 2 passing tests', function () {
147 assert.equal(results.passingNum, 2)
148 })
149
150 it('should 0 failing tests', function () {
151 assert.equal(results.failureNum, 0)
152 })
153
154 it('should return 4 messages', function () {
155 deepEqualExcluding(tests, [
156 { type: 'accountList', value: accounts },
157 { type: 'contract', value: 'MyTest', filename: 'tests/examples_2/simple_storage_test.sol' },
158 { type: 'testPass', value: 'Initial value should be100', context: 'MyTest' },
159 { type: 'testPass', value: 'Value is set200', context: 'MyTest' }
160 ], ['time'])
161 })
162 })
163
164 // Test string equality
165 describe('test string equality', function () {
166 const filename: string = 'tests/examples_3/simple_string_test.sol'
167
168 before(function (done) {
169 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
170 runTest('StringTest', contracts.StringTest, compilationData[filename]['StringTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
171 })
172 })
173
174 after(() => { tests = [] })
175
176 it('should 2 passing tests', function () {
177 assert.equal(results.passingNum, 2)
178 })
179
180 it('should return 4 messages', function () {
181 deepEqualExcluding(tests, [
182 { type: 'accountList', value: accounts },
183 { type: 'contract', value: 'StringTest', filename: 'tests/examples_3/simple_string_test.sol' },
184 { type: 'testPass', value: 'Initial value should be hello world', context: 'StringTest' },
185 { type: 'testPass', value: 'Value should not be hello wordl', context: 'StringTest' }
186 ], ['time'])
187 })
188 })
189
190 // Test multiple directory import in test contract
191 describe('test multiple directory import in test contract', function () {
192 const filename: string = 'tests/examples_5/test/simple_storage_test.sol'
193
194 before(function (done) {
195 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
196 runTest('StorageResolveTest', contracts.StorageResolveTest, compilationData[filename]['StorageResolveTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
197 })
198 })
199
200 after(() => { tests = [] })
201
202 it('should 3 passing tests', function () {
203 assert.equal(results.passingNum, 3)
204 })
205
206 it('should return 4 messages', function () {
207 deepEqualExcluding(tests, [
208 { type: 'accountList', value: accounts },
209 { type: 'contract', value: 'StorageResolveTest', filename: 'tests/examples_5/test/simple_storage_test.sol' },
210 { type: 'testPass', value: 'Initial value should be100', context: 'StorageResolveTest' },
211 { type: 'testPass', value: 'Check if even', context: 'StorageResolveTest' },
212 { type: 'testPass', value: 'Check if odd', context: 'StorageResolveTest' }
213 ], ['time'])
214 })
215 })
216
217 //Test signed/unsigned integer weight
218 describe('test number weight', function () {
219 const filename: string = 'tests/number/number_test.sol'
220
221 before(function (done) {
222 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
223 runTest('IntegerTest', contracts.IntegerTest, compilationData[filename]['IntegerTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
224 })
225 })
226
227 after(() => { tests = [] })
228
229 it('should have 6 passing tests', function () {
230 assert.equal(results.passingNum, 6)
231 })
232 it('should have 2 failing tests', function () {
233 assert.equal(results.failureNum, 2)
234 })
235 })
236
237 // Test Transaction with custom sender & value
238 describe('various sender', function () {
239 const filename: string = 'tests/various_sender/sender_and_value_test.sol'
240
241 before(function (done) {
242 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
243 runTest('SenderAndValueTest', contracts.SenderAndValueTest, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, resultsCallback(done))
244 })
245 })
246
247 after(() => { tests = [] })
248
249 it('should have 5 passing tests', function () {
250 assert.equal(results.passingNum, 5)
251 })
252 it('should have 0 failing tests', function () {
253 assert.equal(results.failureNum, 0)
254 })
255 })
256
257 // Test `runTest` method without sending contract object (should throw error)
258 describe('runTest method without contract json interface', function () {
259 const filename: string = 'tests/various_sender/sender_and_value_test.sol'
260 const errorCallback: Function = (done) => {
261 return (err, _results) => {
262 if (err && err.message.includes('Contract interface not available')) {
263 results = _results
264 done()
265 }
266 else throw err
267 }
268 }
269 before(function (done) {
270 compileAndDeploy(filename, function (_err: Error | null | undefined, compilationData: object, contracts: any, asts: any, accounts: string[]) {
271 runTest('SenderAndValueTest', undefined, compilationData[filename]['SenderAndValueTest'], asts[filename], { accounts }, testCallback, errorCallback(done))
272 })
273 })
274
275 it('should have 0 passing tests', function () {
276 assert.equal(results.passingNum, 0)
277 })
278 it('should have 0 failing tests', function () {
279 assert.equal(results.failureNum, 0)
280 })
281 })
282 })
283})