Returning value from a recursive function involving Promise - protractor

I am trying to return value from a recursive function involving Promises.
Here's the example method:
getRecursionValue = function(count, i, num, isFound) {
if (i < count && !isFound) {
somePage.someNum.then(function(numVal) {
if (numVal == num) {
console.log('Matched at index: ' + i);
<RETURN VALUE OF I>
} else {
element(by.css('css.for.next.link')).click();
utils.getRecursionValue(count, i + 1, num, false);
}
});
}
}
I am not able to return the value of 'i' correctly! Any suggestions for a way to achieve this?
Thanks,
Sakshi

You are returning from inside a promise but the promise in turn returns nothing to the function. You can solve this by returning the first promise which will in turn return the value of i:
getRecursionValue = function(count, i, num, isFound) {
if (i < count && !isFound) {
return somePage.someNum.then(function(numVal) {
if (numVal == num) {
console.log('Matched at index: ' + i);
<RETURN VALUE OF I>
}

Related

Fixed List is not updating with for loop - Flutter

I've a fixed list reservedGuest. After checking the condition in for loop I want to update the seats if the membership date has expired. The list is not updating. The code is as follows. PS. The List is filled through API on init().
class MyClubController extends GetxController {
List goldLane = List.filled(3, null, growable: false);
void _alterLanesOnContractEnds() {
for (var i in goldLane) {
print("\n\n I: $i");
if (i == null ||
DateTime.parse(i['contractEnds']).isBefore(
DateTime.now(),
)) {
i = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
}
A for-in loop will not allow you to reassign elements of the List. When you do:
for (var i in goldLane) {
// ...
i = null;
}
you are reassigning what the local i variable refers to, not mutating the goldLane List.
You instead can iterate with an index:
void _alterLanesOnContractEnds() {
for (var i = 0; i < goldLane.length; i += 1) {
var element = goldLane[i];
print("\n\n I: $element");
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
goldLane[i] = null;
print('Can be removed');
} else {
print('Cannot be removed');
}
}
update();
}
You can just create a new List where unqualified guests are nullified. For example,
void _alterLanesOnContractEnds() {
goldLane = goldLane.map(
(guest) => guest == null || DateTime.parse(guest['contractEnds']).isBefore(DateTime.now()) ? null: guest
).toList(growable: false);
update();
}
You should not and cannot modify a list while iterating with its iterator.
Elaborated by Jamesdlin,
Modifying the elements of a List while iterating is fine. Modifying
the length of the List while iterating is not, but that won't be a
problem for a non-growable List.
The bottom line is you should not mutate the size of the list while iterating.
I solved it by using
goldLane.forEach(
(element) {
print('\n\n ELEMENT: $element');
if (element == null ||
DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)) {
int ix = goldLane.indexWhere(
(element) => element != null
? DateTime.parse(element['contractEnds']).isBefore(
DateTime.now(),
)
: true,
);
goldLane[ix] = null;
} else {
print('Cannot be removed');
}
},
);
Yet I'll test the other answers. Thank You.

Protractor - How to resolve the promise to get number output

I have the following method in my helper class. I need the method to return the rowNum of Number type. But I always get a Promise when i call the method. I want to see the number when I call the method.
getRowNum(table, colNum, searchText) {
let rowNum = -1;
return table.all(by.css("tbody tr td:nth-child(" + colNum + ")")).map(function (element) {
return element.getText();
}).then(function (textArray) {
for (var i in textArray) {
if (textArray[i].trim().indexOf(searchText) != -1) {
console.log(i);
console.log(textArray[i]);
rowNum = i + 1;
}
}
return rowNum;
});
});
//I'm using it in my other js file like this
let rowNum = helper.getRowNum($("div.sponsor-table table"), 2, "some text");
Have you tried this?
getRowNum = (table, colNum, searchText) => {
let rowNum = -1;
let text;
table.all(by.css("tbody tr td:nth-child(" + colNum + ")")).map(function (element) {
return text = element.getText();
})
.then(function () {
for (var i in text) {
if (text[i].trim().indexOf(searchText) != -1) {
console.log(i);
console.log(text[i]);
rowNum = i + 1;
break;
}
}
return rowNum;
});
};
Let me know if it works

How can i fix my code to make my count value update from my function

How can i make _handlerRadioValuegender() update my count value which I declared as var count = 3 on top.
I tried what i can do and here are all debugprint() functions results. It is now always taking the value which I define on top means my _handler function has no effect on the count value.
var count = 3;
int _handleRadioValuegender(int value) {
setState(() {
_gender = value;
switch (_gender) {
case 0:
debugPrint('case0');
count++;
debugPrint('$count');
break;
case 1:
debugPrint('case1');
this.count++;
this.count++;
debugPrint('$count');
break;
}
});
}
String gender() {
if (count == 1) {
debugPrint('$count');
return 'Male';
} else if (count == 3) {
debugPrint('$count');
return 'Female';
} else {
debugPrint('$count');
}
}
I want my count value to be updated from my _handlerRadioValuegender() function and when gender() access it, then it should return value according to that.Screenshot of debugprints()

How to wait for element.all to get resolved?

I am trying to find index of an item from a listing view. To find out the index I am using this function
function restFunction(appName) {
var indexForItem = 0;
var a = element.all(by.repeater("app in itemList").column("app.itemName")).each(function (element, index) {
element.getText().then(function (name) {
console.log("Name is " + name);
if (name == "sam") {
indexForItem = index + 1;
console.log("Ïndex is " + indexForItem );
a = index;
}
});
});
return a;
}
In protractor how can I wait for the above promise to get resolved. Right now when I call my restFunction I always get promise in pending state
Your code looks incorrect especially, the return value. You are returning the function call - element.all(locator).each(eachFunction) which will return a Promise which will not resolve to anything. Check the documentation here.
Returns
!webdriver.promise.Promise A promise that will resolve when the
function has been called on all the ElementFinders. The promise will
resolve to null.
Though you are re-assigning the value later inside the call, since the mode is async, it doesn't wait till the re-assignment.
You have to change it to return the index directly
function restFunction(appName) {
return element.all(by.repeater("app in itemList").column("app.itemName")).each(function (element, index) {
return element.getText().then(function (name) {
if (name === "sam") {
return (index+1);
}
});
});
}
And when you call the function - You have to resolve the Promise
restFunction('').then(function _resolvePromiseOfCall(value){
console.log('value')
})

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"]);