I am trying to use two browser instances in one test. After forking new driver instance and opening url in new window, protractor cannot find element on that window, even though elements are definitely visible.
Here is my code sample:
app.js
var app = {
browser: undefined,
useBrowser: function (b) {
this.browser = b;
return this;
},
useBrowserAlpha: function () {
return this.useBrowser(browsers.alpha);
},
useBrowserBeta: function () {
return this.useBrowser(browsers.beta);
},
}; module.exports = app;
Then, in test file I use it like this:
it('Test', function () {
browser.ignoreSynchronization = true;
app.openGoogle();
element(by.css('#lst-ib')).sendKeys('Hello');
browsers.beta = browser.forkNewDriverInstance();
app.useBrowserBeta();
app.openGoogle();
element(by.css('#lst-ib')).sendKeys('Hello');
});
In this test, first browser instance is opened and navigates to www.google.com, then types word 'Hello' in search bar, then second instance of browser is initiated, also opens www.google.com and then protractor sends keys to first browser search bar again. Any ideas on how it can be resolved will be highly appreciated.
Related
I open a new tab in the browser with const w = window.open('www.example.com'); and I get the DOM with let d = w.document; Then I go to another webpage with an click-event: d.querySelector('a').click(); The new webpage opens, in the same window, and I want to grap the DOM of the just openend page by running d = w.document again. And this is the point where I get stuck.
I aspect the DOM of the currently openend window, but instead I get the DOM of the previous window back. When console.log(w) (in the .js itself not in the console), with the new webpage open, I get the window object of the current page and the window.document matches the DOM of the openend page. But as I said in reality I get the DOM of the previous page back when I run d = w.document on the new page.
The following code is the whole function I use. Sidenote: I didn't(/couldn't) use window.document.onload fom I reason I don't understand, but It seems I can't attach an function to the window onload event. Also to make things clear my code is inside of a ES6 Class so I didn't use the constas in the example.
The Problem:
When I run the getDOM method on the new openend webpage it returns the DOM of the previous page.
async foo() {
await this.getDOM()
.then(w => this.d = w.document);
const x = this.d.querySelector('button.x');
console.log(send); //null
}
getDOM () {
return new Promise(resolve => {
const interval = setInterval(() => {
if (this.w.document.readyState === 'complete') {
clearInterval(interval);
resolve(this.w);
}
}, 500);
});
}
I hope someone can help, thanks in advance!
This Meteor client code located in the client/lib.js returns true for the first time but if the method is called again it returns false. The two exact calls happens in the browser console.
Unless I hard reload the page, then it works again correctly the first time only.
Why and how to fix it? Thanks
validate = (function () {
const patterns = {
usernamePat: new RegExp('^[0-9a-zA-Z]{16}$', 'g')
};
return {
username: (name) => {
return patterns.usernamePat.test(some_username);
}
}
}());
I want to test some keypresses against a ui-ace instance. However, Protractor can't get focus on the ace element. Ace includes a <textarea> that I can get focus on (and thus send keys to) but ui-ace doesn't recognize keys inputted there (and subsequently doesn't update the model).
Selecting method (by.model, etc) has no impact.
My current workaround is to use evaluate to set the scope value manually, but this breaks the point of using Protractor.
Good question! Seems that the workaround is double clicking first.
The following works at least on Chrome:
"use strict";
describe('Testing ui-ace', function() {
var divInput = $('div.ace_content');
var inputElm = $('textarea.ace_text-input');
it('opens a ui-ace page', function() {
browser.ignoreSynchronization = true; // sorry but no angular page
browser.get('http://angular-ui.github.io/ui-ace/');
browser.sleep(3000); // sorry but no angular page
});
it('starts editing', function() {
browser.actions().doubleClick(divInput).perform();
});
it('enters some text', function() {
inputElm.sendKeys('Hola');
browser.sleep(5000); // to let you see the result
});
});
I've created this custom command for my UI testing in Nightwatch. Here it is in full:
exports.command = function(element, callback) {
var self = this;
try {
this.waitForElementVisible('body', 15000);
console.log("trying..");
window.addEventListener('load', function() {
var selects = document.getElementsByName("select");
console.log(selects);
}, false);
} catch (err) {
console.log("code failed, here's the problem..");
console.log(err);
}
this
.useXpath()
// click dropdowns
.waitForElementVisible(element, 15000)
.click(element)
.useCss()
.waitForElementVisible('option[value="02To0000000L1Hy"]', 15000)
// operation we want all select boxes to perform
.setValue('option[value="02To0000000L1Hy"]', "02To0000000L1Hy")
.useXpath()
.click(element + '/option[4]');
if (typeof callback === "function") {
callback.call(self);
}
return this; // allows the command to be chained.
};
What I'm attempting to do is after I load the page, I want to retrieve all the select boxes and perform the same operation on them. Everything is working correctly except for the code in the try/catch block. I keep getting '[ReferenceError: window is not defined]' and am unsure of how to get past that.
The 'window' property is undefined in the global scope because it's being run via command line Node and not in the browser as one might assume initially.
You could try to use this.injectScript from the Nightwatch API but I would suggest using the Selenium Protocol API 'elements'
Hey there #logan_gabriel,
You could also use the execute command which I use when I need to inject a bit of JavaScript on the actual page. As #Steve Hyndig pointed out, your tests are running in the Node instead of on an actual browser window (somewhat confusing, since a window is generally open while tests are being run! Except if using PhantomJS to headless test, of course).
Here is an example custom command which will inject some JavaScript onto the page based on your original post:
exports.command = function(callback) {
var self = this;
this.execute(function getStorage() {
window.addEventListener('load', function() {
let selects = document.getElementsByName('select');
return selects;
}
},
// allows for use of callbacks with custom function
function(result) {
if (typeof callback === 'function') {
callback.call(self, selects);
}
});
// allows command to be chained
return this;
};
Which you could call from your test using the below syntax, including an optional callback to do something with the result:
client
.setAuth(function showSession(result) {
console.log(result);
});
You could opt to just do the work inside of the custom function, but I run into problems due to the async nature of Nightwatch sometimes if I don't nest stuff inside of callbacks, so it's more a safety thing.
Good luck!
app.js
if (osname === 'android') {
Window = require('ui/handheld/android/SignIn');
}
else {
Window = require('ui/handheld/SignIn');
}
new Window().open();
SignIn.js
function SignIn() {
var self = Ti.UI.createWindow();
//Some design and sign-in validation code
...
var StatusMain = require('/ui/handheld/android/StatusMain');
new StatusMain(global_vars).open();
return self;
}
StatusMain.js
function StatusMain(global_vars) {
var self = Ti.UI.createWindow();
return self;
}
On StatusMain.js, screen When I click on device's back button APP exits instead of going back on SignIn.js screen
Any help will be highly appreciable!
Thanks in advance,
Mohsin
You can handle back button event like this in your code
window.addEventListener('android:back', function(){
// close your current window
});
I suggest you set the (Android specific) exitOnClose property on false when creating the new window:
http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.UI.Window-property-exitOnClose
exitOnClose : Boolean
CREATION-ONLY
Boolean value indicating if the application should exit when the Android Back button is > > pressed while the window is being shown.
You can only set this as a createWindow({...}) option. Setting it after window creation > has no effect.
StatusMain.js
function StatusMain(global_vars) {
var self = Ti.UI.createWindow({
exitOnClose: false
});
return self;
}
That should do the trick. Although the default value is false, it seems that your issue has something to do with that. I recommend experimenting with settings this property to true/false.
Word of advise, you should also test your app on a device if you haven't done so already. My experience with the Android emulators is rather inconsistent at some points.
StatusMain is a lightweight window. It doesn't create new Android activity, instead it shares with SignIn window activity. That's why your app closes when press back button. You need to create a heavyweight window to (specify fullscreen or navBarHidden properties) StatusMain window.
Set the modal property for the new window to true.
function StatusMain(global_vars) {
var self = Ti.UI.createWindow({
modal: true
});
return self;
}