Checking if an element is really visible to the user - selenium

I'd like to check whether the user can see an element in the current web browser view without scrolling.
What I've found can check whether the element is somewhere on the page.
Another hint suggested to check the elements position but then I would need to get the dimensions of the visible window of the browser plus its x/y offset to 0/0.
I would be grateful if someone could point me to a solution that does not need JavaScript code.

How do you define 'visible to the user'? How do you propose to check it?
If it has a height? If it isn't hidden by CSS? What if it's parent element is hidden by CSS?
The most reliable way will be to use Selenium's built in .Displayed property (if you are using C#, Java has something similiar), and combine it with jQuery's 'visible' selector: http://api.jquery.com/visible-selector/. Example below, in C#.
var element = Driver.FindElement(By.Id("test"));
bool isVisible = element.Displayed;
var javascriptCapableDriver = (IJavascriptExecutor)Driver;
bool jQueryBelivesElementIsVisible = javascriptCapableDriver.ExecuteScript("return $('#myElement').is(:visible);");
bool elementIsVisible = isVisible && jQueryBelievesElementIsVisible;
This will get the majority of cases.
It isn't possible without client side code, or in the preparation that someone else finds a way that it can be done in a server side language, I highly doubt it will be pretty, readable or reliable.
jQuery has the offset() method:
http://api.jquery.com/offset/
This, however, won't work when taking into account borders, margins, that kind of stuff.

Related

Webkit: Finding absolute position of clicked DOMElement with Objective-C

I'd like to find out the position of a clicked DOMElement in a WebView. In my delegate -[webView:decidePolicyForNavigationAction:request:frame:
decisionListener:] gets called. I can extract the clicked DOM element from the dictionary passed as actionInformation parameter. But I cannot figure out how to retrieve its position.
I tried get the click location through webview.window.currentEvent, but that returned some an WebKit event with a bogus location.
Any ideas how to solve this without dropping down into JavaScript?
The easiest way that should work without actual JavaScript is to use the Objective-C properties of DOMElement, which mirror the underlying JS properties. Unfortunately, there does not seem to be good documentation, but you can read the headers, e. g. WebKit/Headers/DOMElement.h etc.
Here, your best bet would be offsetLeft/Top/Width/Height. You need to add these to the scrollLeft/Top values of the document element. Also, for some elements, especially text or spans across multiple lines, calling the JS function getBoundingClientRect() would return better results. But you can do that from Objective-C as well, using the WebScriptObject API. If you need assistance with that, I can help.

optimize drag and drop with svg library & javascript

