templateUrl을 사용한 단위 테스트 AngularJS 지시문
templateUrl
정의 된 AngularJS 지시문이 있습니다 . Jasmine으로 단위 테스트를하려고합니다.
내 Jasmine JavaScript는 권장 사항에 따라 다음과 같습니다 .
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');
});
});
});
});
Jasmine 사양 오류에서 이것을 실행하면 다음 오류가 발생합니다.
TypeError: Object #<Object> has no method 'passThrough'
내가 원하는 것은 templateUrl을 그대로로드하는 것입니다-사용하고 싶지 않습니다 respond
. 나는 이것이 사용하여 관련이있을 수 있습니다 생각 ngMock 대신 ngMockE2E을 . 이것이 범인이라면 전자 대신 후자를 어떻게 사용합니까?
미리 감사드립니다!
ngMock과 관련된 것이 맞습니다. ngMock 모듈은 모든 Angular 테스트마다 자동으로로드 되며 템플릿 가져 오기를 포함한 서비스 $httpBackend
사용을 처리하기 위해 모의 를 초기화합니다 $http
. 템플릿 시스템은 템플릿을 통해로드하려고 시도 $http
하고 모형에 "예기치 않은 요청"이됩니다.
$templateCache
Angular가 요청할 때 템플릿을 사용하지 않고 이미 사용할 수 있도록 템플릿을 미리로드하는 방법이 필요합니다 $http
.
선호하는 솔루션 : 카르마
Karma 를 사용 하여 테스트를 실행하는 경우 ng-html2js 프리 프로세서로 템플릿을로드하도록 구성 할 수 있습니다 . Ng-html2js는 지정한 HTML 파일을 읽고을 사전로드하는 Angular 모듈로 변환합니다 $templateCache
.
1 단계 : karma.conf.js
// karma.conf.js
preprocessors: {
"path/to/templates/**/*.html": ["ng-html2js"]
},
ngHtml2JsPreprocessor: {
// If your build process changes the path to your templates,
// use stripPrefix and prependPrefix to adjust it.
stripPrefix: "source/path/to/templates/.*/",
prependPrefix: "web/path/to/templates/",
// the name of the Angular module to create
moduleName: "my.templates"
},
Yeoman 을 사용 하여 앱을 스캐 폴딩하는 경우이 구성이 작동합니다.
plugins: [
'karma-phantomjs-launcher',
'karma-jasmine',
'karma-ng-html2js-preprocessor'
],
preprocessors: {
'app/views/*.html': ['ng-html2js']
},
ngHtml2JsPreprocessor: {
stripPrefix: 'app/',
moduleName: 'my.templates'
},
2 단계 : 테스트에서 모듈 사용
// my-test.js
beforeEach(module("my.templates")); // load new module containing templates
완전한 예를 보려면 Angular 테스트 전문가 Vojta Jina 의이 표준 예를 보십시오 . 여기에는 카르마 구성, 템플릿 및 테스트와 같은 전체 설정이 포함됩니다.
비 카르마 솔루션
어떤 이유로 든 Karma를 사용하지 않고 (레거시 앱에서 융통성없는 빌드 프로세스를 가졌음) 브라우저에서 테스트 $httpBackend
하는 경우 원시 XHR을 사용하여 ngMock의 인수를 처리 하여 실제 템플릿을 가져올 수 있음을 발견했습니다. 에 삽입하십시오 $templateCache
. 이 솔루션은 유연성이 훨씬 떨어지지 만 지금은 작업이 완료됩니다.
// my-test.js
// Make template available to unit tests without Karma
//
// Disclaimer: Not using Karma may result in bad karma.
beforeEach(inject(function($templateCache) {
var directiveTemplate = null;
var req = new XMLHttpRequest();
req.onload = function() {
directiveTemplate = this.responseText;
};
// Note that the relative path may be different from your unit test HTML file.
// Using `false` as the third parameter to open() makes the operation synchronous.
// Gentle reminder that boolean parameters are not the best API choice.
req.open("get", "../../partials/directiveTemplate.html", false);
req.send();
$templateCache.put("partials/directiveTemplate.html", directiveTemplate);
}));
심각하게 생각. Karma를 사용하십시오 . 설정하는 데 약간의 작업이 필요하지만 명령 줄에서 여러 브라우저에서 한 번에 모든 테스트를 실행할 수 있습니다. 따라서 지속적인 통합 시스템의 일부로 사용하거나 편집기에서 바로 가기 키로 만들 수 있습니다. alt-tab-refresh-ad-infinitum보다 훨씬 낫습니다.
내가 한 일은 템플릿 캐시를 가져 와서 뷰를 넣는 것이 었습니다. ngMock을 사용하지 않도록 제어 할 수 없습니다.
beforeEach(inject(function(_$rootScope_, _$compile_, $templateCache) {
$scope = _$rootScope_;
$compile = _$compile_;
$templateCache.put('path/to/template.html', '<div>Here goes the template</div>');
}));
이 초기 문제는 다음을 추가하여 해결할 수 있습니다.
beforeEach(angular.mock.module('ngMockE2E'));
기본적으로 ngMock 모듈 에서 $ httpBackend 를 찾으려고 시도하고 있기 때문에 전체가 아닙니다.
내가 도달 한 솔루션에는 jasmine-jquery.js와 프록시 서버가 필요합니다.
나는 다음 단계를 따랐다.
- karma.conf에서 :
jasmine-jquery.js를 파일에 추가하십시오
files = [
JASMINE,
JASMINE_ADAPTER,
...,
jasmine-jquery-1.3.1,
...
]
비품을 서버에 넣을 프록시 서버 추가
proxies = {
'/' : 'http://localhost:3502/'
};
귀하의 사양에서
describe ( 'MySpec', function () {var $ scope, template; jasmine.getFixtures (). fixturesPath = 'public / partials /'; // 사용자 정의 경로를 사용하여 beforeEach (function 전에 앱에서 사용하는 실제 템플릿을 제공 할 수 있습니다 () {템플릿 = angular.element ( '');
module('project'); inject(function($injector, $controller, $rootScope, $compile, $templateCache) { $templateCache.put('partials/resources-list.html', jasmine.getFixtures().getFixtureHtml_('resources-list.html')); //loadFixture function doesn't return a string $scope = $rootScope.$new(); $compile(template)($scope); $scope.$apply(); }) });
});
앱의 루트 디렉토리에서 서버를 실행하십시오.
python -m SimpleHTTPServer 3502
업장을 실행하십시오.
많은 게시물을 검색 해야하는 것을 이해하는 데 시간이 걸렸습니다.이 문제에 대한 문서는 중요한 문제이므로 명확해야한다고 생각합니다.
내 해결책 :
test/karma-utils.js
:
function httpGetSync(filePath) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/base/app/" + filePath, false);
xhr.send();
return xhr.responseText;
}
function preloadTemplate(path) {
return inject(function ($templateCache) {
var response = httpGetSync(path);
$templateCache.put(path, response);
});
}
karma.config.js
:
files: [
//(...)
'test/karma-utils.js',
'test/mock/**/*.js',
'test/spec/**/*.js'
],
시험:
'use strict';
describe('Directive: gowiliEvent', function () {
// load the directive's module
beforeEach(module('frontendSrcApp'));
var element,
scope;
beforeEach(preloadTemplate('views/directives/event.html'));
beforeEach(inject(function ($rootScope) {
scope = $rootScope.$new();
}));
it('should exist', inject(function ($compile) {
element = angular.element('<event></-event>');
element = $compile(element)(scope);
scope.$digest();
expect(element.html()).toContain('div');
}));
});
Grunt를 사용하는 경우 grunt-angular-templates를 사용할 수 있습니다. templateCache에 템플릿을로드하고 사양 구성에 투명합니다.
내 샘플 구성 :
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
ngtemplates: {
myapp: {
options: {
base: 'public/partials',
prepend: 'partials/',
module: 'project'
},
src: 'public/partials/*.html',
dest: 'spec/javascripts/angular/helpers/templates.js'
}
},
watch: {
templates: {
files: ['public/partials/*.html'],
tasks: ['ngtemplates']
}
}
});
grunt.loadNpmTasks('grunt-angular-templates');
grunt.loadNpmTasks('grunt-contrib-watch');
};
선택한 솔루션과 약간 다른 방식으로 동일한 문제를 해결했습니다.
먼저 karma를 위해 ng-html2js 플러그인을 설치하고 구성했습니다 . karma.conf.js 파일에서 :
preprocessors: { 'path/to/templates/**/*.html': 'ng-html2js' }, ngHtml2JsPreprocessor: { // you might need to strip the main directory prefix in the URL request stripPrefix: 'path/' }
그런 다음 beforeEach에서 작성된 모듈을로드했습니다. Spec.js 파일에서 :
beforeEach(module('myApp', 'to/templates/myTemplate.html'));
그런 다음 $ templateCache.get을 사용하여 변수에 저장했습니다. Spec.js 파일에서 :
var element, $scope, template; beforeEach(inject(function($rootScope, $compile, $templateCache) { $scope = $rootScope.$new(); element = $compile('<div my-directive></div>')($scope); template = $templateCache.get('to/templates/myTemplate.html'); $scope.$digest(); }));
마지막으로 이런 식으로 테스트했습니다. Spec.js 파일에서 :
describe('element', function() { it('should contain the template', function() { expect(element.html()).toMatch(template); }); });
To load the template html dynamically into $templateCache you could just use html2js karma pre-processor, as explained here
this boils down to adding templates '.html' to your files in the conf.js file as well preprocessors = { '.html': 'html2js' };
and use
beforeEach(module('..'));
beforeEach(module('...html', '...html'));
into your js testing file
if you're using Karma, consider using karma-ng-html2js-preprocessor to pre-compile your external HTML templates and avoid having Angular try to HTTP GET them during test execution. I struggled with this for a couple of ours - in my case templateUrl's partial paths resolved during normal app execution but not during tests - due to differences in app vs. test dir structures.
If you are using the jasmine-maven-plugin together with RequireJS you can use the text plugin to load the template content into a variable and then put it in the template cache.
define(['angular', 'text!path/to/template.html', 'angular-route', 'angular-mocks'], function(ng, directiveTemplate) {
"use strict";
describe('Directive TestSuite', function () {
beforeEach(inject(function( $templateCache) {
$templateCache.put("path/to/template.html", directiveTemplate);
}));
});
});
If you use requirejs in your tests then you can use the 'text' plugin to pull in the html template and put it in the $templateCache.
require(["text!template.html", "module-file"], function (templateHtml){
describe("Thing", function () {
var element, scope;
beforeEach(module('module'));
beforeEach(inject(function($templateCache, $rootScope, $compile){
// VOILA!
$templateCache.put('/path/to/the/template.html', templateHtml);
element = angular.element('<my-thing></my-thing>');
scope = $rootScope;
$compile(element)(scope);
scope.$digest();
}));
});
});
I resolve this issue with compiling all templates to templatecache. I'm using gulp, you can find similar solution for grunt too. My templateUrls in directives, modals looks like
`templateUrl: '/templates/directives/sidebar/tree.html'`
Add a new npm package in my package.json
"gulp-angular-templatecache": "1.*"
In gulp file add templatecache and a new task:
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')); });
Add all js files in index.html
<script src="/assets/js/lib.js"></script> <script src="/assets/js/app.js"></script> <script src="/assets/js/templates.js"></script>
Enjoy!
참고URL : https://stackoverflow.com/questions/15214760/unit-testing-angularjs-directive-with-templateurl
'IT박스' 카테고리의 다른 글
C ++에서 파일 크기를 어떻게 얻을 수 있습니까? (0) | 2020.07.12 |
---|---|
Postgres 데이터베이스의 인코딩 가져 오기 (0) | 2020.07.12 |
C # LINQ Select와 동일한 Javascript (0) | 2020.07.12 |
Firebase 메시징, 서버 키를 어디서 구할 수 있습니까? (0) | 2020.07.12 |
ASP.NET의 문자열에서 HTML 태그를 어떻게 제거 할 수 있습니까? (0) | 2020.07.12 |