Selenium and iframe - iframe

I have an iframe that gets loaded when i click on a tab on a page. When i use Firebug to look at the iframe on IE8, all i see is:
iframe id=tabContextFrame class=contextFrame contentEditable=inherit src=/xyz.dt?forward=show&layouttype=NoHeader&runid=1234 name=tabContextFrame url=/xyz.dt?forward=show&layouttype=NoHeader&runid=1234 scrolling=auto
and that's it.The hierarchy below the iframe can't be seen. I want to click on a link within the iframe. To find the elements within the iframe, I did a selenium.click("on the tab that loads the iframe") and then selenium.getHtmlSource(). From this source, I can at least locate my link of interest. I did a selenium.click("//span[text()='Link']") but it doesn't seem to do anything. Any ideas please?
Here is the code:
selenium.click("//span[text()='tab that loads iframe']");
Thread.sleep(5000);
selenium.selectFrame("tabContextFrame");
selenium.mouseOver("//span[text()='Link']");
selenium.mouseDown("//span[text()='Link']");
selenium.mouseUp("//span[text()='Link']");
Thread.sleep(5000);
selenium.selectFrame("null");

I'm guessing you are using Selenium 1.0. Have you looked at Selenium 2.0 and WebDriver. I found the following and it worked for me:
Q: How do I type into a contentEditable iframe? A: Assuming that the
iframe is named "foo":
driver.switchTo().frame("foo");
WebElement editable = driver.switchTo().activeElement();
editable.sendKeys("Your text here");
Sometimes this doesn't work, and this is because the iframe
doesn't have any content. On Firefox you can execute the following
before "sendKeys":
((JavascriptExecutor) driver).executeScript("document.body.innerHTML = '<br>'");
This is needed because the iframe has no content by default:
there's nothing to send keyboard input to. This method call inserts an
empty tag, which sets everything up nicely.
Remember to switch out of the frame once you're done (as all further
interactions will be with this specific frame):
driver.switchTo().defaultContent();
I found this on http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions

Use driver.switchTo().defaultContent(); first then do your operation

Related

Print Friendly Page

