Ignore Wait step timeout in CasperJS - casperjs

Is there a way in casperjs to ignore a timeout for a specific event? I know there is an onStepTimeout function but I believe it is for all step timeouts. I have a loop doing a refresh and don't care if it times out versus the other steps. Any way to flag or ignore timeout based on the step it is performing?
Edit: here is my code snippet. I got it working using a global variable flag but don't know if this the correct way:
//flag
var tout="yes";
//onStepTimeout function
onStepTimeout: function(self,m) {
console.log('List Detection: Process step timed out.');
if ( tout == "yes" ) {
this.exit();
}
},
//Event I dont want to skip if timeout
tout="no";
casper.thenOpen('https://url/account/gotoLogin.action', function() {
//...
});
//Event I do want to skip if timeout
tout="yes";
casper.thenOpen('https://url/browse/browse.action', function() {
//...
});

You can certainly do this with a global variable, but you missed that casper.then* only schedules the steps and does not execute them. You need to move the global variable inside a step to assure that it is flipped at the right time.
//flag
var mayExit = true;
function addMayExitStep(newMayExit){
casper.then(function(){
mayExit = newMayExit;
});
}
//onStepTimeout function
onStepTimeout: function(self,m) {
console.log('List Detection: Process step timed out.');
if ( mayExit ) {
this.exit();
}
},
//Event I dont want to skip if timeout
addMayExitStep(false);
casper.thenOpen('https://url/account/gotoLogin.action', function() {
//...
});
//Event I do want to skip if timeout
addMayExitStep(true);
casper.thenOpen('https://url/browse/browse.action', function() {
//...
});

Related

How to use a while loop in cypress? The control of is NOT entering the loop when running this spec file? The way I am polling the task is correct?

The way i am polling tasks for async POST call, is it correct??? Because program control doesn't enter 'while' loop in spec file. Please help!
Previous query: How to return a value from Cypress custom command
beforeEach(function () {
cy.server()
cy.route('POST', '/rest/hosts').as("hosts")
})
it('Create Host', function () {
let ts =''
let regex = /Ok|Error|Warning/mg
// Some cypress commands to create a host. POST call is made when I create a host. I want to poll
// task for this Asynchronous POST call.
cy.wait("#hosts").then(function (xhr) {
expect(xhr.status).to.eq(202)
token = xhr.request.headers["X-Auth-Token"]
NEWURL = Cypress.config().baseUrl + xhr.response.body.task
})
while((ts.match(regex)) === null) {
cy.pollTask(NEWURL, token).then(taskStatus => {
ts= taskStatus
})
}
})
-------------------------
//In Commands.js file, I have written a function to return taskStatus, which I am using it in spec
file above
Commands.js -
Cypress.Commands.add("pollTask", (NEWURL, token) => {
cy.request({
method: 'GET',
url: NEWURL ,
failOnStatusCode: false,
headers: {
'x-auth-token': token
}
}).as('fetchTaskDetails')
cy.get('#fetchTaskDetails').then(function (response) {
const taskStatus = response.body.task.status
cy.log('task status: ' + taskStatus)
cy.wrap(taskStatus)
})
})
You can't use while/for loops with cypress because of the async nature of cypress. Cypress doesn't wait for everything to complete in the loop before starting the loop again. You can however do recursive functions instead and that waits for everything to complete before it hits the method/function again.
Here is a simple example to explain this. You could check to see if a button is visible, if it is visible you click it, then check again to see if it is still visible, and if it is visible you click it again, but if it isn't visible it won't click it. This will repeat, the button will continue to be clicked until the button is no longer visible. Basically the method/function is called over and over until the conditional is no longer met, which accomplishes the same thing as a loop, but actually works with cypress.
clickVisibleButton = () => {
cy.get( 'body' ).then( $mainContainer => {
const isVisible = $mainContainer.find( '#idOfElement' ).is( ':visible' );
if ( isVisible ) {
cy.get( '#idOfElement' ).click();
this.clickVisibleButton();
}
} );
}
Then obviously call the this.clickVisibleButton() in your test. I'm using typescript and this method is setup in a class, but you could do this as a regular function as well.
With recursion, you can simulate loops.
Add this to your custom commands file (/cypress/support/commands.js):
Cypress.Commands.add('recursionLoop', {times: 'optional'}, function (fn, times) {
if (typeof times === 'undefined') {
times = 0;
}
cy.then(() => {
const result = fn(++times);
if (result !== false) {
cy.recursionLoop(fn, times);
}
});
});
On your tests, just define a function that does what you want for one iteration, and return false if you don't want to iterate again.
cy.recursionLoop(times => {
cy.wait(1000);
console.log(`Iteration: ${times}`);
console.log('Here goes your code.');
return times < 5;
});
while loop is not working for me, so as a workaround I did a for loop, a sort of while loop with a timeout of retries
let found = false
const timeout = 10000
for(let i = 0; i<timeout && !found;i++){
if(..){
// exiting from the loop
found = true
}
}
it is not helpful for everyone, I know.

