var async = require('async')
var changeCase = require('change-case')
var Web3 = require('web3')

function getAvailableFunctions (jsonInterface) {
  return jsonInterface.reverse().filter((x) => x.type === 'function').map((x) => x.name)
}

function getTestFunctions (jsonInterface) {
  let specialFunctions = ['beforeAll', 'beforeEach']
  return jsonInterface.filter((x) => specialFunctions.indexOf(x.name) < 0 && x.type === 'function')
}

function createRunList (jsonInterface) {
  let availableFunctions = getAvailableFunctions(jsonInterface)
  let testFunctions = getTestFunctions(jsonInterface)
  let runList = []

  if (availableFunctions.indexOf('beforeAll') >= 0) {
    runList.push({name: 'beforeAll', type: 'internal', constant: false})
  }

  for (let func of testFunctions) {
    if (availableFunctions.indexOf('beforeEach') >= 0) {
      runList.push({name: 'beforeEach', type: 'internal', constant: false})
    }
    runList.push({name: func.name, type: 'test', constant: func.constant})
  }

  return runList
}

function runTest (testName, testObject, testCallback, resultsCallback) {
  let runList = createRunList(testObject._jsonInterface)

  let passingNum = 0
  let failureNum = 0
  let timePassed = 0
  let web3 = new Web3()

  testCallback({type: 'contract', value: testName})
  async.eachOfLimit(runList, 1, function (func, index, next) {
    let method = testObject.methods[func.name].apply(testObject.methods[func.name], [])
    let startTime = Date.now()
    if (func.constant) {
      method.call().then((result) => {
        let time = Math.ceil((Date.now() - startTime) / 1000.0)
        if (result) {
          testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName})
          passingNum += 1
          timePassed += time
        } else {
          testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: 'function returned false', context: testName})
          failureNum += 1
        }
        next()
      })
    } else {
      method.send().on('receipt', function (receipt) {
        try {
          let time = Math.ceil((Date.now() - startTime) / 1000.0)
          // if (func.type === 'test') {
          let topic = Web3.utils.sha3('AssertionEvent(bool,string)')

          let matchingEvents = []
          for (let i in receipt.events) {
            let event = receipt.events[i]
            if (event.raw.topics.indexOf(topic) >= 0) {
              matchingEvents.push(web3.eth.abi.decodeParameters(['bool', 'string'], event.raw.data))
            }
          }

          if (matchingEvents.length === 0) {
            return next()
          }

          let result = matchingEvents[0]

          if (result[0]) {
            testCallback({type: 'testPass', value: changeCase.sentenceCase(func.name), time: time, context: testName})
            passingNum += 1
          } else {
            testCallback({type: 'testFailure', value: changeCase.sentenceCase(func.name), time: time, errMsg: result[1], context: testName})
            failureNum += 1
          }
          // }
        } catch (err) {
          console.log('error!')
          console.dir(err)
          return next(err)
        }
        next()
      }).on('error', function (err) {
        next(err)
      })
    }
  }, function () {
    resultsCallback(null, {
      passingNum: passingNum,
      failureNum: failureNum,
      timePassed: timePassed
    })
  })
}

module.exports = {
  runTest: runTest
}

@@ -2176,49 +2176,8 @@
 .0)%0A
-          // if (func.type === 'test') %7B%0A
     
@@ -2246,42 +2246,8 @@
 ')%0A%0A
-          let matchingEvents = %5B%5D%0A
     
@@ -2400,28 +2400,24 @@
     
-matchingEvents.push(
+var testEvent = 
 web3
@@ -2477,17 +2477,16 @@
 aw.data)
-)
 %0A       
@@ -2494,176 +2494,34 @@
     
-%7D%0A          %7D%0A%0A          if (matchingEvents.length === 0) %7B%0A            return next()%0A          %7D%0A%0A          let result = matching
+  if (test
 Event
-s
 %5B0%5D
-%0A
+) %7B
 %0A    
-      if (result%5B0%5D) %7B%0A
     
@@ -2639,32 +2639,36 @@
 e%7D)%0A            
+    
 passingNum += 1%0A
@@ -2669,32 +2669,36 @@
  += 1%0A          
+    
 %7D else %7B%0A       
@@ -2694,32 +2694,36 @@
 e %7B%0A            
+    
 testCallback(%7Bty
@@ -2804,21 +2804,24 @@
 errMsg: 
-resul
+testEven
 t%5B1%5D, co
@@ -2842,32 +2842,36 @@
 e%7D)%0A            
+    
 failureNum += 1%0A
@@ -2872,32 +2872,36 @@
  += 1%0A          
+    
 %7D%0A          // %7D
@@ -2900,12 +2900,47 @@
     
-// %7D
+  %7D%0A          %7D%0A          return next()
 %0A   
@@ -3052,39 +3052,24 @@
 )%0A        %7D%0A
-        next()%0A
       %7D).on(

Allow returning more than one Assert per function