QTP/UFT - Function That Creates WebLink Variables - vbscript

I am thinking of doing something I am not sure if it is possible - perhaps not the best practice even, but nonetheless want to give it a try.
I have a function library and I have the action in which I do the main scripting, obviously calling functions from the library.
Originally in my action, the code looked something like this:
Code
Browser("Browser").Page("Page").WebElement("Element").Click
I have, however, changed it to this:
Code
Set WebLink = Browser("Browser").Page("Page")
WebLink.WebElement("Element").Click
I did this because i feel that it has a cleaner look with "less" code in each line.
I know that I can code a function to do this:
Public Function myLink(WebLink)
Set WebLink = Browser("Browser").Page("Page")
End Function
Then in my action, I do a call just once at the top:
Code
Call myLink(WebLink)
WebLink.WebElement("Name").HighLight
However, I was thinking that in some instances, I would have different page names, for example:
Code
Browser("Browser").Page("Page1")
Browser("Browser").Page("Page2")
Browser("Browser").Page("Page3")
So perhaps, creating a function that would store my variables and then I am able to call the variables could be an alternative.
My function could look like this:
Code
Public Function myLinks(WebLink)
Dim Pages(): Pages = ("Login","CreateUser","SelectOption","DeleteUser",)
Browser("Browser").Page(Pages())
For Each Elem In Pages
Set WebLink = Browser("Browser").Page(Pages())
End For
End Function
Then in my action, I use it like this:
Code
Call myLinks(WebLink)
Login.WebElement("Element").Click
CreateUser.WebElement("Element").Click
SelectOption.WebElement("Element").Click
DeleteUser.WebElement("Element").Click
I know that what I have is probably illogical but if something like this could perhaps work, I would like to give it a try.

