Selenium with Webdriver - Switch to child window without name - php

I'm performing acceptance testing with webdriver and codeception. I'm a bit new to it, so please bear with me. I am trying to switch to a child window that is generated after clicking a button:
<input class="submit_btn" type="button" onclick="openHAWin(this.form.purchase_clinic.value)" value="add" name="add_ha">
As there is no name for this page embedded in the code, nor on the target page itself, I attempted to use the following recommended code to switch to the child page:
$I->executeInSelenium(function (\Webdriver\Session $webdriver) {
$handles=$webdriver->window_handles();
$last_window = end($handles);
$webdriver->focusWindow($last_window);});
However, the above code throws an error in the step that uses it:
"I execute in selenium "lambda function""
The webdriver acceptance fails...

I have method that I'm using when I'm sure that only 2 windows/tabs may be opened at one time (parent and new one), but it is in java so you have to port it to your env. This code is based on my research on this portal + mine additions.
Basically what is done below: get all available windows and switch to one that is not a parent.
String parent = driver.getWindowHandle();
Thread.sleep(1000);
Set<String> availableWindows = driver.getWindowHandles();
String newWindow = null;
for (String window : availableWindows) {
if (!parent.equals(window)) {
newWindow = window;
}
}
if (newWindow != null) {
WebDriver op = driver.switchTo().window(newWindow);
//("Driver switched to new window: " + op.getTitle() + " | " + op.getCurrentUrl());
]

Related

How to integrate CakePHP 3 application with Firebase

Having read documentations and tutorials for hours, I ended up in more confusion after all. So, here I'm asking for your help/tips and I'd really appreciate any effort helps me take a step further. Sorry for any mistakes I might possibly make, I'm quite newbie on this topic, so to say.
I'm building a web application, actually a single web page, that will start running as soon as it receives a GET/POST request from an external source. So, the page will be updated asynchronously if any request is received, for which I thought of using AngularJS and AngularFire on the front-end later on. I know there are many other ways and probably much simpler too, but I'm quite curious about how to integrate my CakePHP application with Firebase platform. So, let's stick with CakePHP + Firebase solutions for now.
So far, using the SDK Firebase PHP Client made much sense, however, I'm still confused about the files that needs to be manipulated. Since there are simply not many -I've found none so far- examples that use CakePHP3 Framework with Firebase, I'm stuck here and I'd really appreciate any help here. Firstly, this code is given in the link and I wonder how it works and what those vars and constants stand for.
const DEFAULT_URL = 'https://kidsplace.firebaseio.com/';
const DEFAULT_TOKEN = 'MqL0c8tKCtheLSYcygYNtGhU8Z2hULOFs9OKPdEp';
const DEFAULT_PATH = '/firebase/example';
$firebase = new \Firebase\FirebaseLib(DEFAULT_URL, DEFAULT_TOKEN);
// --- storing an array ---
$test = array(
"foo" => "bar",
"i_love" => "lamp",
"id" => 42
);
$dateTime = new DateTime();
$firebase->set(DEFAULT_PATH . '/' . $dateTime->format('c'), $test);
// --- storing a string ---
$firebase->set(DEFAULT_PATH . '/name/contact001', "John Doe");
// --- reading the stored string ---
$name = $firebase->get(DEFAULT_PATH . '/name/contact001');
And here is the main question, assuming that I have a test function on one of the end points of my application, let say www.example.com/visits/test, how do I make sure that my application is integrated to Firebase platform and any request sent to that end point is being listened continuously?
Here is how I solved it, just so you know. It's needed to add a test end point to the controller file that you're using. You can find your token using Project Settings in your project file. A quick example is below.
public function test()
{
$DEFAULT_URL = 'YOUR_URL';
$DEFAULT_TOKEN = 'YOUR_TOKEN';
$DEFAULT_PATH = '/';
$firebase = new \Firebase\FirebaseLib($DEFAULT_URL, $DEFAULT_TOKEN);
$lines = [
"I had a problem once",
"I used Java to solve it",
"Now, I have ProblemFactory",
];
foreach ($lines as $line) {
$foo = $firebase->push($DEFAULT_PATH."code/",$line);
echo "child_added";
sleep(0.1);
echo "<br> ";
}
Then, in order to capture the lines added on the front-end, you may use a code similar to the code below. You can easily reach the version that fits your code from your firebase console by clicking Add "firebase to your web app" button or sth like this.
<script src="https://www.gstatic.com/firebasejs/live/3.0/firebase.js"> </script>
<script>
// Initialize Firebase
var config = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR-DOMAIN",
databaseURL: "YOUR_URL",
storageBucket: "YOUR_BUCKET",
};
firebase.initializeApp(config);
var codeRef = firebase.database().ref('code/');
codeRef.on('child_added', function(data) {
console.log(data.val());
});
</script>
I'm not done with the app yet, however, this insight may help you deal with similar issues.

