Call function from string value JavaScript
I was hoping that TestComplete offered a method in which we can dynamically call specific functions based off of a string variable.
For example: This is how I would do it in C#. Unfortunately I am not sure if JavaScript has something similar, or even if TestComplete offers it.
using System; using System.Reflection; /// <summary> /// Will invoke the method passed in. Then, it will return the generic type used in the function /// Example: InvokeMethod<int>("methodName", "param"); /// </summary> /// <typeparam name="T"></typeparam> /// <param name="methodName"></param> /// <param name="stringParam"></param> /// <returns></returns> public static T InvokeMethod<T>(string methodName, string stringParam) { return (T)typeof(T).InvokeMember(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new Object[] { stringParam }); }
Thoughts?
Different script languages have a functionality like "Evaluate" or "eval" which will take any string and evaluate it as such. It works well but it does run some risks.
There is a method of Runner.CallMethod (https://support.smartbear.com/testcomplete/docs/reference/project-objects/items/script/runner/callmethod.html). It's listed as obselete because it had been the means, before, of calling methods from other script units. That's no longer necessary. But for doing the kind of data reflection you're wanting to do, this still works well.
If your method to be invoked is a method on an object, you can use aqObject.CallMethod instead (https://support.smartbear.com/testcomplete/docs/reference/program-objects/aqobject/callmethod.html).
I created a kind of data reflection myself as part of the mini-framework I have under development. The code is below. It requires a certain structuring for creating the classes themself (each class is a script unit named for the class with a method called "returnClass" which returns an instance of the object. I use the flexibility of the Runner.CallMethod means of doing this which works well in my situation:
/* Initial source retrieved from https://bitbucket.org/tristaanogre/tabledrivenframework and developed by Robert Martin. The initial source is under a Creative Commons Creative Commons Attribution-ShareAlike 4.0 International License and any modifications to this source are similarly available under the same license */ function toProperties(listProperties) { var listLength, listPropertyName, listPropertyValue, listPropertyString; listLength = aqString.GetListLength(listProperties); listPropertyString = ''; for (var i = 0; i<listLength; i += 2){ listPropertyName = aqString.GetListItem(listProperties, i); listPropertyValue = aqString.GetListItem(listProperties, i+1); listPropertyString = listPropertyString + '"' + listPropertyName + '": "' + listPropertyValue + '", '; } return JSON.parse('{' + aqString.SubString(listPropertyString, 0, aqString.GetLength(listPropertyString)-2) + '}'); } function returnClass(className, properties){ var classMethod = className + ".returnClass"; var localObject = Runner.CallMethod(classMethod) if (properties === undefined) { properties = ""; } localObject.data = toProperties(properties); return localObject; }