How to handle testing an HTML control that lacks sufficiently unique attributes? - html

I'm using Coded UI Test to test a web application.
I have a class Locator that I use to stash the specifics needed for CUIT to find a control. To operate on a control, a page object specifies the locator, not the control, and lower-level functions find the control and perform the operation.
Right now, my class has:
Locator name.
One or more attrName/attrValue pairs that can locate the HTML element for the control.
An operator (Contains or EqualTo) that specifies the matching needed.
The problem: Some of the controls I need to operate on don't have enough unique attributes to allow them to be found. (Yes, I know the developers should improve their HTML, but I don't control that.) I have been using a locator to find a nearby element, then "walking" in the DOM to get to the element I want. I hate having this DOM-walking code in my page object, even factored into a function.
A possible solution: I'm considering enhancing class Locator so that it can have either the attrName/attrValue pairs or a reference to a function that has the DOM-walking code. One advantage of this is that the page objects would always use a locator object. Another is that when the HTML is improved, the locator could change from DOM-walking code to attrName/attrValue pairs, which would be transparent to the page object.
Still, I think this may be over-complicated.
Is there a better solution to this problem?

Not sure specifically how your locator works, but could you find the closest parent to that object, let's say an HTML Div with an id of "parent", and then count the tag instances underneath? For example:
HtmlDiv id="parent">
HtmlHyperlink>text1</
HtmlHyperlink>text2</
Would require the following code:
public HtmlHyperlink text2Link
{
get
{
HtmlDiv parentDiv = new HtmlDiv(browser);
parentDiv.SearchProperties["id"] = "parent";
HtmlHyperlink target = new HtmlHyperlink(parentDiv);
target.SearchProperties["TagInstance"] = "2";
}
}
This would find the 2nd hyperlink under the parent object. (Tag instances are not zero based).
Then, you'd just interact with your object as needed:
Mouse.Click(text2Link);
for example.

Related

Pass element refrence to self from DOM back to view model

Known feature:
<div #element (click)="myMethod(element)"></div>
this passes the div back to the VM for manipulation, etc.
What I'm looking for is short hand to pass an element to a method without declaring a template variable. It could look like this:
<div (click)="myMethod($self)"></div>
This would be helpful in cases where creating elements in an ngFor stops you from giving every element a variable name or in cases where using a third party library that sends its own $event and the element ref is missing. Does anyone know of any way to do this?

Polymer two-way data binding and Facebook callback

I am very new to JavaScript and Polymer. I do like the PWA concept but now hit some roadblocks.
I tried to use polymerfire <firebase-auth> and was able to do google provider logins. But got blocked as I don't know how to do Facebook provider login and didn't find anywhere on how to use the tag as I wish to provide Facebook login too in JavaScript. If someone guides me to a source that works I will then not need part 2 of the question.
So, I tried facebook login via Graph API FB.login(). FB.login() has callback and I was not able to extract the response.name, public_profile and set it to Polymer attribute say {{user}} like
var userName = response.name; and then this.user = {displayName : userName};
I noticed that as soon as I exit FB.login() callback on successful login, I lose the changes done in assignment in callback to 'this.user ' object.
My question is - I am not able to make two way binding work in polymer. How can I change the object in child element and then it propagates to all the pages / polymer elements?
How can I change the object in child element and then it propagates to all the pages / polymer elements?
Well really that depends on how you set up all the pages. If you're in the parent, you can pass functions, variables, and objects to the child element by passing it in the component.
<ChildElement details={{_details}}/> // If you want to pass a details object to the child
<ChildElement sqft={{square(size)}}/> // This will call the square function inside your ChildElement and pass in the parameter size
Use the latter to call a function in your child and that function will have access to all the elements within that scope.
If you're in the child and you want to change something in the parent, you can do a callback with this.fire(someFunction()), and then create a function in your parent that with the same name. It's not too bad when you're just passing from parent to child or vice versa but if you're passing it everywhere, then you might want to look into some sort of state management. Passing things from one place to everywhere else will get ugly real fast.

finding width of an element using VB.net

Is there a way to access the css, specifically the width, of an element using VB.net? I am trying to use the width as a variable in VB but I'm having trouble finding it using the class attribute of the div I want
If I'm reading your question correctly: you'll need to have the 'runat="server"' attribute added to your HTML tag on your page. For example:
<div id="divTest" runat="server">Test Me</div>
In your code behind:
dim myDiv = Ctype(Me.Page.FindControl("divTest"), System.Web.UI.HtmlControls.HtmlGenericControl)
myDiv.Style.Add("color", "#ff0000")
You can add a style as shown, or just simply access it to find the current set value:
div.Style("width")
Of course, if you are using master pages you will have to drill down with FindControl() from your uppermost masterpage.
I am not sure how you are accessing a webElement. I am assuming that this is done by either internet control library or by IE browser control.
For Internet control library you can use. This interface is available in MSHTML library DLL.
You can determine the location, width, and height of an object by using a combination of the IHTMLElement::offsetLeft, IHTMLElement::offsetTop, IHTMLElement::offsetHeight, and IHTMLElement::offsetWidth properties. These numeric properties specify the physical coordinates and dimensions of the object relative to the object's offset parent.
Or just go to this place to find the information about measuring WebElements specifics
Here
I would request you to explain your problem in a bit more detail.

Retrieving all address information along Google Maps route