Laravel Echo and whisper

I'm running echo server and redis. Private channels work perfectly, and messaging I have built for it works. Now I'm trying to get the whisper to work for the typing status as well but no luck. Does whisper require a pusher to work?
What I have tried on keyup (jquery)
Echo.private(chat- + userid)
.whisper('typing',{e: 'i am is typing...'});
console.log('key up'); // this one works so the keyup is triggered
then I'm of course listening the channel what I am whispering into:
Echo.private(chat- + userid).listenForWhisper('typing', (e) => {
console.log(e + ' this is typing');
});
But I get absolutely nothing anywhere. (debugging on at the echo server, nothing on console etc) Any help how to get this to work would be much appreciated.
Your input event:
$('input').on('keydown', function(){
let channel = Echo.private('chat')
setTimeout( () => {
channel.whisper('typing', {
user: userid,
typing: true
})
}, 300)
})
Your listening event:
Echo.private('chat')
.listenForWhisper('typing', (e) => {
e.typing ? $('.typing').show() : $('.typing').hide()
})
setTimeout( () => {
$('.typing').hide()
}, 1000)
Of course you have to have setup the authentication for this channel ahead of time to ensure that the trusted parties have access:
Broadcast::channel('chat', function ($user) {
return Auth::check();
});
Where $user will be the userid we passed to the user param in our object on the front end.
This is what my ReactJS componentDidMount looks like.
Your listening event.
componentDidMount() {
let timer; // timer variable to be cleared every time the user whispers
Echo.join('chatroom')
.here(...)
.joining(...)
.leaving(...)
.listen(...)
}).listenForWhisper('typing', (e) => {
this.setState({
typing: e.name
});
clearTimeout(timer); // <-- clear
// Take note of the 'clearTimeout' before setting another 'setTimeout' timer.
// This will clear previous timer that will make your typing status
// 'blink' if not cleared.
timer = setTimeout(() => {
this.setState({
typing: null
});
}, 500);
});
}

How to exit Protractor test from Spec on specific condition?

