I want to have to function that returns a promise that resolves when the DOM is loaded:
function waitForDom() {
return $q((resolve) => {
$window.addEventListener('DOMContentLoaded', () => {
resolve("yay, i've loaded");
});
})
})
This works just fine running in the browser. However, when I try to test it, the test never finishes as this promise never resolves:
it('some test', (done) => inject(($window, $q, $rootScope) => {
waitForDom()
.then(it => expect(it).toBe("yay, i've loaded"))
.then(done);
$rootScope.$digest();
}));
From what I understand of angular, promises don't resolve (and chain) until you call $digest. This makes it so that you can test angular in a synchronous fashion. I get it. However, the example that I have here should finish, but for some reason it always times out.
I've tried putting the resolve() inside $scope.$apply(), but I get "$digest already in progress".
I've tried putting the $digest inside setTimeout and that gives me a $digest already in progress too, which I'm really confused about. But that's not really the problem.
TLDR How do I get my test to actually finish?
Edit
While I can work around my above example, I'm looking for a general solution for when you resolve a promise inside the body of a DOM event listener, like this:
function appendIframe() {
return $q((resolve) => {
const iframe = $window.document.createElement('iframe');
const iframeParent = $window.document.body;
iframe.src = authUrl;
iframe.onload = function() {
resolve('iframe loaded')
};
iframeParent.appendChild(iframe);
});
})
And no, doing this with jqlite doesn't make a difference.
Use angular.element:
From the Docs: