Ich habe Code, der Informationen über Filteränderungen speichern sollte. Im Browser $watch
wird der Rückruf jedes Mal ausgelöst, wenn ich den Wert ändere. Wenn ich jedoch versuche, das im Jasmin/Karma-Test zu replizieren, wird es gleich nach der ersten Änderung ausgelöst.
-Controller
var tableFilter = this
;
var init0 = true
;
$scope.$watch('tableFilter.config.period', function() {
console.log('watch');
if (!init0) {
console.log('set dirty');
tbFilterConfig.set('pristine', false);
tbFilterConfig.setDirty('period');
}
init0 = false;
});
-Test
describe('$scope $watch', function() {
it('should add period to dirty after second change', function() {
$scope.$apply(console.log(1), controller.config.period = 'test');
expect(tbFilterConfigObj.get('dirty')).toEqual([]);
$scope.$apply(console.log(2), controller.config.period = 'test2');
expect(tbFilterConfigObj.get('dirty')).toEqual([ 'period' ]);
});
});
Ausgabe in der Konsole:
LOG: 1
LOG: 'watch'
LOG: 2
PhantomJS 1.9.8 (Windows 8 0.0.0) Controller: TableFilterCtrl $scope $watch should add period to dirty after second change FAILED
Expected [ ] to equal [ 'period' ].
at C:/Projects/trackback-network-insight-ui/test/spec/controllers/table_filter.js:74
Aber in Browser:
setTimeout(function () {
$scope.$apply(console.log(1), tableFilter.config.period = 'test');
$scope.$apply(console.log(2), tableFilter.config.period = 'test2');
}, 1000);
Gibt mir:
LOG: watch
LOG: 1
LOG: watch
LOG: set dirty
LOG: 2
LOG: watch
LOG: set dirty
Das Verhalten erwartet wird.
Was ist dann falsch an meinem Test? Danke im Voraus!
EDIT
Voll Controller-Code:
angular.module('insightApp')
.controller('TableFilterCtrl', [ '$rootScope', 'tbConfig', '$scope', '$http', 'API_PATH', 'uiAlerts', 'tbFilterConfig',
function ($rootScope, tbConfig, $scope, $http, API_PATH, uiAlerts, tbFilterConfig) {
var tableFilter = this
, newData = {}
;
/* EXTRACT INITIAL DATA OR LOAD DATA IF TYPE OF DATA IS STRING */
/* FETCH !!SELECT!! DATA FROM API */
function fetchData(url, name) {
return $http.post(API_PATH + url, tbFilterConfig.get())
.success(function (data) {
newData[ name ] = data;
})
.error(function (error) {
uiAlerts.set({
error: 'Ooops! We were unable to get filter data.'
});
console.error(error);
});
}
tableFilter.filters = tbConfig.get('filters');
tableFilter.reports = tbConfig.get('reports');
tableFilter.config = tbFilterConfig.getRaw();
/* RESET VALUES OF ALL DEPENDENT FILTERS */
function resetDependent(name) {
var filters = tbConfig.get('filters')
;
filters.forEach(function (filter) {
if (filter.dependencies && filter.dependencies.indexOf(name) > -1) {
if (tbFilterConfig.get(filter.key) !== filter.defaultVal) {
tbFilterConfig.set(filter.key, filter.defaultVal);
tbFilterConfig.setDirty(filter.key);
}
}
});
}
/* GET INITIAL DATA FOR SELECT OPTIONS */
tableFilter.getData = function (name, data, defaultVal) {
if (!(name in newData)) {
newData[ name ] = [];
if (typeof data === 'string') {
fetchData(data, name);
} else if (typeof data === 'object') {
newData[ name ] = data;
} else {
console.error('Unexpected data type:', typeof data, data);
}
if (!tbFilterConfig.get(name)) {
tbFilterConfig.set(name, defaultVal);
}
var init = true;
$scope.$watch('tableFilter.config.' + name, function() {
if (!init) {
resetDependent(name);
tbFilterConfig.set('pristine', false);
tbFilterConfig.setDirty(name);
}
init = false;
});
}
return newData[ name ];
};
/* WATCH FIXED PROPERTIES: PERIOD, DATE_FROM, DATE_TO */
var init0 = true
, init1 = true
, init2 = true
;
$scope.$watch('tableFilter.config.period', function() {
if (!init0) {
tbFilterConfig.set('pristine', false);
tbFilterConfig.setDirty('period');
}
init0 = false;
});
/* WATCH FIXED PROPERTIES DATE_FORM */
$scope.$watch('tableFilter.config.date_from', function() {
if (!init1) {
tbFilterConfig.set('pristine', false);
tbFilterConfig.setDirty('date_from');
}
init1 = false;
});
/* WATCH FIXED PROPERTIES DATE_TO */
$scope.$watch('tableFilter.config.date_to', function() {
if (!init2) {
tbFilterConfig.set('pristine', false);
tbFilterConfig.setDirty('date_to');
}
init2 = false;
});
/* UPDATE FILTER DATA */
tableFilter.updateSelectData = function (url, name, dependencies) {
if (typeof url === 'string') {
var touched = false;
/* CHECK IF DEPENDENCIES CHANGED */
for (var i = 0; i < dependencies.length; i++) {
if (tableFilter.config.dirty.indexOf(dependencies[ i ]) > -1) {
touched = true;
break;
}
}
/* IF DEPENDENCIES CHANGED GET NEW DATA */
if (touched) {
return fetchData(url, name);
}
}
};
} ]);
und Test:
describe('Controller: TableFilterCtrl', function() {
// load the controller's module
beforeEach(function() {
module('insightApp');
});
var controller
, $scope
, alerts
, tbFilterConfigObj
;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, uiAlerts, tbFilterConfig) {
tbFilterConfigObj = tbFilterConfig;
$scope = $rootScope.$new();
alerts = uiAlerts;
controller = $controller('TableFilterCtrl', {
$scope: $scope
});
$scope.$apply();
}));
describe('$scope $watch', function() {
it('should add period to dirty after second change', function() {
$scope.$apply(console.log(1), controller.config.period = 'test');
expect(tbFilterConfigObj.get('dirty')).toEqual([]);
$scope.$apply(console.log(2), controller.config.period = 'test2');
expect(tbFilterConfigObj.get('dirty')).toEqual([ 'period' ]);
});
});
});
EDIT2
Ich bin für die Code-Qualität leid, aber es ist noch nicht die Produktion.
den zweiten Test mit setTimeout (function() {{expect (tbFilterConfigObj.get ('dirty')) .toEqual (['period']); done();}, 500); und vergessen Sie nicht, die Parameter im Test zu übergeben. – srinivasan
@srinivasan wie es mein Problem lösen soll? –