Overriding Commands in SenseTalk

hi all,

i am trying to override some eggplants commands so that they provide a better error handling for my testing.

I have, within my suite a script call myUtil wich i “start using” before any script i create.

most of the things work fine, but i am having an issue with this particular piece of code:


to Click myImage, myError, myDesc
	If myError is empty then put "UNEXPECTED" into myError
	If myDesc is empty then put "Unable to find image: "&myImage into myDesc
	try
		If ImageFound(myImage) then 
			send Click FoundImageLocation()  to SenseTalk
		end if
	catch anException
		throw myError, myDesc
	end try
end Click

when i try to do Click “SomeImage” from a script, i get this result:

Wed, 11-02-23 3:10:41 PM START Running WorkingTest.script
Wed, 11-02-23 3:10:44 PM imagefound Unable to Find Image Document/Window_AutoCurvilinear/TextField_EndDepth
Wed, 11-02-23 3:10:44 PM SUCCESS Execution Time 0:00:02 WorkingTest.script

I would have expected to catch the exception and get a big fail with “UNEXPECTED” “Unable to find image <>” witch is not the case… what am i missing?

I just want to add that it occured to me that for some reason the try is understanding the if command as being the one to test…

I am going to try to express the function with a waitfor instead of ImageFound… but, am i wrong in doing it like that?

Is there a better way to do it?

So i was right, the try was “testing” the success of the if command.

i changed the code a bit, and now works as intended… i am posting it here, but if any of you have suggestions for improving this i will appreciate it because i feel is not too elegant.


to Click myImage, myError, myDesc
	If myError is empty then put "UNEXPECTED" into myError
	If myDesc is empty then put "Unable to find image: "&myImage into myDesc
	try
		ImageFound(myImage)
	catch anException
		throw myError, myDesc
	end try
	send Click FoundImageLocation() to SenseTalk
end Click


So you are very close but are missing a key point:

The imageFound() function returns a bool value as to if the image is found on screen or not; but it won’t throw an exception if the image isn’t found. This was the problem in your first syntax. Mostly imageFound() won’t ever throw an exception, except when used as a statement like your second case where it will ALWAYS raise an exception.

I think what you really want is to just try the click and if THAT throws an exception you want to do your own error.

to Click myImage, myError, myDesc 
   If myError is empty then put "UNEXPECTED" into myError 
   If myDesc is empty then put "Unable to find image: "&myImage into myDesc 
   try 
      send Click myImage to SenseTalk 
   catch anException 
      throw myError, myDesc 
   end try 
end Click 

You are absolutely right, i didn’t notice that before, although your code is right on the spot is missing something i want, which is ensure the image is there before clicking it.

Any suggestions? i am trying to avoid the

waitFor Time, Image
click FoundImageLocation()

idiom.

( less lines of codes in the test )

[EDIT: Maybe ensure is too strong of a wording, to avoid timing issues without sprinkling waits in the test code, i want to wait for the image before clicking it ]

The first issue is what do you want your handler to do if the image is NOT on screen. Do you want it to throw an error or just warn and continue?

The code above will throw an error (just like the click command).

As far as waiting is concerned. The click command already has a certain amount of waiting that it will do all the time (the imageSearchTime). If you want to specify a longer (or shorter) minimum search time you can pass an optional time argument as it’s first value.

Click 20, “MyImage” – short for search for MyImage for 20 seconds and click it.

Thank you very much, didn’t know that. how about this


to Click howLong, myImage, myError, myDesc 
   If howLong is empty then put 1.0 into howLong
   If myError is empty then put "UNEXPECTED" into myError 
   If myDesc is empty then put "Unable to find image: "&myImage into myDesc 
   try 
      send Click howLong, myImage to SenseTalk 
   catch anException 
      throw myError, myDesc 
   end try 
end Click 


i think this would do the trick :smiley:

Just found an error in my previous solution, if i provide image, error and desc but not a time ( Click “Image”, “ERROR”, “Reason” ) the positional arguments will think “Image” is the time to wait… :S Help!

You can do:

if howLong is empty then
  click myImage
else
  click howLong, myImage

