How to use promise in if condition - protractor

I am trying following lines of code to get a numeric value when condition is met
this.getMessageThreadsPosition = function (k, sub, callback) {
console.log(sub);
for(var i = 1; i <= k; i++){
commonsMethod.findElementDriver(that.messageSubjectTextPath(i)).then(function(foundelement){
foundelement.getText().then(function(text){
console.log(text);
if(text == sub){
callback(i);
}
});
});
}
};
But it seems that it never goes inside if condition.

Related

why writing function of setTimeout separately would not work

I am trying to build 'Simon Game' and used setTimeout method to lighten the buttons. when I write the the functions directly inside the setTimeout method it works.
$(function(){
var randPattern=[];
var buttonId=['red','yellow','green','blue'];
var origColor=['#B40404','#D7DF01','#0B610B','#0B0B61'];
var patternColor=['#F78181','#F4FA58','#A9BCF5','#81F781'];
var level= 5;
var count= 0;
var time= 1000;
$('#start').click(function gameStart() {
patternGenerate();
for(i=0; i<randPattern.length; i++){
display(i);
}
});
function patternGenerate() {
for(var h=0; h<level; h++){
randPattern.push( Math.floor( Math.random()*4) );
}
}
function display(i){
setTimeout(function(){document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = patternColor[randPattern[i]];document.getElementById(randPattern[i]).play();}, 1500*i);
setTimeout(function(){document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = origColor[randPattern[i]]}, 750+1500*i );
}
but when I write the functions that is going inside setTimeout method separately, such function a(i), and function b(i). It doesn't work. And the console says ''cannot read the property 'style' of null''. I think there is no difference between these two. I can't understand why the second way doesn't work while the first one does.
$(function(){
var randPattern=[];
var buttonId=['red','yellow','green','blue'];
var origColor=['#B40404','#D7DF01','#0B610B','#0B0B61'];
var patternColor=['#F78181','#F4FA58','#A9BCF5','#81F781'];
var level= 5;
var count= 0;
var time= 1000;
$('#start').click(function gameStart() {
patternGenerate();
for(i=0; i<randPattern.length; i++){
display(i);
}
});
function patternGenerate() {
for(var h=0; h<level; h++){
randPattern.push( Math.floor( Math.random()*4) );
}
}
function a (i){
document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = patternColor[randPattern[i]];
document.getElementById(randPattern[i]).play();
}
function b (i){
document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = origColor[randPattern[i]];
}
function display(i){
setTimeout(a,1500*i);
setTimeout(b,750+1500*i);
}
});
a and b expect to be passed an argument which will be assigned to i.
While you have a variable called i in the display function: You aren't passing it to a or b.
function display(i){
setTimeout( a, 1500*i, i );
setTimeout( b, 750+1500*i, i );
}
You are using an i inside function display(i){ but this variable is not passed to a or b. If you want to pass a variable, you still need to create a new closure and call your function from it:
function display(i){
setTimeout(function() { a(i) }, 1500*i);
setTimeout(function() { b(i) }, 750+1500*i);
}

How to pass a test if expect fails

I have this code
it('This should pass anyway', function (done) {
testObj.testIt(regStr);
});
testObj
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
for (var curr = 0; curr < count; curr++) {
checkField(curr, regStr);
}
});
};
function checkField(curr, regStr) {
selector.get(curr).all(by.tagName('li')).get(0).getInnerHtml().then(function (text) {
expect(text).to.match(regStr, curr + '#ERR');
});
}
If one of these expects get a failure, test fails. How can i handle this? I mean - can i somehow count passed and failed expect()ations and return it? or, at least, dont let test break on first error.
I've tried try-catch, but nothing good happened.
it('This should pass anyway', function (done) {
try {
testObj.testIt(regStr);
} catch (e) {
console.log('#err' + e);
}
});
And then i wanted to use done(), but havent found any examples to do the similar. Can u please help me?
Sry for my english
UPD
You can return either null or a string from checkField(), join them up, and expect the array to be empty:
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
var errors = [];
for (var curr = 0; curr < orgCount; curr++) {
var e = checkField(curr, regStr);
if (e) { errors.push(e); }
}
assert.equal(0, errors.length, errors);
});
};
A cleaner approach would be to use map() to collect the data into an array:
var data = selector.map(function (elm) {
return elm.element(by.tagName('li')).getText();
});
expect(data).toEqual(["test1", "test2", "test3"]);

How to check if text is found in column in Protractor

