I currently use Selenium 2 with a local Selenium web server and the PHP-Webdriver written by Facebook.
Now I want to write an automated test for the Facebook Like Button. Because this Button is loaded through an iframe, I first select this frame via $driver->frame(array('id' => 1)) (I Found out, that Facebook loads normally two frames and the second frame is the Like Button). After clicking the Like Button a new Frame is loaded, where the user also can send a comment to his wall. Unfortunately the focus is still on the Like Button Frame so that I have to switch to the second frame. How can I do this?
Because I do not use Selenium RC there is no Selenium.SelectFrame("relative=top") method. I also cannot use the method driver.switchTo().defaultContent() because I do not use the Java webdriver. It seems that I just can use methods specified in the JsonWireProtocol. How can I switch between frames or change the focus back to the top frame?
Python webdriver client has these methods for switching between iframes, windows and pop ups:
switch_to_active_element
switch_to_alert
switch_to_default_content
switch_to_frame
switch_to_window
switch_to_default_content is the one you need. Find its analog for php client.
UPDATE:
Since you mentioned JasonWireProtocol:
http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/frame
POST /session/:sessionId/frame
Change focus to another frame on the page.
If the frame ID is null, the server should switch to the page's default content.
I had this same problem. The issue I discovered, that the "frame" in the PHP webdrivers only switches to frames below the current one. So if you want to switch to a different frame that is above the current frame, you are out of luck. I had to select the main window, which essentially reset me to the top frame. From there I was able to select the correct frame.
//putting a sleep so the page can load
sleep(SLEEPTIME + 5);
//getting a list of windows on the page
$windows = $webdriver->getWindows(); // function below
//switching to the
$webdriver->selectWindow($windows[0]);
$webdriver->focusFrame('cpAppFrame');
public function getWindows() {
$request = $this->requestURL . "/window_handles";
$response = $this->execute_rest_request_GET($request);
return $this->extractValueFromJsonResponse($response);
}
Related
1) Is there a way to send a Tab key through to the browser to test the tab index of a page?
2) Is there a way to send a W key through to the browser while also simulating the holding down of the cmd key to close a tab in chrome?
We have tried using the keyPress() function, and have also used the following function with jQuery:
/**
* #Given /^(?:|I )manually press "([^"]*)"$/
*/
public function manuallyPress($key)
{
$script = "jQuery.event.trigger({ type : 'keypress', which : '" . $key . "' });";
$this->getSession()->evaluateScript($script);
}
Neither of them will behave as expected (they do not seem to be working at all).
Has anyone got a solution to this problem?
I've spent a fair bit of time on this issue and here are my results:
Behat does not have a pre-defined step to just send keys to any element on the page. It does have pressKey method (#Given I press the :char key in the :field field), but it works only with field as a target of the key event. You would have to write your own pressKey to send keys to a custom CSS element
Behat uses Selenium, which in its turn uses JS Syn library to symulate synthetic browser events. This library is injected into the page by Selenium.
Selenium uses Syn.trigger('keydown',...) to send characters to elements, but it does not seem to work as expected. Instead, using Syn.key(DOMElement, 'tab') would actually send the tab key to the DOMElement element. You would have to implement this as well to make your pressKey work as expected.
Behat is written using Symfony components and uses DriverFactory class to create drivers, including selenium driver. For some reason, the Selenium2Driver class is hardcoded, so there is no way to inject your own extended implementation of this class. You would have to use reflection to piggy-back on exiting protected methods of Selenium2Driver class to include Syn library and execute JS code from previous step.
There is a special case for tab key triggered in window without target element focused - this is the case when you want to test something like Skip to content accessibility link. Such link should appear on first Tab character press, but Syncan tab only from another element that can receive focus.
A working solution is to inject such element as a very first element after opening <body> tag. This element would be visually hidden, but compatible with screen readers. Then we trigger key on this element to make sure that an element that supposed to get the very first focus from tab index actually gets it. Note that injecting element and triggering key press on it does not make it focused itself.
The good news is that it is all doable and is working for me. The bad news is that, unfortunately, I cannot share the code (well, at least not this version and not just yet) :(
I have a webpage that needs to check to see if an app exists using a deep link, but it doesn't seem to work like it should. I have tried the following things.
Using a redirect in PHP (Doesn't work)
header('Location: exampleapp://param=test');
Using a redirect using JavaScript (Doesn't work)
var appurl = 'exampleapp://param=test';
var appstore = 'https://itunes.apple.com/us/app/...';
var timeout;
function preventPopup() {
clearTimeout(timeout);
timeout = null;
window.removeEventListener('pagehide', preventPopup);
}
function startApp() {
window.location = appurl;
timeout = setTimeout(function(){
if(confirm('You do not seem to have the App installed, do you want to go download it now?')){
document.location = appstore;
}
}, 100);
window.addEventListener('pagehide', preventPopup);
}
// app start is then called in the onload
Same as above but replace the the line window.location = appurl; with document.getElementById('deeplink').click(); and adding a link in the html's webpage. (Works) <a id="deeplink" href="exampleapp://param=test">Deep Link</a>
Is there a reason why you can't redirect using a header in PHP?
The PHP version doesn't work, because of the way HTTP works. The HTTP protocol doesn't specify that it should work to redirect to a different protocol from within the "Location:" header. There is nothing specific to PHP here, it's a HTTP issue.
The Javascript version doesn't work because you wanted to set the windows location. And the window cannot show the contents of "exampleapp://..." . You want the link to open like when the user clicks on it. Instead of using window.location you may use document.location.href. That should work.
Another problem:
in your code you write exampleapp:// in 1) and 2). And in 3) you write testapp:// - make sure you use the same URL in all three cases, so that you can be sure that the URL can work eventually..
The answer is to use Apples implementation called 'Smart Banners'
<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">
You can include three comma-separated parameters in the content
attribute:
app-id: (Required.) Your app's unique identifier. To find your app ID
from the iTunes Link Maker, type the name of your app in the Search
field, and select the appropriate country and media type. In the
results, find your app and select iPhone App Link in the column on the
right. Your app ID is the nine-digit number in between id and ?mt.
affiliate-data: (Optional.) Your iTunes affiliate string, if you are
an iTunes affiliate. If you are not, find out more about becoming an
iTunes affiliate at http://www.apple.com/itunes/affiliates/.
app-argument: (Optional.) A URL that provides context to your native
app. If you include this, and the user has your app installed, she can
jump from your website to the corresponding position in your iOS app.
Typically, it is beneficial to retain navigational context because: If
the user is deep within the navigational hierarchy of your website,
you can pass the document’s entire URL, and then parse it in your app
to reroute her to the correct location in your app. If the user
performs a search on your website, you can pass the query string so
that she can seamlessly continue the search in your app without having
to retype her query. If the user is in the midst of creating content,
you can pass the session ID to download the web session state in your
app so she can nondestructively resume her work. You can generate the
app-argument of each page dynamically with a server-side script. You
can format it however you'd like, as long as it is a valid URL.
https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
I want to send some info back to my database when a user prints a certain web page. I can do this in IE with onbeforeprint() and onafterprint() but I would like to browser agnostic way of doing the same thing. Don't care which combination of technologies I have to use (PHP, MySQL, JavaScript, HTML) so long as it gets done. Any ideas?
EDIT:
Still having some problems with this. I tried the putting my function in my Print.css as an image, but I am messing it up some how. Then I tried just adding a event listener, but I cannot get that to work quite right either. If anyone can provide some more details on how I might call a function right before print in ANY browser I would appreciate it.
EDIT:
I am giving up on this for now, I have settled with another way of doing what I want. I look forward to the day when FireFox supports onbeforeprint() and onafterprint().
Many browsers now support window.matchMedia. This API allows you to detect when CSS media queries go into effect (e.g., rotating the screen or printing the document). For a cross-browser approach, combine window.matchMedia with window.onbeforeprint/window.onafterprint.
The following may result in multiple calls to beforePrint() and afterPrint() (for example, Chrome fires the listener every time the print preview is regenerated). This may or may not be desirable depending on the particular processing you're doing in response to the print.
if ('matchMedia' in window) {
// Chrome, Firefox, and IE 10 support mediaMatch listeners
window.matchMedia('print').addListener(function(media) {
if (media.matches) {
beforePrint();
} else {
// Fires immediately, so wait for the first mouse movement
$(document).one('mouseover', afterPrint);
}
});
} else {
// IE and Firefox fire before/after events
$(window).on('beforeprint', beforePrint);
$(window).on('afterprint', afterPrint);
}
More: http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
I m not sure other browsers will allow you to. You could of course specify an image somewhere in a print stylesheet, which probably only will be called on a print, for the onbeforeprint
Try masking the native window.print() with your own...
// hide our vars from the global scope
(function(){
// make a copy of the native window.print
var _print = this.print;
// create a new window.print
this.print = function () {
// if `onbeforeprint` exists, call it.
if (this.onbeforeprint) onbeforeprint(this);
// call the original `window.print`.
_print();
// if `onafterprint` exists, call it.
if (this.onafterprint) onafterprint(this);
}
}())
Updated: comments.
I think that it's simply not possible to this properly. Or at least - not with any technology I know nor with any of the answers given previously.
Both using onafterprint and using serverside dynamic-image-generating script would tell you that the page was printed even when the visitor merely went to print preview mode and then canceled out.
However, I would like to learn how to get the proper information, so that I can be sure that page was actually printed.
I want to create a way to test different layouts on a page to see which get more conversions.
For example. If I have 2 versions of a page and I send 50% to page A and 50% to page B and see which one converts more sales.
So I am thinking maybe use .htaccess to rewrite half to page A and the other half to page B.
But how can I do that with .htaccess is there a way? do I need to use PHP instead to do this?
Also if there is a better way to do this, or any cautions I should be aware of, please let me know.
Lots of ways to deal with it on your own code. If however you're already using Google Analytics and don't care to use javascript for the test, spare yourself a lot of trouble and look at http://www.google.com/websiteoptimizer/index.html
Update (Reconfine): Google website optimizer no longer exists, this has been replaced with "Google Analytics content experiments" https://developers.google.com/analytics/devguides/platform/experiments-overview
I would do that using php, following way:
After the user got to the default php file, i would store his browser data in a db table, and the active layout identifier (filename, row id, etc...).
Everytime the server gets a request from this user, it shows the page, mapped to him.
But! If you have two independent pages, i would only store how many people visited site one, and site two, and redirect them to page A, and to page B by a 50% division.
If you've got a supported database and are using PHP 5.2 or later, you can use a free split testing library called phpScenario, found at www.phpscenario.org
Then you write more or less something like this:
require_once 'scenario_setup.php'; // you write this
if (Scenario::IsControl('experimentname')) {
// read and output version 1
} else {
// read and output version 2
}
Then when you get to your conversion point (say, sign up):
require_once 'scenario_setup.php'; // same
Scenario::Complete('experimentname');
And to view the stats (probably on your admin page):
require_once 'scenario_setup.php'; // yup
Scenario::RenderXml('experimentname');
I think php will be very useful. For example, you can use rand or push a variable in a file :
$int = file_get_contents('var');
if ($int) {
$int++;
} else{
$int = 1;
}
if (($int % 2) == 0) {
header('Location: url1);
} else {
header('Location: url2);
}
file_put_contents ('var', $int);
With apache, you have to setup a load balancer : http://httpd.apache.org/docs/2.1/mod/mod_proxy_balancer.html
I would use php personally. Then you can save which page layout you chose for them as a session var making it easy to load that layout on each page refresh. You would probably also want to save into the database with their username (if they login) and if they visit later show them the same layout.
I have several components who's screen position depends on the resolution of the monitor on which the browser lives.
loginBox.x = (flash.system.Capabilities.screenResolutionX - loginBox.width) / 2;
loginBox.y = (flash.system.Capabilities.screenResolutionY - loginBox.height) / 2;
The problem I'm encountering is that the flash.system.Capabilities method pulls the resolution of the primary monitor attached to the computer. In most situations this isn't a problem but on one of my computers, I have a 1680x1050 and a 1440x900. At work, I have a 1920x1200 and a 1680x1050, so if I open the page in a browser on the smaller monitor, things are not centered and my tools panel is completely off to the right of the screen.
I have a block of javascript that I've tried, both in html and through php but the problem is that if I use either httpRequest or urlLoader to grab the html file, I get the source of html and if I try the php script, I get a script block that is attempting to write a cookie. If that page has not been visited prior to loading the flash site, or if cookies are disabled, it never gets written and I'm nowhere.
Is there a method that I can use, that doesn't rely on cookies, to detect the resolution of the monitor that the browser is actually on, and not just the resolution of the first monitor?
Why don't you use stage.stageWidth and stage.stageHeight for positioning purposes?
EDIT:
Ok, here's an example.
I'm considering that you'll place this code inside the container where loginBox also resides.
The stage property is undefined unless your object is added to the DisplayList, so you need to listen for when it's added and then position the loginBox.
// in the constructor
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
and then
private function onAddedToStage(evt:Event) {
loginBox.x = (stage.stageWidth - loginBox.width)/2;
loginBox.y = (stage.stageHeight - loginBox.height)/2;
}
Also, if you have stage scaleMode set to noScale (which maybe is the case), if you need to constantly reposition the loginBox based on browser resizing, you need to listen to an Event.RESIZE event
stage.addEventListener(Event.RESIZE, onResize);
If you're trying to communicate between flash and javascript, ExternalInterface is the way to go. Rather that writing a cookie, just grab the information from javascript, and send it to flash via a callback.