I am developing an Windows Forms application using VB.NET that offers the user to lookup addresses on Google Maps through a Web Browser. I can also successfully show the directions between two points to the user, as well as allow the user to drag the route as he/she pleases. My question now is - is it possible for me to get the lattitude/longitude information of the route, i.e. the overview_polyline array of encoded lattitude/longitude points and save it to e.g. a text file on my computer? Or is it possible to get a list of all the addresses located both sides of the route over the entire length of the route, and then save the data to a file on my computer? I'm using HTML files to access and display the Google Maps data in the Web Browser item.
Thank you
This is actually pretty simple if your just looking for the screen coordinates.
// this probably should be in your form initialization
this.MouseClick += new MouseEventHandler(MouseClickEvent);
void MouseClickEvent(object sender, MouseEventArgs e)
{
// do whatever you need with e.Location
}
if your strictly looking for the point in the browser, you need to consider the functions
browser.PointToClient();
browser.PointToScreen();
So, this method is usable if you know exactly where your form is (easy to get its coords) and where you webbrowser control is (easy to get coords of this as well since it's just a control in your form) and then, as long as you know how many pixels from the left or right, and from the top or bottom the image will be displayed, once you get the global mouse click coords (which is easy) you can predict where it was clicked on the image.
Alternatively, there are some scarier or uglier ways to do it here...
You can use the ObjectForScripting property to embed code to do this in the webbrowser. It's ugly to say the least. MSDN has some documentation on the process here: http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx
Because its really ugly, maybe a better solution is to use AxWebBrowser - it's ugly too but not so scary.
In addition, I found this post of someone wanting to do it on a pdf document, and a MSFT person saying its not possible, but really what he is trying to say is that it isn't built in, even with a pdf document its still possible to predict with high to certain accuracy where it was clicked if you use the first method i described. Here is the post anyway: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/2c41b74a-d140-4533-9009-9fcb382dcb60
However, it is possible, and there are a few ways to do it, so don't get scared from that last link I gave ya.
Also, this post may help if you want to do it in javascript:
http://www.devx.com/tips/Tip/29285
Basically, you can add an attribute on the image through methods available in the webbrowser control, you can add something like onclick="GetCoords();" so when it is clicked, the JavaScript function will get the coords, and then you can use javascript to place the values in a hidden input field (input type="hidden") which you can add through the webbrowser control, or if there is one already on the page, you can use that. So, once you place the coords using javacript into that input field, you can easily grab the value in that using the webbrowser control, eg:
webbrowser1.document.getElementById("myHiddenInputField").value
That will get the value in that field, which you've set through JavaScript. Also, the "GetCoords()" function i mentioned is called SetValues() in the javascript method link i provided above (in the devx.com site) but I named it GetCoords because it makes more sense and didn't want to confuse you with the actual name they used, you can change this to any name you want of course. Here is the javascript they were using, this only gets the coords into a variable, doesn't put it into a hidden input field, we will need to do that in addition (at the end of the javascript SetValues/GetCoords function).
function SetValues()
{
var s = 'X=' + window.event.clientX + ' Y=' + window.event.clientY ;
document.getElementById('divCoord').innerText = s;
}
These guys are just saving it inside a div element, which is visible to users, but you can make the div invisible if you want to use a div field, there is no advantage or disadvantage in doing that, you would just need to set the visible property to false using javascript or css, but still, it is easier to use a hidden input field so you don't need to mess with any of that.
Let me know how you get along.

Building HtmlElement object trees

I'm using the MSIE WebBrowser control in a C# desktop application and am looking for a way to build and maintain trees of HtmlElement objects outside of this control. I am trying to quickly switch between multiple complex pages without incurring the overhead of re-parsing the HTML each time (and I don't want to maintain multiple controls that are shown/hidden as needed).
I discovered that a) I can only create HtmlElement objects via the control's HtmlDocument and b) once I remove a "trunk" of HtmlElement objects from the control's HtmlDocument, it "dies off," even though I keep maintaining a strong reference to the root element.
How can I do this?
P.S. I am willing to consider alternative browser controls (e.g. Gecko) if they allow me to accomplish the above.
This will do it
// On screen webbrowser control
webBrowserControl.Navigate("about:blank");
webBrowserControl.Document.Write("<div id=\"div1\">This will change</div>");
var elementToReplace = webBrowserControl.Document.GetElementById("div1");
var nodeToReplace = elementToReplace.DomElement as mshtml.IHTMLDOMNode;
// In memory webbrowser control to load fragement into
// It needs this base object as it is a COM control
var webBrowserFragement = new WebBrowser();
webBrowserFragement.Navigate("about:blank");
webBrowserFragement.Document.Write("<div id=\"div1\">Hello World!</div>");
var elementReplacement = webBrowserFragement.Document.GetElementById("div1");
var nodeReplacement = elementReplacement.DomElement as mshtml.IHTMLDOMNode;
// The magic happens here!
nodeToReplace.replaceNode(nodeReplacement);
I doubt this will improve performce as the text renderer is fast, and the memory consumed will still be the same if you have one large page with hidden div's or have multiple div's in memory in other objects?
You can use the MSHTML library (mshtml.dll) to achieve this. Basically you would use a single about:blank page and then dynamically write and remove content from it.
See this blog post on this subject
You can also write a custom interface wrapper that exposes the functionality you need from mshtml rather than referencing the whole thing (Nearly 8MB) and it is really easy to do using f12 in VS.
Do you really need to remove them enturely? How about leaving your "branch" in the DOM as the child of a DIV whose style="display:none". That way they're real, live DOM objects but not visible.
I think you could also use the htmlagilitypack
It allows you to parse once, querying the HTML tree using XPath or via iterators and re-writing the tree with a save method when done.
Depending on your structure, you might just create an adapter around the classes, because it only works on an entire html document and you want it on elements only, but this should be not too hard.