I have a suite which includes multiple specs. Each spec uses code on some libraries that return a rejected promise upon failure.
I can easily catch those rejected promises inside my spec. What I'm wondering about is that if I can make Protractor exit the whole suite inside that catch function, because the next specs inside the same suite are dependent on the success of the previous specs.
Pretend I have a suite called testEverything which has these specs openApp,signIn,checkUser,logout. If openApp fails, all next specs will fail due to dependency.
Consider this code for openApp:
var myLib = require('./myLib.js');
describe('App', function() {
it('should get opened', function(done) {
myLib.openApp()
.then(function() {
console.log('Successfully opened app');
})
.catch(function(error) {
console.log('Failed opening app');
if ( error.critical ) {
// Prevent next specs from running or simply quit test
}
})
.finally(function() {
done();
});
});
});
How would I exit the whole test?
There is a module for npm called protractor-fail-fast. Install the module npm install protractor-fail-fast. Here's an example from their site where you would place this code into your conf file:
var failFast = require('protractor-fail-fast');
exports.config = {
plugins: [{
package: 'protractor-fail-fast'
}],
onPrepare: function() {
jasmine.getEnv().addReporter(failFast.init());
},
afterLaunch: function() {
failFast.clean(); // Cleans up the "fail file" (see below)
}
}
Their url is here.
I have managed to come up with a workaround. Now the actual code that I used is way more complex, but the idea is the same.
I added a global variable inside protractor's config file called bail. Consider the following code at the top of config file:
(function () {
global.bail = false;
})();
exports.config: { ...
The above code uses an IIFE (Immediately Invoked Function Expression) which defines bail variable on protractor's global object (which would be available throughout the whole test).
I also have written asynchronous wrappers for the Jasmine matchers I need, which would execute an expect expression followed by a comparison, and return a promise (using Q module). Example:
var q = require('q');
function check(actual) {
return {
sameAs: function(expected) {
var deferred = q.defer();
var expectation = {};
expect(actual).toBe(expected);
expectation.result = (actual === expected);
if ( expectation.result ) {
deferred.resolve(expectation);
}
else {
deferred.reject(expectation);
}
return deferred.promise;
}
};
}
module.exports = check;
Then at the end of each spec, I set the bail value based on the spec's progress, which would be determined by the promise of those asynchronous matchers. Consider the following as first spec:
var check = require('myAsyncWrappers'); // Whatever the path is
describe('Test', function() {
it('should bail on next spec if expectation fails', function(done) {
var myValue = 123;
check(myValue).sameAs('123')
.then(function(expectation) {
console.log('Expectation was met'); // Won't happen
})
.catch(function(expectation) {
console.log('Expectation was not met'); // Will happen
bail = true; // The global variable
})
.finally(function() {
done();
});
});
});
Finally, on the beginning of next specs, I check for bail and return if necessary:
describe('Test', function() {
it('should be skipped due to bail being true', function(done) {
if ( bail ) {
console.log('Skipping spec due to previous failure');
done();
return;
}
// The rest of spec
});
});
Now I want to mention that there's one module out there called protractor-fail-fast which bails on the whole test whenever an expectation fails.
But in my case, I needed to set that bail global variable depending on which type of expectation has been failed. I ended up writing a library (really small) that distinguishes failures as critical and non-critical and then using that, specs would be stopped only if a critical failure has occurred.

Nested it in Protractor/Jasmine

Can I create a nested it in Protractor/Jasmine.
it("outer it", function () {
it("inner it", function () {
expect(1).toBe(1);
});
});
I am trying to execute it test cases inside a loop, and in every iteration I want to run a test, for example:
it("outer it", function () {
for(var i=0;i<10;i++){
it("inner it", function () {
expect(1).toBe(1);
});
}
});
The reason I want to do it is that I want to initialize an array and then in a dynamically way to loop trough all the element and run a number of "it", for example:
describe ("[Components]", function() {
var grid = new Grid();
it("Initialize the grid for the history window", function () {
grid.init();
});
for(var i=0;i<grid.length;i++){
it("test 1", function () {
expect(1).toBe(1);
});
}
});
The grid.length is equal to 0 when the for loop execute, I want the for loop execute after the initialize "it".
Answering to your question, no you cannot nest it's one inside other. Though Jasmine framework doesn't throw any error, the code inside a nested it doesn't execute. Also, I don't see any use of nesting it's as they are specs or functions that run on their own to complete a particular test step. It also gives an overview of the function that is being executed currently. If you are trying to run something in a loop, you can create another function and then call it inside the for loop, something like this -
it("outer it", function () {
var newFunction = function(){
expect(1).toBe(1);
};
for(var i=0;i<10;i++){
newFunction();
};
});
Hope this helps. More on it's can be found here - Jasmine Framework - it's
As mentioned earlier - no, you can not place it inside of another it block, BUT you could place a whole describe block inside another one
You also have an ability to run it blocks inside of for loops, OR for example make it block conditional.
You can find a real example of a code below (I've added for loop just for demonstration purposes)
describe("E2E: Environment configuration test", function () {
beforeAll(function () {
logIn();
});
afterAll(function () {
logOut();
});
describe("Members page configuration test", function() {
for (let i=0; i<3; i++) {
it("Members page - columns", function () {
//code that verifies that all columns of the page are presented
});
}
it( "Members page - filters", function() {
//code that verifies that all filters of the UI are presented as expected
});
it( "Members page - eligibility feature", function() {
//code that verifies that if the feature is set to true then additional column must be displayed
});
});
describe("Providers page configuration test", function() {
// use of conditional it blocks
// if feature is turned on run one set it blocks
// otherwise execute another set of it blocks
if (envConfig.providerFeature) {
it( "Organizations tab configuration test", function() {
//code that verifies that all elements of the current tab are displayed according to configurations of all features of the application
});
it( "Practitioners tab configuration test", function() {});
//code that verifies that all elements of the current tab are displayed according to configurations of all features of the application
} else {
it( "Providers page - verification of the page being disabled", function() {
//code that verifies that both tabs are not present in the UI
console.log('Providers feature is set to FALSE for the environment by default configuration, the test case will be skipped');
});
}
});
it( "Users page configuration test", function() {
//code that verifies that all elements of the current page are displayed according to configurations of all features of the application
});
it( "Reports page configuration test", function() {
if (!envConfig.disabledReportsFeature) {
//code that verifies that all elements of the current page are displayed according to configurations of all features of the application
} else {
console.log('Reports DISABLED_REPORTS_FEATURE is set to TRUE for the environment by default configuration, the test case will be skipped');
}
});
});
The console output in this case will look well organized
P.S. Additionally I will attach an image of clean console

How can i execute the DOH test synchronously?

Can anybody help me in finding a solution for this problem.
I have (assume) 3 doh functions 1st one is async and the rest are synchronous. I have to make async function to be called first and the result of this function to be passed to other two functions is it possible?
Example :
doh.register(".....", [
{
name : "asyncFunction",
runTest : function(){
function callback(result){
//How to pass the result to fun_2 and fun_3
//also fun_2 or fun_3 should be deferred until this function executes
}
}
},
function fun_2(result){
//doh.assertTrue(.....);
},
function fun_3(result){
//doh.assertTrue(.....);
}
Any help would be great.
So, it sounds like your first function is basically a setup function for the other tests.
It is possible to do - basically using Deferreds/promises, but it's a little bit icky, and you might get badly stung by test timeouts.
So, here's something that does a setup with a bit of asynchronous code that takes 2s. All the tests become asynchronous tests that do their work once the 'setup' Deferred has completed.
Because your 'follow on' tests have become asynchronous, you need to make sure that their timeouts cope with the time that'll be taken by your asynchronous setup (at least for the first one that happens to run).
// Some asynchronous initialization that takes 2s
setTimeout(function() {
setupCompletion.resolve({ result: 42 });
}, 2000);
doh.register("my.test1", [
{
name: "waits for async setup to complete",
timeout: 5000,
runTest: function() {
var d = new doh.Deferred();
setupCompletion.then(function (res) {
doh.is(42, res.result);
d.callback(true);
});
return d;
}
},
{
name: "also waits for async setup to complete",
timeout: 5000,
runTest: function() {
var d = new doh.Deferred();
setupCompletion.then(function (res) {
doh.is(43, res.result + 1);
d.callback(true);
});
return d;
}
}
]);
Of course, it would be nice if it were possible to arrange for a test's setUp function to return a Deferred, but doh doesn't support that right now (as of v1.7.2).

Resources