setting iframe ID via fancybox2 to allow webdriver switchTo()->frame(id)

I'm using fancybox2 to create iframes but I can't see a way of setting the ID of the iframe that gets created, which is preventing me from using php-webdriver and selenium to test the contents of the iframe.
Simplified version of the code:
iframe
<script>
$(document).ready(function() {
$(".various").fancybox()
});
</script>
Which works, but using Chrome's inspector, the iframe was (this time) generated with an ID of
fancybox-frame1443817733402, which appears to be random. This means when I try to use php-webdriver to switch to this frame (having clicked the link to create the iframe), I can't predict the frame's ID to pass in:
$frame_id = 'fancybox-frame1443817733402'; // can't predict this in advance
$driver->switchTo()->frame($frame_id);
The iframe is always generated with a class of fancybox-iframe but calls to
$iframe = $driver->findElement(WebDriverBy::class("fancybox-iframe"))
return nothing.
I've also tried using fancybox2's afterLoad callback to try explicitly setting the iframe's ID before trying to switch to the frame by this ID, but that also fails (I think because current is an object, not an element?)
$(".various").fancybox({
afterLoad: function(current, previous) {
//console.log(current);
current.attr('id', 'rob');
}});
Is there a way of explicitly setting the iframe's ID so that I can switch to it via selenium/webdriver? Or is there a simpler way of doing this?
I don't know about setting the frame id here, but you can switch to a frame via xpath (such as //frame):
protected WebElement gotoIframeByXpath(final String iframeXpath) {
if (driver.findElements(By.xpath(iframeXpath)).size() > 0) { // find elements so an exception isn't thrown if not found
WebElement contentFrame = driver.findElement(By.xpath(iframeXpath));
driver.switchTo().frame(contentFrame);
return contentFrame;
} else {
System.out.println("Unable to find " + iframeXpath);
}
return null;
}
For anyone interested, following #EGHM's answer above, this is how I did it.
// this also works & is a little simpler
//$iframes = $driver->findElements(WebDriverBy::tagName('iframe'));
$iframes = $driver->findElements(WebDriverBy::xPath('//*[starts-with(#id,"fancybox-frame")]'));
$id = $iframes[0]->getAttribute('id');
$driver->switchTo()->frame($id);
echo $driver->getPageSource();

JQuery wheel spin onload

