Protractor IF condition was executed first before IT - jasmine

Is there a way to ensure that it will be executed first before the if condition located below it?
Sample Code:
it('should click ' + strName + ' from the list', function() {
exports.waitForElementDisp(10, global.elmGravityPanel, false);
browser.sleep(2000).then(function() {
element(by.css('[cellvalue="' + strName + '"]')).click();
element(by.id('uniqueid')).getText().then(function(tmpText) {
global.tempObject.isPresent = false;
if (tmpText == strName) {
global.tempObject.isPresent = true;
}
});
});
});
if (global.tempObject.isPresent == true) {
it('should click the settings icon', function() {
global.elmSettingBtn.click();
});
it...
}
Currently, global.tempObject.isPresent was set to null and protractor did not go inside the IF even though it will be set as true inside the first IT.

Because this 'if' is executed on file parsing.
I would suggest to try something like this:
it(`should click ${strName} from the list`, function () {
exports.waitForElementDisp(10, global.elmGravityPanel, false);
browser.sleep(2000)
$(`[cellvalue="${strName}"]`).click();
$('#uniqueid').getText().then(function (tmpText) {
global.tempObject.isPresent = false;
if (tmpText == strName) {
global.tempObject.isPresent = true;
}
});
});
/**
*
* #param condition Any boolean condition to check
* #param suiteOrTest function, that contains scheduling of tests.
*/
function runIf(condition, suiteOrTest) {
if (condition) {
return suiteOrTest
} else {
console.log('Skipping execution')
}
}
describe('Conditional execution', () => {
it('1', function () {
global.elmSettingBtn.click();
});
it('This test is with condition', runIf(process.env.IS_LINUX, ()=> {
// Some other test
global.elmSettingBtn.click();
}))
}))

I'm not a fan of wrapping the it block in a conditional. So below are my thoughts of how you would change your code to avoid using the conditional around the it block.
If you are expecting the unique text to appear on the element for the following it block, you could increase the browser wait for the expected conditions that element appears instead of having an arbitrary sleep time. After the element is available we could then do some checks against the text.
If you have a mixture of workflows that sometimes test to see if a unique text is present and other times where the unique tests is not present, I would then split that out into two different workflows.
If the element is not there, we could fail the tests after that based on the uniqueText not being present. This could be overkill.
let EC = ExpectedConditions;
let button = element(by.css('[cellvalue="' + strName + '"]'));
let uniqueText = element(by.id('uniqueid'));
// your locator strategy here.
let elemSettingBtn = element(by.css('something'));
it('should click ' + strName + ' from the list', function() {
// Leaving this line alone. Not sure what this is doing.
exports.waitForElementDisp(10, global.elmGravityPanel, false);
browser.wait(EC.elementToBeClickable(button), 3000);
button.click();
browser.wait(EC.presenceOf(uniqueText), 3000);
expect(uniqueText.getText()).toEqual(strName);
});
it('should click the settings icon', function() {
uniqueText.isPresent().then(present => {
if (present) {
// click the settings button because the unique text is there.
return elmSettingBtn.click();
} else {
// Maybe fail the test when the button is not present?
fail('unique text is not present.');
}
});
});

Related

failing to reset language selection after sync

I am facing a problem which I am not aware how to resolve. Let me describe elaborately below:
I have a commonViewModel kendo class where event like save, cancel are written. I am facing problem with the save event of this class.
save: function () {
var that = this;
var routeLanguage = "";
that._showBackConfirmation(false);
that.set("isFormSubmitted", true);
console.log("form is valid, sending the save request!");
if (vm.get("languageTabsVm.selectedLanguage")) {
routeLanguage = "/" + vm.get("languageTabsVm.selectedLanguage");
}
else if (that.get("model.Languages") && that.get("model.Languages").length > 1) {
that.get("model.Languages").forEach(function (lang) {
if (lang.get("IsActive") === true) {
//sätt cv-visning till det språk jag senast redigerade på detta item
routeLanguage = "/" + lang.LanguageId;
}
});
}
//if i call the function _loadDefaultLanguageSelection here, it
// works. because, the datasource is not synced yet.
//Make sure the datasource are syncing changes to the server (includes all crud)
return that.dataSource.sync().fail(function (e) {
//i need to do something here to be in the same language tab. But
//as i am changing directly in to model, it is not possible. But
//saving directly to model is essential because that model is
//shared to other viewmodel for language tab synching purpose.
that.set("isFormSubmitted", false);
console.log("form rejected");
}).done(function () {
if (that.get("isPersonaldetail")) {
var name = that.get("model.Name");
if (name.length > 12)
name = name.substring(0, 11) + "...";
$("#profileName").text(name);
}
that.set("isFormSubmitted", false);
that.set("isSelected", false);
// it is called from here right now. but it is failing because
// model is updated but not synced in that function
that._loadDefaultLanguageSelection();
router.navigate(that.nextRoute + routeLanguage);
});
},
_loadDefaultLanguageSelection: function () {
var that = this;
if (that.get("model.Languages") && that.get("model.Languages").length > 1) {
that.get("model.Languages").forEach(function (lang) {
if (!that.get("isPersonaldetail")) {
lang.set("IsActive", lang.get("LanguageId") === vm.get("languageTabsVm.selectedLanguage"));
}
});
}
},
So, my question is, how can i resolve this problem. one solution is i will have to sync twice. that is not nice. So, I am looking for efficient solution.

