diff --git a/bsc-plugin/src/lib/rooibos/MockUtil.spec.ts b/bsc-plugin/src/lib/rooibos/MockUtil.spec.ts index 8f963933..13ae670a 100644 --- a/bsc-plugin/src/lib/rooibos/MockUtil.spec.ts +++ b/bsc-plugin/src/lib/rooibos/MockUtil.spec.ts @@ -85,6 +85,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.sayhello __stubOrMockResult = __stubFunction(a1, a2) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("sayhello") + value = __stubs_globalAa.__globalStubs.sayhello + return value end if print "hello" end function @@ -122,6 +125,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.sayhello __stubOrMockResult = __stubFunction(a1, a2) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("sayhello") + value = __stubs_globalAa.__globalStubs.sayhello + return value end if print "hello" end function @@ -162,6 +168,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.redlines_setrulerlines __stubOrMockResult = __stubFunction(rulerLines) return + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("redlines_setrulerlines") + value = __stubs_globalAa.__globalStubs.redlines_setrulerlines + return end if For Each line In rulerLines.Items() RedLines_AddLine(line.key, line.value.position, line.value.coords, m.node, m.childMap) @@ -177,6 +186,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.redlines_addline __stubOrMockResult = __stubFunction(id, position, coords, node, childMap) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("redlines_addline") + value = __stubs_globalAa.__globalStubs.redlines_addline + return value end if line = CreateObject("roSGNode", "Rectangle") line.setField("id", id) @@ -213,6 +225,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.sayhello __stubOrMockResult = __stubFunction(a1, a2) return + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("sayhello") + value = __stubs_globalAa.__globalStubs.sayhello + return end if print "hello" end sub @@ -250,6 +265,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.person_utils_sayhello __stubOrMockResult = __stubFunction(a1, a2) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("person_utils_sayhello") + value = __stubs_globalAa.__globalStubs.person_utils_sayhello + return value end if print "hello" end function @@ -287,6 +305,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.person_utils_sayhello __stubOrMockResult = __stubFunction(a1, a2) return + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("person_utils_sayhello") + value = __stubs_globalAa.__globalStubs.person_utils_sayhello + return end if print "hello" end sub @@ -378,6 +399,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.beings_sayhello __stubOrMockResult = __stubFunction() return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("beings_sayhello") + value = __stubs_globalAa.__globalStubs.beings_sayhello + return value end if print "hello2" end function @@ -391,6 +415,9 @@ describe('MockUtil', () => { __stubFunction = __stubs_globalAa.__globalStubs.sayhello __stubOrMockResult = __stubFunction() return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("sayhello") + value = __stubs_globalAa.__globalStubs.sayhello + return value end if print "hello3" end function diff --git a/bsc-plugin/src/lib/rooibos/MockUtil.ts b/bsc-plugin/src/lib/rooibos/MockUtil.ts index 1462d6c3..525251b7 100644 --- a/bsc-plugin/src/lib/rooibos/MockUtil.ts +++ b/bsc-plugin/src/lib/rooibos/MockUtil.ts @@ -112,6 +112,9 @@ export class MockUtil { __stubFunction = ${globalAaName}.${storageName}.${methodName} ${resultName} = __stubFunction(${paramNames}) return${requiresReturnValue ? ` ${resultName}` : ''} + else if ${globalAaName}?.${storageName} <> invalid and ${globalAaName}.${storageName}.doesExist("${methodName}") + value = ${globalAaName}.${storageName}.${methodName} + return${requiresReturnValue ? ` value` : ''} end if `; const astCodeToInject = Parser.parse(template).ast.statements; diff --git a/bsc-plugin/src/plugin.spec.ts b/bsc-plugin/src/plugin.spec.ts index 3ff66c93..bb0267c1 100644 --- a/bsc-plugin/src/plugin.spec.ts +++ b/bsc-plugin/src/plugin.spec.ts @@ -1063,6 +1063,9 @@ describe('RooibosPlugin', () => { __stubFunction = __stubs_globalAa.__globalStubs.sayhello __stubOrMockResult = __stubFunction(firstName, lastName) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("sayhello") + value = __stubs_globalAa.__globalStubs.sayhello + return value end if print firstName + " " + lastName end function @@ -1151,6 +1154,9 @@ describe('RooibosPlugin', () => { __stubFunction = __stubs_globalAa.__globalStubs.utils_sayhello __stubOrMockResult = __stubFunction(firstName, lastName) return __stubOrMockResult + else if __stubs_globalAa?.__globalStubs <> invalid and __stubs_globalAa.__globalStubs.doesExist("utils_sayhello") + value = __stubs_globalAa.__globalStubs.utils_sayhello + return value end if print firstName + " " + lastName end function diff --git a/bsconfig-prod.json b/bsconfig-prod.json new file mode 100644 index 00000000..2a748abc --- /dev/null +++ b/bsconfig-prod.json @@ -0,0 +1,14 @@ +{ + "rootDir": "framework/src", + "files": ["manifest", "source/**/*.*", "components/**/*.*"], + "autoImportComponentScript": true, + "createPackage": false, + "stagingFolderPath": "dist", + "diagnosticFilters": [ + { + "src": "**/roku_modules/**/*.*", + "codes": [1107, 1009] + } + ], + "plugins": ["@rokucommunity/bslint"] +} diff --git a/framework/src/source/BaseTestSuite.bs b/framework/src/source/BaseTestSuite.bs index 5a031091..fe73329d 100644 --- a/framework/src/source/BaseTestSuite.bs +++ b/framework/src/source/BaseTestSuite.bs @@ -1833,7 +1833,7 @@ namespace rooibos end if if not type(stubOrReturnValue).endsWith("Function") - throw "Did not provide a stub function" + ' throw "Did not provide a stub function" end if ' Store the stub on the component scope diff --git a/tests/.vscode/launch.json b/tests/.vscode/launch.json index 728cb81a..26f48708 100644 --- a/tests/.vscode/launch.json +++ b/tests/.vscode/launch.json @@ -30,7 +30,7 @@ "stopDebuggerOnAppExit": true, "enableVariablesPanel": false, "injectRaleTrackerTask": false, - "enableDebugProtocol": false + "enableDebugProtocol": true }, { "name": "watch tests", @@ -61,7 +61,7 @@ "stopDebuggerOnAppExit": true, "enableVariablesPanel": false, "injectRaleTrackerTask": false, - "enableDebugProtocol": false + "enableDebugProtocol": true, } ] } diff --git a/tests/bsconfig.json b/tests/bsconfig.json index 08ba2e32..891684c7 100644 --- a/tests/bsconfig.json +++ b/tests/bsconfig.json @@ -27,7 +27,7 @@ ], "rooibos": { "showOnlyFailures": true, - "catchCrashes": true, + "catchCrashes": false, "lineWidth": 70, "failFast": false, "sendHomeOnFinish": false, diff --git a/tests/package-lock.json b/tests/package-lock.json index 7eff43d1..b8765bdc 100644 --- a/tests/package-lock.json +++ b/tests/package-lock.json @@ -166,6 +166,16 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@xml-tools/parser": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", @@ -1658,6 +1668,13 @@ "node": ">=4.2.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -2022,6 +2039,16 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "peer": true, + "requires": { + "undici-types": "~5.26.4" + } + }, "@xml-tools/parser": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", @@ -3183,6 +3210,13 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", diff --git a/tests/src/source/Charlies-Issues.spec.bs b/tests/src/source/Charlies-Issues.spec.bs new file mode 100644 index 00000000..889f2913 --- /dev/null +++ b/tests/src/source/Charlies-Issues.spec.bs @@ -0,0 +1,61 @@ +namespace tests + @suite + class MockExample extends rooibos.BaseTestSuite + + protected override function setUp() + super.setUp() + end function + + protected override function beforeEach() + m.SUT = SomeModel() + end function + + protected override function afterEach() + m.cleanMocks() + m.cleanStubs() + m.SUT = invalid + end function + + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + @describe("Example Tests on SomeModel public methods") + '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + @it("globalMockExample1_passing") + function _() + m.stubCall(getManifestValue, function(key) : return "stubCall hardcoded title" : end function) + m.SUT.globalMockExample() + m.assertEqual(m.SUT.appTitle, "stubCall hardcoded title") + end function + + @it("globalMockExample2_crashing_due_to_returnValue") + @params("stubCall dynamic title") + function _(manifestValue as string) + m.stubCall(getManifestValue, manifestValue) + m.SUT.globalMockExample() + m.assertEqual(m.SUT.appTitle, manifestValue) + end function + + @it("stubExample1_passing") + @params({ configSetVia_config: true }, { configSetViaStub: true }) + function _(config1 as object, config2 as object) + m.SUT._config = config1 + m.stub(m.SUT, "_getConfig", config2) + m.SUT.setUpdatedConfig1() + expectedKeyNameConfig2 = config2.keys()[0] + resultKeyName = m.SUT.updatedConfig.keys()[0] + m.assertEqual(expectedKeyNameConfig2, resultKeyName) + end function + + @ignore("this is not supported - we do not support mocking singleton objects between test runs") + @it("stubExample2_crashing_stub_from_stubExample1_persisting") + @params({ configSetVia_config: true }, { configSetViaStub: true }) + function _(config1 as object, config2 as object) + m.SUT._config = config1 + m.SUT.setUpdatedConfig2() + expectedKeyNameConfig1 = config1.keys()[0] + resultKeyName = m.SUT.updatedConfig.keys()[0] + m.assertEqual(expectedKeyNameConfig1, resultKeyName) + end function + + end class +end namespace \ No newline at end of file diff --git a/tests/src/source/SomeModel.brs b/tests/src/source/SomeModel.brs new file mode 100644 index 00000000..116f4b2d --- /dev/null +++ b/tests/src/source/SomeModel.brs @@ -0,0 +1,34 @@ +function SomeModel() as object + if (m._someModel = invalid) + + obj = {} + obj.appTitle = "" + obj._config = invalid + obj.updatedConfig = invalid + + obj.globalMockExample = sub() + appTitle = getManifestValue("title") + m.appTitle = appTitle + end sub + + obj.setUpdatedConfig1 = sub() + m.updatedConfig = m._getConfig() + end sub + + obj.setUpdatedConfig2 = sub() + m.updatedConfig = m._getConfig() + end sub + + obj._getConfig = function() as object + return m._config + end function + + m._someModel = obj + end if + + return m._someModel +end function + +function getManifestValue(key as string) as string + return createObject("roAppInfo").getValue(key) +end function \ No newline at end of file