Sometime scope variable not getting set - angularjs

This seems pretty strange to me but I hope there's someone that has come across this before and point me in the right direction.
I have a variable being set in scope within an $interval and the value is sometimes "sticking" and sometimes not.
someInterval = $interval(function() {
SomeFactory.getsomething($scope.highestnumber)
.then(function(response) {
if (response.number > $scope.highestnumber)
$scope.highestnumber = response.number;
});
}, 30000);
Most of the time this works - $scope.highestnumber is set with the updated value and 30 seconds later getSomething() is called passing the updated value.
However, every now and then (and I wish I could duplicate on demand), $scope.highestnumber is set with a new value but getSomething() is called with the value it had before the update executed. I have verified it by catching the value of $scope.highestnumber after it's been set to the new value, and then checking what's being passed into getSomething() on the next cycle.
So the sequence would be...
$scope.highestnumber = 10
getsomething(10) called
returns response.number = 11
$scope.highestnumber set to 11 (verified)
getSomething(10) called 30 seconds later

Related

changing state before next keydown in react

I am creating a game that when your health goes below 0, on a keydown it prints in a div:
"Game_over_:(_click_to_continue" letter by letter. I was getting a bug where the letters would print out multiple times like ggggaaammmeee ooovvveerr.
I set up a conditional statement where if the state gameOver is 0 and after a keydown event, then it activates the setInterval, else it does not. That solved the problem to some extent, however, the state sometimes changes a second late, and after setting up console.log(this.state.gameOver), it sometimes prints 0 twice before this.state.gameOver actually changes to 1. Other times it works just fine.
if (this.state.gameOver===0){
console.log(this.state.gameOver)
var s1="Game_Over\n:(\nClick_to_continue..."
var v1 =0
var b = document.getElementById("redButton")
var arr1 = setInterval(function(){
if(v1===0){b.innerText=""};b.innerText= b.innerText+s1[v1];v1+=1;
if(v1==s1.length){clearInterval(arr1)}}, 100)
this.setState({gameOver:1})
}
It's still sometimes printing Ggaammee Ovveerr.
So all I had to do was set up a conditional statement that depends on whether a variable is true or false. Once the setInterval function is triggered, the variable changes to false so that more keydowns wont cause multiple calls to setInterval.
var check;
if (check!==false){
check=false;
var arr1 = setInterval(function(){
if(v1===0){b.innerText=""};
b.innerText= b.innerText+s1[v1];v1+=1;
if(v1==s1.length){clearInterval(arr1)}}, 100)}
Once I click the screen with the mouse:
check=true;

Converting HH:MM String into Time Object

