If there a way to perform .click() after the element become visible.
My function chain is built like that:
this.remote.findByXpath("//div[#data-index='blockContainer']/button[text()='Create new']").then(function(element) {
return element.click().end();
})
Sometimes I got error says 'the element is not visible', is it possible to perform click after the element displayed in browser? I know Leadfoot supplies pollUntil to do similar thing but I don't want to execute xpath at browser side, instead of I want to do until at running server side.
To solve my problem I tried following two ways but doesn't help:
I tried to pass Leadfoot Element to browser side script and check if it is visible. But it seems browser side code doesn't recognize leadfoot/element object.
command.find(...).then(function(element) {
return command.then(pollUntil(
function(element) {
if (element.style.display == 'none') return null;
return true;
}, [element], 60000, 500)).then(function(el){
});
}).click().end();
Also tried to customize pollUntil myself but doesn't work as well
function pollVisible(element, timeout) {
var dfd = new Deferred();
var endTime = Number(new Date()) + timeout;
(function poll() {
element.isDisplayed().then(function (displayed) {
if (displayed) {
dfd.resolve();
}
else if (Number(new Date()) < endTime) {
setTimeout(poll, 500);
}
else {
var error = new Error('timed out; final url is ' + url);
dfd.reject(error);
}
});
})();
return dfd.promise;
}
You've probably had an answer to this by now but here's my solution to this just in case you're still unsure or if anyone else comes across this issue.
I'm not sure why you are polling until an element is visible here. What I would do is set the find timeout of your leadfoot/Session as follows:
this.remote.setFindTimeout(60000)
Then when you invoke the this.remote.findByXPath method, it will automatically search for your element for a maximum of 1 minute (in the case of my above example). If it finds the element within that time, it will then proceed to the next step in your code. If it doesn't find the element within that time, the test case will time out.
You can then simplify your code to (for example):
this.remote
.setFindTimeout(60000)
.findByXpath("//div[#data-index='blockContainer']/button[text()='Create new']")
.click()
.end();
Of course there's no need to set the find timeout every time you wish to find an element in the UI. You can set it once somewhere more appropriate (ie. at the beginning of your test) and it will remain in place for the duration of your test. I'm just doing it here as a means of documenting a full example for you.
Hope this helps!
Related
I'm trying to create a small plugin to make my day-to-day job easier. I have faced a very strange situation within the popup.js script. The promise function randomly refuses to get executed. I have spent some hours trying to debug or at least understand where the issue could be but without any results.
Here is the skeleton of the code:
document.addEventListener('DOMContentLoaded', function () {
// some initialization
document.getElementById("signinbutton").addEventListener("click", function(event) {
try {
// some more initialization
var user_email = '';
var advertiserId = '';
var checkibm = '';
user_email = $('#emailfield').val().trim();
advertiserId = $('#advertiseridfield').val().trim();
checkibm = $('#checkibm').is(':checked');
if (advertiserId && checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (advertiserId && !checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (user_email && validateEmail(user_email))
{
_act = 'getTokenIdByEmail',
_data = user_email
}
else
{
throw new Error("Valid input has not been provided");
}
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
.then(responseHandler)
.then(responseReplaceTokenHandler)
.then(show_ok('Done'))
.catch(failureCallback);
}
catch (error){
//doing some error catching here
});
});
The code above works perfectly. However, as soon as I fill in the real values in sendMessagePromise e.g
//_act and _data show the proper values when inspected
sendMessagePromise({
act : _act,
data: _data//encodeURIComponent(user_email)
})
the flow skips execution of sendMessagePromise and any other chained function, except the last one ".then(show_ok('Done'))", i.e the only result is the "Done" message on the screen.
I made sure the values are correct. I'm able to debug step-by-step and see the values being properly supplied. I have also put a bunch of console messages inside the chain promise functions to see where the execution gets stuck, but it seems like it doesn't even start executing sendMessagePromise.
As soon as I replace expression back to hardcoded values i.e
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
it starts working again. I'm really stuck and not sure how to debug or which steps to take further.
Please assist
When I log in to my application, I am being shown a number of broadcast messages which may or may not be shown and whose number is not under my control. I need to click on a checkbox and next button to dismiss one message and move to the next. So, I need to write a loop on basis of a common element present on the messages with webdriver.io and node.js
I am new to selenium with node.js and webdriver.io and trying to write webdriver.io fucntion inside while and if loop, correct me if that is not possible
The code which I have used is below :
//Code to loop the click on elements depending upon presence of an Element
//Gherkin- I should see if Elementxyz exist then I click on Elementabc and Elementdef
//Author : Rohit
this.Then(/^I should see if "([^"]*)" exist then I click on "([^"]*)" and "([^"]*)"$/, function (selectorelement, selectorcheckbox, selectornext) {
// Element whose presence is checked
selectorelement = this.getSelector(selectorelement);
//Checkbox which needs to be ticked
selectorcheckbox = this.getSelector(selectorcheckbox);
//next button which needs to be clicked
selectornext = this.getSelector(selectornext);
return this.client
.waitForElemReady(selectornext, this.TIMEOUT_CONST)
.then(function(){
if(this.client.isExisting(selectorelement))
{
while(this.client.isExisting(selectorelement))
{
this.client
.click(selectorcheckbox)
.click(selectornext)
.pause(12000)
}
}
else{
console.log("you got lucky there are no messages this time :)")
}
}.bind(this)); });
Please help me as i am new to node.js and wedriver.io world
Hi t33n ,
i have tried the below code and loop is working fine now only thing is that my script is not waiting as .pause() is not working. Could you please help in that.
When I log in to my application, I am being shown a number of broadcast messages which may or may not be shown and whose number is not under my control. I need to click on a checkbox and next button to dismiss one message and move to the next. So, I need to write a loop on basis of a element present on the messages with webdriver.io and node.js I am new to selenium with node.js and webdriver.io and trying to write webdriver.io function for loop.
The code which i am trying to use is working and looping, only thing is giving me problem is pause which is not working as i need to pause a bit till the next message appears.
this.Then(/^I should see if "([^"])" exist then I click on "([^"])" and "([^"]*)"$/, function (selectorelement, selectorcheckbox, selectornext) {
selectorelement = this.getSelector(selectorelement);
// Checking presence of selectorcheckbox
selectorcheckbox = this.getSelector(selectorcheckbox);
selectornext = this.getSelector(selectornext);
var flag1 = false;
// function used for loop
function runNext(flag1,selectorcheckbox, selectornext,browser) {
setTimeout(function (){
browser
.isExisting(selectorcheckbox)
.then(function (isExisting) {
flag1 = isExisting;
if (flag1) {
flag1 = false;
browser.click(selectorcheckbox)
.pause(1000)
.click(selectornext)
.pause(5000); // Pause statements not working
runNext(flag1, selectorcheckbox, selectornext, browser);
}
else {
console.log("no messages left or no messages this time");
}
}, 50000)
}
.bind(this));
}
var loop= runNext(flag1,selectorcheckbox, selectornext,this.client);
});
.pause statements are only working when i am doing return this.client.pause but this stops the execution wherever i write this line.
Please help me with some solution.
maybe this working for you. If not you should see how loops can work and you can create your own loop with this.
function loop() {
client
.isVisible(selectornext).then(function(isVisible) {
if (isVisible) {
client
.isVisible(selectorelement).then(function(isVisible2) {
if (isVisible2) {
client
.click(selectorcheckbox)
.pause(1000)
.click(selectornext)
.pause(12000)
loop()
} // if (isVisible2) {
}) // .isVisible(selectorelement).then(function(isVisible2) {
} // if (isVisible) {
else{
// cancel loop here?
}
}) // .isVisible(selectornext).then(function(isVisible) {
} // function loop() {
i'm attempting to create a function I can call from any test that'll look at the element being passed (link text, Css Selector, Xpath, ID), click on the element, and then verify the URL that comes up after it loads. The problem i'm having is that it's returning before the function is finished.
I know I need to implement async and a callback, but i'm having a hard time understanding the structure.
clickIDverifyURL: function clickByID (elementVar, elementURL){
var rem = this.remote;
// if statements to look at elementVar and select the right one.. example:
// rem.setFindByTimeout(10000)
// .findByXpath (elementVar)
// .click()
// .end()
return this.remote
// if I code it right, I shouldn't need this sleep right?
.sleep(30000)
.getCurrentUrl()
.then(function(currURL) {
console.log(currURL);
try {
assert.strictEqual(currURL, elementURL, "This test checks to see if the current URL is correct.")
}
catch (e)
{
console.log(e)
}
});
}
Appreciate any help or comments.
You're on the right track. Assuming you want to click the element, wait for a page transition, then check the resulting URL, you could do something like:
clickIDverifyURL: function (elementURL) {
return function (element) {
return this.parent
.then(function () {
return element.click();
})
// Wait for the page transition. This can be a sleep, or you can search for an
// element that should be on the new page (intern will implicitly wait for it
// to appear), or use pollUntil to wait for a more specific condition.
.sleep(1000)
// Get the page URL
.getCurrentUrl()
.then(function (url) {
assert.strictEqual(url, elementURL);
});
}
}
You would use it like:
.findElementByCssSelector('.someselector')
.then(myModule.clickIDverifyURL('expectedURL'))
clickIDVerifyURL takes in some configuration data (the expected URL) and returns a function that can be called in a Command's then callback. Such functions have a parent property in their context that references the parent Command chain (the chain of functions started from this.remote).
Note that methods called on Elements, like element.click() above, return Promises, not Commands. This means that only standard Promise methods can be chained, not Command methods like click, findElementByX, etc. That's why the code above starts the inner chain from this.parent rather than element.
Update
The same basic structure works for other types of helper method. For example, if you wanted to use a helper method to do a find, it might look like:
findBySomething: function (selector) {
return function () {
var setContext = arguments[arguments.length - 1];
return this.parent
.findByCssSelector(selector)
.then(function (element) {
setContext(element);
});
}
}
Then you could do
this.remote
.then(myModule.findBySomething('.selector'))
.then(myModule.clickIDverifyURL('expected URL'))
Preparation
Hi i am using CasperJS in combination with grunt-casper (github.com/iamchrismiller/grunt-casper) for running automated functional and regression tests in our GUI Development process for verification.
We use it like this, casper runner in gruntfile.js:
casper: {
componentTests: {
options: {
args: ['--ssl-protocol=any', '--ignore-ssl-errors=true', '--web-security=no'],
test: true,
includes: ['tests/testutils/testutils.js']
},
files: {
'tests/testruns/logfiles/<%= grunt.template.today("yyyy-mm-dd-hhMMss") %>/componenttests/concat-testresults.xml': [
'tests/functionaltests/componenttests/componentTestController.js']
}
},
so as it can be seen here we just normally run casper tests with SSL params and calling only ONE Controllerclass here instead of listing the single tests (this is one of the roots of my problem). grunt-casper delivers the object which is in charge for testing and inside every single Controllerclass the tests are included and concatenated....
...now the componentTestController.js looks like the following:
var config = require('../../../testconfiguration');
var urls = config.test_styleguide_components.urls;
var viewportSizes = config.test_styleguide_components.viewportSizes;
var testfiles = config.test_styleguide_components.testfiles;
var tempCaptureFolder = 'tests/testruns/temprun/';
var testutils = new testutils();
var x = require('casper').selectXPath;
casper.test.begin('COMPONENT TEST CONTROLLER', function(test) {
casper.start();
/* Run tests for all given URLs */
casper.each(urls, function(self, url, i) {
casper.thenOpen(url, function() {
/* Test different viewport resolutions for every URL */
casper.each(viewportSizes, function(self, actViewport, j) {
/* Reset the viewport */
casper.then(function() {
casper.viewport(actViewport[0], actViewport[1]);
});
/* Run the respective tests */
casper.then(function() {
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
});
});
});
});
casper.run(function() {
test.done();
});
});
Here you can see that we running a 3 level loop for testing
ALL URLs given in a JSON config file which are contained in an ARRAY of String ["url1.com","url2.com"....."urln.com"]
ALL VIEWPORT SIZES so that every URL is tested in our desired Viewport resolutions to test the correct Responsibility behaviour of the components
ALL TESTFILES, all testfiles only include a TEST STUB what means, no start, begin or something else, its all in a large Testsourrounding.
MAYBE this is already mocky and can be done in a bette way, so if this is the case i would glad if someone has proposals here, but don't forget that grunt-casper is involved as runner.
Question
So far, so good, the tool in general works fine and the construction we built works as we desired. But the problem is, because all testfiles are ran in a large single context, one failing component fails the whole suite.
In normal cases this is a behaviour i would support, but in our circumstances i do not see any proper solution than log the error / fail the single testcomponent and run on.
Example:
I run a test, which is setUp like described above and in this part:
/* Single tests for every resolution and link */
casper.each(testfiles, function(self, actTest, k) {
casper.then(function() {
require('.'+actTest);
});
});
we include 2 testfiles looking like the following:
Included testfile1.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Atoms']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
casper.click(x("//a[normalize-space(text())='Atoms']"));
},
function fail() {
casper.test.assertExists(x("//a[normalize-space(text())='Atoms']"));
});
});
Included testfile2.js
casper.then(function () {
casper.waitForSelector(x("//a[normalize-space(text())='Buttons']"),
function success() {
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
casper.click(x("//a[normalize-space(text())='Buttons']"));
},
function fail() {
testutils.createErrorScreenshot('#menu > li.active > ul > li:nth-child(7)', tempCaptureFolder, casper, 'BUTTONGROUPS#2-buttons-menu-does-not-exist.png');
casper.test.assertExists(x("//a[normalize-space(text())='Buttons']"));
});
});
So if the assert in testfile1.js fails, everthing failes. So how can i move on to testfile2.js, even if the first fails? Is this possible to configure? Can it be encapsulated somehow?
FYI, this did not work:
https://groups.google.com/d/msg/casperjs/3jlBIx96Tb8/RRPA9X8v6w4J
Almost similar problems
My problem is almost the same like this here:
https://stackoverflow.com/a/27755205/4353553
And this guy here has almost another approach i tried but got his problems too because multiple testsuites ran in a loop occuring problems:
groups.google.com/forum/#!topic/casperjs/VrtkdGQl3FA
MUCH THANKS IN ADVICE
Hopefully I understood what you ware asking - is there a way to suppress the failed assertion's exception throwing behavior?
The Tester's assert method actually allows for overriding the default behavior of throwing an exception on a failed assertion:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
test.assert(false, message, { doThrow: false });
Not all assert helpers have this option though and the only other solution I can think of is catching the exception:
var message = "This test will always fail, but never throw an exception and fail the whole suite.";
try {
test.assertEquals(true, false, message);
} catch (e) { /* Ignore thrown exception. */ }
Both of these approaches are far from ideal since the requirement in our cases is to not throw for all assertions.
Another short term solution that requires overriding the Tester instance's core assert method is (but is still quite hacky):
// Override the default assert method. Hopefully the test
// casper property doesn't change between running suites.
casper.test.assert =
casper.test.assertTrue = (function () {
// Save original assert.
var __assert = casper.test.assert;
return function (subject, message, context) {
casper.log('Custom assert called!', 'debug');
try {
return __assert.apply(casper.test, arguments);
}
catch (error) {
casper.test.processAssertionResult(error.result);
return false;
}
};
})();
That said, I'm currently looking for a non-intrusive solution to this "issue" (not being able to set a default value for doThrow) as well. The above is relative to Casper JS 1.1-beta3 which I'm currently using.
mongoosejs async code .
userSchema.static('alreadyExists',function(name){
var isPresent;
this.count({alias : name },function(err,count){
isPresent = !!count
});
console.log('Value of flag '+isPresent);
return isPresent;
});
I know isPresent is returned before the this.count async function calls the callback , so its value is undefined . But how do i wait for callback to change value of isPresent and then safely return ?
what effect does
(function(){ asynccalls() asynccall() })(); has in the async flow .
What happens if var foo = asynccall() or (function(){})()
Will the above two make return wait ?
can process.nextTick() help?
I know there are lot of questions like these , but nothing explained about problem of returning before async completion
There is no way to do that. You need to change the signature of your function to take a callback rather than returning a value.
Making IO async is one of the main motivation of Node.js, and waiting for an async call to be completed defeats the purpose.
If you give me more context on what you are trying to achieve, I can give you pointers on how to implement it with callbacks.
Edit: You need something like the following:
userSchema.static('alreadyExists',function (name, callback) {
this.count({alias : name}, function (err, count) {
callback(err, err ? null : !!count);
console.log('Value of flag ' + !!count);
});
});
Then, you can use it like:
User.alreadyExists('username', function (err, exists) {
if (err) {
// Handle error
return;
}
if (exists) {
// Pick another username.
} else {
// Continue with this username.
}
}
Had the same problem. I wanted my mocha tests to run very fast (as they originally did), but at the same time to have a anti-DOS layer present and operational in my app. Running those tests just as they originally worked was crazy fast and ddos module I'm using started to response with Too Many Requests error, making the tests fail. I didn't want to disable it just for test purposes (I actually wanted to have automated tests to verify Too Many Requests cases to be there as well).
I had one place used by all the tests that prepared client for HTTPS requests (filled with proper headers, authenticated, with cookies, etc.). It looked like this more or less:
var agent = thiz.getAgent();
thiz.log('preReq for user ' + thiz.username);
thiz.log('preReq for ' + req.url + ' for agent ' + agent.mochaname);
if(thiz.headers) {
Object.keys(thiz.headers).map(function(header) {
thiz.log('preReq header ' + header);
req.set(header, thiz.headers[header]);
});
}
agent.attachCookies(req);
So I wanted to inject there a sleep that would kick in every 5 times this client was requested by a test to perform a request - so the entire suite would run quickly and every 5-th request would wait to make ddos module consider my request unpunishable by Too Many Requests error.
I searched most of the entries here about Async and other libs or practices. All of them required going for callback - which meant I would have to re-write a couple of hundreds of test cases.
Finally I gave up with any elegant solution and fell to the one that worked for me. Which was adding a for loop trying to check status of non-existing file. It caused a operation to be performed long enough I could calibrate it to last for around 6500 ms.
for(var i = 0; i < 200000; ++i) {
try {
fs.statSync('/path' + i);
} catch(err) {
}
};