问题
I am writing some basic unit tests for my AngularJS app. I have some bindings on the UI with a scope variable inside my directive whichis populated on the completion of a promise.
HTML:
<div id="parent">
<div id="child" ng-repeat="l in aud">
// Other Stuff
</div>
</div>
Directive:
link: function(scope){
service.getArray().$promise.then(function(data){
scope.aud = data;
}
Test:
describe('my module', function () {
var $compile: ICompileService, $rootScope: IScope, directive: JQuery<HTMLElement>;
// Load the myApp module, which contains the directive
beforeEach(angular.mock.module('my-module'));
beforeEach(angular.mock.module(($provide) => {
$provide.service('service', () => {
return {
getArray: () => {
return Promise.resolve(
["item1", "item2"]
);
}
}
});
// Store references to $rootScope and $compile
// so they are available to all tests in this describe block
beforeEach(inject(($httpBackend: IHttpBackendService, _$compile_: ICompileService, _$rootScope_: IRootScopeService) => {
$compile = _$compile_;
$rootScope = _$rootScope_.$new();
directive = $compile('<my-directive></my-directive>')($rootScope)
$rootScope.$apply();
}));
describe('account-utility directive', function () {
it('account utility directive details panel is shown on click', function () {
let list = directive.find("parent"); // Finds this
let listItems = list.find("child"); // Cannot find this. Throws error.
console.log(list); // innerHTML still shows ngrepeat unsubstituted by divs
expect(listItems.length).toBe(2);
});
});
});
I debugged the whole thing and the promise is resolved and the data is assigned to the scope variable 'aud'. However seems like my copy of scope for the test and the app are different. Whats going on here?
回答1:
When the Angular's promise is resolved you need to notify it so it will run its dirty check.
In order to do that you need to invoke $rootScope.apply()
inside yours it
clause.
Think of it like that, your $rootScope.apply()
call in the before each clause invokes your directive's link
function, the that function registers a Promise resolvment in Angulars queue, but it not got processed.
回答2:
beforeEach((done) => {
directive = $compile('<my-directive></my-directive>')($rootScope);
$rootScope.$digest();
setTimeout(() => {
$rootScope.$digest();
done();
});
});
Done helps you wait till all asynchronous tasks are picked up from the stack.
apply()
works too
来源:https://stackoverflow.com/questions/58110497/angularjs-testing-directive-html-not-re-rendered-after-promise-completion