Repository: sjbarag/brs
Pull request #564 (2020-10-22 20:11:36)

fix(mocks, stdlib): mocked component callFunc works now
# Change summary

Yep, you guessed it... more `callFunc` updates! This time, we need to account for mocked components in `callFunc` calls.


Patch:
diff --git a/src/brsTypes/components/RoSGNode.ts b/src/brsTypes/components/RoSGNode.ts
index 6cce821..ccbdc9e 100644
--- a/src/brsTypes/components/RoSGNode.ts
+++ b/src/brsTypes/components/RoSGNode.ts
@@ -545,6 +545,14 @@ export class RoSGNode extends BrsComponent implements BrsValue, BrsIterable {
 
                 // Only allow public functions (defined in the interface) to be called.
                 if (componentDef && functionname.value in componentDef.functions) {
+                    // Use the mocked component functions instead of the real one, if it's a mocked component.
+                    if (interpreter.environment.isMockedObject(this.nodeSubtype.toLowerCase())) {
+                        let maybeMethod = this.getMethod(functionname.value);
+                        return (
+                            maybeMethod?.call(interpreter, ...functionargs) || BrsInvalid.Instance
+                        );
+                    }
+
                     return interpreter.inSubEnv((subInterpreter) => {
                         let functionToCall = subInterpreter.getCallableFunction(functionname.value);
                         if (!functionToCall) {
diff --git a/src/interpreter/Environment.ts b/src/interpreter/Environment.ts
index 6ebc10d..aaf45bd 100644
--- a/src/interpreter/Environment.ts
+++ b/src/interpreter/Environment.ts
@@ -274,6 +274,14 @@ export class Environment {
         return newEnvironment;
     }
 
+    /**
+     * returns true if the variable has a mocked object
+     * @param objName the object to mock
+     */
+    public isMockedObject(objName: string): boolean {
+        return this.mockObjects.has(objName);
+    }
+
     /**
      * retrieves mocked object if it exists
      * @param objName the object to mock


Test patch:
diff --git a/test/e2e/CallFunc.test.js b/test/e2e/CallFunc.test.js
index 389b7a9..b89f1a9 100644
--- a/test/e2e/CallFunc.test.js
+++ b/test/e2e/CallFunc.test.js
@@ -52,6 +52,8 @@ describe("callFunc", () => {
             "component: inside privateFunction",
             "private return value",
             "component: overriding parent func",
+            "main: mocked component voidFuncNoArgs return value:",
+            "this is a mock",
         ]);
 
         expect(allArgs(outputStreams.stderr.write).filter((arg) => arg !== "\n")).toEqual([
diff --git a/test/e2e/resources/components/call-func/scripts/main.brs b/test/e2e/resources/components/call-func/scripts/main.brs
index d667173..adeddfd 100644
--- a/test/e2e/resources/components/call-func/scripts/main.brs
+++ b/test/e2e/resources/components/call-func/scripts/main.brs
@@ -18,4 +18,13 @@ sub main()
     print node.callFunc("parentFunc")
 
     print node.callFunc("overridenParentFunc")
+
+    _brs_.mockComponent("CallFuncTestbed", {
+        voidFuncNoArgs: function() as string
+            return "this is a mock"
+        end function
+    })
+    node = createObject("RoSGNode", "CallFuncTestbed")
+    result = node.callFunc("voidFuncNoArgs")
+    print "main: mocked component voidFuncNoArgs return value:" result ' => "this is a mock"
 end sub