So I would like to be able to have a print button for entries in our database so users can print an entry via a print friendly "form".
My thought was to create a separate page, add labels and have those labels pull the relevant information.
I know I can add the open widget information via this code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.TestPrint);
But I'm running into a few problems:
I can't get the page to open in a new window. Is this possible?
window.open(app.pages.TestPrint);
Just gives me a blank page. Does the browser lose the widget source once the new window opens?
I can't get the print option (either onClick or onDataLoad) to print JUST the image (or widget). I run
window.print();
And it includes headers + scroll bars. Do I need to be running a client side script instead?
Any help would be appreciated. Thank you!
To get exactly what you'd want you'd have to do a lot of work.
Here is my suggested, simpler answer:
Don't open up a new tab. If you use showPage like you mention, and provide a "back" button on the page to go back to where you were, you'll get pretty much everything you need. If you don't want the back to show up when you print, then you can setVisibility(false) on the button before you print, then print, then setVisibility(true).
I'll give a quick summary of how you could do this with a new tab, but it's pretty involved so I can't go into details without trying it myself. The basic idea, is you want to open the page with a full URL, just like a user was navigating to it.
You can use #TestPrint to indicate which page you want to load. You also need the URL of your application, which as far as I can remember is only available in a server-side script using the Apps Script method: ScriptApp.getService().getUrl(). On top of this, you'll probably need to pass in the key so that your page knows what data to load.
So given this, you need to assemble a url by calling a server script, then appending the key property to it. In the end you want a url something like:
https://www.script.google.com/yourappaddress#TestPage?key=keyOfYourModel.
Then on TestPage you need to read the key, and load data for that key. (You can read the key using google.script.url).
Alternatively, I think there are some tricks you can play by opening a blank window and then writing directly to its DOM, but I've never tried that, and since Apps Script runs inside an iframe I'm not sure if it's possible. If I get a chance I'll play with it and update this answer, but for your own reference you could look here: create html page and print to new tab in javascript
I'm imagining something like that, except that your page an write it's html content. Something like:
var winPrint = window.open('', '_blank', 'left=0,top=0,width=800,height=600,toolbar=0,scrollbars=0,status=0');
winPrint.document.write(app.pages.TestPage.getElement().innerHTML);
winPrint.document.close();
winPrint.focus();
winPrint.print();
winPrint.close();
Hope one of those three options helps :)
So here is what I ended up doing. It isn't elegant, but it works.
I added a Print Button to a Page Fragment that pops up when a user edits a database entry.
Database Edit Button code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showDialog(app.pageFragments.FragmentName);
That Print Button goes to a different (full) Page and closes the Fragment.
Print Button Code:
app.datasources.ModelName.selectKey(widget.datasource.item._key);
app.showPage(app.pages.ModelName_Print);
app.closeDialog();
I made sure to make the new Print Page was small enough so that Chrome fits it properly into a 8.5 x 11" page (728x975).
I then created a Panel that fills the page and populated the page with Labels
#datasource.item.FieldName
I then put the following into the onDataLoad for the Panel
window.print();
So now when the user presses the Print Button in the Fragment they are taken to this new page and after the data loads they automatically get a print dialog.
The only downside is that after printing the user has to use a back button I added to return to the database page.
1.
As far as I know, you cannot combine window.open with app.pages.*, because
window.open would require url parameter at least, while app.pages.* is essentially an internal routing mechanism provided by App Maker, and it returns page object back, suitable for for switching between pages, or opening dialogs.
2.
You would probably need to style your page first, so like it includes things you would like to have printed out. To do so please use #media print
ex: We have a button on the page and would like to hide it from print page
#media print {
.app-NewPage-Button1 {
display : none;
}
}
Hope it helps.
1. Here is how it is done, in a pop up window, without messing up the current page (client script):
function print(widget, title){
var content=widget.getElement().innerHTML;
var win = window.open('', 'printWindow', 'height=600,width=800');
win.document.write('<head><title>'+title+'/title></head>');
win.document.write('<body>'+content+'</body>');
win.document.close();
win.focus();
win.print();
win.close();
}
and the onclick handler for the button is:
print(widget.root.descendants.PageFragment1, 'test');
In this example, PageFragment1 is a page fragment on the current page, hidden by adding a style with namehidden with definition .hidden{display:none;} (this is different than visible which in App Maker seems to remove the item from the DOM). Works perfectly...
2. You cannot open pages from the app in another tab. In principle something like this would do it:
var w=window.parent.parent;
w.open(w.location.protocol+'//'+w.location.host+w.location.pathname+'#PrintPage', '_blank');
But since the app is running in frame nested two deep from the launching page, and with a different origin, you will not be able to access the url that you need (the above code results in a cross origin frame access error). So you would have to hard code the URL, which changes at deployment, so it gets ugly very fast. Not that you want to anyway, the load time of an app should discourage you from wanting to do that anyway.

iframe doesn't obey color styling

As you can see here, I have set up an addon to replace some contents of the network-inspect-popup with pretty-printed values. The odd thing is, I'm setting background of both the iframe and the inner document (background;#FFF), but it still shows the bluish background of the net-inspector. What's wrong with this, and why does DOM Inspector addon not even let me inspect to see what's wrong here?
Your own code overrides your own style. You have:
netPanel.iframe.addEventListener('load',function(event) {
var doc = event.originalTarget;
doc.body.style.backgroundColor='rgb(85,87,128)';
// ...
}, true);
This event listener will be called for all load events bubbling in the netPanel.iframe DOM, and that includes the load event the iframe document you insert creates. Change your code to first check the load is actually coming from a document you want to "overlay".
PS: You can actually use the DOM Inspector. But note that the "window" is not actually a window, but a <panel> in under the browser.xul top-level DOM.