I have little problem with JQuery.
Am making spinning wheel application. That application start when I click on button.
I want to change that, because my client will determine when wheel to begin.
Most of my configuration is stored in a database but I try with single number 1 = start, 0 stop.
My app have this for button click and start:
this.cache.wheelSpinBtn = $('.wheel');
// test
this.cache.wheelSpin = 1; // 1 auto start 0 False
Application start when i press button with class .wheel
this.cache.wheelSpinBtn.on('click', function (e) {
e.preventDefault();
if (!$(this).hasClass('disabled')) _this.spin();
});
But I want to remove the button from the other visitors, and this command is issued in the administration. As I said in my configuration is based
I try without database :
if(this.cache.wheelSpin === 1) {
this.spin(); // if is 1 start spinning
}
With database that looks:
if(this.cache.wheelSpin === <?php echo $obj->getStatus()?> ) {
this.spin(); // if is 1 start spinning
}
In both cases that is not work when i refresh page.
I just want when i refresh page wheel start spins. If is value 1 and my core know when need to stop.
My applucation code is little compicated and my code is in and its inposible to use .ready() on only one this.cache.wheelSpin...
Check video.
http://www.youtube.com/watch?v=H-yi6Sv71rs&feature=youtu.be

Can I send raw keyboard input using Mink and Selenium2?