Currently most of the SVG framework provides drag and dropping. I have used RaphaelJs , Extjs Drawing , and SVG.js(http://www.svgjs.com/). All of the framework provides the event handling method by binding it with the element itself. For example:
dragStart: function(event){
//'this' refers to the element itself
this.doSomething();
this.moveTo(event.x,event.y);
};
However the consequences of this is that browser performance is greatly degraded, when there are more than hundred of elements and some logic processing aside. My elements will be composite elements, meaning maybe some text or path in a rect but the rect should be the target (or this) of the event when dragged. The elements will have other event to listen to , for example onclick, onDblClick, onHover & etc.
My question is, is there any way to optimize this ? The user experience is bad after the application is showing a lot of the composite elements I mentioned above.
UPDATE:
I have built an application using the mean that i spoke of above. Binding the event handler to each of the objects. The result is not very user friendly when the element is listening to onhover and onmousedown events. I am thinking to optimize the application but not sure how. The effect is more obvious in FF, chrome is better.
Are you sure you need SVG? Fabric.js is an awesome API for scaling, rotating, drag-drop, and grouping, based on the Canvas element.

Dojo 1.4.2 Tree Grid "expando click" event? persist state?

Question:
Given a DOJO TreeGrid, how can I capture the event when a user clicks the expando ("+") button to expand a row, and store the specific row number or associated item's identifier? I'd like to do this for the express purpose of completely deleting the TreeGrid from the DOM, rebuilding it, and restoring it's state once rebuilt (i.e. programmatically expanding the rows that the user has previously expanded).
Background:
So I've got a custom DOJO TreeGrid, hooked up to a custom QueryReadStore, in my app. It was constructed using the following tutorial:
http://www.ibm.com/developerworks/web/library/wa-dojotreegrid/index.html?ca=drs-
Pretty interesting tutorial, but it might be irrelevant to my question because it doesn't really squash any functionality, it only seems to augment it.
Anyway, googling around for a moment, I found a nice function in the DOJO forums that I can use to programmatically expand a row, given the specific row index. Works perfectly.
The problem is that I haven't been able to find a good way to capture the expando click event, and relate it to a specific "parent item row" index in the grid.
Details aside, I'd like to get the row index of every row that the user has expanded, into an array (and delete the index of a row that the user collapses, obviously), so I can destroy this TreeGrid, and faithfully rebuild it, with the user's selections expanded properly.
I'm not really a novice to DOJO, but I'm certainly no expert by any means. I've done a fair bit of googling, and FireBugging, and haven't really been able to find anything that I can use to do this.
Suggestions? Anybody done something similar before? Stupid question with obvious answer that I've missed? I'm totally misguided and am going about it all wrong? Thanks everybody!
Something similar to this would probably work, this is how the dijit.Tree implementation wouldve looked;
var expandedNodes = {}
dijit.tree._onExpandoClick = function (args /* object wrap for args.node */) {
var treeNode = args.node,
path = treeNode.getTreePath(),
id = treeNode.getIdentity();
expandedNodes[id] = path;
}
I am not 100% sure im being strictly correct but for the TreeGrid you will have to look through code of dojox/grid/_TreeView.js (link). The _setOpen would be an entrypoint from which you can 'hook' the onclick action. from there, find the expandoCell.openStates hash, this is a true/false variable set, indexed by itemId. This hash is most likely what you need as your state

How would you verify that a certain css element on a page is a certain image with selenium

I have a page that I want to check with selenium that uses a certain background image for one element. I want to ensure that this image still exists on the page connected to the element. How would I do this with selenium. If this changes anything I am using browsermob.com to do the testing once I get it running through selenium ide.
Well aside from the suggested things on the almos duplicate issue... You could check if the property of your body element is set to the image.
By if getAttribute returns a valid value or not. Like:
new Wait()
{
public boolean until()
{
return selenium.getAttribute("ElementLocator")
+ "#class").equals("active");
}
}.wait("The menu item did not get active.",
defaultTimeOutValue);
This will wait for the attribute #class to have the value "active".
Or simply use an If statement after you are sure that the page got loaded.
Hope this helps,
Cheers,
Gergely.

Dojox.grid.DataGrid - in a widget - only renders on visible tab

I am using a Widget that contains a DataGrid object. The Widget works fine when included in the first tab (this is the visible tab), but not when I use the same code on a second tab.
The code is the same I have done several checks to make sure there are no other problems - and non Grid code is rendering fine - only the grid that has a problem. I have tried setting the height and width manually and this just results in a large grey rectangle on the second tab.
Do I need to tell the Grid to refresh in some way - or is it a property for the TabContainer?
Help - this is driving me mad!
Yeah, that's a big problem with the grid. If you use it declaritively in a tab container, it won't render properly on the non-visible tabs. It needs to calculate height/width (even though you specify them)...as you have seen.
The way I got around it was to create the grids programatically on tab select. I posted about my solution on the dojo forums. My code sample is over on github. It's a bit too large to post here methinks. Let me know if you want it, and i'll edit my answer.
There's also a discussion on nabble with a different solution.
"resize" works like a charm! Been looking for this for a long time (didn't know what I had to search for), thanks.
I use this routine to dynamically determine if the tab has more than one datagrid, as I may not know the ID of one single grid, maybe someone else might use that, too:
dojo.query('div#container div[id^="gridNode_"]').forEach(function(node, index, arr) {
dijit.byId(node.id).resize();
});
This will check the div with id="container" (skip that part if you want to search the whole DOM) for divs with an id starting with "gridNode_" and apply "resize" to those widgets.
An alternate approach is to resize the grid upon tab element selection. Sample code
dojo.connect(dijit.byId('my_tab_container'), "selectChild", function(child){
// if second tab (could be any...) selected
if(child.id == 'mySecondTabId'){
var myGrid = dijit.byId('myGridInsideTabId');
if(myGrid != null) myGrid.resize();
}
});