As an aside, I would make the howLong argument the 4th argument and then you can more easily include or exclude it (if you plan to only specify it some of the time.

Is there any way to specify it as the first argument while at the same time making it optional? something like verifying the first parameter is a number or a string?

Making anything other than the last argument(s) optional is bad coding practice. But if you want to leave a parameter out, just use a comma:

doSomething , , "dog", "cat"

to dosomething 
	put param(1) -- outputs nothing
	put param(2) -- outputs nothing
	put param(3) -- outputs "dog"
	put param(4) -- outputs "cat"
end doSomething

Thank you, this is helpful

I dont mean to second guess your advice, regarding bad coding practice, but why exactly is it bad to have the first parameter be optional? i was just trying to replicate the functionality of ImageFound(“Image”) that has an optional parameter for timing ImageFound(Time,“Image”)

Thanks in advance.

While the time parameter may be described as optional parameter, it’s really not optional. What happens is the first parameter is checked to see if it is a number and if it is, then it is used as a timeout value. When you don’t specify a time, it’s not as though the function treats it like there’s an empty value in the first position, it just uses the first parameter as an image name. Some people might argue that that’s not great programming practice either, but it’s a little cleaner than truly having an optional first parameter.

To look at it another way, you’re not required to do anything to indicate that you’re not specifying a time parameter; if it were truly an optional parameter, you’d need to somehow provide an empty value to indicate that you knew it was there and you were intentionally leaving it out. That’s why it’s better to have truly optional parameters at the end of the list of arguments – the user doesn’t need to do anything special to leave them out.

In some languages the function with the time parameter and the one without would be two different functions and the compiler would use the correct one based on the “signature” of the function. The call with a number in the first position would be distinct from the call with an image (string) in the first position. We don’t have that ability, largely, I believe, because SenseTalk is not strongly typed.

I hope that’s at least somewhat clear.

just wanted to share my click override as well:


(* Overrides default click--Clicks a an image until the target display opens.  This is necessary because certain display clicks do not always register, regardless of whether the click is via automation or not *)
//imageToClick: [any image]
//imageToSearchFor: [usually a display identifier--any image that you would expect to find after the click is successful
to Click imageToClick, imageToSearchFor
    if imageToClick is a number or imageToClick is a point or imageToSearchFor is empty then
        //Timeout value, coordinates, or no imageToSearchFor indicate normal clicking is desired
        send Click parameterList() as parameters to SenseTalk 
    else //Click until expected image is found, or operation fails too many times
        if ImageFound(imageToClick) then
            repeat while not ImageFound(imageToSearchFor)
                send Click FoundImageLocation() to SenseTalk
                if repeatIndex() is greater than 10 then 
                    
            LogError "Could not open" && display_id && "display.  Please correct script.  See screenshot for moree information"
                end if
            end repeat
        else
            LogError imageToClick && "could not be found on the screen.  See screenshot and correct script."
        end if
    end if
end Click 

Wow, this is really good, i hope you don’t mind me “stealing” some bits from this :slight_smile:

Hey Craig,

what exactly is display_id in your script?

[quote=“craigmachaffie”]just wanted to share my click override as well:


(* Overrides default click--Clicks a an image until the target display opens.  This is necessary because certain display clicks do not always register, regardless of whether the click is via automation or not *)
//imageToClick: [any image]
//imageToSearchFor: [usually a display identifier--any image that you would expect to find after the click is successful
to Click imageToClick, imageToSearchFor
    if imageToClick is a number or imageToClick is a point or imageToSearchFor is empty then
        //Timeout value, coordinates, or no imageToSearchFor indicate normal clicking is desired
        send Click parameterList() as parameters to SenseTalk 
    else //Click until expected image is found, or operation fails too many times
        if ImageFound(imageToClick) then
            repeat while not ImageFound(imageToSearchFor)
                send Click FoundImageLocation() to SenseTalk
                if repeatIndex() is greater than 10 then 
                    
            LogError "Could not open" && display_id && "display.  Please correct script.  See screenshot for moree information"
                end if
            end repeat
        else
            LogError imageToClick && "could not be found on the screen.  See screenshot and correct script."
        end if
    end if
end Click 

[/quote]