Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS issue testing AngularJS directives with Karma + Jasmine

I'm using Karma + Jasmine to test my AngularJS directives, I wrote more than 300 tests and I was very happy... until I found an issue that taken me here because I'm stuck: some tests are failing because they need a CSS applied to some elements (a piece of code in my directive does a size computation based on this style), and despite I added the file containing the CSS implementation, this file seems ignored during tests. In my karma config I added the css file in this way:

files: [
     // ..
     'styles/foo.css',
     // ..
],

the settings above generates a link tag in the body rather than head, so I tried to inject the CSS "manually" using js:

angular.element(document).find('head').prepend(
        '<style type="text/css">@charset "UTF-8";' +
        '/* THE STYLE I NEED FOR MY TESTS HERE */' +
        '</style>'
);

but neither this approach seems to work (I tested and the style tag gets injected correctly). I finally tried to add a block of style among the html that I compile using angular $compile:

var element = ng.element('<div>' +
'<style type="text/css">@charset "UTF-8";' +
            '/* THE STYLE I NEED FOR MY TESTS HERE */' +
            '</style>' +
'<my-directive></my-directive>' +
+ '</div>');
$compile(element)(scope);

...but still no lucky... I also tried to switch the test runner from PhantomJS to Chrome, but the problem is the same: styles are somehow ignored (they are injected but they don't get applied to elements, in fact using jQuery(targetElement).css('width') it returns 0)...

so, my big question: how should I import and successfully apply stylesheet in karma tests??? :(

like image 665
daveoncode Avatar asked Sep 03 '14 21:09

daveoncode


2 Answers

Ok, the problem is very simple and stupid... I wonder why I lost so much time to realize it :P So... the CSS are perfectly injected by Karma by specifying them in the config file, like I've done as the first approach (there is no need for other plugin or black magic), but... CSS styles are not applied to elements until they get added to the DOM! and this is not an issue related to karma, angular, jasmine or what else... this is how a browser engine works! A browser parses CSS definitions and it renders elements in the page according, but when in angular test I write:

var element = angular.element('<my-directive></my-directive>');
$compile(element)(scope);

I'm dealing with in-memory DOM nodes, which are unknown to all but my JavaScript code! How should the browser engine apply CSS to an in-memory node living in a js variable? It can't obviously... it can only traverse the nodes tree in the page, so... the "fix" is very simple: I have to add the element to the DOM:

angular.element(document).find('body').append(element);
like image 92
daveoncode Avatar answered Oct 24 '22 18:10

daveoncode


From the sounds of your situation, you're looking to test if the DOM is in a certain state. I found a plugin that looks like it was designed with this use case in mind: jasmine-jquery. Even though you're using AngularJs for your DOM manipulation, this extension will still let you test the resultant DOM's state.

In particular I think you should have a look at the StyleSheet Fixtures which lets you inject CSS in to the test.

Disclaimer: I haven't tested any of this yet, the answer is just the result of research.

like image 31
klyd Avatar answered Oct 24 '22 17:10

klyd