How can I check until an element is clickable using nightwatchjs?

How can I check until an element is clickable using nightwatch js? I want to click on an element but when I run nightwatch, selenium does not click on the element because it is not clickable yet.
Something like this should work. Let me know if you have questions
var util = require('util');
var events = require('events');
/*
* This custom command allows us to locate an HTML element on the page and then wait until the element is both visible
* and does not have a "disabled" state. It rechecks the element state every 500ms until either it evaluates to true or
* it reaches maxTimeInMilliseconds (which fails the test). Nightwatch uses the Node.js EventEmitter pattern to handle
* asynchronous code so this command is also an EventEmitter.
*/
function WaitUntilElementIsClickable() {
events.EventEmitter.call(this);
this.startTimeInMilliseconds = null;
}
util.inherits(WaitUntilElementIsClickable, events.EventEmitter);
WaitUntilElementIsClickable.prototype.command = function (element, timeoutInMilliseconds) {
this.startTimeInMilliseconds = new Date().getTime();
var self = this;
var message;
if (typeof timeoutInMilliseconds !== 'number') {
timeoutInMilliseconds = this.api.globals.waitForConditionTimeout;
}
this.check(element, function (result, loadedTimeInMilliseconds) {
if (result) {
message = '#' + element + ' was clickable after ' + (loadedTimeInMilliseconds - self.startTimeInMilliseconds) + ' ms.';
} else {
message = '#' + element + ' was still not clickable after ' + timeoutInMilliseconds + ' ms.';
}
self.client.assertion(result, 'not visible or disabled', 'visible and not disabled', message, true);
self.emit('complete');
}, timeoutInMilliseconds);
return this;
};
WaitUntilElementIsClickable.prototype.check = function (element, callback, maxTimeInMilliseconds) {
var self = this;
var promises =[];
promises.push(new Promise(function(resolve) {
self.api.isVisible(element, function(result) {
resolve(result.status === 0 && result.value === true);
});
}));
promises.push(new Promise(function(resolve) {
self.api.getAttribute(element, 'disabled', function (result) {
resolve(result.status === 0 && result.value === null);
});
}));
Promise.all(promises)
.then(function(results) {
var now = new Date().getTime();
const visibleAndNotDisabled = !!results[0] && !!results[1];
if (visibleAndNotDisabled) {
callback(true, now);
} else if (now - self.startTimeInMilliseconds < maxTimeInMilliseconds) {
setTimeout(function () {
self.check(element, callback, maxTimeInMilliseconds);
}, 500);
} else {
callback(false);
}
})
.catch(function(error) {
setTimeout(function () {
self.check(element, callback, maxTimeInMilliseconds);
}, 500);
});
};
module.exports = WaitUntilElementIsClickable;
Add this code as a file to your commands folder. It should be called waitUntilElementIsClickable.js or whatever you want your command to be.
Usage is:
browser.waitUntilElementIsClickable('.some.css');
You can also use page elements:
var page = browser.page.somePage();
page.waitUntilElementIsClickable('#someElement');
You can use waitForElementVisible() combined with the :enabled CSS pseudo-class.
For example, the following will wait up to 10 seconds for #element to become enabled, then click it (note that the test will fail if the element doesn't become enabled after 10 seconds):
browser
.waitForElementVisible('#element:enabled', 10000)
.click('#element');
Can you show an example element,usually there should be an attribute name "disabled" if the button is not clickable, this should work.
browser.assert.attributeEquals(yourCSS, 'disabled', true)
I'm unable to comment but there are a couple of issues with the code suggested by Alex R.
First, the code will not work with Firefox as geckodriver does not return a 'status'. So this:
resolve(result.status === 0 && result.value === true)
needs to be changed to this:
resolve(result.value === true).
Second, the line:
self.client.assertion(result, 'not visible or disabled', 'visible and not disabled', message, true);
doesn't work and needs to be commented out in
order to get the code to run.

