2015-02-09 10 views
5

Sto provando a testare una direttiva AngularJS usando Jasmine. La direttiva ha lo scopo di aggiungere elementi SVG al modello nella fase postLink usando D3js. Questo funziona bene nell'applicazione reale.Unit test Direttiva AngularJS, postLink D3 che non cambia DOM

Nel test dell'unità sembra che il codice D3 non venga mai eseguito.

Questa è una versione semplificata del codice che riproduce l'errore ancora:

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'); 
    } 
    }; 
}); 

Questo è il test dell'unità:

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>'); 
    }); 

}); 

L'errore che ricevo è:

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>'. 

La mia aspettativa è sbagliata su come posso testare le modifiche del DOM effettuate da D3? Come posso testarlo meglio?

+0

Ehi, a me la linea element = $ compile (elemento) (scope); sembra strano. È intenzionale? Sembra che tu voglia passare l'ambito come parametro. – Codebryo

+0

nm, apparentemente quello scrive. Ma nella pagina AnuglarJS usano scope. $ Digest(); insted di applicare. $ digest innesca un ciclo tutto nuovo ov tutto quando ricordo correttamente – Codebryo

+0

https://docs.angularjs.org/guide/unit-testing#testing-directives – Codebryo

risposta

7

il problema è molto semplice. Il metodo d3.select sta cercando l'elemento nello window.document. Nel tuo caso di test il tuo elemento si trova in un elemento dom detached e non fa parte di window.document.

Per risolvere questo problema è possibile ottenere il nodo direttamente tramite l'elemento della direttiva anziché utilizzare un selettore globale.

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

Nota: questo codice funziona con angular + jQuery. Se non si utilizza jQuery all'interno del progetto, potrebbe essere necessario adattare il selettore perché in questo caso si è limitati alla ricerca per nome del tag. https://docs.angularjs.org/api/ng/function/angular.element

+0

Wow mi ha salvato la vita. Ho quasi completamente rinunciato a testare questo codice d3. Si rattrista quando qualcosa di così semplice può causare così tanto angoscia. Ma immagino che sia quello a cui mi sono iscritto quando ho scelto questo campo. –

Problemi correlati