I'm trying to assert that a name is displayed in a column of a table. I've written an inResults function that will iterate through a column's text to see if a name exists. Here's what I'm trying:
Page object:
this.names = element.all(by.repeater('row in rows').column('{{row}}'));
this.inResults = function(nameString) {
var foundit = '';
this.names.each(function(name) {
name.getText().then(function(it) {
console.log(it); // each name IS printed...
if(it == nameString) {
console.log('it\'s TRUE!!!!'); // this gets printed...
foundit = true;
}
});
});
return foundit; // returns '' but should be true?
};
Spec expect:
expect(friendPage.inResults('Jo')).toBeTruthy();
Both console statements print as expected... but my expect fails as foundit's value is still ''. I've tried this a number of ways and none are working. What am I missing?
I've devised what I think is a better/cleaner way to solve this. It's less complex and doesn't require locator/css code in the method.
friend.page.js
// locator
this.friendName = function(text) { return element.all(by.cssContainingText('td.ng-binding', text)) };
// method
this.inResults = function(name) {
return this.friendName(name).then(function(found) {
return found.length > 0;
});
};
friend.spec.js
expect(friendPage.inResults('Jo')).toBeTruthy();
I've added this to my protractor_example project on GitHub...
I would recommend you to use filter: http://angular.github.io/protractor/#/api?view=ElementArrayFinder.prototype.filter
this.inResults = function(nameString) {
return this.names.filter(function(name) {
return name.getText().then(function(text) {
return text === nameString;
});
}).then(function(filteredElements) {
// Only the elements that passed the filter will be here. This is an array.
return filteredElements.length > 0;
});
});
// This will be a promise that resolves to a boolean.
expect(friendPage.inResults('Jo')).toBe(true);
Use map to do this.This will return a deferred that will resolve with the values in an array, so if you have this:
this.mappedVals =element.all(by.repeater('row in rows').column('{{row}}')).map(function (elm) {
return elm.getText();
});
It will resolve like this:
this.inResults = function(nameString) {
var foundit = '';
mappedVals.then(function (textArr) {
// textArr will be an actual JS array of the text from each node in your repeater
for(var i=0; i<textArr.length; i++){
if(it == textArr[i]) {
console.log('it\'s TRUE!!!!'); // this gets printed...
foundit = true;
}
}
return foundit;
});
}
And Use that in Spec file like,
friendPage.inResults('Jo').then(function(findIt){
expect(findIt).toBeTruthy();
});

Reactively counting the number of form inputs completed in Meteor.js

I've been struggling with this implementation so I figure I'd give the good ol' community here at Stack Overflow a shot at solving my problem.
So i got a standard personal information form. The form id is "personal-form".
I have a helper method called {{numFormsCompleted}} from the template.
Here is my implementation of the method --
numFormsCompleted : function(){
var count = 0;
var form = document.getElementById("quote-form");
console.log(form);
if(form == null)
return 0;
else{
for(i = 0; i < form.length; i++){
value = form.elements[i].value;
if(value != "" || value != null)
count++;
}
console.log(count);
return count;
}
}
The form is showing up as null. Anyone know why?
Your template may or may not have been rendered when your code runs, therefore instead of providing it as a helper of your template, you can run your function at your template's rendered callback, and then assign the return value to a reactive session variable.
Template.myFormTemplate.rendered = function() {
Session.setDefault("formElementCount", 0);
var count = 0;
var form = this.find("#quote-form");
console.log(form);
if(!!form){
for(i = 0; i < form.length; i++){
value = form.elements[i].value;
if(value != "" || value != null)
count++;
}
console.log(count);
Session.set("formElementCount", count);
}
}
and then as your helper in your template
Template.myFormTemplate.numFormsCompleted = function() {
var count = Session.get("formElementCount");
return count;
}
This way, whenever your form template gets rendered, it will reactively give you the element count in your helper and as an added bonus, you can use it from within other templates as well.

How to do a very simple for loop

I want to accomplish this in coffeescript:
for (i = 0, i < count, i++) {
doSomething();
} // count is a number
But it is always handled as an array.
Is there way to prevent this? I have tried a while loop, but it didnĀ“t work out for me.
Thanks!
First of all, you want to implement this:
for(i = 0; i < count; i++) { ... }
in CoffeeScript, not for(i = 0, ...).
There's an example of this sort of thing right in the documentation:
countdown = (num for num in [10..1])
and the JavaScript version:
var countdown, num;
countdown = (function() {
var _i, _results;
_results = [];
for (num = _i = 10; _i >= 1; num = --_i) {
_results.push(num);
}
return _results;
})();
So you just want to use this:
for i in [1..count]
doSomething()
or
doSomething() for i in [1..count]
Note the the range starts at 1 so that [1..count] gives you count iterations.