import "pkg:/source/rooibos/Matchers.bs"
import "pkg:/source/rooibos/TestGroup.bs"
import "pkg:/source/rooibos/Utils.bs"
import "pkg:/source/roku_modules/rooibos_promises/promises.brs"
namespace rooibos
class BaseTestSuite
'test state
protected name = "BaseTestSuite" 'set the name to the name of your test
protected filePath = invalid
protected pkgPath = invalid
protected isValid = false
protected hasSoloTests = false
protected hasIgnoredTests = false
protected isSolo = false
protected isIgnored = false
protected noCatch = false
protected isNodeTest = false
protected nodeName = invalid
protected lineNumber = 1
protected groups = []
protected groupsData = []
protected stats = invalid
protected currentAssertLineNumber = -1
protected valid = false
protected hasFailures = false
protected hasSoloGroups = false
protected isFailingFast = false
protected stubs = invalid
protected mocks = invalid
protected __stubId = -1
protected __mockId = -1
protected __mockTargetId = -1
protected currentExecutionTime = 0
protected timedOut = false
public deferred = invalid
'special values
protected invalidValue = "#ROIBOS#INVALID_VALUE" ' special value used in mock arguments
protected ignoreValue = "#ROIBOS#IGNORE_VALUE" ' special value used in mock arguments
'built in any matchers
protected anyStringMatcher = { "matcher": rooibos.Matcher.anyString }
protected anyBoolMatcher = { "matcher": rooibos.Matcher.anyBool }
protected anyNumberMatcher = { "matcher": rooibos.Matcher.anyNumber }
protected anyAAMatcher = { "matcher": rooibos.Matcher.anyAA }
protected anyArrayMatcher = { "matcher": rooibos.Matcher.anyArray }
protected anyNodeMatcher = { "matcher": rooibos.Matcher.anyNode }
protected allowNonExistingMethodsOnMocks = true
protected isAutoAssertingMocks = true
protected currentResult = invalid
protected global = invalid
protected catchCrashes = false
protected throwOnFailedAssertion = false
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ base methods to override
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function new()
data = m.getTestSuiteData()
if data = invalid then
rooibos.common.logError("ERROR RETRIEVING TEST SUITE DATA!! this is a rooibos BUG - please report the suite that resulted in a corrupt test. Thanks")
else
m.name = data.name
m.filePath = data.filePath
m.pkgPath = data.pkgPath
m.valid = data.valid
m.hasFailures = data.hasFailures
m.hasSoloTests = data.hasSoloTests
m.hasIgnoredTests = data.hasIgnoredTests
m.hasSoloGroups = data.hasSoloGroups
m.isSolo = data.isSolo
m.isIgnored = data.isIgnored
m.isAsync = data.isAsync
m.asyncTimeout = data.asyncTimeout
m.noCatch = data.noCatch
m.groupsData = data.testGroups
m.lineNumber = data.lineNumber
m.isNodeTest = data.isNodeTest
m.nodeName = data.nodeName
m.generatedNodeName = data.generatedNodeName
m.isFailingFast = false
if m.isNodeTest then
m.deferred = rooibos.promises.create()
end if
m.stats = new rooibos.Stats()
end if
end function
' @ignore
function getTestSuiteData()
'this will be injected by the plugin
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ used for entire suite - use annotations to use elsewhere
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
protected function setup()
end function
protected function tearDown()
end function
protected function beforeEach()
end function
protected function afterEach()
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ running
'++++++++++++++++++++++++++++++++++++?+++++++++++++++++++++++++
' @ignore
function run()
m.notifyReportersOnSuiteBegin()
rooibos.common.logTrace(">>>>>>>>>>>>")
rooibos.common.logTrace("RUNNING TEST SUITE")
if m.isNodeTest = true then
rooibos.common.logTrace("THIS GROUP IS ASYNC")
m.runAsync()
else
rooibos.common.logTrace("THIS GROUP IS SYNC")
m.runSync()
end if
end function
' @ignore
function runSync()
for each groupData in m.groupsData
group = new TestGroup(m, groupData)
m.groups.push(group)
group.run()
m.stats.merge(group.stats)
if m.stats.hasFailures and m.isFailingFast = true then
rooibos.common.logDebug("Terminating suite due to failed group")
exit for
end if
end for
m.notifyReportersOnSuiteComplete()
end function
' @ignore
function runASync()
rooibos.common.logTrace("Running groups async")
m.groups = []
for each groupData in m.groupsData
group = new TestGroup(m, groupData)
m.groups.push(group)
end for
m.currentGroupIndex = -1
m.runNextAsync()
end function
' @ignore
private function runNextAsync()
rooibos.common.logTrace("Getting next async group")
m.currentGroupIndex++
m.currentGroup = m.groups[m.currentGroupIndex]
if m.currentGroup = invalid then
rooibos.common.logTrace("All groups are finished")
'finished
m.testSuiteDone()
else
group = m.currentGroup
group.run()
if rooibos.promises.isPromise(group.deferred) then
rooibos.promises.onFinally(group.deferred, function(context as roAssociativeArray)
context.self.onAsyncGroupComplete(context.group)
end function, { group: group, self: m })
else
m.onAsyncGroupComplete(group)
end if
end if
end function
' @ignore
private function onAsyncGroupComplete(group = invalid as rooibos.TestGroup) as void
rooibos.common.logTrace("++ CURRENT GROUP COMPLETED")
group = group = invalid ? m.currentGroup : group
if group = invalid then
rooibos.common.logError("Cannot find test group to mark async finished for?!")
return
end if
m.stats.merge(group.stats)
if m.stats.hasFailures and m.isFailingFast then
rooibos.common.logTrace("Terminating group due to failed test")
m.isTestFailedDueToEarlyExit = true
m.testSuiteDone()
else
m.runNextAsync()
end if
end function
' calculate if the suite has timed out. Will return true if the suite flipped the timedOut flag
' @ignore
function isSuiteTimedOut() as boolean
if m.isNodeTest and m.asyncTimeout > 0 and m.currentExecutionTime >= m.asyncTimeout then
m.timedOut = true
return true
end if
return false
end function
' @ignore
function runTest(test as rooibos.Test) as dynamic
m.currentResult = test.result
if test.isIgnored then
m.currentResult.skip("Test is ignored")
return invalid
end if
' Fail the test if the suite has timed out.
' Currently, this will only happen if the suite is a node test.
if m.isNodeTest and m.timedOut then
m.currentResult.fail("Suite test execution exceeded " + m.asyncTimeout.toStr() + "ms")
return invalid
end if
m.currentAssertLineNumber = -1
m.currentResult.throwOnFailedAssertion = m.throwOnFailedAssertion
if m.catchCrashes and not test.noCatch and not m.noCatch then
try
test.run()
if m.isAutoAssertingMocks = true and test.deferred = invalid then
m.AssertMocks()
m.CleanMocks()
m.CleanStubs()
end if
catch error
m.currentResult.crash("test crashed!", error)
if rooibos.promises.isPromise(test.deferred) then
rooibos.promises.reject(error, test.deferred)
end if
end try
else
test.run()
if m.isAutoAssertingMocks = true and test.deferred = invalid then
m.AssertMocks()
m.CleanMocks()
m.CleanStubs()
end if
end if
return test.deferred
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ Assertions
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Fail immediately, with the given message
' @param {String} [msg=""] - message to display in the test report
' @returns {Boolean} true if the assert was satisfied, false otherwise
function fail(msg = "Error" as string, actual = "" as string, expected = "" as string, createError = false as boolean) as boolean
if m.currentResult.isFail then
if m.throwOnFailedAssertion then
throw m.currentResult.getMessage()
end if
return false
end if
error = invalid
if createError then
try
throw msg
catch error
end try
end if
m.currentResult.fail(msg, m.currentAssertLineNumber, actual, expected, error)
return false
end function
' Fail immediately, with the given message
' @ignore
' @param {String} [msg=""] - message to display in the test report
' @returns {Boolean} true if the assert was satisfied, false otherwise
function skip(msg = "Skipped" as string) as boolean
if m.currentResult.isFail then
if m.throwOnFailedAssertion then
throw m.currentResult.getMessage()
end if
return false
end if
m.currentResult.skip(msg)
return false
end function
' Fail immediately, with the given exception
' @param {Dynamic} [error] - exception to fail on
' @param {String} [msg=""] - message to display in the test report
' @returns {Boolean} true if failure was set, false if the test is already failed
function failCrash(error as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
if m.throwOnFailedAssertion then
throw m.currentResult.getMessage()
end if
return false
end if
if msg = "" then
msg = error.message
end if
m.currentResult.fail(msg, m.currentAssertLineNumber)
m.currentResult.crash(msg, error)
return true
end function
function failBecauseOfTimeOut() as boolean
if m.currentResult.isFail then
return false
end if
m.currentResult.fail("Async test execution exceeded " + m.currentTimeout.toStr() + "ms")
m.done()
return false
end function
' Fail the test if the expression is true.
' @param {Dynamic} expr - An expression to evaluate.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertFalse(expr as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isBoolean(expr) or expr then
actual = rooibos.common.asMultilineString(expr, true)
expected = rooibos.common.asMultilineString(false, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(actual)}" to be ${rooibos.common.truncateString(expected)}`
end if
return m.fail(msg, actual, expected, true)
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail the test unless the expression is true.
' @param {Dynamic} expr - An expression to evaluate.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertTrue(expr as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isBoolean(expr) or not expr then
actual = rooibos.common.asMultilineString(expr, true)
expected = rooibos.common.asMultilineString(true, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(actual)}" to be ${rooibos.common.truncateString(expected)}`
end if
return m.fail(msg, actual, expected, true)
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the two objects are unequal as determined by the '<>' operator.
' @param {Dynamic} first - first object to compare
' @param {Dynamic} second - second object to compare
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertEqual(first as dynamic, second as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.eqValues(first, second) then
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = "" then
messageActual = rooibos.common.truncateString(actual)
messageExpected = rooibos.common.truncateString(expected)
msg = `expected "${messageActual}" to equal "${messageExpected}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' does a fuzzy comparison
' @param {Dynamic} first - first object to compare
' @param {Dynamic} second - second object to compare
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertLike(first as dynamic, second as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.eqValues(first, second, true) then
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = "" then
messageActual = rooibos.common.truncateString(actual)
messageExpected = rooibos.common.truncateString(expected)
msg = `expected "${messageActual}" to be like "${messageExpected}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the two objects are equal as determined by the '=' operator.
' @param {Dynamic} first - first object to compare
' @param {Dynamic} second - second object to compare
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNotEqual(first as dynamic, second as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if rooibos.common.eqValues(first, second) then
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = "" then
messageActual = rooibos.common.truncateString(actual)
messageExpected = rooibos.common.truncateString(expected)
msg = `expected "${messageActual}" to not equal "${messageExpected}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the value is not invalid.
' @param {Dynamic} value - value to check - value to check for
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertInvalid(value as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if rooibos.common.getSafeType(value) <> "Invalid" then
if msg = "" then
actual = rooibos.common.asMultilineString(value, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to be invalid`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the value is invalid.
' @param {Dynamic} value - value to check - value to check for
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNotInvalid(value as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if rooibos.common.getSafeType(value) = "Invalid" then
if msg = "" then
actual = rooibos.common.asMultilineString(value, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to not be invalid`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the aa doesn't have the key.
' @param {Dynamic} aa - target aa
' @param {String} key - key name
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertAAHasKey(aa as dynamic, key as string, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(aa) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if not aa.ifAssociativeArray.DoesExist(key) then
if msg = "" then
actual = rooibos.common.asMultilineString(aa, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to have property "${key}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the aa has the key.
' @param {Dynamic} aa - target aa
' @param {String} key - key name
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertAANotHasKey(aa as dynamic, key as string, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(aa) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if aa.ifAssociativeArray.DoesExist(key) then
if msg = "" then
actual = rooibos.common.asMultilineString(aa, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to not have property "${key}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the aa doesn't have the keys list.
' @param {Dynamic} aa - A target associative array.
' @param {Dynamic} keys - Array of key names.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertAAHasKeys(aa as dynamic, keys as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(aa) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isArray(keys) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(keys, true))}" to be an Array`
end if
m.fail(msg, "", "", true)
return false
end if
foundKeys = []
missingKeys = []
for each key in keys
if not aa.ifAssociativeArray.DoesExist(key) then
missingKeys.push(key)
else
foundKeys.push(key)
end if
end for
if missingKeys.count() > 0 then
actual = rooibos.common.asMultilineString(foundKeys, true)
expected = rooibos.common.asMultilineString(keys, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to have properties ${rooibos.common.truncateString(missingKeys.join(", "))}`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the aa has the keys list.
' @param {Dynamic} aa - A target associative array.
' @param {Dynamic} keys - Array of key names.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertAANotHasKeys(aa as dynamic, keys as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(aa) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isArray(keys) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(keys, true))}" to be an Array`
end if
m.fail(msg, "", "", true)
return false
end if
foundKeys = []
for each key in keys
if aa.ifAssociativeArray.DoesExist(key) then
foundKeys.push(formatJson(key))
end if
end for
if foundKeys.count() > 0 then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(aa, true))}" to not have properties ${rooibos.common.truncateString(foundKeys.join(", "))}`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array doesn't have the item.
' @param {Dynamic} array - target array
' @param {Dynamic} value - value to check - value to check for
' @param {Dynamic} key - key name in associative array
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayContains(array as dynamic, value as dynamic, key = invalid as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.arrayContains(array, value, key) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to contain "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array does not contain all of the aa's in the values array.
' @param {Dynamic} array - target array
' @param {Dynamic} values - array of aas to look for in target array
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayContainsAAs(array as dynamic, values as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isArray(values) then
if msg = "" then
msg = `expected value "${rooibos.common.truncateString(rooibos.common.asMultilineString(values, true))}" must be an Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isArray(array) then
if msg = "" then
msg = `actual value "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" must be an Array`
end if
m.fail(msg, "", "", true)
return false
end if
for each value in values
isMatched = false
if not rooibos.common.isAssociativeArray(value) then
if msg = "" then
msg = `expected search value "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
for each item in array
if rooibos.common.IsAssociativeArray(item) then
isValueMatched = true
for each key in value
fieldValue = value[key]
itemValue = item[key]
if not rooibos.common.eqValues(fieldValue, itemValue) then
isValueMatched = false
exit for
end if
end for
if isValueMatched then
isMatched = true
exit for
end if
end if
end for ' items in array
if not isMatched then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to contain "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
end for 'values to match
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array has the item.
' @param {Dynamic} array - target array
' @param {Dynamic} array - target array
' @param {Dynamic} value - value to check - Value to check for
' @param {Dynamic} key - A key name for associative array.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayNotContains(array as dynamic, value as dynamic, key = invalid as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.arrayContains(array, value, key) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to not contain "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array doesn't have the item subset.
' @param {Dynamic} array - target array
' @param {Dynamic} subset - items to check presence of
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayContainsSubset(array as dynamic, subset as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected target "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isAssociativeArray(subset) and not rooibos.common.isArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isAssociativeArray(array) and not rooibos.common.isAssociativeArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray to match type "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isArray(array) and not rooibos.common.isArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an Array to match type "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
isAA = rooibos.common.isAssociativeArray(subset)
for each item in subset
key = invalid
value = item
if isAA then
key = item
value = subset[key]
end if
if not rooibos.common.arrayContains(array, value, key) then
if msg = "" then
if isAA then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to contain property "${rooibos.common.truncateString(key)}" with value "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
else
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to contain "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
end if
end if
m.fail(msg, "", "", true)
return false
end if
end for
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array have the item from subset.
' @param {Dynamic} array - target array
' @param {Dynamic} subset - items to check presence of
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayNotContainsSubset(array as dynamic, subset as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected target "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isAssociativeArray(subset) and not rooibos.common.isArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isAssociativeArray(array) and not rooibos.common.isAssociativeArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray to match type "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isArray(array) and not rooibos.common.isArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an Array to match type "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}"`
end if
m.fail(msg, "", "", true)
return false
end if
isAA = rooibos.common.isAssociativeArray(subset)
for each item in subset
key = invalid
value = item
if isAA then
key = item
value = subset[key]
end if
if rooibos.common.arrayContains(array, value, key) then
if msg = "" then
if isAA then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to not contain property "${rooibos.common.truncateString(key)}" with value "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
else
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to not contain "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}"`
end if
end if
m.fail(msg, "", "", true)
return false
end if
end for
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array items count <> expected count
' @param {Dynamic} array - target array
' @param {Dynamic} count - An expected array items count
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayCount(array as dynamic, count as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isNumber(count) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(count, true))}" to be an Number`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isAssociativeArray(array) then
actualCount = array.ifAssociativeArray.count()
else
actualCount = array.count()
end if
if actualCount <> count then
if msg = "" then
msg = `expected count "${actualCount}" to be "${count}"`
end if
m.fail(msg, rooibos.common.asMultilineString(actualCount, true), rooibos.common.asMultilineString(count, true), true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array items count = expected count.
' @param {Dynamic} array - target array
' @param {Dynamic} count - An expected array items count.
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayNotCount(array as dynamic, count as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isNumber(count) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(count, true))}" to be an Number`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isAssociativeArray(array) then
actualCount = array.ifAssociativeArray.count()
else
actualCount = array.count()
end if
if actualCount = count then
if msg = "" then
msg = `expected count "${actualCount}" to not be "${count}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the item is not empty array or string.
' @param {Dynamic} item - item to check
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertEmpty(item as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if rooibos.common.isAssociativeArray(item) then
if not item.isEmpty() then
actual = rooibos.common.asMultilineString(item, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(actual)}" to be empty`
end if
m.fail(msg, actual, rooibos.common.asMultilineString({}, true), true)
return false
end if
else if rooibos.common.isArray(item) then
if not item.isEmpty() then
actual = rooibos.common.asMultilineString(item, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(actual)}" to be empty`
end if
m.fail(msg, actual, rooibos.common.asMultilineString([], true), true)
return false
end if
else if rooibos.common.isString(item) then
if not item.isEmpty() then
actual = rooibos.common.asMultilineString(item, true)
if msg = "" then
msg = `expected ${rooibos.common.truncateString(actual)} to be empty`
end if
m.fail(msg, actual, "", true)
return false
end if
else
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(item, true))}" to be an AssociativeArray, Array, or String`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the item is empty array or string.
' @param {Dynamic} item - item to check
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNotEmpty(item as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if rooibos.common.isAssociativeArray(item) then
if item.isEmpty() then
if msg = "" then
actual = rooibos.common.asMultilineString(item, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to not be empty`
end if
m.fail(msg, "", "", true)
return false
end if
else if rooibos.common.isArray(item) then
if item.isEmpty() then
if msg = "" then
actual = rooibos.common.asMultilineString(item, true)
msg = `expected "${rooibos.common.truncateString(actual)}" to not be empty`
end if
m.fail(msg, "", "", true)
return false
end if
else if rooibos.common.isString(item) then
if item.isEmpty() then
if msg = "" then
actual = rooibos.common.asMultilineString(item, true)
msg = `expected ${rooibos.common.truncateString(actual)} to be empty`
end if
m.fail(msg, "", "", true)
return false
end if
else
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(item, true))}" to be an AssociativeArray, Array, or String`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the array doesn't contains items of specific type only.
' @param {Dynamic} array - target array
' @param {String} typeStr - type name - must be String, Array, Boolean, or AssociativeArray
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertArrayContainsOnlyValuesOfType(array as dynamic, typeStr as string, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if typeStr <> "String" and typeStr <> "Integer" and typeStr <> "Boolean" and typeStr <> "Array" and typeStr <> "AssociativeArray" then
if msg = "" then
msg = `expect type ${rooibos.common.asMultilineString(typeStr, true)} to be "Boolean", "String", "Integer", "Array", or "AssociativeArray"`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray or Array`
end if
m.fail(msg, "", "", true)
return false
end if
isAA = rooibos.common.isAssociativeArray(array)
methodName = "Rooibos_Common_Is" + typeStr
typeCheckFunction = m.getIsTypeFunction(methodName)
if typeCheckFunction <> invalid then
for each item in array
key = invalid
if isAA then
key = item
item = array[key]
end if
if not typeCheckFunction(item) then
if msg = "" then
if isAA then
msg = `expected "${rooibos.common.truncateString(key)}: ${rooibos.common.truncateString(rooibos.common.asMultilineString(item, true))}" to be type ${rooibos.common.asMultilineString(typeStr, true)}`
else
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(item, true))}" to be type ${rooibos.common.asMultilineString(typeStr, true)}`
end if
end if
m.fail(msg, "", "", true)
return false
end if
end for
else
' I think we can remove this check, as we are already checking for valid types?
' Will revisit this later.
throw `could not find comparator for type ${rooibos.common.asMultilineString(typeStr, true)}`
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' @ignore
function getIsTypeFunction(name as string) as dynamic
if name = "Rooibos_Common_IsFunction" then
return rooibos.common.isFunction
else if name = "Rooibos_Common_IsXmlElement" then
return rooibos.common.isXmlElement
else if name = "Rooibos_Common_IsInteger" then
return rooibos.common.isInteger
else if name = "Rooibos_Common_IsBoolean" then
return rooibos.common.isBoolean
else if name = "Rooibos_Common_IsFloat" then
return rooibos.common.isFloat
else if name = "Rooibos_Common_IsDouble" then
return rooibos.common.isDouble
else if name = "Rooibos_Common_IsLongInteger" then
return rooibos.common.isLongInteger
else if name = "Rooibos_Common_IsNumber" then
return rooibos.common.isNumber
else if name = "Rooibos_Common_IsList" then
return rooibos.common.isList
else if name = "Rooibos_Common_IsArray" then
return rooibos.common.isArray
else if name = "Rooibos_Common_IsAssociativeArray" then
return rooibos.common.isAssociativeArray
else if name = "Rooibos_Common_IsSGNode" then
return rooibos.common.isSGNode
else if name = "Rooibos_Common_IsString" then
return rooibos.common.isString
else if name = "Rooibos_Common_IsDateTime" then
return rooibos.common.isDateTime
else if name = "Rooibos_Common_IsUndefined" then
return rooibos.common.isUndefined
else
return invalid
end if
end function
' Asserts that the value is a node of designated type
' @param {Dynamic} value - value to check - target node
' @param {String} typeStr - type name
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertType(value as dynamic, typeStr as string, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(value) <> typeStr then
actual = rooibos.common.asMultilineString(type(value), true)
expected = rooibos.common.asMultilineString(typeStr, true)
if msg = "" then
msg = `expected ${rooibos.common.truncateString(actual)} to be type ${rooibos.common.truncateString(expected)}`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts that the value is a node of designated subtype
' @param {Dynamic} value - value to check - target node
' @param {String} typeStr - type name
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertSubType(value as dynamic, typeStr as string, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(value) <> "roSGNode" then
actual = rooibos.common.getTypeWithComponentWrapper(value)
expected = `<Component: roSGNode:${typeStr}>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
else if value.subType() <> typeStr then
actual = rooibos.common.getTypeWithComponentWrapper(value, true)
expected = `<Component: roSGNode:${typeStr}>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
function assertClass(value as dynamic, expectedClassName as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
if rooibos.common.isFunction(expectedClassName) then
expectedClassName = expectedClassName.toStr().mid(10).replace("_", ".")
end if
try
if not rooibos.common.isAssociativeArray(value) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}" to be an instance of ${rooibos.common.truncateString(rooibos.common.asMultilineString(expectedClassName, true))}`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isString(value?.__classname) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(value, true))}" to be an instance of ${rooibos.common.truncateString(rooibos.common.asMultilineString(expectedClassName, true))}`
end if
m.fail(msg, "", "", true)
return false
end if
className = value?.__classname
fail = false
if not rooibos.common.isString(value?.__classname) then
className = "Invalid"
fail = true
end if
className = lCase(className)
if fail or className <> lCase(expectedClassName) then
actual = rooibos.common.asMultilineString(className, true)
expected = rooibos.common.asMultilineString(lCase(expectedClassName), true)
if msg = "" then
msg = `expected class ${rooibos.common.truncateString(actual)} to be an instance of ${rooibos.common.truncateString(expected)}`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ NEW NODE ASSERTS
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Asserts that the node contains the designated number of children
' @param {Dynamic} node - target node
' @param {Integer} count - expected number of child items
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert w, false otherwise
function assertNodeCount(node as dynamic, count as integer, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if node.isSubType("mc_Node") then
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount <> count then
actual = rooibos.common.asMultilineString(childCount, true)
expected = rooibos.common.asMultilineString(count, true)
if msg = "" then
msg = `expected count "${actual}" to be "${expected}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the node items count = expected count.
' @param {Dynamic} node - A target node
' @param {Integer} count - Expected item count
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeNotCount(node as dynamic, count as integer, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if node.isSubType("mc_Node") then
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount = count then
actual = rooibos.common.asMultilineString(childCount, true)
expected = rooibos.common.asMultilineString(count, true)
if msg = "" then
msg = `expected count "${actual}" to not be "${expected}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts the node has no children
' @param {Dynamic} node - a node to check
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeEmpty(node as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if node.isSubType("mc_Node") then
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount > 0 then
if msg = "" then
msg = `expected child count "${childCount}" to be "0"`
end if
m.fail(msg, "", "", true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts the node has children
' @param {Dynamic} node - a node to check
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeNotEmpty(node as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if node.isSubType("mc_Node") then
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount = 0 then
if msg = "" then
msg = `expected child count "${childCount}" to be greater then "0"`
end if
m.fail(msg, "", "", true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts the node contains the child _value_
' @param {Dynamic} node - a node to check
' @param {Dynamic} value - value to check - value to look for
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeContains(node as dynamic, value as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if not rooibos.common.nodeContains(node, value) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to contain child "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(value, true))}" by reference`
end if
m.fail(msg, "", "", true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts the node contains only the child _value_
' @param {Dynamic} node - a node to check
' @param {Dynamic} value - value to check - value to look for
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeContainsOnly(node as dynamic, value as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if not rooibos.common.nodeContains(node, value) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to contain child "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(value, true))}" by reference`
end if
m.fail(msg, "", "", true)
return false
else
if node.isSubType("mc_Node") then
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount <> 1 then
if msg = "" then
msg = `expected child count "${childCount}" to be "1"`
end if
m.fail(msg, "", "", true)
return false
end if
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the node h item.
' @param {Dynamic} node - A target node
' @param {Dynamic} value - value to check - a node child
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeNotContains(node as dynamic, value as dynamic, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if type(node) = "roSGNode" then
if rooibos.common.nodeContains(node, value) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to not contain child "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(value, true))}" by reference`
end if
m.fail(msg, "", "", true)
return false
end if
else
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the node doesn't have the item subset.
' @param {Dynamic} node - A target node
' @param {Dynamic} subset - items to check
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertNodeContainsFields(node as dynamic, subset as dynamic, ignoredFields = invalid as string[], msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not type(node) = "roSGNode" then
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
if not rooibos.common.isAssociativeArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isArray(ignoredFields) then
filteredSubset = {}
for each key in subset
if rooibos.common.isString(key) and not rooibos.common.arrayContains(ignoredFields, key) then
filteredSubset[key] = subset[key]
end if
end for
else
filteredSubset = subset
end if
foundValues = {}
missingValues = {}
for each key in filteredSubset
subsetValue = filteredSubset[key]
nodeValue = node[key]
if rooibos.common.eqValues(nodeValue, subsetValue) then
foundValues[key] = subsetValue
else
missingValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() <> filteredSubset.ifAssociativeArray.count() then
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString(filteredSubset, true)
if msg = "" then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to have properties "${rooibos.common.truncateString(rooibos.common.asMultilineString(missingValues))}"`
end if
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, error.message)
end try
return false
end function
' Fail if the node have the item from subset.
' @param {Dynamic} node - A target node
' @param {Dynamic} subset - the items to check for
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert w, false otherwise
function assertNodeNotContainsFields(node as dynamic, subset as roArray or roAssociativeArray, msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not type(node) = "roSGNode" then
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = "" then
msg = `expected type "${rooibos.common.truncateString(actual)}" to be type "${rooibos.common.truncateString(expected)}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
if rooibos.common.isArray(subset) then
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' NOTE: Legacy check for children via array support.
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
for each value in subset
if rooibos.common.nodeContains(node, value) then
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to not contain child "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(value, true))}" by reference`
end if
m.fail(msg, "", "", true)
return false
end if
end for
else if rooibos.common.isAssociativeArray(subset) then
foundValues = {}
for each key in subset
subsetValue = subset[key]
nodeValue = node[key]
if rooibos.common.eqValues(nodeValue, subsetValue) then
foundValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() > 0 then
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString({}, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.getTypeWithComponentWrapper(node, true))}" to have not have properties "${rooibos.common.truncateString(rooibos.common.asMultilineString(foundValues))}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
else
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ END NODE ASSERTS
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Asserts the associative array contains the fields contained in subset; while ignoring the fields in the ignoredFields array
' @param {roAssociativeArray} array - associative array to check
' @param {roAssociativeArray} subset - associative array of values to check for
' @param {roArray} ignoredFields - array of field names to ignore while comparing
' @param {String} [msg=""] - alternate error message
' @returns {Boolean} true if the assert was satisfied, false otherwise
function assertAAContainsSubset(array as dynamic, subset as roAssociativeArray, ignoredFields = invalid as string[], msg = "" as string) as boolean
if m.currentResult.isFail then
return false
end if
try
if not rooibos.common.isAssociativeArray(array) then
if msg = "" then
msg = `expected target "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if not rooibos.common.isAssociativeArray(subset) then
if msg = "" then
msg = `expected subset "${rooibos.common.truncateString(rooibos.common.asMultilineString(subset, true))}" to be an AssociativeArray`
end if
m.fail(msg, "", "", true)
return false
end if
if rooibos.common.isArray(ignoredFields) then
filteredSubset = {}
for each key in subset
if rooibos.common.isString(key) and not rooibos.common.arrayContains(ignoredFields, key) then
filteredSubset[key] = subset[key]
end if
end for
else
filteredSubset = subset
end if
foundValues = {}
missingValues = {}
for each key in filteredSubset
subsetValue = filteredSubset[key]
nodeValue = array[key]
if rooibos.common.eqValues(nodeValue, subsetValue) then
foundValues[key] = subsetValue
else
missingValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() <> filteredSubset.ifAssociativeArray.count() then
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString(filteredSubset, true)
if msg = "" then
msg = `expected "${rooibos.common.truncateString(rooibos.common.asMultilineString(array, true))}" to have properties "${rooibos.common.truncateString(rooibos.common.asMultilineString(missingValues))}"`
end if
m.fail(msg, actual, expected, true)
return false
end if
return true
catch error
m.currentResult.failCrash(error, msg)
end try
return false
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ Stubbing helpers
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Creates a stub to replace a real method with
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} stub that was wired into the real method
function stub(target as roAssociativeArray, methodName as dynamic, returnValue = invalid as dynamic, allowNonExistingMethods = false as boolean) as roAssociativeArray
if target = invalid and not rooibos.common.isFunction(methodName) then
m.fail("could not create Stub. Global function", methodName, ", is invalid")
return {}
else if type(target) <> "roAssociativeArray" then
m.fail("could not create Stub provided target was null")
return {}
end if
if m.stubs = invalid then
m.__stubId = -1
m.stubs = {}
end if
m.__stubId++
if m.__stubId > 25 then
rooibos.common.logError(`ERROR ONLY 25 MOCKS PER TEST ARE SUPPORTED!! you're on # ${m.__mockId}`)
rooibos.common.logError("Method was " + methodName)
return invalid
end if
id = strI(m.__stubId).trim()
fake = m.createFake(id, target, methodName, 1, invalid, returnValue)
m.stubs[id] = fake
if target.isGlobalCall = true then
rooibos.getMocksByFunctionName()[methodName] = fake
else
allowNonExisting = m.allowNonExistingMethodsOnMocks = true or allowNonExistingMethods
isMethodPresent = type(target[methodName]) = "Function" or type(target[methodName]) = "roFunction"
if isMethodPresent or allowNonExisting then
target[methodName] = m["StubCallback" + id]
target.__stubs = m.stubs
' FIXME: add a log setting for this - and add better detection so that stubs know that they are colliding/don't exist/have correct sigs
' if not isMethodPresent
' rooibos.common.logWarning(`stubbing call ${methodName} which did not exist on target object`)
' end if
else
rooibos.common.logTrace("Could not create Stub : method not found " + rooibos.common.asString(target) + "." + methodName)
end if
end if
return fake
end function
function expectLastCallToThrowError(error as dynamic)
try
mock = m.mocks[m.__mockId.toStr()]
mock.toThrow(error)
catch error
m.log.error("could not add throw to last call", error)
end try
end function
function expectCalled(invocation as dynamic, returnValue = invalid as dynamic) as object
'mock function body - the plugin replaces this
return invalid
end function
' @ignore
function _expectCalled(target as dynamic, methodName as dynamic, rootObject = invalid as dynamic, fullPath = invalid as dynamic, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic) as roAssociativeArray
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid then
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.mock(target, methodName, 1, expectedArgs, returnValue, true)
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return invalid
end function
function stubCall(invocation as dynamic, stubOrReturnValue = invalid as dynamic, functionName = "" as string) as roAssociativeArray
' When stubbing global functions this will be called. Other wise the test code will be updated to call m._stubCall()
if type(invocation).endsWith("Function") and functionName = "" then
functionName = invocation.toStr().tokenize(" ").peek()
else
throw "Did not provide a function to be stubbed"
end if
if not type(stubOrReturnValue).endsWith("Function") then
' throw "Did not provide a stub function"
end if
' Store the stub on the component scope
globalAa = getGlobalAa()
if type(globalAa?.__globalStubs) <> "roAssociativeArray" then
globalAa.__globalStubs = {}
end if
globalAa.__globalStubs[lCase(functionName)] = stubOrReturnValue
return invalid
end function
' @ignore
function _stubCall(target as dynamic, methodName as dynamic, rootObject = invalid as dynamic, fullPath = invalid as dynamic, returnValue = invalid as dynamic) as object
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid then
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.stub(target, methodName, returnValue, true)
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return false
end function
function expectNotCalled(invocation as dynamic) as object
'mock function body - the plugin replaces this
return invalid
end function
' @ignore
function _expectNotCalled(target as dynamic, methodName as dynamic, rootObject = invalid as dynamic, fullPath = invalid as dynamic) as object
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid then
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.mock(target, methodName, 0, invalid, invalid, true)
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return false
end function
' Creates a stub to replace a real method with, which the framework will track. If it was invoked the wrong number of times, or with wrong arguments, it will result in test failure
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} [expectedArgs=invalid] - array containing the arguments we expect the method to be invoked with
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} mock that was wired into the real method
function expectOnce(target as dynamic, methodName as dynamic, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic, allowNonExistingMethods = false as boolean) as object
'HACK
'HACK
'HACK
'HACK
'HACK
' try
return m.mock(target, methodName, 1, expectedArgs, returnValue, allowNonExistingMethods)
' catch error
' m.fail("Setting up mock failed: " + error.message, "", "", true)
' return false
' end try
' return false
end function
' Toggles between expectOnce and expectNone, to allow for easy parameterized expect behavior
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} isExpected - if true, then this is the same as expectOnce, if false, then this is the same as expectNone
' @param {Dynamic} [expectedArgs=invalid] - array containing the arguments we expect the method to be invoked with
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} mock that was wired into the real method
function expectOnceOrNone(target as dynamic, methodName as dynamic, isExpected as dynamic, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic, allowNonExistingMethods = false as boolean) as dynamic
try
if isExpected then
return m.expectOnce(target, methodName, expectedArgs, returnValue, allowNonExistingMethods)
else
return m.expectNone(target, methodName, allowNonExistingMethods)
end if
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return false
end function
' Creates a stub to replace a real method with, which the framework will track. If it was invoked, it will result in test failure
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} mock that was wired into the real method
function expectNone(target as dynamic, methodName as dynamic, allowNonExistingMethods = false as boolean) as object
try
return m.mock(target, methodName, 0, invalid, invalid, allowNonExistingMethods)
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return false
end function
' Creates a stub to replace a real method with, which the framework will track. If it was invoked the wrong number of times, or with wrong arguments, it will result in test failure
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} [expectedInvocations=1] - number of invocations we expect
' @param {Dynamic} [expectedArgs=invalid] - array containing the arguments we expect the method to be invoked with
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} mock that was wired into the real method
function expect(target as dynamic, methodName as dynamic, expectedInvocations = 1 as integer, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic, allowNonExistingMethods = false as boolean) as object
try
return m.mock(target, methodName, expectedInvocations, expectedArgs, returnValue, allowNonExistingMethods)
catch error
m.fail("Setting up mock failed: " + error.message, "", "", true)
end try
return false
end function
' Creates a stub to replace a real method with, which the framework will track. If it was invoked the wrong number of times, or with wrong arguments, it will result in test failure
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} expectedInvocations - number of invocations we expect
' @param {Dynamic} [expectedArgs=invalid] - array containing the arguments we expect the method to be invoked with
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @param {Boolean} [allowNonExistingMethods=false] - if true, then rooibos will only warn if the method did not exist prior to faking
' @returns {Object} mock that was wired into the real method
function mock(target as dynamic, methodName as dynamic, expectedInvocations = 1 as integer, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic, allowNonExistingMethods = false as boolean) as object
lineNumber = m.currentAssertLineNumber
'check params
if target <> invalid and not rooibos.common.isFunction(target) and not rooibos.common.isAssociativeArray(target) then
methodName = ""
m.mockFail(lineNumber, "", "mock args: target should be an AA or in-scope Global function", methodName)
else if not rooibos.common.isString(methodName) then
methodName = ""
m.mockFail(lineNumber, "", "mock args: methodName was not a string")
else if not rooibos.common.isNumber(expectedInvocations) then
m.mockFail(lineNumber, methodName, "mock args: expectedInvocations was not an int")
else if not rooibos.common.isArray(expectedArgs) and rooibos.common.isValid(expectedArgs) then
m.mockFail(lineNumber, methodName, "mock args: expectedArgs was not invalid or an array of args")
else if rooibos.common.isUndefined(expectedArgs) then
m.mockFail(lineNumber, methodName, "mock args: expectedArgs undefined")
else if rooibos.common.isUndefined(returnValue) then
m.mockFail(lineNumber, methodName, "mock args: returnValue undefined")
end if
if m.currentResult.isFail then
rooibos.common.logError(`Cannot create MOCK. method ${methodName} ${lineNumber} ${m.currentResult.message}`)
return {}
end if
if m.mocks = invalid then
m.__mockId = -1
m.__mockTargetId = -1
m.mocks = {}
rooibos.resetMocksByFunctionName()
end if
fake = invalid
if rooibos.common.isFunction(target) then
target = {
isGlobalCall: true
}
end if
if not target.doesExist("__rooibosTargetId") then
m.__mockTargetId++
target["__rooibosTargetId"] = m.__mockTargetId
end if
'ascertain if mock already exists
for i = 0 to m.__mockId
id = strI(i).trim()
mock = m.mocks[id]
if mock <> invalid and mock.methodName = methodName and (mock.target.__rooibosTargetId = target.__rooibosTargetId or (mock.target.isGlobalCall = true and target.isGlobalCall = true)) then
fake = mock
fake.lineNumbers.push(lineNumber)
exit for
end if
end for
if fake = invalid then
m.__mockId++
id = strI(m.__mockId).trim()
if m.__mockId > 25 then
rooibos.common.logError(`ERROR ONLY 25 MOCKS PER TEST ARE SUPPORTED!! you're on # ${m.__mockId}`)
rooibos.common.logError("Method was " + methodName)
return invalid
end if
fake = m.createFake(id, target, methodName, expectedInvocations, expectedArgs, returnValue)
m.mocks[id] = fake 'this will bind it to m
if target.isGlobalCall = true then
rooibos.getMocksByFunctionName()[methodName] = fake
else
allowNonExisting = m.allowNonExistingMethodsOnMocks = true or allowNonExistingMethods
isMethodPresent = type(target[methodName]) = "Function" or type(target[methodName]) = "roFunction"
if isMethodPresent or allowNonExisting then
target[methodName] = m["MockCallback" + id]
target.__mocks = m.mocks
if not isMethodPresent then
rooibos.common.logWarning(`mocking call ${methodName} which did not exist on target object`)
end if
else
rooibos.common.logError(`Could not create Mock : method not found ${target}.${methodName}`)
end if
end if
else
m.combineFakes(fake, m.createFake(id, target, methodName, expectedInvocations, expectedArgs, returnValue))
end if
return fake
end function
' Creates a stub to replace a real method with. This is used internally.
' @param {Dynamic} target - object on which the method to be stubbed is found
' @param {Dynamic} methodName - name of method to stub
' @param {Dynamic} [expectedInvocations=1] - number of invocations we expect
' @param {Dynamic} [expectedArgs=invalid] - array containing the arguments we expect the method to be invoked with
' @param {Dynamic} [returnValue=invalid] - value that the stub method will return when invoked
' @returns {Object} stub that was wired into the real method
function createFake(id as dynamic, target as dynamic, methodName as dynamic, expectedInvocations = 1 as integer, expectedArgs = invalid as dynamic, returnValue = invalid as dynamic) as object
expectedArgsValues = []
lineNumber = m.currentAssertLineNumber
hasArgs = rooibos.common.isArray(expectedArgs)
defaultValue = m.ignoreValue
if hasArgs then
defaultValue = m.invalidValue
else
expectedArgs = []
end if
lineNumbers = [lineNumber]
for i = 0 to 9
if hasArgs and expectedArgs.count() > i then
'guard against bad values
value = expectedArgs[i]
if not rooibos.common.isUndefined(value) then
if rooibos.common.isAssociativeArray(value) and rooibos.common.isValid(value.matcher) then
if not rooibos.common.isFunction(value.matcher) then
rooibos.common.logError("You have specified a matching function; but it is not in scope!")
expectedArgsValues.push("#ERR-OUT_OF_SCOPE_MATCHER!")
else
expectedArgsValues.push(expectedArgs[i])
end if
else
expectedArgsValues.push(expectedArgs[i])
end if
else
expectedArgsValues.push("#ERR-UNDEFINED!")
end if
else
expectedArgsValues.push(defaultValue)
end if
end for
'todo - make into a class
fake = {
id: id
target: target
errorToThrow: invalid
methodName: methodName
returnValue: returnValue
lineNumbers: lineNumbers
isCalled: false
invocations: 0
invokedArgs: [invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid]
expectedArgs: expectedArgsValues
expectedInvocations: expectedInvocations
callback: function(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
rooibos.common.logTrace(`FAKE CALLBACK CALLED FOR ${m.methodName}`)
if m.allInvokedArgs = invalid then
m.allInvokedArgs = []
end if
m.invokedArgs = [arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15]
m.allInvokedArgs.push ([arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15])
m.isCalled = true
m.invocations++
if m.errorToThrow <> invalid then
throw m.errorToThrow
end if
if type(m.returnValue) = "roAssociativeArray" and m.returnValue.ifAssociativeArray.doesExist("multiResult") then
returnValues = m.returnValue["multiResult"]
returnIndex = m.invocations - 1
if type(returnValues) = "roArray" and returnValues.count() > 0 then
if returnValues.count() <= m.invocations then
returnIndex = returnValues.count() - 1
rooibos.common.logDebug("Multi return values all used up - repeating last value")
end if
return returnValues[returnIndex]
else
rooibos.common.logError("Multi return value was specified; but no array of results were found")
return invalid
end if
else
return m.returnValue
end if
end function
toThrow: function(error as roAssociativeArray)
m.errorToThrow = error
end function
}
return fake
end function
function combineFakes(fake as roAssociativeArray, otherFake as roAssociativeArray)
'add on the expected invoked args
lineNumber = m.currentAssertLineNumber
if type(fake.expectedArgs) <> "roAssociativeArray" or not fake.expectedArgs.ifAssociativeArray.doesExist("multiInvoke") then
currentExpectedArgsArgs = fake.expectedArgs
fake.expectedArgs = {
"multiInvoke": [currentExpectedArgsArgs]
}
end if
for i = 1 to otherFake.expectedInvocations
fake.expectedArgs.multiInvoke.push(otherFake.expectedArgs)
end for
'add on the expected return values
if type(fake.returnValue) <> "roAssociativeArray" or not fake.returnValue.ifAssociativeArray.doesExist("multiResult") then
currentReturnValue = fake.returnValue
fake.returnValue = {
"multiResult": [currentReturnValue]
}
end if
for i = 1 to otherFake.expectedInvocations
fake.returnValue.multiResult.push(otherFake.returnValue)
end for
fake.lineNumbers.push(lineNumber)
fake.expectedInvocations += otherFake.expectedInvocations
end function
' Will check all mocks that have been created to ensure they were invoked the expected amount of times, with the expected args.
function assertMocks() as void
if m.__mockId = invalid or not rooibos.common.isAssociativeArray(m.mocks) then
return
end if
for each id in m.mocks
mock = m.mocks[id]
methodName = mock.methodName
if mock.expectedInvocations <> mock.invocations then
m.mockFail(mock.lineNumbers[0], methodName, "Wrong number of calls. (" + strI(mock.invocations).trim() + " / " + strI(mock.expectedInvocations).trim() + ")")
m.cleanMocks()
return
else if mock.expectedInvocations > 0 and (rooibos.common.isArray(mock.expectedArgs) or (type(mock.expectedArgs) = "roAssociativeArray" and rooibos.common.isArray(mock.expectedArgs.multiInvoke))) then
isMultiArgsSupported = type(mock.expectedArgs) = "roAssociativeArray" and rooibos.common.isArray(mock.expectedArgs.multiInvoke)
for invocationIndex = 0 to mock.invocations - 1
invokedArgs = mock.allInvokedArgs[invocationIndex]
if isMultiArgsSupported then
expectedArgs = mock.expectedArgs.multiInvoke[invocationIndex]
else
expectedArgs = mock.expectedArgs
end if
if rooibos.common.isAssociativeArray(expectedArgs) then
expectedArgsCount = expectedArgs.ifAssociativeArray.count()
else
expectedArgsCount = expectedArgs.count()
end if
for i = 0 to expectedArgsCount - 1
value = invokedArgs[i]
expected = expectedArgs[i]
didNotExpectArg = rooibos.common.isString(expected) and expected = m.invalidValue
if didNotExpectArg then
expected = invalid
end if
isUsingMatcher = rooibos.common.isAssociativeArray(expected) and rooibos.common.isFunction(expected.matcher)
if isUsingMatcher then
if not expected.matcher(value) then
m.mockFail(mock.lineNumbers[invocationIndex], methodName, "on Invocation #" + strI(invocationIndex).trim() + ", expected arg #" + strI(i).trim() + " to match matching function '" + rooibos.common.asString(expected.matcher) + "' got '" + rooibos.common.asString(value, true) + "')")
m.cleanMocks()
end if
else
if not (rooibos.common.isString(expected) and expected = m.ignoreValue) and not rooibos.common.eqValues(value, expected) then
if expected = invalid then
expected = "[INVALID]"
end if
m.mockFail(mock.lineNumbers[invocationIndex], methodName, "on Invocation #" + strI(invocationIndex).trim() + ", expected arg #" + strI(i).trim() + " to be '" + rooibos.common.asString(expected, true) + "' got '" + rooibos.common.asString(value, true) + "')")
m.cleanMocks()
return
end if
end if
end for
end for
end if
end for
m.cleanMocks()
end function
' Cleans up all tracking data associated with mocks
function cleanMocks() as void
if m.mocks = invalid then
return
end if
for each id in m.mocks
mock = m.mocks[id]
mock.target.__mocks = invalid
end for
m.mocks = invalid
rooibos.resetMocksByFunctionName()
end function
' Cleans up all tracking data associated with stubs
function cleanStubs() as void
' Clean up the global functions mocks as well
globalAa = getGlobalAa()
globalAa.__globalStubs = invalid
if m.stubs = invalid then
return
end if
for each id in m.stubs
stub = m.stubs[id]
stub.target.__stubs = invalid
end for
m.stubs = invalid
rooibos.resetMocksByFunctionName()
end function
function mockFail(lineNumber as integer, methodName as dynamic, message as string) as dynamic
if m.currentResult.isFail then
return false
end if
m.fail("mock failure on '" + methodName + "' : " + message, "", "", true)
return false
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ Fake Stub callback functions - this is required to get scope
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' @ignore
private function stubCallback0(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["0"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback1(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["1"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback2(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["2"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback3(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["3"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback4(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["4"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback5(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["5"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback6(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["6"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback7(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["7"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback8(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["8"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback9(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["9"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback10(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["10"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback11(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["11"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback12(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["12"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback13(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["13"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback14(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["14"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback15(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["15"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback16(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["16"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback17(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["17"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback18(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["18"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback19(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["19"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback20(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["20"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback21(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["21"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback22(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["22"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback23(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["23"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback24(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["24"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function stubCallback25(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__Stubs["25"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ Fake Mock callback functions - this is required to get scope
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' @ignore
private function mockCallback0(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["0"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback1(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["1"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback2(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["2"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
private function mockCallback3(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["3"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback4(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["4"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback5(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["5"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback6(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["6"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback7(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["7"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback8(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["8"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback9(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["9"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback10(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["10"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback11(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["11"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback12(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["12"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback13(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["13"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback14(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["14"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback15(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["15"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback16(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["16"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback17(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["17"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback18(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["18"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback19(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["19"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback20(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["20"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback21(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["21"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback22(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["22"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback23(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["23"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
' @ignore
private function mockCallback24(arg1 = invalid as dynamic, arg2 = invalid as dynamic, arg3 = invalid as dynamic, arg4 = invalid as dynamic, arg5 = invalid as dynamic, arg6 = invalid as dynamic, arg7 = invalid as dynamic, arg8 = invalid as dynamic, arg9 = invalid as dynamic, arg10 = invalid as dynamic, arg11 = invalid as dynamic, arg12 = invalid as dynamic, arg13 = invalid as dynamic, arg14 = invalid as dynamic, arg15 = invalid as dynamic) as dynamic
fake = m.__mocks["24"]
return fake.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ crude async support
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' observeField doesn't work in regular unit tests, so we have to wait for the result. We can use this to wait for a network task, foe example, and pass the result directly to a handler. Note - we wait for the value TO CHANGE - so make sure that will be the case, or you'll get stuck forever :)
' @param {any} target to observe
' @param {String} field to observe
' @param {int} delay for each wait
' @param {int} max attempts
function waitForField(target as dynamic, fieldName as string, delay = 500 as integer, maxAttempts = 10 as integer) as boolean
attempts = 0
if target = invalid then
return false
end if
initialValue = target[fieldName]
while target[fieldName] = initialValue
port = CreateObject("roMessagePort")
wait(delay, port)
attempts++
if attempts = maxAttempts then
return false
end if
rooibos.common.logDebug(`Waiting for signal field '${fieldName}' - ${attempts}`)
end while
return true
end function
function wait(delay = 1 as integer)
port = CreateObject("roMessagePort")
wait(delay, port)
end function
function done()
rooibos.common.logTrace("Async test is complete")
if m.isDoneCalled = false then
m.isDoneCalled = true
deferred = m.currentGroup?.currentTest?.deferred
if rooibos.promises.isPromise(deferred) then
rooibos.promises.resolve(true, deferred)
end if
else
rooibos.common.logWarning("extra done call after test is done! Did you properly clean up your observers?")
end if
end function
' @ignore
function testSuiteDone()
rooibos.common.logTrace("Indicating test suite is done")
m.notifyReportersOnSuiteComplete()
m.testRunner.top.rooibosTestResult = {
stats: m.stats
tests: m.tests
groups: m.groups
}
end function
function assertAsyncField(target as dynamic, fieldName as string, delay = 500 as integer, maxAttempts = 10 as integer) as boolean
try
if m.currentResult.isFail then
return false
end if
if target = invalid then
m.fail("Target was invalid", "", "", true)
end if
result = m.waitForField(target, fieldName, delay, maxAttempts)
if not result then
return m.fail("Timeout waiting for targetField " + fieldName + " to be set on target", "", "", true)
end if
return true
catch error
m.currentResult.fail("Error while waiting: " + error.message, m.currentAssertLineNumber)
end try
return false
end function
' @ignore
protected function createNodeClass(clazz as dynamic, useClassAsTop = true as boolean, nodeTop = new rooibos.utils.MockNode("top") as dynamic, nodeGlobal = new rooibos.utils.MockNode("top") as dynamic) as roAssociativeArray
instance = tests_maestro_nodeClassUtils_createNodeClass(clazz, nodeTop, nodeGlobal) 'bs:disable-line 1140 LINT1001
if instance <> invalid and useClassAsTop then
'note - we use the clazz itself as TOP, so that we don't have to write tests that do
'thing.top.value, thing.top.value2, etc all over the place
instance.append(nodeTop)
instance.top = instance
instance.__rooibosSkipFields = { "top": true }
end if
return instance
end function
' @ignore
protected function createMockViews(instance as dynamic, bundlePath as string, viewsPath = "views" as string)
bundle = m.global.testStyleManager@.loadBundle(bundlePath)
ids = mv_getIdsFromStyleJson(mc_getArray(bundle, viewsPath)) 'bs:disable-line 1140 LINT1001
for each id in ids
instance[id] = { id: id }
end for
end function
' @ignore
private function notifyReportersOnSuiteBegin()
for each reporter in m.testReporters
if rooibos.common.isFunction(reporter.onSuiteBegin) then
reporter.onSuiteBegin({ suite: m })
end if
end for
end function
' @ignore
private function notifyReportersOnSuiteComplete()
for each reporter in m.testReporters
if rooibos.common.isFunction(reporter.onSuiteComplete) then
reporter.onSuiteComplete({ suite: m })
end if
end for
end function
end class
' @ignore
function getMocksByFunctionName() as dynamic
if m._rMocksByFunctionName = invalid then
m._rMocksByFunctionName = {}
end if
return m._rMocksByFunctionName
end function
' @ignore
function resetMocksByFunctionName()
m._rMocksByFunctionName = invalid
end function
' @ignore
function getMockForFunction(functionName as string) as dynamic
return rooibos.getMocksByFunctionName()[functionName]
end function
' @ignore
function isFunctionMocked(functionName as string) as boolean
return rooibos.getMockForFunction(functionName) <> invalid
end function
end namespace