I am using Behat and Mink with the Selenium2 driver, and I'm trying to type directly into a form field (simulating raw keyboard input), instead of using the fillField() function.
This is what I'm trying:
$element = $this->getSession()->getPage()->find('css', '#questionName');
$element->focus();
$element->keyPress('a');
// also tried this, with no success
// $element->keyDown('a');
// $element->keyUp('a');
There is an <input type="text" id="questionName"> element on the page. It correctly receives the focus, but does not respond to any of the simulated keyboard input.
Is it possible to simulate raw keyboard input like this?
What am I doing wrong?
There seems to be a lot of posts complaining about keyPress not working as intended and some drivers don't support it at all. e.g.:
Goutte - Keyboard manipulations are not supported by Behat\Mink\Driver\GoutteDriver
The Selenium driver in particular uses a custom js library to run it's commands, however it doesn't seem to work. I've tried using both the $this->getSession()->getDriver()->keyPress() and the $element->getPress() without luck.
https://github.com/Behat/MinkSelenium2Driver/blob/master/src/Behat/Mink/Driver/Selenium2Driver.php#L815
https://github.com/Behat/MinkSelenium2Driver/blob/master/src/Behat/Mink/Driver/Selenium2/syn.js
What is interesting is that there are no unit tests for the keyPress event in the Selenium2 code base yet (so I assume it's currently in development).
So, for the moment, an adequate solution is to use the javascript emulation of key events from Is it possible to simulate key press events programmatically? (see this for an alternative if you're not using jQuery) and Behat Mink's evaluateScript function.
If you're using straight PHPUnit to test:
$key = 'a';
$script = "jQuery.event.trigger({ type : 'keypress', which : '" . $key . "' });";
$this->getSession()->evaluateScript($script);
Or if you're using Cucumber, add this to your FeatureContext.php file you can add this function:
/**
* #Given /^(?:|I ) manually press "([^"]*)"$/
*/
public function manuallyPress($key)
{
$script = "jQuery.event.trigger({ type : 'keypress', which : '" . $key . "' });";
$this->getSession()->evaluateScript($script);
}
And use it in your feature file like this:
Given I manually press "a"
As for using the javascript as the solution, some of the drivers use javascript to perform the required keyPress. E.g.:
https://github.com/Behat/MinkZombieDriver/blob/master/src/Behat/Mink/Driver/ZombieDriver.php#L819
I'm using Mink with Zombie.js and as it does not catching keyboard events natively, I both listen to focusout and keyup jQuery events.
$('form[name="order"]').find('input[id$="quantity"],input[id$="price"]').bind('keyup focusout', function(){
// [...] update order price
});
I has solved the problem for me but I didn't try it with Selenium2.
The easiest answer I have found is to trigger the key event in javascript and write a specific behat step to send the js to the browser and trigger it.
We have been using YUI so we use the YUI event simulate but jquery or native js handles it. The concept is what matters. It's the best solution I've found until the native behat support is there.
hope this helps.
public function press_key_in_the_ousupsub_editor($keys, $fieldlocator) {
// NodeElement.keyPress simply doesn't work.
if (!$this->running_javascript()) {
throw new coding_exception('Selecting text requires javascript.');
}
// We delegate to behat_form_field class, it will
// guess the type properly.
$field = behat_field_manager::get_form_field_from_label($fieldlocator, $this);
if (!method_exists($field, 'get_value')) {
throw new coding_exception('Field does not support the get_value function.');
}
$editorid = $this->find_field($fieldlocator)->getAttribute('id');
// Get query values for the range.
$js = '
function TriggerKeyPressBehat() {
// http://www.wfimc.org/public/js/yui/3.4.1/docs/event/simulate.html
YUI().use(\'node-event-simulate\', function(Y) {
var id = "'.$editorid.'";
var node = Y.one("#" + id + "editable");
node.focus();
var keyEvent = "keypress";
if (Y.UA.webkit || Y.UA.ie) {
keyEvent = "keydown";
}
// Key code (up arrow) for the keyboard shortcut which triggers this button:
var keys = ['.$keys.'];
for(var i=0; i<keys.length;i++) {
node.simulate(keyEvent, { charCode: keys[i] });
}
});
}
TriggerKeyPressBehat();';
$this->getSession()->executeScript($js);
}

google app engine problem of post method in flash and php

I'm trying to deploy flash files embeded in html to the google app engine.
Flash(action script 2.0) uses "post" method to send hostname and get its ip address through php function gethostbyname().
In fact, I know google app engine does not support php.
So I tried to use another way to deploy ipPHP.php in other free web server and only flash file in google app engine.
But it does not work and I can not know why.
Can you give me a tip for this problem ?
--------------domaintoip.fla ---------------------
result_lv = new LoadVars();
result_lv.byname = _root.domainnm;
trace("Sending... " + result_lv.byname);
result_lv.onLoad = function (success)
{
if (success)
{
_root.ip = unescape(this.result);
trace("Return value from the PHP : " + unescape(this));
if(_root.ip.length==5){
_root.flag=1;
}
else{
var mystring=_root.ip;
arr=mystring.split(".");
_root.ipby1=arr[0];
_root.ipby2=arr[1];
_root.ipby3=arr[2];
if(arr[3].length==15)
{
_root.ipby4=arr[3].substr(0,3);
}
if(arr[3].length==14)
{
_root.ipby4=arr[3].substr(0,2);
}
if(arr[3].length==13)
{
_root.ipby4=arr[3].substr(0,1);
}
_root.flag=0;
}
}
else
{
trace("Cannot call the PHP file...");
_root.flag=1;
}
}
result_lv.sendAndLoad("http://anotherserver../ipPHP.php", result_lv, "POST");
-------------- ipPHP.php ---------------------
<?php
$Var1 = $_POST['byname'];
$rtnValue = gethostbyname(trim($Var1));
if(ip2long($rtnValue) == -1 || $rtnValue == $Var1 ) {
$rtnValue =0;
echo (result=$rtnValue");
}
else {
echo("result=$rtnValue");
}
?>
If your site is hosted on the app engine, you cannot make AJAX calls to a host other than the app engine due to the Same Origin Policy. This limitation is generally true, and is not specific to the app engine. To generalize, for any web page hosted at domain X, that web page cannot make AJAX requests to domain Y.
You actually are experiencing a much more fundamental problem: When the only tool you have is a hammer, every problem looks like a nail. In fact, you can trivially handle POST requests with the app engine using the doPost method, and you can very easily get the client's IP address in a very similar manner as your PHP script. There is absolutely no reason to use PHP here; you've set up a completely new server to call one built-in PHP function? That's insane; you can do the exact same thing with an app engine servlet.
Consider the following code:
public void doPost(HttpServletRequest request,HttpServletResponse response) {
/* get "byname" param, equivalent to $POST['byname'] */
String rtnValue = request.getParameter("byname");
/* TODO: your if statements and other logic */
/* print response to client, equivalent to your echo statement */
response.getWriter().print("result=" + rtnValue);
}

Categories