2013-06-24 4 views
2

Я полный новичок в карме, так что простите меня, если это глупый вопрос.Тестирование директивы angularjs, которая управляет DOM

Я тестирует ДИРЕКТИВОЙ шахты, которая свойственна два способа:

1 - Это условно изменяет шаблон на основе содержания объема и перекомпилирует элемент директивы внутри линкера

var linker = function(scope, element, attrs) { 
//... 

var getTemplate = function(contentType) { 
      var template = ''; 

      switch(contentType) { 
      case 'canvas': 
       template = '<div> stuff here </div>'; 
       break; 
      case 'div': 
       template = '<div> other stuff here </div>'; 
       break; 
       //... 
      } 

      return template; 
     }; 

var html = getTemplate(scope.content.uiType); 
      var ae = angular.element(html); 

      element.replaceWith(ae); 
      $compile(ae)(scope); 

} 

2 - он использует jsplumb в линкере agument элемент директивы и установить некоторые jsplumb конечных точки:

// Inside the linker function 

var outEndPoint = jsPlumb.addEndpoint (ae, { /* parameters */ }, AudioOutPoint); 

проблема возникает, когда jsPlumb.addEndpoint получить называется. Отладка библиотеки, похоже, что в определенный момент jsPlumb использует jQuery для возврата некоторого элемента - того, который он создал - по id, по линиям $ ("# jsplumb-element");

JQuery в свою очередь, выполняет тис строку:

elem = document.getElementById(match[2]); 

и getElementById возвращает нуль (может быть, потому что нет никакого реального DOM?). На данный момент возникает исключение, и все рушится.

Чтобы быть ясным: если я установил точку останова для этого оператора и сделаю document.getElementsByTagName('div'); в консоли, он вернет null.

Я использую Chrome, чтобы проверить эту директиву, и простой тестовый код как таковой:

describe('Directive: hyPluginWindow', function() { 

    beforeEach(module('hyacinthHostApp')); 

    var element, $compile, scope; 

    beforeEach(inject(function(_$compile_, $rootScope) { 
     $compile = _$compile_; 
     scope = $rootScope.$new(); 
    })); 


    it('should set the right audioDestinations', inject(function() { 

     scope.content = { 
      name: "testElement", 
      id: "testElement000", 
      uiType: "canvas", 
      audioIn: 0, 
      audioOut: 1, 
      audioSources: [], 
      audioDestinations: [] 
     }; 

     var grandparent = angular.element('<div id="pluginArea"></div>'); 
     var parent = angular.element('<div class="plugin"></div>'); 
     var element = angular.element('<div hy-plugin-window content="content"></div>'); 
     grandparent.append(parent); 
     parent.append(element); 
     debugger; 
     element = $compile(element)(scope); 

     expect(scope.audioDestinations.length).toBe(1); 

    })); 
}); 

ожидать часть никогда не встречались, потому что директива excepts как только это связано. Обратите внимание, что в приложении этот код работает нормально (поэтому проблема заключается в директиве теста).

Что мне не хватает?

+0

Прощение с очевидным, но вы включили jquery в karma.config.js? Есть некоторая странность, которая может возникнуть в результате jqlite, маскирующего отсутствие jQuery в тестах кармы. –

+0

Да, да. Если я отлаживаю всю партию и вступаю в вызовы функций, инструменты разработчика войдут в код jquery. Проблема в том, что в DOM ничего нет. Если я установил точку останова перед ее разрывом и сделаю 'document.getElementsByTagName ('div');', он вернет 'null'. – janesconference

+1

Хм. В качестве альтернативы использованию getTemplate для условного выбора шаблона HTML вы можете перенести этот переключатель в сам шаблон, используя ng-switch. Кажется, что Карма справляется с этим просто прекрасно, поэтому, если он все еще взорвется, вы, по крайней мере, знаете, что ваша проблема была где-то в другом месте. –

ответ

7

Append элемент в DOM, в тесте, сделать что-то вроде:

grandparent.appendTo(document.body); 

КСТАТИ. плагин, который вы используете, не должен делать document.getElementsByTagName('div') и скорее делать element.find(...). Затем вам не нужно добавлять его в DOM, что ускорит выполнение теста.

+0

Насколько я знаю, jsPlumb делает '$ (" # jsplumb-element ");', который в свою очередь переводит в 'document.getElementById ('jsplumb-element')' внутри jQuery. 'document.getElementsByTagName ('div')' был примером, который я использовал в консоли, чтобы продемонстрировать свою проблему. Думаю, ваша точка все еще стоит. – janesconference

+0

Yep, делая '$ (" # x ");' то же самое - он ищет в документе скорее в корневом элементе. Дело в том, что если он искал в корневом элементе (используя '.find() 'или что-то подобное), вам не нужно было бы добавлять его в DOM, чтобы заставить его работать ... – Vojta

+0

Если только jqLite, но все еще имеет дело с сторонней библиотекой, ищущей документ для id: $ document.find («тело») добавить (элемент). –