Forum Discussion

tristaanogre's avatar
tristaanogre
Esteemed Contributor
9 years ago

Pro-tip: More JScript vs. JavaScript -> Objects, iterations, and arrays

So, today, I went around in circles for a while looking for why my code wasn't working.

 

Context:

I'm building a framework utilizing a lot of Script Extension runtime objects to encapsulate as much of my code as possible. The advantage to this is that my framework is portable and there is minimal code that needs to be added to any single TestComplete project in order to execute a set of tests.

 

Part of the requirements for this is that we are going to be executing a series of scenarios generated as KeywordTests, each with a set of parameters. However, Script Extensions cannot call anything on the KeywordTests object. So, any interaction with KeywordTests needs to be handled in local project code.

 

Additionally, we chose JavaScript as the code base for the main projects. But script extensions can only be written in VBScript or JScript.

 

Proposed Solution:

 

Thanks to HKosova, I learned something new where you can pass in an array to a method and that array can be set to "explode" into the set of parameters.  Additionally, because JavaScript supports either bracket or dot notation for object properties, I can do the following to run any keyword test.

var myTestName = 'TestCase1'
var myParameters = ['Value1', 'Value2']

KeywordTests[myTestName].Run(...myParameters)

This works AMAZINGLY and really helped out a lot... except...

The Problem

That darn JScript.  Arrays and objects defined in JScript extensions and then passed to the above JavaScript doesn't work. There are a lot of the exposed prototype methods and properties in JavaScript that JScript just doesn't expose.  So, the following scenario DOES NOT work:

 

[JScript Extension]
MyRTObject.parameterArray = ['value1'. 'value2'];
MyRTObject.testName = 'TestCase1';

[JavaScript Code]

KeywordTest[myRTObject.testName].Run(...MyRTObject.parameterArray) //This line blows up with stuff about things not being functions, etc.

The Actual Solution

 

JSON... It's how data and information is encapsulated on web pages to move stuff from place to place in a code independent fashion. So, I'm using some JSON. Now, my actual code is a lot more complex but, essentially, it looks like this:

 

[JScript Extension]
MyRTObject.parameterArray = JSON.stringify(['value1'. 'value2']);
MyRTObject.testName = 'TestCase1';

[JavaScript Code]

var localArray = JSON.parse(MyRTObject.parameterArray)
KeywordTest[myRTObject.testName].Run(...localArray)

This worked like a charm. My structure is actually a bit more complicated where I basically created a HashTable of objects, each representing a test case and each having a set of properties, one of which being an array of parameters.  Without the JSON conversion, I couldn't do any of the fancy for(testcase in MyObjects) or the parameter "trick". But, by converting my object structure to JSON within the extension and passing it out to my JavaScript code, now it all works.

Again, just sharing something here to help those who come after me. This is a cool little trick to move stuff back and forth and allowed me to write some much more concise code.

Enjoy!

  • Manfred_F's avatar
    Manfred_F
    Regular Contributor

    have also built my Framework, using vbScript.

     

    I can NOT recommend to do so.

    The Problem is the poor functionality of the Scripting engines, all of them.

    There is no helpful compile-time Syntax check, so any typo in an object Name will Show only after the script ran two hours to reach that Location. Then You start again...

    There IS better Scripting, e.g. VBA does have a perfect Syntax check.

     

    Maybe the SDK would be a better solution here? Did anybody try?

  • tristaanogre's avatar
    tristaanogre
    Esteemed Contributor

    In my case, it's not a syntax problem but a transport problem. The JSCRIPT objects created within the context of the extension either are not 100% compatible with the JavaScript code or they lose some of the context.

    I developed my framework code within the TestComplete IDE so I had all the syntax stuff worked out. It even worked PERFECTLY in that IDE environment because it was all JSCRIPT. So, whIle the SDK might have a lot more power, I think Script Extensions are still viable for framework construction.

     

    EDIT: Specifically, the JScript array does not support the spread syntax.  IF, somehow, I could create a Script Extension in JavaScript... THEN... things my be different.

    • tristaanogre's avatar
      tristaanogre
      Esteemed Contributor

      I did some poking around today to see if I could determine if it is a JScript vs JavaScript... not exactly. It's more a matter of, as I mentioned, context. Encapsulated within the Script Extension itself, the objects created are completely useable as JScript.  However, once the object is passed out of the ScriptExtension to the regular project, something gets lost in the transition.

       

      For example, in the MusicBox extension I created, there is a constructor called Notes.  Within the Script Extension, you would do the following:

       

      function foo() {
      
      var myNote = new Notes('C4', 2000);
      if (myNote.constructor == Notes) Log.Message('It worked');
      }

      This would actually log the message just fine.  Now, I expose that Notes constructor to the script extension as a method.  So, MusicBox.Notes will return an object.  So, if I change my ode just a little bit...

       

      function foo() {
      
      var myNote = new MusicBox.Notes('C4', 2000);
      if (myNote.constructor == Notes) Log.Message('It worked');
      }

      No message gets logged. So, something is lost in the "translation" of the object from the Script Extension to the IDE where the constructor gets lost.  This, I'm assuming, would be the problem no matter what language my extension is written in.  

      HKosova  You seem to be one of the resident experts on JavaScript/JScript etc...  Do you know if there is a work around for this limitation? 

      • tristaanogre's avatar
        tristaanogre
        Esteemed Contributor

        OK... I actually submitted this problem as a SmartBear customer care ticket because I just wanted to make sure that this wasn't a bug in TC and was actually a limitation in JScript extensions (can't vouch for VBScript).

         

        It turns out that, technically speaking, there are two instances of the JScript engine in TestComplete.  One is used for running the automation code, one is used for script extensions.  The problem has to do with transporting objects from one instance to another... and apparently, even, transporting from the JScript engine instance for Script Extensions across to any other engine (VBScript, JavaScript, etc). It's something funky with JScript itself that it just doesn't play nice... it's not a TC issue, but an issue with JScript.

         

        So, the JSON workaround that I've implemented is actually a good way of getting around this.  Customer care also suggested that you can created an iterable collection of the fields or properties or methods on any object generated in the extension using aqObject. This worked VERY well as well. I did a quick performance check between using the JSON method or using aqObject and it doesn't seem like either one is faster or slower than the other for this particular situation.