Not able to click a button which sites inside form which sits under Iframe which sits under table

I want to click a button*-Create Order* which sits under Iframe. In order to do that I need to switch my driver to iframe , for which I need to find iframe first. Now I have tried everything to locate this iframe.When I started digging in I relaized that if I do this
WebElement table= dr.findElement(By.xpath(or.getProperty("html/body/div[4]/form/table/tbody/tr[2]")));
I get some value for the table.size()
But if I do this :
WebElement table= dr.findElement(By.xpath(or.getProperty("html/body/div[4]/form/table/tbody/tr[3]")));
I get 0 count.
I have spent so many hours to get to this frame.When I failed with cssSelector or xpath I started going by each node and that's how I found this.
Please help.
Assuming you are using Java, you can address an iframe with SwitchTo().Frame() in three ways
By iframe name or id. If the iframe has name="frameName" or id="frameID", you can use dr.SwitchTo().Frame("frameName") or dr.SwitchTo().Frame("frameID").
By iframe element. You can address an iframe by something along these lines:
dr.SwitchTo().Frame(dr.findElement(By.Css("table>tbody>tr:nth-child(3)>iframe")));
By count, starting from 0. You can address an iframe by:
dr.SwitchTo().Frame(0), which would switch to the first iframe.
For #2, we can give you better help on a CSS selector if you include some html including the iframe in question, and a few lines above it in your question.

set div's innerHTML with an iframe, shows up in firebug but not on page

I'm using the extjs library. I've got a blank panel and I want to load another one of my ext projects into it with an iframe. Here is my function (called from a button), "thepanel" is my blank panel.
function(button){
var div = document.getElementById('thepanel');
div.innerHTML = "<iframe src=\"../../../project2/?&type=grades&gradeitem1=40691&\"></iframe>";
}
I can see the GET request in firebug's console when I run the function and all my second project code/data all shows up in an iframe when I look a the HTML in firebug but nothing new shows up in the browser. Any ideas of what could be keeping my iframe's contents from showing
I am using MVC architecture, here is the code that declares my panel:
items:[{
xtype:'panel',
itemId:'two',
id:'thepanel',
region:'center',
}]
UPDATE: I've tried moving the iframe to the html config option of the panel instead of adding it through jquery with a button click. Again, I can see the code from the url in the iframe show up in firebug but nothing shows up in my application. Here is the code declaring my panel:
xtype:'panel',
itemId:'two',
id:'thepanel',
region:'center',
html:'<iframe src=\"../../../extjproh2/?&type=grades&gradeitem1=40691\"></iframe>',
height:400,
width:400,
Ended up using this plugin from the sencha forums:
http://www.sencha.com/forum/showthread.php?110311-iframePanel&p=943573#post943573

anchor target blank - how to always open in same popup window

I have a number of anchors in a page. I want that when the user clicks on an anchor it would open a blank window. I have used target='_blank' and that works correctly. However, I want that if the user clicks on another link in the original page, I would like that it uses the same popup that was opened for the first window. What I do not want is that the user ends up with like 10 popups as this would be a bit messy for the user.
Is this achievable please?
Any assistance would be greately appreciated.
target is deprecated since HTML 4.01, you can however use JS like this:
test
<script>
var clicky = document.getElementById("clicky");
clicky.onclick = function(){
window.open(clicky.href, "test");
return false;
}​
</script>
in the window.open, the first attribute is the URL the link should go to, the second is the name of the window, clicking any link setup like this will open in the same window.
there's better and easier ways to do this to multiple elements with jquery etc. but it all hinges on the window.open.
Instead of using _blank (which is a special value for a new window), use a name - any name would do.
target="mySpecialPopup"
When naming a window this way, every time you call it by name it uses the same instance.
Just name your target.
target='mywindow'
This should open a blank window the first click and repopulate it when other target='mywindow' links are clicked.

Resources