I'm using Selenium client driver 2.4.0. When running tests using the WebDriverBackedSelenium object, e.g.
final FirefoxDriver driver = new FirefoxDriver();
selenium = new WebDriverBackedSelenium(driver, baseUrl);
how do I inject a Javascript array into my tests that can retain scope across different pages? That is, I want to create a JS var "myArray" that I can access (using selenium.getEval) when I open "http://mydomain.com/page1.html" but I can then reference when I open a different page ("http://mydomain.com/page2.html") within the same Selenium test.
Thanks, - Dave
I don't think it is possible out of box.
Workaround should work - add to the page some library that can deserialize from JSON (e.g. Dojo), use it to load an array definition to some JavaScript variable and before leaving page get it back, storing it out of scope request.
But I must say you have a kind of strange request - what are trying to do ?
You can do it with casting. Execute JavaScript to return an array. The JS array must contain only one type, which must be primitive.
For example, execute a script which returns an array of Strings:
ArrayList<String> strings = (ArrayList<String>) js.executeScript(returnArrayOfStrings);
If you need an array of any other type, you can build it from those strings. For example, if you need an array of WebElements, design your JS to return locators, and then iterate through, finding elements and building a new array:
ArrayList<String> xpaths = (ArrayList<String>) js.executeScript(getLocators);
ArrayList<WebElement> elements = new ArrayList<WebElement>();
for (String xpath: xpaths){
element = driver.findElement(By.xpath(xpath));
elements.add(element);
}
You have the Array in Java, so you can keep it in memory when your tests go to different pages and still reference the Java Array,
The only catch is, if your JS array is changing on the client side, your Java Array won't automatically update itself (the jsexecuter only returns once per execution), but that's not a big deal - instead of referencing the Java Array directly, you can access it via a getter which first executes the JS again to get a new Array, which you can use to replace the previous one, or merge them etc, before returning the new/updated array to your test code.
Related
I need to loop a string (split by ',') and get each element passed to the feature files automatically. I know there is excellent support for json array data-driven test, but does it support data-driven with normal strings or string array
As I know, I need to get it converted to a json array to support data-driven test at runtime, however, I want to know any existing support for normal array looping directly and automatically.
Here is my string(separated by ',') that needs to get passed as request parameter:
"PHE,TSH,17_a_OHP,G6PD,MSMS,THALASSEMIA,DGT"
Because my string is dynamically produced at runtime, I want to loop it automatically and pass to other feature files, not manually,
Note that converting arrays into other "shapes" is easy in Karate. And in 0.9.3 we introduced the karate.mapWithKey() API, so you can do this:
* def string = 'PHE,TSH,17_a_OHP,G6PD,MSMS,THALASSEMIA,DGT'
* def array = string.split(',')
* def list = karate.mapWithKey(array, 'name')
* print list
So you can see, list is ready to use for data-driven features. Also note that you can use this in dynamic scenario outlines !
I need to loop a string (split by ',') and get each element passed to the feature files automatically. I know there is excellent support for json array data-driven test, but does it support data-driven with normal strings or string array
As I know, I need to get it converted to a json array to support data-driven test at runtime, however, I want to know any existing support for normal array looping directly and automatically.
Here is my string(separated by ',') that needs to get passed as request parameter:
"PHE,TSH,17_a_OHP,G6PD,MSMS,THALASSEMIA,DGT"
Because my string is dynamically produced at runtime, I want to loop it automatically and pass to other feature files, not manually,
Note that converting arrays into other "shapes" is easy in Karate. And in 0.9.3 we introduced the karate.mapWithKey() API, so you can do this:
* def string = 'PHE,TSH,17_a_OHP,G6PD,MSMS,THALASSEMIA,DGT'
* def array = string.split(',')
* def list = karate.mapWithKey(array, 'name')
* print list
So you can see, list is ready to use for data-driven features. Also note that you can use this in dynamic scenario outlines !
Is there any way so that we can parameterize the string which we pass to create a page object using a page factory?
ex:
String v = "password";
#FindBy(name=v)
private WebElementFacade password_Field;
I am trying to push the string v into the #FindBy but I am getting an error.
I am getting
The value for annotation attribute FindBy.name must be a constant expression.
Yes. It is possible. Please find the solution below:
In your Page, instead of using #FindBy, get the WebElementFacade using find method of the Page and then use it for operations.
For example: If you need to click on an element, please see the code below:
public void click(String elementId) {
WebElementFacade element = find(ById.id(elementId));
element.click();
}
This works perfectly for me. And the element id is coming all the way from .story examples.
No, Unfortunately, it's not possible to send arguments to annotation (reference). Since Java annotations does not allow dynamic parameterization. The compiler evaluates annotation metadata at compile time. So, it must be present. Though there are work around for this.
Check this- Java Annotations values provided in dynamic manner
Given:
<span>{{person.name}}</span>
<span ng-bind="person.email"></span>
Question:
Is there anyway I can use a Protractor locator like this:
var eles = element.all(by.binding('person.*'));
Or better yet...
var eles = element.all(by.binding('*'));
I'm wanting to find all elements that are "bound" without knowing the binding string before hand...
A regular CSS selector would do the job. E.g. getting all elements that have a person in binding:
$$("[ng-bind*=person]"); // *= means "contains".
Or, all elements having a binding (having the ng-bind attribute):
$$("[ng-bind]");
Or, $$(".ng-binding") - FYI, this is how Protractor internally locates the elements with a binding.
where $$ is a shortcut for element.all(by.css()).
Note that this would not work if data-ng-bind is used, for example. You may tweak the expression to handle that.
I'm working on a vb.net application that interacts with a (third party provided) web app to provide additional functionality (e.g. removing menu items, pulling information from the pages, etc.). The web app is completely driven by javascript but is hosted in asp.net and is only used with Internet Explorer.
I'm trying to read properties from a javascript object and execute some of it's functions. I've managed to get hold of the javascript object by getting the mshtml.HTMLDocument of the iframe the script resides in and using the following code:
Dim jsObject as Object
jsObject = htmldoc.Script.jsObject
jsObject exists as a {System.__ComObject} and i can use it to execute any of it's functions or read it's properties as follows:
Dim value as String = jsObject.FunctionThatReturnsAString()
jsObject.FunctionTHatDoesSomethingInWebApp("Param1", "Param2")
This works great. However, when I leave the page/frame with jsObject in and return to it, the same code throws an exception when getting the javascript object from the frame again (i.e. executing the following line):
jsObject = htmldoc.Script.jsObject
Exception: Member not found. (Exception from HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))
If I stop debugging and restart, it works again (until i leave the page, etc.). I'm not sure what's happening that's causing the javascript object to disappear as far as my app's concerned. I'm presuming it's due to my app holding a reference to the COM object and i need to release it in some way (particulary as it's got a base type of MarshalByRefObject - which makes sense as it's being passed between app domains).
Why is this happening? Is there a better way of accessing a javascript object, it's properties and functions?
I've found what is, in my case, a better way of achieving what I need. Instead of accessing the jsObject directly as a COM Object (and worrying about Marshaling, etc.), I either use:
execScript to call functions with no return value or
create a hidden div element in the frame i'm working in, set the innerHTML of that div equal to whatever javascript variable/function return value that i'm interested in using execScript and then read that value seperately from the DOM
To read a variable/function return i use the following vb.net function:
Private Function getJScriptVariable(ByVal JScript As String)
Dim command As New StringBuilder()
command.Append("var e = document.getElementById('Matt_JScriptReturn');")
command.Append("if (e == null) {")
command.Append("var e = document.createElement('div');")
command.Append("e.id = 'Matt_JScriptReturn';")
command.Append("e.type = 'hidden';")
command.Append("document.body.appendChild(e);")
command.Append("}")
command.Append("e.innerHTML = ")
command.Append(JScript)
command.Append(";")
'fMaster is the frame containing the javascript's mshtml.IHTMLWindow2
fMaster.execScript(command.ToString(), "JScript")
'N.B. fMaster_Document is the fMaster's mshtml.HTMLDocument
Return fMaster_Document.getElementById("Matt_JScriptReturn").innerHTML
'Optionally execScript to remove element from DOM at this point
End Function
Then i would use that function as follows (respecting my example in the original question):
Dim value as String = getJScriptVariable("jsObject.FunctionThatReturnsAString()")
To execute javascript code without needing to return a value I simply execute it as follows:
fMaster.execScript("jsObject.FunctionTHatDoesSomethingInWebApp('Param1', 'Param2')")
I'd still be interesting in finding out why i had the problem earlier with the javascipt object being unable to access after leaving the page and returning, however this solves my problem so i'm happy for now! I hope this helps someone else at some point.