angular testing promise within a promise - angularjs

I have code that works. But I have no idea how to test it. A FeeRule has many FeeParameters.
angular.module('feeSuitesApp')
.controller('RootCtrl', [
'FeeSuiteCrud',
'FeeSuite',
'FeeRule',
'FeeParameter',
'feeSuites',
'$scope',
'$q',
function(FeeSuiteCrud, FeeSuite, FeeRule, FeeParameter, feeSuites, $scope, $q){
$scope.feeSuite = feeSuites[0];
if($scope.feeSuite){
getFeeRules().then(function(response){
$scope.feeRules = response;
$scope.feeRules.forEach(function(feeRule){
getFeeParameters(feeRule).then(function(response){
feeRule.parameter_name = response.name
feeRule.parameter_type = response.parameter_type;
});
});
});
}
function getFeeRules(){
var feeCrud = new FeeSuiteCrud(FeeSuite, FeeRule);
return feeCrud.get($scope.feeSuite.id);
}
function getFeeParameters(feeRule){
var feeCrud = new FeeSuiteCrud(FeeParameter);
return feeCrud.get(feeRule.fee_parameter_id);
}
getFeeRules and getFeeParameters return promises from $http.get().
My test:
it("gets feeRules and their feeParameters", function(){
var JSONResponse = {"master":[{"id":30,"fee_suite_id":8,"fee_parameter_id":2,"name":"Discover Fee","multiplier":0.045,"addend":0.0,"order":1,"created_at":"2016-09-27T10:12:26.000-05:00","updated_at":"2016-09-27T10:12:26.000-05:00"}]};
var feeRule = new FeeRule({
id: 30,
name: 'Discover Fee',
fee_suite_id: 8,
fee_parameter_id: 2,
multiplier: 0.045,
addend: 0,
order: 1
});
var feeParameter = new FeeParameter({
id: 2,
fee_type_id: 1,
name: "Discover subtotal",
value: "discover",
parameter_type: "currency"
});
feeRule.parameter_name = feeParameter.name;
feeRule.parameter_type = feeParameter.parameter_type;
$httpBackend.expectGET('/api/v3/fee_suites/8?association=fee_rules').respond(JSONResponse);
JSONResponse = {"id":2,"fee_type_id":1,"name":"Discover subtotal","value":"discover","parameter_type":"currency","created_at":"2016-09-27T10:12:25.000-05:00","updated_at":"2016-09-27T10:12:25.000-05:00"};
$httpBackend.expectGET('/api/v3/fee_parameters/2').respond(JSONResponse);
$rootScope.$digest();
$httpBackend.flush();
expect(scope.feeRules).toEqual([feeRule]);
});
Doesn't seem the second promise gets resolved as I get the following error:
Expected [ FeeRule({ id: 30, name: 'Discover Fee', fee_suite_id: 8,
fee_parameter_id: 2, multiplier: 0.045, addend: 0, order: 1 }) ] to equal [
FeeRule({ id: 30, name: 'Discover Fee', fee_suite_id: 8, fee_parameter_id: 2,
multiplier: 0.045, addend: 0, order: 1, parameter_name: 'Discover subtotal',
parameter_type: 'currency' }) ].

use it twice it will work
$httpBackend.flush();
$httpBackend.flush();
and instead of expect get use when('GET',URL)

Related

How to split my JSON object in angularJS

I am trying to create pagination for my table that lists the objects returned from my DB as an object. My data structure will look something like:
$scope.myJSONObj = {
app1: {
id: 1,
appName: "appIntegrated1",
status: "Pending"
},
app2: {
id: 2,
appName: "appIntegrated2",
status: "Pending"
},
app3: {
id: 3,
appName: "appIntegrated3",
status: "Completed"
},
app4: {
id: 4,
appName: "appIntegrated4",
status: "Pending"
},
app5: {
id: 5,
appName: "appIntegrated5",
status: "Pending"
},
app6: {
id: 6,
appName: "appIntegrated6",
status: "Pending"
},
app7: {
id: 7,
appName: "appIntegrated7",
status: "Pending"
},
app8: {
id: 8,
appName: "appIntegrated8",
status: "Pending"
},
app9: {
id: 9,
appName: "appIntegrated9",
status: "Pending"
},
app10: {
id: 10,
appName: "appIntegrated10",
status: "Pending"
}
I am trying to split my structure in half, and display the first five results. I have a prev/next button, and when I click next, it should display the next 5 results (in this case the last 5). However, for everything to work, I need to be able to split my object, and so far every method I've researched involves arrays, and objects requiring some hack. I was wondering if I was missing something, or I have to create a solution to work with?
In pure JavaScript :
function getEntries(from, to) {
var entries = [];
for(var key in myJSONObj) {
// extract index after `app`
// var index = key.substring(3);
// Better way : extract index using regular expression, so it will match `something1`, `foo2`, `dummy3`
var index = parseInt(key.replace( /^\D+/g, ''));
if(index >= from && index <= to) {
entries.push(myJSONObj[key]);
}
}
return entries;
}
console.log(getEntries(0, 5));
Try _.chunk
https://lodash.com/docs/4.17.4#chunk
$scope.pages = _.chunk($scope.myJSONObj,5);
$scope.getPage = function( pageIndex ){
return $scope.pages[pageIndex];
}
It's untested - but I wrote a chunk method for you in vanilla JS since you can't use lodash.
function chunk(obj, chunkSize) {
var resultArray = [];
var resultArrayCurrentIndex = 0;
for (var key in obj) {
var item = obj[key];
if (resultArray[resultArrayCurrentIndex].length <= chunkSize) {
if (!resultArray[resultArrayCurrentIndex]) {
resultArray[resultArrayCurrentIndex] = [item];
} else {
resultArray[resultArrayCurrentIndex].push(item)
}
} else {
resultArrayCurrentIndex++
resultArray[resultArrayCurrentIndex] = [item];
}
}
return resultArray;
}
Then you can access it like this:
$scope.pages = chunk(yourObject, 5);
$scope.getPage = function(index){
return $scope.pages[index];
}
EDIT - changed it to accept an obj.
Used Object.keys, Array.prototype.slice and Array.prototype.reduce to solve your issue. Hope this helps
angular.module('app',[])
.controller('TestCtrl', function($scope){
$scope.myJSONObj = {"app1":{"id":1,"appName":"appIntegrated1","status":"Pending"},"app2":{"id":2,"appName":"appIntegrated2","status":"Pending"},"app3":{"id":3,"appName":"appIntegrated3","status":"Completed"},"app4":{"id":4,"appName":"appIntegrated4","status":"Pending"},"app5":{"id":5,"appName":"appIntegrated5","status":"Pending"},"app6":{"id":6,"appName":"appIntegrated6","status":"Pending"},"app7":{"id":7,"appName":"appIntegrated7","status":"Pending"},"app8":{"id":8,"appName":"appIntegrated8","status":"Pending"},"app9":{"id":9,"appName":"appIntegrated9","status":"Pending"},"app10":{"id":10,"appName":"appIntegrated10","status":"Pending"}};
$scope.currentPage = 0;
$scope.pageSize = 5;
$scope.totalPage = Math.ceil( Object.keys($scope.myJSONObj).length/$scope.pageSize);
//pageNumber starts from 0 here
$scope.goToPage = function(pageNumber) {
pageNumber = pageNumber>=0?pageNumber:0;
var from = pageNumber*$scope.pageSize;
var to = from + $scope.pageSize;
return Object.keys($scope.myJSONObj).slice(from,to).reduce(function(a,b){
a[b] = $scope.myJSONObj[b];
return a;
},{});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="TestCtrl">
<button ng-disabled="currentPage===0" ng-click="currentPage = currentPage - 1">prev</button>
<button ng-disabled="currentPage===totalPage-1" ng-click="currentPage = currentPage + 1">next</button>
<b>Page: {{currentPage+1}}/{{totalPage}}</b>
<pre>{{goToPage(currentPage) | json}}</pre>
</div>

How we can merge json object together

i have my first function:
$scope.loadDataFromToMonth= function (from,to,year) {
// $scope.loadDataFromToMonthArrivee(from,to,2016);
var url = servername+'admin/dashboard/getIncidentDepartByMonthFromTo/'+from+'/'+to+'/'+year;
// alert(url);
function onSuccess(response) {
console.log("+++++getIncidentDepartByMonthFromTo SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadgetIncidentDepartByMonthFromTo = response.data.data;
var getIncidentDepartByMonthFromTo= $scope.payloadgetIncidentDepartByMonthFromTo;
console.log(JSON.stringify(getIncidentDepartByMonthFromTo));
$scope.data = {}; // new object
$scope.data.datasets = []; // new array in data object ..
$scope.data.labels =[];
var theWholeOb={};
var dataSetObj = {}; //temp object to push into dataset array..
var dataSetObjtwo = {};
/////////////anomalies depart
dataSetObj.data = [];
dataSetObj.label= 'My First dataset';
dataSetObj.fillColor='rgba(220,220,220,0.2)';
dataSetObj.strokeColor= 'rgba(220,220,220,1)';
dataSetObj.pointColor= 'rgba(220,220,220,1)';
dataSetObj.pointStrokeColor= '#fff';
dataSetObj.pointHighlightFill= '#fff';
dataSetObj.pointHighlightStroke='rgba(220,220,220,1)';
getIncidentDepartByMonthFromTo.forEach(function(data) {
var monthNumber = $filter('date')(data.la_date, "MM");
var mun = data.number;
$scope.data.labels.push(monthNumber);
dataSetObj.data.push(mun);
});
$scope.data.datasets.push(dataSetObj);
}
else {
alert("failure");
}
};
function onError(response) {
console.log("-------getIncidentDepartByMonthFromTo FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentDepartByMonthFromTo error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,username,password, 'GET', '').then(onSuccess,onError);
};
this function return this result:
$scope.data = {
labels: ['Jan', 'Feb' 'Jul'],
datasets: [
{
label: 'My First dataset',
fillColor: 'rgba(220,220,220,0.2)',
strokeColor: 'rgba(220,220,220,1)',
pointColor: 'rgba(220,220,220,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(220,220,220,1)',
data: [75, 59, 80, 81, 56, 55]
}
]
};
it works good.
and i have the second function its return the same result but with different data of cours:
$scope.loadDataFromToMonthArrivee= function (from,to,year) {
var url =servername+'admin/dashboard/getIncidentArriveeByMonthFromTo/'+from+'/'+to+'/'+year;
//alert(url);
function onSuccess(response) {
console.log("+++++getIncidentArriveeByDate SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadDayMonthYearData = response.data.data;
var loadedDataByDayMonthYear= $scope.payloadDayMonthYearData;
alert('xxx'+JSON.stringify(loadedDataByDayMonthYear));
$scope.data = {}; // new object
$scope.data.datasets = []; // new array in data object ..
$scope.data.labels =[];
var theWholeOb={};
var dataSetObj = {}; //temp object to push into dataset array..
var dataSetObjtwo = {};
/////////////anomalies arrivee
dataSetObjtwo.data = [];
$scope.date=[];
dataSetObjtwo.label='My Second dataset';
dataSetObjtwo.fillColor= 'rgba(151,187,205,0.2)';
dataSetObjtwo.strokeColor= 'rgba(151,187,205,1)';
dataSetObjtwo.pointColor= 'rgba(151,187,205,1)';
dataSetObjtwo.pointStrokeColor= '#fff';
dataSetObjtwo.pointHighlightFill='#fff';
dataSetObjtwo.pointHighlightStroke= 'rgba(151,187,205,1)';
loadedDataByDayMonthYear.forEach(function(data) {
var monthNumber = $filter('date')(data.la_date, "MM");
$scope.date.push(monthNumber);
var mun = data.number;
$scope.data.labels.push($scope.monthNumber);
dataSetObjtwo.data.push(mun);
});
$scope.data.datasets.push(dataSetObjtwo);
} else {
alert("failure");
}
// $scope.stopSpin('spinner-0');
};
function onError(response) {
console.log("-------getIncidentArriveeByDate FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentArriveeByDate error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,username,password, 'GET', '').then(onSuccess, onError);
};
this function return this result:
$scope.data = {
labels: [ 'Jan', 'Feb' 'Jul','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [
{
label: 'My Second dataset',
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(151,187,205,1)',
data: [ 102, 123, 145, 60, 161]
}
]
};
it works good also, but my question is : how i can declare the second function inside the first function and combine the data returned and get the final result like this:
$scope.data = {
labels: [ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [
{
label: 'My Second dataset',
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(151,187,205,1)',
data: [ 102, 123, 145, 60, 161]
},{
label: 'My First dataset',
fillColor: 'rgba(220,220,220,0.2)',
strokeColor: 'rgba(220,220,220,1)',
pointColor: 'rgba(220,220,220,1)',
pointStrokeColor: '#fff',
pointHighlightFill: '#fff',
pointHighlightStroke: 'rgba(220,220,220,1)',
data: [75, 59, 80, 81, 56, 55]
}
]
};
As long as your objects do only contain arrays you might solve this as follows:
$scope.combineParts = function(part1, part2) {
var merged = angular.copy( part1 );
for ( key in part1 )
{
if ( part2.hasOwnProperty(key) )
merged[key].push.apply(merged[key], part2[key])
}
return merged;
}
Demo in this fiddle: https://jsfiddle.net/gat4co9x/
Hope this helps. ;)
EDIT: To integrate just call the second function in onSuccess of the first, and the combineParts in the onSuccess of the second.
Thisis a bit of easier change for you,first call the $scope.loadDataFromToMonth(params); function and inside that function on success call second function $scope.loadDataFromToMonthArrivee(params); after you prepare $scope.data.
Now don't initialise $scope.data again in $scope.loadDataFromToMonthArrivee(params); and just do this $scope.data.datasets.push(dataSetObjtwo);
I have below provided the similar code so just try using same don't get confused and try anything new but stick to it and after this works you can work on separating labels list from the both objects.
$scope.loadDataFromToMonth= function (from,to,year) {
// $scope.loadDataFromToMonthArrivee(from,to,2016);
var url = servername+'admin/dashboard/getIncidentDepartByMonthFromTo/'+from+'/'+to+'/'+year;
// alert(url);
function onSuccess(response) {
console.log("+++++getIncidentDepartByMonthFromTo SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadgetIncidentDepartByMonthFromTo = response.data.data;
var getIncidentDepartByMonthFromTo= $scope.payloadgetIncidentDepartByMonthFromTo;
console.log(JSON.stringify(getIncidentDepartByMonthFromTo));
$scope.data = {}; // new object
$scope.data.datasets = []; // new array in data object ..
$scope.data.labels =[];
var theWholeOb={};
var dataSetObj = {}; //temp object to push into dataset array..
var dataSetObjtwo = {};
/////////////anomalies depart
dataSetObj.data = [];
dataSetObj.label= 'My First dataset';
dataSetObj.fillColor='rgba(220,220,220,0.2)';
dataSetObj.strokeColor= 'rgba(220,220,220,1)';
dataSetObj.pointColor= 'rgba(220,220,220,1)';
dataSetObj.pointStrokeColor= '#fff';
dataSetObj.pointHighlightFill= '#fff';
dataSetObj.pointHighlightStroke='rgba(220,220,220,1)';
getIncidentDepartByMonthFromTo.forEach(function(data) {
var monthNumber = $filter('date')(data.la_date, "MM");
var mun = data.number;
$scope.data.labels.push(monthNumber);
dataSetObj.data.push(mun);
});
$scope.data.datasets.push(dataSetObj);
$scope.loadDataFromToMonthArrivee(params);//call the second list http call after you prepare first object ...
}
else {
alert("failure");
}
};
function onError(response) {
console.log("-------getIncidentDepartByMonthFromTo FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentDepartByMonthFromTo error condition...");
};
$scope.loadDataFromToMonthArrivee= function (from,to,year) {
var url =servername+'admin/dashboard/getIncidentArriveeByMonthFromTo/'+from+'/'+to+'/'+year;
//alert(url);
function onSuccess(response) {
console.log("+++++getIncidentArriveeByDate SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadDayMonthYearData = response.data.data;
var loadedDataByDayMonthYear= $scope.payloadDayMonthYearData;
alert('xxx'+JSON.stringify(loadedDataByDayMonthYear));
var theWholeOb={};
var dataSetObj = {}; //temp object to push into dataset array..
var dataSetObjtwo = {};
/////////////anomalies arrivee
dataSetObjtwo.data = [];
$scope.date=[];
dataSetObjtwo.label='My Second dataset';
dataSetObjtwo.fillColor= 'rgba(151,187,205,0.2)';
dataSetObjtwo.strokeColor= 'rgba(151,187,205,1)';
dataSetObjtwo.pointColor= 'rgba(151,187,205,1)';
dataSetObjtwo.pointStrokeColor= '#fff';
dataSetObjtwo.pointHighlightFill='#fff';
dataSetObjtwo.pointHighlightStroke= 'rgba(151,187,205,1)';
loadedDataByDayMonthYear.forEach(function(data) {
var monthNumber = $filter('date')(data.la_date, "MM");
$scope.date.push(monthNumber);
var mun = data.number;
$scope.data.labels.push($scope.monthNumber);
dataSetObjtwo.data.push(mun);
});
$scope.data.datasets.push(dataSetObjtwo);
} else {
alert("failure");
}
// $scope.stopSpin('spinner-0');
};
function onError(response) {
console.log("-------getIncidentArriveeByDate FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentArriveeByDate error condition...");
};

Custom store implementing errors

I'm trying to implement custom store with ExtJS 3.4.
I use this forum post with ExtJS4 version.
Now my code looks like this:
Ext.define('TestStore', {
extend: 'Ext.data.Store',
//model: 'TestModel',
fields: [
{name: 'date'},
{name: 'number'},
{name: 'percent'}
],
storeId: 'TestStore',
generateData: function() {
var me = this,
data = [];
// generate 10 records
for( var i=0;i<10;i++) {
data.push([
me.randomDate(new Date(2012, 0, 1), new Date()),
Math.floor( Math.random() * 1000 ),
( ( Math.random() * 1000 ) / 3.2 ).toFixed( 1 )
]);
}
console.log(data);
return data;
},
randomDate: function(start, end) {
return new Date(
start.getTime() + Math.random() * (end.getTime() - start.getTime())
);
},
constructor: function() {
console.log('constructor!');
var me = this;
me.superclass.constructor.apply(me, arguments);
me.loadData(me.generateData(), true);
//me.add(me.generateData());
}
});
And I see this error:
TypeError: this.reader is undefined
Part where my code breaks:
loadData : function(o, append){
var r = this.reader.readRecords(o); <-------
this.loadRecords(r, {add: append}, true);
},
How to correctly set reader? I think I need ArrayReader, but I can't set it properly. I tried so much ways...
Working code for ExtJS 3.4:
App.store.documents.documentsRandomStore = Ext.extend(Ext.data.Store, {
reader: new Ext.data.ArrayReader(
{
idIndex: 0 // id for each record will be the first element
},
//rt // recordType
Ext.data.Record.create([
{name: 'date'},
{name: 'number'},
{name: 'percent'}
])
),
storeId: 'documentsRandomStore',
generateData: function(count) {
var data = [];
// generate records
for(var i=0; i<count; i++) {
data.push([
this.randomDate(new Date(2016, 0, 1), new Date()),
'Документ ' + Math.floor( Math.random() * 100 ),
( ( Math.random() * 1000 ) / 3.2 ).toFixed( 1 )
]);
}
return data;
},
randomDate: function(start, end) {
return new Date(
start.getTime() + Math.random() * (end.getTime() - start.getTime())
);
},
constructor: function(count) {
App.store.documents.documentsRandomStore.superclass.constructor.apply(this, arguments);
this.loadData(this.generateData(count));
}
});

ngChange is not picking up changes from the model

I am trying to access the obj from the select in my controller but the only thing that I end up getting is null and undefined.
<select
ng-change="watchActions(part)"
ng-options="part.serial as part.description for part in rawBaList.items"
ng-model="currentChose"
></select>
$scope.currentChose = null;
$scope.watchActions = function (obj) {
console.log($scope.currentChose);
console.log(obj);
};
$scope.$watch('currentChose', function (newValue, oldValue) {
if(newValue){
console.log("here the new value goes");
}
});
Here is the ex of data:
{
count: 2,
items: [
{serial: 2, description: 'here is some description'},
{serial: 24, description: 'some other description'}
]
}
it was a scope issue, $parent.currentChose fixed it

How to get and compare values in table from another table in angularjs?

I am new at angularjs. So, it might be fool question.Anyway, please let me explain my problem. I have a table which is listed by ng-repeat and I'd like to change a column datas with another datas in another table column.
<tr data-ng-repeat=" list in listTypes">
<td>{{list.Comments}}</td>
<td>{{list.Modul}}</td>
<td>{{list.UserId}}</td>
<td data-ng-repeat="user in userNames">{{user.UserName}}</td>
I want to get UserName instead of UserId, but the problem that UserName is recorded in another table. Here is my angular for getting listTypes :
$scope.GetList = function () {
var onSuccess = function (response, status) {
//1
$scope.listTypes = response.Data;
var str = response.Data;
$scope.listTypes = eval('(' + str + ')');
for (var key in $scope.listTypes) {
$scope.listTypes[key].selected = "";
}
$scope.GetUserNames();
};
var data = null;
var request = $rest.GetList(data);
NGTools.CallNgServiceWithRequest(request, onSuccess, "GetList");
};
And trying to get usernames with this code:
$scope.userdatas= [];
$scope.userNames = [];
$scope.GetUserNames = function () {
var onSuccess = function (response, status) {
//1
$scope.userNames = response.Data;
};
$scope.userdatas= $scope.listTypes.UserId;
var data = { userdatas: JSON.stringify( $scope.userdatas) };
var request = $rest.GetUserNames(data);
NGTools.CallNgServiceWithRequest(request, onSuccess, "GetUserNames");
};
but it doesn't work. I couldn't figure out what's wrong with this code block. Please let me know if any tip is available. Thank you!
Assuming that you have to collections in your scope - one of which holds the id of the user, and the other holding the name, like so:
$scope.users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Doe' },
{ id: 3, name: 'Janice Doe' } ];
$scope.userInfo = [
{ userId: 1, gender: 'male' },
{ userId: 2, gender: 'female' },
{ userId: 3, gender: 'female' }];
Then what you could do is ng-repeat over the one with the userInfo and in your binding expression - use the id to get the name from the other collection:
<li ng-repeat="item in userInfo">
{{ item.gender }} {{ getNameFor(item.userId) }}</li>
Where the getNameFor is defined as:
$scope.getNameFor = function(id) {
var user = $scope.users.filter(function(item) { return item.id === id })[0];
console.log(user);
return user.name;
Which I checked in a fiddle here: http://jsfiddle.net/01kmoxw9/

Resources