well, if you do not have the Option Explicit enabled at the beginning of your vbs files (which would force you to declare each variable before usage) then you can simply say:
For Each strPage in Pages()
ExecuteGlobal "Set " & strPage & " = Browser(""Browser"").Page(""" & strPage & """)"
Next
This one would create for you Global Variables having as names the Strings in your Pages Array. You do not need any Input Parameter
P.S: A better name would be InitPageObjects - as what you are trying to achieve has nothing to do with Links

Related

ruby: howto use multiple boolean options and keep the code readable

I need to process a couple of boolean options, and I am trying to do it like it is usually done in C:
DICT = 0x000020000
FILTER = 0x000040000
HIGH = 0x000080000
KEEP = 0x000100000
NEXT = 0x000200000
I can now assign arbitrary options to a Integer variable, and test for them:
action if (opts & HIGH|KEEP) != 0
But this looks ugly and gets hard to read. I would prefer writing it like
action if opts.have HIGH|KEEP
This would require to load have method onto Integer class.
The question now is: where would I do that, in order to keep this method contained to the module where those options are used and the classes that include this module? I don't think it's a good idea to add it globally, as somebody might define another have somewhere.
Or, are there better approaches, for the general task or for the given use-case? Adding a separate Options class looks like overkill - or should I?
You can use anybits?:
action if opts.anybits?(HIGH|KEEP)
The methods returns true if any bits from the given mask are set in the receiver, and false otherwise.

Debugging a custom function in Google Apps Script

I am trying to create my first custom function for a Google Spreadsheet in Apps Script and I am having a hard time using the debugger.
I am working on the custom function demo code from the Google documentation and I have set a breakpoint in the custom function drivingDistance(origin, destination) that is used in a cell of my spreadsheet. The problem I have is, that that the debugger shows the parameters that are passed into the function as being undefined. The content of any other variables that are created during execution is displayed correctly though (as long as they do not depend on the input parameters).
Funny thing is that although the input parameters are displayed as undefined, the function's calculations succeed, so this seems to be a debugger issue. Unfortunately this problem prevents me from successfully learning to create and debug own code (as I will have to work with complex input parameters).
I have a feeling that the problem is connected to the server-side execution of Apps Script, so I tried to log the input parameters using the Logger class and I also tried to copy these variables into new local variables. But all I came up with was undefined.
Another strange hint is, that typeof of the parameters returns String. But getting the length of them throws an error and trying to concatenate them with another string returns the string "undefined" (see my screen dump).
I am looking for insights about what is going on here.
The debugger is probably not lying to you - if you launch that function in the debugger, it will have no parameters passed to it. No worries, though, you just need to make sure that you get values to use for debugging. Take a look at How can I test a trigger function in GAS?, which demonstrates techniques that can be applied for custom functions.
Instead of defining an event to pass to the function, you'll want to provide (or retrieve from your spreadsheet) values for the parameters.
function test_drivingDistance() {
// Define a set of test values
var testSet = [[ 'Washington, DC', 'Seattle, WA' ],
[ 'Ottawa, ON', 'Orlando, FL'],
[ 'Paris, France', 'Dakar, Senegal']];
// Run multiple tests
for (var test in testSet) {
Logger.log('Test ' + test + ' = ' + drivingDistance(testSet[test][0],testSet[test][1]));
}
// Get parameters from sheet
var TestFromSheet = drivingDistance(ss.getRange('A1').getValue(),ss.getRange('A2').getValue());
}
You get the idea. You can still set breakpoints inside your function, or use debugger to pause execution.
Edit - examining arguments
What arguments is the custom function receiving when called from a spreadsheet?
You're limited in what you can do to debug this, since the debugger can't be used to examine your custom function when invoked from Sheets, and security limitations on custom functions block Logging. It might be enough to get an understanding of argument passing in general. While javascript functions may have named parameters, all arguments are passed as an Array-like object, called arguments. This custom function will return an array that reports the arguments received. When called from a spreadsheet, each argument will appear in its own cell, starting at the cell you enter the function into:
function testArguments( ) {
var argArray = [];
for (var arg in arguments) {
argArray.push("arguments[" + arg + "] = " + JSON.stringify(arguments[arg]))
}
return argArray;
}
In javascript, there aren't really types like int or float - just Number. Those parameters will show up without quotes on them, and look like numbers. Dates arrive as Date objects, but when printed this way show up as Date-y strings. Strings have quotes.
A custom function never receives a range as an argument; when you provide a range parameter in the spreadsheet, its contents are collected into a one or two-dimensional array, and the array is the argument.
You can use this hack to see the structure of the arguments being sent into the custom function:
function TEST(input) {
return (JSON.stringify(input));
}
The results will show up in your sheet like this:

Stringify a method call in VBScript

I'm currently working every day with QuickTest Professional 11, which uses VBScript behind the scenes. Lately, I've started developing some of my own functions to handle common situations. I'm pretty new to VBscript, most of my programming experience is in C and Python.
I'm trying to implement Python's Try/Except in VBScript, mostly to wrap around actions like clicking links or selecting values from dropdown boxes. Here's what I have so far:
Class cls_ErrorHandler
Private bWasError
Private Sub Class_Initialize()
bWasError = False
End Sub
Private Sub IsErr
If Err.Number <> 0 Then
bWasError = True
Else
bWasError = False
End If
Err.Clear
End Sub
' If the command fails, set bWasError
Public Sub Try(strCommandToTry)
On Error Resume Next
Execute(strCommandToTry)
me.IsErr
On Error Goto 0
End Sub
Public Sub Except(strCommandInCaseOfError)
If bWasError Then
Execute(strCommandInCaseOfError)
End If
bWasError = False
End Sub
End Class
I'd like to be able to write things like this:
Set oErrorHandler = New cls_ErrorHandler
oErrorHandler.Try(Stringify(Browser("Browser Name").Page("Page Name").WebCheckBox("Checkbox Name").Set "ON"
oErrorHander.Except(Stringify(Browser("Browser Name").Page("Page Name").WebButton("Save").Click))
As far as I can tell, there really isn't any nice way to pass a function as an argument to another function in VBScript. The best way seems to be to pass a string containing the name of a function, and then feed that string into Execute() or Eval(). Objects in QuickTest Professional tend to have lots of quotation marks, so escaping them all by hand would make the code unreadable.
In C, I'd use something like this:
#define Stringify(obj) #obj
and it would be done... but nothing like that seems to exist in VBScript. Is there any way to implement this? Is there anything in VBScript that takes an object as its input and returns a string representation of that object's name? Would it be possible to write a DLL in C/C# that would provide this kind of functionality?
You can use GetRef to obtain a function/sub pointer, and call the function/sub using that pointer. See online help, it shows an example for an event handler, but you can refer to any global function or sub with GetRef, and use the variable holding the GetRef return value just like an alias for the sub/function.
Be aware, however, that there are cases you won't be able to cover with this:
You cannot use a GetRef function pointer if the current calling stack contains a
method call that is a function registered to a test object via
RegisterUserFunc.
You cannot call such a test object method from within a routine call
that was adressed via a GetRef function pointer.
Also consider using ExecuteGlobal instead of Execute so the code you pass can set global variables that the ExecuteGlobal caller can access afterwards.

ASP Issue: Is it possible to pass session variables as parameters to functions in the Global.asa file?

I plan to write the Global.asa file in JavaScript. When a session or application ends, I need changes to be made in a database. Specifically, I need to break up a string and use it in a query in the Global.asa functions. That part doesn't puzzle me at all. Just the part about passing a session variable in as a parameter. I imagine my Global.asa to look something like this:
(Let's say the two variables "variable1" and "variable2" were session variables)
<script language="JScript" runat="Server">
function Application_OnStart() {
}
function Application_OnEnd(variable1) {
}
function Session_OnStart() {
}
function Session_OnEnd(variable2) {
}
</script>
So, I'm not sure if what I'm asking is even feasible. If so, any tips? Keep in mind that I am working in ASP, not ASP.NET. Also, I'm a bit new to using server-side code, so pardon my ignorance.
No, what you suggest is not feasible.
The functions in the global.asa file are callbacks for events. The functions get called, all with no parameters.
You can make use of the Session object to do what you want.
In your code you can set a session variable like this:
session("userid") = 856
In your global.asa you can then use:
variable1 = session("userid")
Have you considered using VBScript for your Global.asa? I've never coded a Global.asa in javascript, but you could code it in VB and use Session or Application level variables:
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
Sub Application_OnStart()
'initialize application level variables
Application("ConnectionString") = "Driver={Microsoft Access Driver (*.mdb)};DBQ=" & Server.mappath("access_db/mydb.mdb")
End Sub
Sub Application_OnEnd()
Application("ConnectionString") = ""
End Sub
Sub Session_OnStart()
'initialize session level variables
Session("UserIP") = Request.ServerVariables("REMOTE_ADDR")
End Sub
Sub Session_OnEnd()
Session("UserIP") = ""
End Sub
Not sure if you can pass a variable into the predefined functions as such, but you can use Session or Application variables anywhere on the website, including within these functions.

Using callback functions in vbscript

I'm trying to make an update script for windows7 in vbscript
when invoking IUpdateSearcher::BeginSearch how do I pass the callback to ISearchCompletedCallback::Invoke Method?
I'm just clueless on this points:
do I need an function or sub or does this a custom object with an invoke method(and how to create)
how I need to pass the callback
is it even possible in vbscript (if not what is a good next step?)
Thanks
I've never tried it, but I'd look at the ConnectObject Method.
This article about scripting events might also be useful.
So maybe something like this (complete guess):
Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateUpdateSearcher
WScript.ConnectObject objSearcher, "searcherCallBack_"
objSearcher.BeginSearch ...
sub searcherCallBack_Invoke()
' handle the callback
end sub
I'd also suggest reading Guidelines for Asynchronous WUA Operations to make sure that you clean up after yourself.
that link also mentions using Windows Script Host, so it should definitely be possible to do this, though unless you need it to be asynchronous, the synchronous methods wouls probably be a easier.

Resources