Recently, i integrate node and phantomjs by phantomjs-node. I opened page that has iframe element, i can get the hyperlink element of iframe, but failed when i execute click on it.
Do you have a way? Anyone can help me?
example:
page.open(url);
...
page.evaluate(function(res){
var childDoc = $(window.frames["iframe"].document),
submit = childDoc.find("[id='btnSave']"),
cf = submit.text();//succeed return text
submit.click()//failed
return cf;
},function(res){
console.log("result="+res);//result=submit
spage.render("test.png");//no submit the form
ph.exit();
});
You can't execute stuff in an iframe. You can only read from it. You even created a new document from the iframe, which will only contain the textual representation of the iframe, but it is in no way linked to the original iframe.
You would need to use page.switchToFrame to switch to the frame to execute stuff on the frame without copying it first.
It looks like switchToFrame is not implemented in phantomjs-node. You could try node-phantom.
If the iframe is on the same domain you can try the following from here:
submit = $("iframe").contents().find("[id='btnSave']")
cf = submit.text();
submit.click()
If the iframe is not from the same domain, you will need to create the page with web security turned off:
phantom.create('--web-security=false', function(page){...});
Related
My use case is: a user goes onto a webpage and modifies it by either filling in a form, populating the page with data from the database, or dragging around some draggables on the page. He can then download the page he modified as pdf. I was thinking of using PhantomJS to do the conversion from html to pdf.
I understand the basic functionality of PhantomJS and got the basic example working but in all the examples I've seen, either a local file or a url is passed in. Example:
page.open('./test.html', function () { ... }
How would I render the page that is getting modified by a user using PhantomJS? I have 2 ideas:
Have the url change as the user modifies the page, and simply pass in the url. For example, the url contains the position of a draggable div.
Send the modified html to back-end, save it, and run PhantomJS
Do these solutions make sense? I'm hoping there would be a simpler way.
Is there a way to force a new window for this menu action? I can't see anything. i was thinking of adding a class, and some JS code to redirect if the class is there.
If your only intent is to open a window in a new tab, then why don't you set the target="_blank" in your transformation or where ever you are generating the HTML markup?
I am not saying that it's incorrect, however it's just that you can avoid js for this and rather do it in HTML.
Here's what i've done.
In the Navigation panel, i added the class 'nw'. I have this snippet add the target attribute.
// we need to use .nw as a class to indicate that a link should open in a new window.
$('.nw a, a.nw').each(function(i,v){
var $this = $(this);
$this.attr('target','_blank');
});
You can use the JS option and put in JS like: window.open("http://www.google.com");
The AUT has links along the top navigation bar. During normal use, each link opens a related application in a different browser.
Is it possible to do a simple page title assertion on the new application, then return to the AUT and click the next link? And so on for each link?
For testing, I don't think it matters whether the link target opens in a new browser, or a new tab, or the same tab. As long as I can jump back and forward between the AUT and the "other" application.
Without sample HTML, this is a bit of a shot in the dark. But--assuming there's a distinct attribute to hook onto--you can collect the links from the navigation div and iterate over each link. This is a simple, contrived example (where the links do not spawn new browsers/tabs):
b = Watir::Browser.new
b.goto("http://www.iana.org/domains")
nav_link_hrefs = b.div(:class, "navigation").links.collect { |link| link.href}
nav_link_hrefs.each do |href|
next if href == "http://www.iana.org/domains" # skip self-referential link
b.link(:href => href).click
b.back
end
In terms of doing a "simple page title assertion", I'm not sure how you'd know the page title in advance. But I'd suggest looking into MiniTest or rspec for an assertion library.
Lastly--if window-switching is required for your use case--check out the watir-webdriver window-switching documentation.
I found the answer. Here's the partial code:
#browser.goto URL
current_url = #browser.url
new_window_url = #browser.link(:text, "Other site").href
#browser.goto(new_window_url)
# test the other site
assert(#browser.text.include?("This is the other site"))
#browser.goto(current_url) # back to the first site
# repeat for all the other navigation links
I've start with phantom.js (btw I'm in love). I'm trying to make the headless browser go to my php admin panel, log in with a username and password, and from the page that it redirects to after log in i want to get some text from a div tag.
So far I manage to successfully fill the fields, create a click event, and even find the access to the DOM part of the div tag and get the inner.Text.
The only missing part for me is what to do when phantom.js clicks on a button (the log in button in this case) which will log me in and change the page content. I can't find how to handle after .click(); event.
This is the code I made so far (by the way its a good way to start with...)
var page = new WebPage();
page.open("the url comes here",
function(status){
if(status != "success"){console.log('fail loading the page');}
page.evaluate(function(){
var arr = document.getElementsByName("formname");
arr[0].elements["username"].value="username here";
arr[0].elements["password"].value="password here";
arr[0].elements["submit"].click();
return;
}
phantom.exit()
});
The code i want run on the page that comes after it is
console.log(window.frames[1].document.getElementById('status').innerHTML)
So the only question remaining is how to handle the redirect and launch the script on the other page.
Thanks,
You need to setup a new callback for the page load:
page.onLoadFinished = function(status){
console.log(window.frames[1].document.getElementById('status').innerHTML)
}
this should come right before triggering .click().
I have a problem with the following HTML:
<a href="javascript:document.formName.submit();" target="iframe">
Where formName is the name of a form inside the iframe. I would like the browser to navigate to the page "javascript:..." in the iframe, so it executes the javascript on the current page in the iframe. My problem is that the browser will attempt to execute the function and use the returned result as the url. Of course there is no form to submit on the current page, so I just get an error.
Cross domain iframes are no fly zones, you won't be able to do anything with or to the DOM inside of a frame on a different domain. Even if the user clicked the submit button inside the frame, your page would not be able to get the new url back out of the frame.
In this case, you can do it by reaching inside the iframe:
<a href="javascript:window.frames[N].contentDocument.FORMNAME.submit()">
(that may not be exactly the right incantation). In general, you should do this with an onclick handler for the hyperlink, that invokes a function defined by the iframe's document.
EDIT: There is NO WAY to make this work cross-domain. It's a violation of the browser's security policies.