How to check the visibility of an element with angular directive testing?
I am trying to write a simple test for my angularjs directive.
The directive wraps div
in another div
, creates a second child to show "LOADING", and chooses which child to display with $scope.ready
. Thus, the original HTML code might look like this:
<loading>
<div>This is my data</div>
</loading>
And the HTML after running the directive will look like this:
<div>
<div ng-show="ready">
<div>This is my data</div>
</div>
<div ng-show="!ready">
LOADING
</div>
</div>
The directive works when launched in browsers. I wrote a unit test (mocha + shouldjs, but might be fine with jasmine + expect) like this:
describe('loading', function(){
var scope, element, loading, wrapper, parent;
beforeEach(function () {
inject(function ($compile,$rootScope) {
scope = $rootScope;
wrapper = $($compile('<div id="a"><loading><div id="b">RUN</div></loading></div>')($rootScope));
element = wrapper.find("#b");
parent = element.parent();
loading = wrapper.children("div").children("div:eq(1)");
});
});
it('should wrap the element with loading', function(){
wrapper.children("div").children("div:eq(0)").children("div")[0].should.equal(element[0]);
});
it('should create the loading element', function(){
loading.html().should.eql("Loading");
});
describe('when ready is false', function(){
before(function () {
scope.ready = false;
});
it('should show the loading element', function(){
loading.is(":visible").should.be.true;
});
it('should hide the actual element', function(){
element.is(":visible").should.be.false;
});
});
describe('when ready is true', function(){
it('should hide the loading element', function(){
loading.is(":visible").should.be.false;
});
it('should show the actual element', function(){
element.is(":visible").should.be.true;
});
});
});
Final work, all HTML added and wrapped correctly. But the elements are not visible. Errors (truncated):
Chrome 37.0.2062 (Mac OS X 10.9.5) loading directives when ready false should show the FAILED loading element
AssertionError: false is expected to be true
Administering Chrome 37.0.2062 directives (Mac OS X 10.9.5) when ready is true should show the actual item FAILED
AssertionError: false is expected to be true
Chrome 37.0.2062 (Mac OS X 10.9.5): Done 7 of 7 (2 FAULTS) (0.235 secs / 0.048 sec)
Note: yes, I have included jQuery in my test suite, so I can do above element.is()
and the like. Of course it doesn't work, so an easier way that actually works is always welcome.
UPDATE:
Based on the information below from @Esteban I simplified it, but it still doesn't work. The change $scope.ready = true
seems to prevent angular from handling the element. Fiddle here:
source to share
Using jasmine-jquery:
I have used jasmine-jquery in the past and have used the attachment system so that elements are actually added to the DOM and you can check situations like this. It will also clear your DOM after each test for you, so you don't have to worry about messy DOM after each test.
See updated example:
function ($compile,$rootScope) {
scope = $rootScope;
wrapper = $($compile('<div id="a"><loading><div id="b">RUN</div></loading></div>')($rootScope));
element = wrapper.find("#b");
jasmine.appendSetFixtures(element);
parent = element.parent();
loading = wrapper.children("div").children("div:eq(1)");
});
Then, to test, you can:
describe('when ready is false', function(){
before(function () {
scope.ready = false;
});
it('should show the loading element', function(){
expect(loading).toBeVisible();
});
it('should hide the actual element', function(){
expect(element).not.toBeVisible();
});
});
Alternative:
You can also check for the existence of a class ng-hide
:
expect(loading.hasClass('ng-hide')).toBe(false);
source to share