In my Ionic AngularJS Project, I have a string called startingTime set as 08:30
I will have a ng-repeat loop which will then make a series of items with an increasing time.
For example , the first item in the list will have 08:30, second item in the list 09:00 etc ( the increment will depend on another variable so its not 30mins every loop )
The problem is I cant seem to turn the string into a Time Object and i get null displayed most of the time if i try the following
$scope.newStartTime = moment(startTime).format('HH-MM');
OR
$scope.newStartTime = var date = new Date(startTime);
So my 2 main questions are.
How do i convert a string "08:30" into a time object ?
After its a time object, how can i make a loop so the time increases by minutes after every loop ?
Thank you.
This method work for me, that transform your startingTime into a MomentObject :
var startingTime = "8:30";
var date = moment(startingTime, "HHmm");`
console.log(date);
plunker demo
For create your timer you can make something like that :
$scope.timer = moment(startingTime,"HHmm");
$scope.setInterval = setInterval(function () { $scope.myTimer(); }, 1000);
$scope.myTimer = function () {
$scope.timer = $scope.timer.add('s', 1);
};

Protractor returning a value from a promise

I'm writing a test to see if my code is removing a level by looking at a text value on the screen which holds the count of levels.
it 'allows deleting level versions', ->
browser.get('/api#/costings')
element(By.id("edit")).click()
startCount = element(By.id("versions_count")).getText().then( (count) ->
return count
)
element(By.id("versions")).click()
first=element.all(By.id("listing")).first()
first.element(By.id("delete")).click()
helper.accept_dialog()
element(By.id("back")).click()
expect(element(By.id("versions_count")).getText()).toEqual(startCount - 1)
Problem here is startCount results in a function. I cannot seem to get startCount into an integer so that I can see if the count has gone down by 1 item.
It gives me the error;
1) edit an existing costing allows deleting level versions
Message:
Expected '1' to equal NaN.
If I try parseInt(startCount) I get the same error.
The variable startCount is a promise, and so startCount - 1 doesn't make sense: there is no automatic type conversion from a promise to its resolved value, so you can't subtract one from it.
What you can do, is create a promise whose resolved value is the expected versions count:
expectedCount = element(By.id("versions_count")).getText().then( (count) ->
return (count - 1).toString();
)
and then you can pass this promise to toEqual, as it automatically unwraps promises at the appropriate point in the control flow
expect(element(By.id("versions_count")).getText()).toEqual(expectedCount)
it("Verify Add Element", function(){
basePage.gotoAssetsPage();
var numberOfElementsBefore = assetsPage.getTotalAssertsNumber();//get text from counter
assetsPage.createAsset(); // add one object on the page
var numberOfElementsAfter = assetsPage.getTotalAssertsNumber(); // get text from counter after creation of object
numberOfElementsBefore.then(function(startNumberText) {
console.log("Number of Asserts before test is " + startNumberText);
return startNumberText;
});
numberOfElementsAfter.then(function(endNumberText) {
console.log("Number of Asserts after test is " + endNumberText);
expect(assertsBefore).toBe((endNumberText-1).toString());
});
});
In this test I'm verifying, that quantity of elements before text will equals quantity of elements after test minus 1.
If I not use .toString(), test result will be: Expect '21' to be 21. So, converting to string works. Maybe someone have a better solution :)

AngularJS' $interval.cancel not working

As stated in the title,
every time I try to use $interval.cancel to cancel an existing interval, it doesn't work.
window.recordedAudio = undefined;
var isRecordingComplete = $interval(function(){
console.log(window.recordedAudio);
if (window.recordedAudio!=undefined) $timeout.cancel(isRecordingComplete);
},100);
$timeout(function(){
window.recordedAudio = "abc";
},2000);
In fact, when window.recordedAudio!= undefined (window.recordedAudio is set to "abc" after 2000ms), the $interval keeps looping and at the same time the
console.log(window.recordedAudio)
keeps being printed (+- 10 times undefined and finally abc but it keeps printing abc rather than just stop).
You are mixing $interval and $timeout.cancel.

AngularJS e2e Testing: How To Get value of repeater().count()?

Problem
Calling repeater('#myTable tr','Rows').count(); returns a Future, not an integer. I need to get the integer value so I can confirm that an additional row was added to a table.
Code
it('should add a new user when save button is clicked',function()
{
showModal();
//here I'm trynig to store the row count of my table into a local variable.
//a future is returned who's 'value' field is undefined.
var memberCount = repeater('#memberTable tr','Member Rows').count();
//this outputs 'undefined'
console.log(memberCount.value);
input('editedMember.name').enter('John');
input('editedMember.grade').enter(5);
input('editedMember.ladderPosition').enter(3);
element('#saveMemberButton').click();
sleep(1);
expect(element(modalId).css('display')).toBe('none');
//here is where I want to do the comparison against the above stored memberCount
expect(repeater('#memberTable tr', 'Member Rows').count()).toBe(memberCount.value + 1);
});
Test Result
Chrome 25.0 e2e should add a new user when save button is clicked FAILED
expect repeater 'Member Rows ( #memberTable tr )' count toBe null
/Users/jgordon/learning/chessClub/web-app/test/e2e/scenarios.js:45:3: expected null but was 6
Chrome 25.0: Executed 2 of 2 (1 FAILED) (1 min 4.117 secs / 1 min 3.773 secs)
Drilling into the source code for Angularjs' e2e support reveals that you have to call execute() on the Future to have it populate its value. Also, when you call execute you have to provide a "done" function to the execute() otherwise Testacular will (oddly enough!) skip your test.
Code
var rowCountFuture = repeater('#memberTable tr','Member Rows').count();
rowCountFuture.execute(function(){
});
var memberCount = rowCountFuture.value;
While I'm jazzed to see this works, I'm concerned there may be some asynchronous bugs that could come out of this, also, I feel like this is a hack and not the right way to do it. Any ideas?
Based on the latest Protractor version:
it('should add a new user when save button is clicked', function() {
var memberCount;
element.all(by.repeater('#memberTable tr','Member Rows')).count().then(function(value) {
memberCount = value;
});
...
// then do all your entering user info, saving etc.
...
browser.refresh(); // or however you want to load new data
expect(element.all(by.repeater('#memberTable tr','Member Rows')).count()).toEqual(memberCount + 1);
});
I've run into the same issue, and have seen confusing results when testing value returned after calling execute(). I've found this method works more reliably:
var getCount = repeater('ul li').count();
getCount.execute(function(value) {
expect(value).toEqual(3);
});
You can do this most easily in the async promise returned by the locator
element.all(By.repeater 'thing in things').then(function(elements){
count = elements.length;
expect(count).toEqual(3);
});

Resources