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
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
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
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
'bs:disable-next-line
group = new TestGroup(m, groupData)
'bs:disable-next-line
m.groups.push(group)
'bs:disable-next-line
group.run()
'bs:disable-next-line
m.stats.merge(group.stats)
if m.stats.hasFailures and m.isFailingFast = true
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
'bs:disable-next-line
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
rooibos.common.logTrace("All groups are finished")
'finished
m.testSuiteDone()
else
group = m.currentGroup
group.run()
if rooibos.promises.isPromise(group.deferred)
rooibos.promises.onFinally(group.deferred, sub(context)
context.self.onAsyncGroupComplete(context.group)
end sub, { group: group, self: m })
else
m.onAsyncGroupComplete(group)
end if
end if
end function
' @ignore
private function onAsyncGroupComplete(group = invalid) as void
rooibos.common.logTrace("++ CURRENT GROUP COMPLETED")
group = group = invalid ? m.currentGroup : group
if group = invalid
rooibos.common.logError("Cannot find test group to mark async finished for?!")
return
end if
'bs:disable-next-line
m.stats.merge(group.stats)
if m.stats.hasFailures and m.isFailingFast
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()
if m.isNodeTest and m.asyncTimeout > 0 and m.currentExecutionTime >= m.asyncTimeout
m.timedOut = true
return true
end if
return false
end function
' @ignore
function runTest(test as rooibos.Test)
m.currentResult = test.result
if test.isIgnored
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
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
try
test.run()
if m.isAutoAssertingMocks = true and test.deferred = invalid
m.AssertMocks()
m.CleanMocks()
m.CleanStubs()
end if
catch error
'bs:disable-next-line
m.currentResult.crash("test crashed!", error)
if rooibos.promises.isPromise(test.deferred)
rooibos.promises.reject(error, test.deferred)
end if
end try
else
test.run()
if m.isAutoAssertingMocks = true and test.deferred = invalid
m.AssertMocks()
m.CleanMocks()
m.CleanStubs()
end if
end if
return test.deferred
end function
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++ Assertions
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Fail immediately, with the given message
' @param {Dynamic} [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 dynamic
if m.currentResult.isFail
if m.throwOnFailedAssertion
throw m.currentResult.getMessage()
end if
return false
end if
error = invalid
if createError
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 {Dynamic} [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 dynamic
if m.currentResult.isFail
if m.throwOnFailedAssertion
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 {Dynamic} [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 dynamic
if m.currentResult.isFail
if m.throwOnFailedAssertion
throw m.currentResult.getMessage()
end if
return false
end if
if msg = ""
msg = error.message
end if
m.currentResult.fail(msg, m.currentAssertLineNumber)
m.currentResult.crash(msg, error)
return true
end function
function failBecauseOfTimeOut() as dynamic
if m.currentResult.isFail
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertFalse(expr as dynamic, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isBoolean(expr) or expr
actual = rooibos.common.asMultilineString(expr, true)
expected = rooibos.common.asMultilineString(false, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertTrue(expr, msg = "")
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isBoolean(expr) or not expr
actual = rooibos.common.asMultilineString(expr, true)
expected = rooibos.common.asMultilineString(true, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertEqual(first, second, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.eqValues(first, second)
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertLike(first, second, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.eqValues(first, second, true)
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNotEqual(first, second, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if rooibos.common.eqValues(first, second)
actual = rooibos.common.asMultilineString(first, true)
expected = rooibos.common.asMultilineString(second, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertInvalid(value, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if rooibos.common.getSafeType(value) <> "Invalid"
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNotInvalid(value, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if rooibos.common.getSafeType(value) = "Invalid"
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} key - key name
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertAAHasKey(aa, key, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(aa)
if msg = ""
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)
if msg = ""
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
'bs:disable-next-line
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Fail if the aa has the key.
' @param {Dynamic} aa - target aa
' @param {Dynamic} key - key name
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertAANotHasKey(aa, key, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(aa)
if msg = ""
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)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertAAHasKeys(aa, keys, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(aa)
if msg = ""
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)
if msg = ""
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)
missingKeys.push(key)
else
foundKeys.push(key)
end if
end for
if missingKeys.count() > 0
actual = rooibos.common.asMultilineString(foundKeys, true)
expected = rooibos.common.asMultilineString(keys, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertAANotHasKeys(aa, keys, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(aa)
if msg = ""
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)
if msg = ""
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)
foundKeys.push(formatJson(key))
end if
end for
if foundKeys.count() > 0
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayContains(array, value, key = invalid, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayContainsAAs(array, values, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isArray(values)
if msg = ""
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)
if msg = ""
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)
if msg = ""
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)
isValueMatched = true
for each key in value
fieldValue = value[key]
itemValue = item[key]
if not rooibos.common.eqValues(fieldValue, itemValue)
isValueMatched = false
exit for
end if
end for
if isValueMatched
isMatched = true
exit for
end if
end if
end for ' items in array
if not isMatched
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayNotContains(array, value, key = invalid, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayContainsSubset(array, subset, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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)
if msg = ""
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)
if msg = ""
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
key = item
value = subset[key]
end if
if not rooibos.common.arrayContains(array, value, key)
if msg = ""
if isAA
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayNotContainsSubset(array, subset, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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)
if msg = ""
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)
if msg = ""
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
key = item
value = subset[key]
end if
if rooibos.common.arrayContains(array, value, key)
if msg = ""
if isAA
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayCount(array, count, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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)
actualCount = array.ifAssociativeArray.count()
else
actualCount = array.count()
end if
if actualCount <> count
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayNotCount(array, count, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array) and not rooibos.common.isArray(array)
if msg = ""
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)
if msg = ""
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)
actualCount = array.ifAssociativeArray.count()
else
actualCount = array.count()
end if
if actualCount = count
if msg = ""
msg = `expected count "${actualCount}" to not be "${count}"`
end if
m.fail(msg, "", "", true)
return false
end if
return true
catch error
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertEmpty(item, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if rooibos.common.isAssociativeArray(item)
if not item.isEmpty()
actual = rooibos.common.asMultilineString(item, true)
if msg = ""
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)
if not item.isEmpty()
actual = rooibos.common.asMultilineString(item, true)
if msg = ""
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)
if not item.isEmpty()
actual = rooibos.common.asMultilineString(item, true)
if msg = ""
msg = `expected ${rooibos.common.truncateString(actual)} to be empty`
end if
m.fail(msg, actual, "", true)
return false
end if
else
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNotEmpty(item, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if rooibos.common.isAssociativeArray(item)
if item.isEmpty()
if msg = ""
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)
if item.isEmpty()
if msg = ""
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)
if item.isEmpty()
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} typeStr - type name - must be String, Array, Boolean, or AssociativeArray
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertArrayContainsOnlyValuesOfType(array, typeStr, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if typeStr <> "String" and typeStr <> "Integer" and typeStr <> "Boolean" and typeStr <> "Array" and typeStr <> "AssociativeArray"
if msg = ""
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)
if msg = ""
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
for each item in array
key = invalid
if isAA
key = item
item = array[key]
end if
if not typeCheckFunction(item)
if msg = ""
if isAA
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
'bs:disable-next-line
m.currentResult.failCrash(error, msg)
end try
return false
end function
' @ignore
function getIsTypeFunction(name)
if name = "Rooibos_Common_IsFunction"
return rooibos.common.isFunction
else if name = "Rooibos_Common_IsXmlElement"
return rooibos.common.isXmlElement
else if name = "Rooibos_Common_IsInteger"
return rooibos.common.isInteger
else if name = "Rooibos_Common_IsBoolean"
return rooibos.common.isBoolean
else if name = "Rooibos_Common_IsFloat"
return rooibos.common.isFloat
else if name = "Rooibos_Common_IsDouble"
return rooibos.common.isDouble
else if name = "Rooibos_Common_IsLongInteger"
return rooibos.common.isLongInteger
else if name = "Rooibos_Common_IsNumber"
return rooibos.common.isNumber
else if name = "Rooibos_Common_IsList"
return rooibos.common.isList
else if name = "Rooibos_Common_IsArray"
return rooibos.common.isArray
else if name = "Rooibos_Common_IsAssociativeArray"
return rooibos.common.isAssociativeArray
else if name = "Rooibos_Common_IsSGNode"
return rooibos.common.isSGNode
else if name = "Rooibos_Common_IsString"
return rooibos.common.isString
else if name = "Rooibos_Common_IsDateTime"
return rooibos.common.isDateTime
else if name = "Rooibos_Common_IsUndefined"
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 {Dynamic} typeStr - type name
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertType(value, typeStr, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(value) <> typeStr
actual = rooibos.common.asMultilineString(type(value), true)
expected = rooibos.common.asMultilineString(typeStr, true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} typeStr - type name
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertSubType(value, typeStr, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(value) <> "roSGNode"
actual = rooibos.common.getTypeWithComponentWrapper(value)
expected = `<Component: roSGNode:${typeStr}>`
if msg = ""
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
actual = rooibos.common.getTypeWithComponentWrapper(value, true)
expected = `<Component: roSGNode:${typeStr}>`
if msg = ""
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
'bs:disable-next-line
m.currentResult.failCrash(error, msg)
end try
return false
end function
function assertClass(value, expectedClassName, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
if rooibos.common.isFunction(expectedClassName)
expectedClassName = expectedClassName.toStr().mid(10).replace("_", ".")
end if
try
if not rooibos.common.isAssociativeArray(value)
if msg = ""
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)
if msg = ""
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)
className = "Invalid"
fail = true
end if
className = lCase(className)
if fail or className <> lCase(expectedClassName)
actual = rooibos.common.asMultilineString(className, true)
expected = rooibos.common.asMultilineString(lCase(expectedClassName), true)
if msg = ""
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
'bs:disable-next-line
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 {Dynamic} count - expected number of child items
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert w, false otherwise
function assertNodeCount(node, count, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if node.isSubType("mc_Node")
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount <> count
actual = rooibos.common.asMultilineString(childCount, true)
expected = rooibos.common.asMultilineString(count, true)
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} count - Expected item count
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeNotCount(node, count, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if node.isSubType("mc_Node")
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount = count
actual = rooibos.common.asMultilineString(childCount, true)
expected = rooibos.common.asMultilineString(count, true)
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeEmpty(node, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if node.isSubType("mc_Node")
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount > 0
if msg = ""
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 = ""
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
'bs:disable-next-line
m.currentResult.failCrash(error, msg)
end try
return false
end function
' Asserts the node has children
' @param {Dynamic} node - a node to check
' @param {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeNotEmpty(node, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if node.isSubType("mc_Node")
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount = 0
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeContains(node, value, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if not rooibos.common.nodeContains(node, value)
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeContainsOnly(node, value, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if not rooibos.common.nodeContains(node, value)
if msg = ""
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")
childCount = node.length
else
childCount = node.getChildCount()
end if
if childCount <> 1
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeNotContains(node, value, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if type(node) = "roSGNode"
if rooibos.common.nodeContains(node, value)
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertNodeContainsFields(node, subset, ignoredFields = invalid, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not type(node) = "roSGNode"
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = ""
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)
if msg = ""
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)
filteredSubset = {}
for each key in subset
if rooibos.common.isString(key) and not rooibos.common.arrayContains(ignoredFields, key)
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)
foundValues[key] = subsetValue
else
missingValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() <> filteredSubset.ifAssociativeArray.count()
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString(filteredSubset, true)
if msg = ""
if msg = ""
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
'bs:disable-next-line
m.currentResult.failCrash(error, error.message)
return false
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 {Dynamic} [msg=""] - alternate error message
' @returns {boolean} - true if the assert w, false otherwise
function assertNodeNotContainsFields(node, subset, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not type(node) = "roSGNode"
actual = rooibos.common.getTypeWithComponentWrapper(node)
expected = `<Component: roSGNode>`
if msg = ""
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)
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' NOTE: Legacy check for children via array support.
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
for each value in subset
if rooibos.common.nodeContains(node, value)
if msg = ""
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)
foundValues = {}
for each key in subset
subsetValue = subset[key]
nodeValue = node[key]
if rooibos.common.eqValues(nodeValue, subsetValue)
foundValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() > 0
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString({}, true)
if msg = ""
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 = ""
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
'bs:disable-next-line
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 {assocarray} array - associative array to check
' @param {assocarray} subset - associative array of values to check for
' @param {array} ignoredFields - array of fieldnames to ignore while comparing
' @param {string} [msg=""] - alternate error message
' @returns {boolean} - true if the assert was satisfied, false otherwise
function assertAAContainsSubset(array, subset, ignoredFields = invalid, msg = "") as dynamic
if m.currentResult.isFail
return false
end if
try
if not rooibos.common.isAssociativeArray(array)
if msg = ""
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)
if msg = ""
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)
filteredSubset = {}
for each key in subset
if rooibos.common.isString(key) and not rooibos.common.arrayContains(ignoredFields, key)
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)
foundValues[key] = subsetValue
else
missingValues[key] = subsetValue
end if
end for
if foundValues.ifAssociativeArray.count() <> filteredSubset.ifAssociativeArray.count()
actual = rooibos.common.asMultilineString(foundValues, true)
expected = rooibos.common.asMultilineString(filteredSubset, true)
if msg = ""
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
'bs:disable-next-line
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, methodName, returnValue = invalid, allowNonExistingMethods = false) as object
if target = invalid and not rooibos.common.isFunction(methodName)
m.fail("could not create Stub. Global function", methodName, ", is invalid")
return {}
else if type(target) <> "roAssociativeArray"
m.fail("could not create Stub provided target was null")
return {}
end if
if m.stubs = invalid
m.__stubId = -1
m.stubs = {}
end if
m.__stubId++
if m.__stubId > 25
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
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
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, methodName, rootObject = invalid as dynamic, fullPath = invalid as dynamic, expectedArgs = invalid, returnValue = invalid as dynamic) as object
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.mock(target, methodName, 1, expectedArgs, returnValue, true)
catch error
'bs:disable-next-line
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 object
' 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 = ""
functionName = invocation.toStr().tokenize(" ").peek()
else
throw "Did not provide a function to be stubbed"
end if
if not type(stubOrReturnValue).endsWith("Function")
' throw "Did not provide a stub function"
end if
' Store the stub on the component scope
globalAa = getGlobalAa()
if type(globalAa?.__globalStubs) <> "roAssociativeArray"
globalAa.__globalStubs = {}
end if
globalAa.__globalStubs[lCase(functionName)] = stubOrReturnValue
return invalid
end function
' @ignore
function _stubCall(target, methodName, rootObject = invalid as dynamic, fullPath = invalid as dynamic, returnValue = invalid as dynamic) as object
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.stub(target, methodName, returnValue, true)
catch error
'bs:disable-next-line
m.fail("Setting up mock failed: " + error.message, "", "", true)
return false
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, methodName, rootObject = invalid as dynamic, fullPath = invalid as dynamic) as object
try
if type(target) <> "roAssociativeArray" and fullPath <> invalid
target = rooibos.common.makePathStubbable(rootObject, fullPath)
end if
return m.mock(target, methodName, 0, invalid, invalid, true)
catch error
'bs:disable-next-line
m.fail("Setting up mock failed: " + error.message, "", "", true)
return false
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, methodName, expectedArgs = invalid, returnValue = invalid, allowNonExistingMethods = false) as object
'HACK
'HACK
'HACK
'HACK
'HACK
' try
return m.mock(target, methodName, 1, expectedArgs, returnValue, allowNonExistingMethods)
' catch error
'bs:disable-next-line
' 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 paremeterized expect behaviour
' @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, methodName, isExpected, expectedArgs = invalid, returnValue = invalid, allowNonExistingMethods = false) as object
try
if isExpected
return m.expectOnce(target, methodName, expectedArgs, returnValue, allowNonExistingMethods)
else
return m.expectNone(target, methodName, allowNonExistingMethods)
end if
catch error
'bs:disable-next-line
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, methodName, allowNonExistingMethods = false) as object
try
return m.mock(target, methodName, 0, invalid, invalid, allowNonExistingMethods)
catch error
'bs:disable-next-line
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, methodName, expectedInvocations = 1, expectedArgs = invalid, returnValue = invalid, allowNonExistingMethods = false) as object
try
return m.mock(target, methodName, expectedInvocations, expectedArgs, returnValue, allowNonExistingMethods)
catch error
'bs:disable-next-line
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, methodName, expectedInvocations = 1, expectedArgs = invalid, returnValue = invalid, allowNonExistingMethods = false) as object
lineNumber = m.currentAssertLineNumber
'check params
if target <> invalid and not rooibos.common.isFunction(target) and not rooibos.common.isAssociativeArray(target)
methodName = ""
m.mockFail(lineNumber, "", "mock args: target should be an AA or in-scope Global function", methodName)
else if not rooibos.common.isString(methodName)
methodName = ""
m.mockFail(lineNumber, "", "mock args: methodName was not a string")
else if not rooibos.common.isNumber(expectedInvocations)
m.mockFail(lineNumber, methodName, "mock args: expectedInvocations was not an int")
else if not rooibos.common.isArray(expectedArgs) and rooibos.common.isValid(expectedArgs)
m.mockFail(lineNumber, methodName, "mock args: expectedArgs was not invalid or an array of args")
else if rooibos.common.isUndefined(expectedArgs)
m.mockFail(lineNumber, methodName, "mock args: expectedArgs undefined")
else if rooibos.common.isUndefined(returnValue)
m.mockFail(lineNumber, methodName, "mock args: returnValue undefined")
end if
if m.currentResult.isFail
rooibos.common.logError(`Cannot create MOCK. method ${methodName} ${lineNumber} ${m.currentResult.message}`)
return {}
end if
if m.mocks = invalid
m.__mockId = -1
m.__mockTargetId = -1
m.mocks = {}
rooibos.resetMocksByFunctionName()
end if
fake = invalid
if rooibos.common.isFunction(target)
target = {
isGlobalCall: true
}
end if
if not target.doesExist("__rooibosTargetId")
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))
fake = mock
fake.lineNumbers.push(lineNumber)
exit for
end if
end for
if fake = invalid
m.__mockId++
id = stri(m.__mockId).trim()
if m.__mockId > 25
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
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
target[methodName] = m["MockCallback" + id]
target.__mocks = m.mocks
if not isMethodPresent
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, target, methodName, expectedInvocations = 1, expectedArgs = invalid, returnValue = invalid) as object
expectedArgsValues = []
lineNumber = m.currentAssertLineNumber
hasArgs = rooibos.common.isArray(expectedArgs)
defaultValue = m.ignoreValue
if hasArgs
defaultValue = m.invalidValue
else
expectedArgs = []
end if
lineNumbers = [lineNumber]
for i = 0 to 9
if hasArgs and expectedArgs.count() > i
'guard against bad values
value = expectedArgs[i]
if not rooibos.common.isUndefined(value)
if rooibos.common.isAssociativeArray(value) and rooibos.common.isValid(value.matcher)
if not rooibos.common.isFunction(value.matcher)
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
rooibos.common.logTrace(`FAKE CALLBACK CALLED FOR ${m.methodName}`)
'bs:disable-next-line
if m.allInvokedArgs = invalid
'bs:disable-next-line
m.allInvokedArgs = []
end if
'bs:disable-next-line
m.invokedArgs = [arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15]
'bs:disable-next-line
m.allInvokedArgs.push ([arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15])
'bs:disable-next-line
m.isCalled = true
'bs:disable-next-line
m.invocations++
if m.errorToThrow <> invalid
throw m.errorToThrow
end if
'bs:disable-next-line
if type(m.returnValue) = "roAssociativeArray" and m.returnValue.ifAssociativeArray.doesExist("multiResult")
'bs:disable-next-line
returnValues = m.returnValue["multiResult"]
'bs:disable-next-line
returnIndex = m.invocations - 1
if type(returnValues) = "roArray" and returnValues.count() > 0
'bs:disable-next-line
if returnValues.count() <= m.invocations
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
'bs:disable-next-line
return m.returnValue
end if
end function
toThrow: function(error)
m.errorToThrow = error
end function
}
return fake
end function
function combineFakes(fake, otherFake)
'add on the expected invoked args
lineNumber = m.currentAssertLineNumber
if type(fake.expectedArgs) <> "roAssociativeArray" or not fake.expectedArgs.ifAssociativeArray.doesExist("multiInvoke")
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")
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)
return
end if
for each id in m.mocks
mock = m.mocks[id]
methodName = mock.methodName
if mock.expectedInvocations <> mock.invocations
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)))
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
expectedArgs = mock.expectedArgs.multiInvoke[invocationIndex]
else
expectedArgs = mock.expectedArgs
end if
if rooibos.common.isAssociativeArray(expectedArgs)
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
expected = invalid
end if
isUsingMatcher = rooibos.common.isAssociativeArray(expected) and rooibos.common.isFunction(expected.matcher)
if isUsingMatcher
if not expected.matcher(value)
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)
if expected = invalid
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
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
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, methodName, message) as dynamic
if m.currentResult.isFail
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, arg2 = invalid, arg3 = invalid, arg4 = invalid, arg5 = invalid, arg6 = invalid, arg7 = invalid, arg8 = invalid, arg9 = invalid, arg10 = invalid, arg11 = invalid, arg12 = invalid, arg13 = invalid, arg14 = invalid, arg15 = invalid) as dynamic
'bs:disable-next-line
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, fieldName, delay = 500, maxAttempts = 10)
attempts = 0
if target = invalid
return false
end if
initialValue = target[fieldName]
while target[fieldName] = initialValue
port = CreateObject("roMessagePort")
wait(delay, port)
attempts++
if attempts = maxAttempts
return false
end if
rooibos.common.logDebug(`Waiting for signal field '${fieldName}' - ${attempts}`)
end while
return true
end function
function wait(delay = 1)
port = CreateObject("roMessagePort")
wait(delay, port)
end function
function done()
rooibos.common.logTrace("Async test is complete")
if m.isDoneCalled = false
m.isDoneCalled = true
deferred = m.currentGroup?.currentTest?.deferred
if rooibos.promises.isPromise(deferred)
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, fieldName, delay = 500, maxAttempts = 10)
try
if m.currentResult.isFail
return false
end if
if target = invalid
m.fail("Target was invalid", "", "", true)
end if
result = m.waitForField(target, fieldName, delay, maxAttempts)
if not result
return m.fail("Timeout waiting for targetField " + fieldName + " to be set on target", "", "", true)
end if
return true
catch error
'bs:disable-next-line
m.currentResult.fail("Error while waiting: " + error.message, m.currentAssertLineNumber)
end try
return false
end function
' @ignore
protected function createNodeClass(clazz, useClassAsTop = true, nodeTop = new rooibos.utils.MockNode("top"), nodeGlobal = new rooibos.utils.MockNode("top"))
'bs:disable-next-line
instance = tests_maestro_nodeClassUtils_createNodeClass(clazz, nodeTop, nodeGlobal)
if instance <> invalid and useClassAsTop
'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)
'bs:disable-next-line
ids = mv_getIdsFromStyleJson(mc_getArray(bundle, viewsPath))
for each id in ids
instance[id] = { id: id }
end for
end function
' @ignore
private sub notifyReportersOnSuiteBegin()
for each reporter in m.testReporters
if rooibos.common.isFunction(reporter.onSuiteBegin)
reporter.onSuiteBegin({ suite: m })
end if
end for
end sub
' @ignore
private sub notifyReportersOnSuiteComplete()
for each reporter in m.testReporters
if rooibos.common.isFunction(reporter.onSuiteComplete)
reporter.onSuiteComplete({ suite: m })
end if
end for
end sub
end class
' @ignore
function getMocksByFunctionName()
if m._rMocksByFunctionName = invalid
m._rMocksByFunctionName = {}
end if
return m._rMocksByFunctionName
end function
' @ignore
function resetMocksByFunctionName()
m._rMocksByFunctionName = invalid
end function
' @ignore
function getMockForFunction(functionName as string)
return rooibos.getMocksByFunctionName()[functionName]
end function
' @ignore
function isFunctionMocked(functionName as string)
return rooibos.getMockForFunction(functionName) <> invalid
end function
end namespace