2015-02-09 66 views
5

我想單元測試使用茉莉花的AngularJS指令。該指令旨在使用D3js在後鏈接階段將SVG元素添加到模板中。這在實際應用中可以正常工作。單元測試AngularJS指令,postlink D3不改變DOM

在單元測試中,似乎D3代碼從未執行過。

這是代碼的簡化版本,仍然再現錯誤:

angular.module('app', []); 

angular.module('app').directive('d3Test', function() { 
    return { 
    template: '<div id="map"></div>', 
    restrict:'E', 
    scope: { 
     someAttr: '@', 
    }, 
    link: function postLink(scope, element, attrs) { 

     d3.select('#map').append('svg'); 
    } 
    }; 
}); 

這是單元測試:

describe('directive test', function() { 

    var element, scope; 

    beforeEach(module('app')); 

    beforeEach(inject(function ($rootScope, $compile) { 
    scope = $rootScope.$new(); 
    element = '<d3-test></d3-test>'; 
    element = $compile(element)(scope); 
    scope.$apply(); 
    })); 

    it('should have an SVG child element', function() { 
    expect(element.html()).toEqual('<div id="map"><svg></svg></div>'); 
    }); 

}); 

我收到的錯誤是:

PhantomJS 1.9.8 (Mac OS X) directive test should have an SVG child element FAILED 
    Expected '<div id="map"></div>' to equal '<div id="map"><svg></svg></div>'. 

我的期望錯了,我該如何測試D3會改變的DOM變化? 我該如何最好地測試這個?

+0

嘿,對我來說行 element = $ compile(element)(scope); 看起來很奇怪。那是intendend嗎?它看起來像你想通過範圍作爲參數。 – Codebryo 2015-02-10 11:07:38

+0

nm,顯然是寫。但是在AnuglarJS頁面上,他們使用範圍。$ digest(); insted的適用。 $摘要觸發一個全新的循環ov當我記得正確時,所有東西 – Codebryo 2015-02-10 11:12:43

+0

https://docs.angularjs.org/guide/unit-testing#testing-directives – Codebryo 2015-02-10 11:13:37

回答

7

問題很簡單。 d3.select方法正在搜索window.document中的元素。 在您的測試案例中,您的元素位於分離的dom元素而不是window.document的一部分。

要解決此問題,您可以直接通過指令的元素而不是使用全局選擇器來獲取節點。

d3.select(element.find('div#map')[0]).append('svg'); 

注意:此代碼適用於angular + jQuery。如果您在項目中不使用jQuery,則可能需要修改選擇器,因爲那樣您的搜索將受限於查找標記名稱。 https://docs.angularjs.org/api/ng/function/angular.element

+0

哇這救了我的命。我幾乎完全放棄了測試這個D3代碼。當這麼簡單的事情會引起如此多的心痛時,它會令人傷心。但我想那是我選擇這個領域時註冊的。 – 2016-04-14 18:11:55