javascript - test - Documento simulado de prueba de unidad de js angular
text regex javascript (2)
No es necesario que se burle del servicio $document
en tal caso. Es más fácil simplemente usar su implementación real:
describe(''Sample test'', function() {
var myService;
var $document;
beforeEach(function() {
module(''plunker'');
});
beforeEach(inject(function(_myService_, _$document_) {
myService = _myService_;
$document = _$document_;
}));
it(''should append my-directive to body element'', function() {
myService.doTheJob();
expect($document.find(''body'').html()).toContain(''<my-directive></my-directive>'');
});
});
Plunker here .
Si realmente necesitas burlarte de él, supongo que tendrás que hacerlo como lo hiciste:
$documentMock = { ... }
Pero eso puede romper otras cosas que se basan en el servicio $document
(por ejemplo, una directiva que utiliza createElement
).
ACTUALIZAR
Si necesita restaurar el documento a un estado coherente después de cada prueba, puede hacer algo en este sentido:
afterEach(function() {
$document.find(''body'').html(''''); // or $document.find(''body'').empty()
// if jQuery is available
});
Plunker here (tuve que usar otro contenedor, de lo contrario no se mostrarían los resultados de Jasmine).
Como @AlexanderNyrkov señaló en los comentarios, tanto Jasmine como Karma tienen sus propias cosas dentro de la etiqueta del body
, y eliminarlas al vaciar el cuerpo del documento no parece una buena idea.
ACTUALIZACIÓN 2
Me las arreglé para simular parcialmente el servicio $document
para que pueda usar el documento de la página real y restaurar todo a un estado válido:
beforeEach(function() {
module(''plunker'');
$document = angular.element(document); // This is exactly what Angular does
$document.find(''body'').append(''<content></content>'');
var originalFind = $document.find;
$document.find = function(selector) {
if (selector === ''body'') {
return originalFind.call($document, ''body'').find(''content'');
} else {
return originalFind.call($document, selector);
}
}
module(function($provide) {
$provide.value(''$document'', $document);
});
});
afterEach(function() {
$document.find(''body'').html('''');
});
Plunker here .
La idea es reemplazar la etiqueta del body
por una nueva que su SUT pueda manipular libremente y que su prueba se pueda eliminar de manera segura al final de cada especificación.
Estoy tratando de probar el servicio angular que hace algunas manipulaciones a DOM a través del servicio $document
con jasmine. Digamos que simplemente agrega alguna directiva al elemento <body>
.
Tal servicio podría parecer
(function(module) {
module.service(''myService'', [
''$document'',
function($document) {
this.doTheJob = function() {
$document.find(''body'').append(''<my-directive></my directive>'');
};
}
]);
})(angular.module(''my-app''));
Y quiero probarlo así.
describe(''Sample test'' function() {
var myService;
var mockDoc;
beforeEach(function() {
module(''my-app'');
// Initialize mock somehow. Below won''t work indeed, it just shows the intent
mockDoc = angular.element(''<html><head></head><body></body></html>'');
module(function($provide) {
$provide.value(''$document'', mockDoc);
});
});
beforeEach(inject(function(_myService_) {
myService = _myService_;
}));
it(''should append my-directive to body element'', function() {
myService.doTheJob();
// Check mock''s body to contain target directive
expect(mockDoc.find(''body'').html()).toContain(''<my-directive></my-directive>'');
});
});
Entonces la pregunta es ¿cuál sería la mejor manera de crear semejante simulacro?
Las pruebas con document
reales nos darán muchos problemas para limpiar después de cada prueba y no parece una forma de hacerlo.
También intenté crear una nueva instancia de documento real antes de cada prueba, pero terminé con diferentes fallas.
Crear un objeto como el de abajo y verificar whatever
variable que funcione pero se ve muy fea.
var whatever = [];
var fakeDoc = {
find: function(tag) {
if (tag == ''body'') {
return function() {
var self = this;
this.append = function(content) {
whatever.add(content);
return self;
};
};
}
}
}
Siento que me estoy perdiendo algo importante aquí y que estoy haciendo algo muy mal.
Cualquier ayuda es muy apreciada.
Puede crear un documento de prueba vacío utilizando DOMImplementation#createHTMLDocument()
:
describe(''myService'', function() {
var $body;
beforeEach(function() {
var doc;
// Create an empty test document based on the current document.
doc = document.implementation.createHTMLDocument();
// Save a reference to the test document''s body, for asserting
// changes to it in our tests.
$body = $(doc.body);
// Load our app module and a custom, anonymous module.
module(''myApp'', function($provide) {
// Declare that this anonymous module provides a service
// called $document that will supersede the built-in $document
// service, injecting our empty test document instead.
$provide.value(''$document'', $(doc));
});
// ...
});
// ...
});
Debido a que está creando un documento nuevo y vacío para cada prueba, no interferirá con la página que ejecuta las pruebas y no tendrá que limpiar explícitamente el servicio entre las pruebas.