Tengo una directiva AngularJS que tiene una templateUrl
definida. Estoy tratando de probarlo con Jasmine.
Mi JavaScript de Jasmine se parece a lo siguiente, según la recomendación de esto :
describe('module: my.module', function () {
beforeEach(module('my.module'));
describe('my-directive directive', function () {
var scope, $compile;
beforeEach(inject(function (_$rootScope_, _$compile_, $injector) {
scope = _$rootScope_;
$compile = _$compile_;
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('path/to/template.html').passThrough();
}));
describe('test', function () {
var element;
beforeEach(function () {
element = $compile(
'<my-directive></my-directive>')(scope);
angular.element(document.body).append(element);
});
afterEach(function () {
element.remove();
});
it('test', function () {
expect(element.html()).toBe('asdf');
});
});
});
});
Cuando ejecuto esto en mi error de especificación de Jasmine obtengo el siguiente error:
TypeError: Object #<Object> has no method 'passThrough'
Todo lo que quiero es que la templateUrl se cargue tal cual, no quiero usar respond
. Creo que esto puede estar relacionado con él usando ngMock en lugar de ngMockE2E . Si este es el culpable, ¿cómo uso el último en lugar del primero?
¡Gracias por adelantado!
.passThrough();
de esa manera, pero a partir de la documentación, he intentado algo así como:$httpBackend.expectGET('path/to/template.html'); // do action here $httpBackend.flush();
Creo que este se adapte a su uso mejor - no está queriendo atrapar la solicitud, es decirwhenGet()
, sino comprobar que se envía, y luego en realidad ¿mándalo?expectGET
envíe solicitudes ... al menos fuera de la caja. En los documentos de su ejemplo con/auth.py
tiene una$httpBackend.when
antes de la$httpBackend.expectGET
y$httpBackend.flush
llamadas.expectGet
solo está verificando si se intentó una solicitud.$httpBackend
simulacro que realmente use la URL provista en la directiva debajotemplateUrl
e ir a buscarla. PensépassThrough
que haría esto. ¿Conoces una forma diferente de hacer esto?Respuestas:
Tienes razón en que está relacionado con ngMock. El módulo ngMock se carga automáticamente para cada prueba angular, e inicializa el simulacro
$httpBackend
para manejar cualquier uso del$http
servicio, que incluye la búsqueda de plantillas. El sistema de plantillas intenta cargar la plantilla$http
y se convierte en una "solicitud inesperada" para el simulacro.Lo que necesita es una forma de cargar previamente las plantillas en el
$templateCache
para que ya estén disponibles cuando Angular las solicite, sin usar$http
.La solución preferida: Karma
Si está utilizando Karma para ejecutar sus pruebas (y debería hacerlo), puede configurarlo para cargar las plantillas con el preprocesador ng-html2js . Ng-html2js lee los archivos HTML que especifique y los convierte en un módulo angular que precarga el
$templateCache
.Paso 1: habilite y configure el preprocesador en su
karma.conf.js
Si está utilizando Yeoman para andamiar su aplicación, esta configuración funcionará
Paso 2: usa el módulo en tus pruebas
Para un ejemplo completo, mira este ejemplo canónico del gurú de la prueba angular Vojta Jina . Incluye una configuración completa: configuración de karma, plantillas y pruebas.
Una solución sin karma
Si no usa Karma por alguna razón (tuve un proceso de compilación inflexible en la aplicación heredada) y solo estoy probando en un navegador, he descubierto que puede evitar la adquisición de ngMock
$httpBackend
utilizando un XHR sin procesar para obtener la plantilla de verdad e insértelo en el$templateCache
. Esta solución es mucho menos flexible, pero hace el trabajo por ahora.Hablando en serio. Usa Karma . La configuración requiere un poco de trabajo, pero le permite ejecutar todas sus pruebas, en varios navegadores a la vez, desde la línea de comandos. Por lo tanto, puede tenerlo como parte de su sistema de integración continua y / o puede convertirlo en una tecla de acceso directo de su editor. Mucho mejor que alt-tab-refresh-ad-infinitum.
fuente
preprocessors
patrón de archivo (por ejemplo"path/to/templates/**/*.html"
) a lafiles
sección enkarma.conf.js
.false
parámetro para laopen
llamada de XHR para hacerlo sincrónico. Si no hace eso, la ejecución continuará alegremente y comenzará a ejecutar sus pruebas, sin tener la plantilla cargada. Eso lo lleva de vuelta al mismo problema: 1) Se apaga la solicitud de plantilla. 2) La prueba comienza a ejecutarse. 3) La prueba compila una directiva y la plantilla aún no está cargada. 4) Angular solicita la plantilla a través de su$http
servicio, que se burla. 5) El$http
servicio simulado se queja: "solicitud inesperada".npm install --save-dev karma-ng-html2js-preprocessor
) y agregarlo a la sección de complementos de sukarma.conf.js
, de acuerdo con stackoverflow.com/a/19077966/859631 .Lo que terminé haciendo fue obtener el caché de la plantilla y poner la vista allí. No tengo control sobre no usar ngMock, resulta que:
fuente
Este problema inicial se puede resolver agregando esto:
Eso es porque intenta encontrar $ httpBackend en el módulo ngMock de forma predeterminada y no está lleno.
fuente
La solución a la que llegué necesita jasmine-jquery.js y un servidor proxy.
Seguí estos pasos:
agregue jasmine-jquery.js a sus archivos
agregue un servidor proxy que sirva sus instalaciones
En su especificación
describe ('MySpec', function () {var $ scope, template; jasmine.getFixtures (). fixturesPath = 'public / partials /'; // ruta personalizada para que pueda servir la plantilla real que usa en la aplicación antes de cada función () {template = angular.element ('');
});
Ejecute un servidor en el directorio raíz de su aplicación
python -m SimpleHTTPServer 3502
Ejecuta karma.
Me tomó un tiempo resolver esto, teniendo que buscar muchas publicaciones, creo que la documentación sobre esto debería ser más clara, ya que es un tema tan importante.
fuente
localhost/base/specs
y agregar un servidor proxy con lapython -m SimpleHTTPServer 3502
ejecución reparada. ¡Usted señor es un genio!Mi solución:
test/karma-utils.js
:karma.config.js
:la prueba:
fuente
static
, por ejemplo,beforeEach(preloadTemplate(static_url +'seed/partials/beChartDropdown.html'));
¡Gracias!Si está usando Grunt, puede usar grunt-angular-templates. Carga sus plantillas en templateCache y es transparente a la configuración de sus especificaciones.
Mi configuración de muestra:
fuente
Resolví el mismo problema de una manera ligeramente diferente a la solución elegida.
Primero, instalé y configuré el complemento ng-html2js para karma. En el archivo karma.conf.js:
Luego cargué el módulo creado en beforeEach. En su archivo Spec.js:
Luego usé $ templateCache.get para almacenarlo en una variable. En su archivo Spec.js:
Finalmente, lo probé de esta manera. En su archivo Spec.js:
fuente
Para cargar la plantilla html dinámicamente en $ templateCache, puede usar el preprocesador de karma html2js, como se explica aquí
esto se reduce a agregar plantillas ' .html' a sus archivos en el archivo conf.js, así como preprocesadores = {' .html': 'html2js'};
y use
en su archivo de prueba js
fuente
Uncaught SyntaxError: Unexpected token <
si está usando Karma, considere usar karma-ng-html2js-preprocessor para precompilar sus plantillas HTML externas y evitar que Angular intente HTTP GET durante la ejecución de la prueba. Luché con esto por un par de los nuestros, en mi caso, las rutas parciales de templateUrl se resolvieron durante la ejecución normal de la aplicación, pero no durante las pruebas, debido a las diferencias en las estructuras de directorios de la aplicación frente a la prueba.
fuente
Si está utilizando el complemento jazmín-maven junto con RequireJS, puede usar el complemento de texto para cargar el contenido de la plantilla en una variable y luego colocarlo en el caché de la plantilla.
fuente
Si usa requirejs en sus pruebas, puede usar el plugin 'text' para extraer la plantilla html y ponerla en $ templateCache.
fuente
Resuelvo este problema compilando todas las plantillas en templatecache. Estoy usando gulp, también puedes encontrar una solución similar para gruñir. Mi plantilla se rige en directivas, parece modales
Agregar un nuevo paquete npm en mi package.json
"gulp-angular-templatecache": "1.*"
En el archivo gulp, agregue templatecache y una nueva tarea:
var templateCache = require('gulp-angular-templatecache'); ... ... gulp.task('compileTemplates', function () { gulp.src([ './app/templates/**/*.html' ]).pipe(templateCache('templates.js', { transformUrl: function (url) { return '/templates/' + url; } })) .pipe(gulp.dest('wwwroot/assets/js')); });
Agregue todos los archivos js en index.html
<script src="/assets/js/lib.js"></script> <script src="/assets/js/app.js"></script> <script src="/assets/js/templates.js"></script>
¡Disfrutar!
fuente