Browser switch handle Phantomjs Issue - selenium

I use protractor with cucumber and whenever there is a need to switch between browser tabs with phantomjs it just hangs without any error message. However the same step works fine with Chrome browser. Why is that? My step is as follows
this.Then(/^the page url hash should be "([^"]*)"$/, function (arg1, callback) {
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[2];
browser.switchTo().window(newWindowHandle).then(function () {
expect(browser.driver.getCurrentUrl()).to.eventually.contain(arg1).and.notify(callback);
});
});

Ok so apparently the issue was with callback. When i modified the above code slightly it works like a charm even in phantomjs!
this.Then(/^the page url hash should be "([^"]*)"$/, function (arg1, callback) {
browser.getAllWindowHandles().then(function (handles) {
newWindowHandle = handles[2];
browser.switchTo().window(newWindowHandle).then(function () {
expect(browser.getCurrentUrl()).to.eventually.contain(arg1);
});
});
callback();
});

Related

How to get browser console logs when using Browser library in Robotframework

I'm using Robotframework and Browser library to automate some tasks on the web. I used to use Selenium, and with selenium there is a way to get the logs, for example in the case of a failure:
driver = webdriver.Remote()
logs = driver.get_log('browser')
I've been struggling to find a way to do the same exact thing using Playwright's Browser library. Is it possible?
Certainly. You can use the page.on('console') event to log what appears in the DevTools console. Here's an example of using debug library to do so.
Make sure to export DEBUG=playwright:console or you won't see anything.
Here's how to do it in JS:
const playwright = require('playwright');
const debugConsole = require('debug')('playwright:console');
(async () => {
const browser = await playwright.chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.on('console', (msg) => {
if (msg && msg.text) {
if (typeof msg.text === 'function') {
debugConsole('PAGE LOG:', msg.text());
} else {
debugConsole('PAGE LOG:', msg.text);
}
} else {
debugConsole('PAGE LOG:', msg);
}
});
await page.goto('https://example.com', { waitUntil: 'networkidle' });
})();
And in python:
from playwright.sync_api import sync_playwright
def print_args(msg):
for arg in msg.args:
print(arg.json_value())
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.on("console", print_args)
page.goto("https://abrahamjuliot.github.io/creepjs/", wait_until="networkidle")
page.wait_for_timeout(5000)
browser.close()
If you are looking for more system-level stuff, there is also a dumpio launch parameter that you can set, which will cause Playwright to provide verbose logs on the actual launch of browser executable.

Nightwatch JS page object returns undefined

I'm using Nightwatch with mocha.
I try to get an element's text from the page object. When trying to compare the received text to another text I receive an error "AssertionError: expected undefined to equal 'Text'".
This is the Page Object function:
const Commands = {
getInstanceLabel() {
this.getText('.DropdownSelect__label', (result) => {
return result.value;
});
}
}
And this is the Test code:
it('Should sort the collection in ascending order by default', (client) => {
const labelText = client.page.instanceCollectionPage().getInstanceLabel();
expect(labelText).to.equal('Text');
});
Why is this showing undefined?
The thing is that you are using arrow functions, and as mentioned in mdn:
An arrow function expression has a shorter syntax compared to function
expressions and does not bind its own this, arguments, super, or
new.target.
You can fix it in two different ways:
using function:
e.g. (you can use this)
it('Should launch', function (browser) {
const url = browser.launchUrl;
browser.url(url).waitForElementVisible('body', 1000);
browser.getText('#txtWelcome', function (result) {
this.verify.equal(result.value, 'Welcome');
});
});
using browser:
e.g. (you need to access the browser object direcly)
it('Should launch', (browser) => {
const url = browser.launchUrl;
browser.url(url).waitForElementVisible('body', 1000);
browser.getText('#txtWelcome', (result) => {
browser.verify.equal(result.value, 'Welcome');
});
});
Those are just examples on how to use this, I can not provide more details on your issue because you don't show what InstanceCollection does.

Protractor not waiting for login redirect before continuing tests in AngularJS, any suggestion?