casperjs click() a form element to submit, wait, run queries on next page?

I would like to click a submit button, wait for the next page to load, then obtain html on that second page.. I do the start, then and run, but the then step is still run on the first page. Any ideas?
var casper = require('casper').create();
var site = 'http://www.example.com';
var data = {};
casper.start(site, function() {
this.evaluate(function() {
$('input[type="submit"]:first').click();
});
});
casper.then(function() {
data.body = this.evaluate(function() {
var rows = $('#content table:first tbody tr');
var listings = rows.eq(3).text();
var count = rows.eq(4).text();
return {
listings: listings,
count: count
};
});
});
casper.run(function() {
this.echo(data.body.listings);
this.exit();
});
This only partially solves your problem, but you can confirm that you've made it to the second page using waitFor. For example:
this.waitFor(function check() {
return (this.getCurrentUrl() === PAGE_2_URL);
},
function then() { // step to execute when check() is ok
this.echo('Navigated to page 2', 'INFO');
},
function timeout() { // step to execute if check has failed
this.echo('Failed to navigate to page 2', 'ERROR');
});
Its a good idea use waitForResource to wait the page load finished, see documentation here documentation
example:
casper.waitForResource(function checkAuth(validcredentials) {
return validcredentials;
}, function onReceived() {
if (authTitle !== this.getTitle()) {
this.log('Autenticação realizada com sucesso, aguarde...');
} else {
// this.capture('pic3.png');
this.log('Usuario ou senha invalidos!', 'ERROR');
this.die('User or password invalids!', 1); }
});
I have a similar problem with doubleclick. Make sure the click event is actually fired. I suspect this is the cause of running the next step within the same content.

hidding elements in a layout page mvc3

ok so im having a hard time hiding some layout sections (divs in my layout page and im using mvc3).
I have this js fragment which is basically the main logic:
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
});
//Cookies Functions========================================================
//Cookie for showing the right container
if ($.cookie('right_container_visible') === 'false') {
if ($('#RightContainer:visible')) {
$('#RightContainer').hide();
}
$.cookie('right_container_visible', null);
} else {
if ($('#RightContainer:hidden')) {
$('#RightContainer').show();
}
}
as you can see, im hidding the container whenever i click into some links that have a specific css. This seems to work fine for simple tests. But when i start testing it like
.contentExpand click --> detail button click --> .contentExpand click --> [here unexpected issue: the line $.cookie('right_container_visible', null); is read but it doesnt set the vaule to null as if its ignoring it]
Im trying to understand whats the right logic to implement this. Anyone knows how i can solve this?
The simpliest solution is to create variable outside delegate of bind.
For example:
var rightContVisibility = $.cookie('right_container_visible');
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
rightContVisibility = "false";
});
if (rightContVisibility === 'false') {
...
}
The best thing that worked for me was to create an event that can catch the resize of an element. I got this from another post but I dont remember which one. Anyway here is the code for the event:
//Event to catch rezising============================================================================
(function () {
var interval;
jQuery.event.special.contentchange = {
setup: function () {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, { type: 'contentchange' });
}
}, 100);
},
teardown: function () {
clearInterval(interval);
}
};
})();
//=========================================================================================
//Function to resize the right container============================================================
(function ($) {
$.fn.fixRightContainer = function () {
this.each(function () {
var width = $(this).width();
var parentWidth = $(this).offsetParent().width();
var percent = Math.round(100 * width / parentWidth);
if (percent > 62) {
$('#RightContainer').remove();
}
});
};
})(jQuery);
//===================================================================================================

.bind() statement not working in jQuery Easy Confirmation plugin

Did anyone who used jQuery Easy Confirmation plugin run into this issue - the button upon which the confirm box is bound loses its original click event after the first click? I had to change the plugin code to this to make it work. The difference here is between .bind and .click. Can anyone explain why? Pls. let me know if my question is not clear. Thx!
Original plugin code:
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
//this is the difference
$target.bind(type, this);
});
}
}
Changed (working) code:
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
//this is the difference
if(type == 'click')
$target.click(this);
else {
$target.bind(type, this);
}
});
}
}
Try using some alerts to see what's happening...
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
if(type == 'click')
alert('$target.click(' + this + ');');
//$target.click(this);
else {
alert('$target.bind(' + type + ', ' + this + ');');
//$target.bind(type, this);
}
});
}
}

Resources