Dynamically verify object property in script via Keyword test
For better or worse, I'm meshing scripts with keyword tests. I'm trying to pass into a function the on-screen object and then the property of said object, like "Exists" or "Enabled".
function waitToRunExists(selector, prop, attempts) { var theElement; //Prime the attempts variable if( typeof attempts == "undefined" || attempts == null ) { attempts = 1; } var theElement = selector; // Wait for theElement/on-screen object to be true, or bail after X attempts do{ attempts++; if (attempts > 500) { Log.Error("Too many attempts. attempts = " + attempts + "."); } } while ( theElement.prop == false || attempts > 500); //attempts was 200 // || attempts > 200 }
In the keyword test, I'm using the "Run Script Routine". For the prop variable, I've tried string, variant, code expression, etc. It seems like a type issue, but I can't find the correct type. Any suggestions?
Question: Is the test simply a test of the properties of "Exists", "Enabled", "Visible"? If so, you don't need a new script routine for it, you can simply use the If-Object operation in Keyword tests (https://support.smartbear.com/testcomplete/docs/keyword-testing/reference/test-actions/if-object.html). This covers these basic items with out needing custom code.
Now, as for your code: The problem with your code as it is written is, if you pass in the object itself and you're checking for "Exists" and the object doesn't ACTUALLY exist, you're going to get an error in your check of that property, no matter how you implement it. You can't evaluate the ANY property of an object that does not exist... that object has to exist first before you can evaluate the property. What I would do is, instead of the object itself, pass in the PARENT of the object. You can then do a "WaitChild" method of sorts to get the object you're wanting to test and, if it comes back empty, you'll know it doesn't exist. If it comes back with Exists being "true", then you can do whatever other tests you want.
So... if I were to rewrite your code to be able to check for a property value given any particular property string, this is how I would do it.
function waitToRunExists(parent, selector, prop, propValue, attempts) { var theElement; var existCounter = 0; var attemptCounter = 0; //Prime the attempts variable if( typeof attempts == "undefined" || attempts == null ) { attempts = 1; } //wait for Element to exist theElement = parent.WaitAliasChild(selector, 500 ); while (existsCounter < 120) { if (theElement.Exists) break; existsCounter++; theElement = parent.WaitAliasChild(selector, 500 ); } //if the element doesn't exist after 2 minutes, log an error and skip the rest of the function if ((existsCounter == 120) && (!theElement.Exists)) { Log.Error('The object ' + selector + ' does not exist'); } else { // if the Object does exist, loop until either the # of loops exceeds the desired # of attempts // or the desired property of theElement is true do { attemptCounter++; if (attemptCounter > attempts) { Log.Error("Too many attempts. attempts = " + attempts + "."); } } while ((aqObject.GetPropertyValue(theElement, prop) != propValue) || (attemptCounter > attempts)); //attempts was 200 // || attempts > 200 } }
Now, that SAID... this is still redundant code if you're looking to wait for a property to come back with a certain value. In your keyword test, after checking to see if the object exists (see my while loop in the above code), you can add an OnScreen Action for the object and, as the action, use WaitProperty method (https://support.smartbear.com/testcomplete/docs/reference/test-objects/members/common-for-all/waitproperty-method.html). Basically, you can tell the test case to wait until an object's property has a particular value OR the wait method times out. To see if it worked, just use the "Last Result" value in an if then statement to check to see if it returns true... if it's true, the property is the desired value. If false, the timeout happened.