I have a standard username/password/submit button form, when the user clicks on the button the form submits with ng-submit="login.submit()" which does the login and on success redirects to the main page using ui.router ($state.go("main")).
The following test fails:
describe("login", function() {
beforeEach(function() {
var email = element(by.model("login.email"));
email.clear().sendKeys("mail");
var password = element(by.model("login.password"));
password.clear().sendKeys("pass");
var submit = element(by.id("submit"));
submit.click();
});
it("should be able to login", function() {
expect(element(by.css(".loginPage")).isPresent()).toBe(false);
expect(element(by.css(".mainPage")).isPresent()).toBe(true);
});
});
and if I try to add wait times around, I can see that the browser stays on the login page the whole time (after clicking on the button) - then I get a timeout.
After a successful login the browser receives a cookie with a token for authenticating each following request.
EDIT: with some tinkering I found out where it fails..
function login(email, pass) {
alert("it gets here");
return _auth.post({ username: email, password: pass }).then(function(data) {
alert("does not get here");
console.log("loginok, token:" +$browser.cookies().apiToken); //this should be the received token
return data;
});
}
EDIT2: the Auth service
var _auth = Restangular.withConfig(function(Configurer) {
Configurer.setBaseUrl("/");
}).service("auth/simple");
return {
login: login,
};
function login(email, pass) {
return _auth.post({ username: email, password: pass });
}
Manually everything works as expected.
#JoMendez's answer was very close but didn't work in my case. Used #DaveGray's here.
Had to wrap the isPresent() call in a function.
browser.wait(function() {
return element(by.css('.mainPage')).isPresent();
});
Try this:
it("should be able to login", function() {
browser.wait(element(by.css(".mainPage")).isPresent);//this is different from sleep, this will stop the excecution of all the protractor code that is after it, until the element is present, but it won't prevent the application of loading or if is redirecting, it will keep working.
expect(element(by.css(".loginPage")).isPresent()).toBe(false);
expect(element(by.css(".mainPage")).isPresent()).toBe(true);
});
});

JQuery include in phantomjs is not working

My code is:
var url = 'https://search.yahoo.com/',
page = new WebPage(),
fs = require('fs');
page.settings.userAgent = 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail appname/appversion';
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.open(url, function(status) {
if (status !== 'success')
{
console.log('Unable to access network');
phantom.exit();
return;
}
else
{
page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js", function()
{
page.evaluate(function()
{
$('#yschsp').val("ask question");
$(".sbb").click();
});
page.onLoadFinished = function(status) {
var content = page.content;
fs.write('1.html', content, 'w');
console.log($('#link-1').val());
phantom.exit();
};
});
}
});
JQuery works perfect in page.evaluate but does not work in page.onLoadFinished. I get an error
Can't get variable: $
That means that in function page.onLoadFinished jquery is not working. But I can not understand why?
Since jQuery is loaded into the page context, you can only use there. The only function that interfaces with the page context is evaluate (and the other evaluate functions).
So this line
console.log($('#link-1').val());
must be inside of an evaluate callback. Since you have a page.onConsoleMessage event handler you will receive the console message from the page context.
The other thing is that adding an page.onLoadFinished event handler after the page has loaded isn't doing anything useful. You can remove the handler surrounding your code since the page load is finished when the page.open callback is called.
If #link-1 is not yet loaded, you should either log the value after a static timeout (setTimeout) or use waitFor.

Exposing variables from PhantomJS call to injectJS

I've followed examples for injecting jQuery from the getting started page and that works just fine. I have a local copy of jQuery in the same directory, and do something like...
if(page.injectJs('jquery.min.js')) {
page.evaluate(function(){
//Use jQuery or $
}
}
When I try to inject my own script(s), none of the functions are available to me. Say I have a script called myScript.js that just has
function doSomething() {
// doing something...
}
I cannot then use doSomething like...
if(page.injectJs('myScript.js')) {
console.log('myScript injected... I think');
page.evaluate(function() {
doSomething();
});
} else {
console.log('Failed to inject myScript');
}
I've tried
window.doSomething = function() {};
and
document.doSomething = function() {};
as well with no luck, as well as trying to call them with window.doSomething() or document.doSomething() in the subsequent page.evaluate().
The following works for me, maybe some other part of your app logic is wrong:
inject.coffee
page = require('webpage').create()
page.onConsoleMessage = (msg) -> console.log msg
page.open "http://www.phantomjs.org", (status) ->
if status is "success"
page.includeJs "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", ->
if page.injectJs "do.js"
page.evaluate ->
title = echoAndReturnTitle('hello')
console.log title
phantom.exit()
do.coffee:
window.echoAndReturnTitle = (arg) ->
console.log "echoing '#{arg}'"
console.log $(".explanation").text()
return document.title
Result:
> phantomjs inject.coffee
echoing 'hello'
PhantomJS is a headless WebKit with JavaScript API.
It has fast and native support for various web standards:
DOM handling, CSS selector, JSON, Canvas, and SVG.
PhantomJS is created by Ariya Hidayat.
PhantomJS: Headless WebKit with JavaScript API
or if you prefer JavaScript (they're auto-generated and a little ugly):
`inject.js':
// Generated by CoffeeScript 1.3.1
(function() {
var page;
page = require('webpage').create();
page.onConsoleMessage = function(msg) {
return console.log(msg);
};
page.open("http://www.phantomjs.org", function(status) {
if (status === "success") {
return page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", function() {
if (page.injectJs("do.js")) {
page.evaluate(function() {
var title;
title = echoAndReturnTitle('hello');
return console.log(title);
});
return phantom.exit();
}
});
}
});
}).call(this);
do.js:
// Generated by CoffeeScript 1.3.1
(function() {
window.echoAndReturnTitle = function(arg) {
console.log("echoing '" + arg + "'");
console.log($(".explanation").text());
return document.title;
};
}).call(this);