Mam dyrektywę AngularJS, która ma templateUrl
zdefiniowany plik . Próbuję przetestować to z Jasmine.
Moja Jasmine JavaScript wygląda jak poniżej, na zalecenie to :
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');
});
});
});
});
Kiedy uruchamiam to w moim błędzie specyfikacji Jasmine, pojawia się następujący błąd:
TypeError: Object #<Object> has no method 'passThrough'
Wszystko, czego chcę, to załadowanie templateUrl bez zmian - nie chcę go używać respond
. Myślę, że może to być związane z używaniem ngMock zamiast ngMockE2E . Jeśli to jest winowajca, jak mam użyć tego drugiego zamiast pierwszego?
Z góry dziękuję!
.passThrough();
tego w ten sposób, ale z dokumentacji, czy próbowałeś czegoś takiego:$httpBackend.expectGET('path/to/template.html'); // do action here $httpBackend.flush();
Myślę, że to lepiej pasuje do twojego użycia - nie chcesz przechwytywać żądania, tj.whenGet()
, Ale zamiast tego sprawdź, czy zostało wysłane, a następnie faktycznie Wyślij to?expectGET
wysyłało to prośby ... przynajmniej po wyjęciu z pudełka. W dokumentach ich przykład/auth.py
ma$httpBackend.when
przed$httpBackend.expectGET
i$httpBackend.flush
wywołuje.expectGet
wystarczy sprawdzić, czy próbowano wykonać żądanie.$httpBackend
makiecie, aby faktycznie używał adresu URL podanego w dyrektywietemplateUrl
i pobierał go. Myślałem, żepassThrough
to zrobię. Czy znasz inny sposób, aby to zrobić?Odpowiedzi:
Masz rację, że jest to związane z ngMock. Moduł ngMock jest automatycznie ładowany dla każdego testu Angular i inicjuje makietę w
$httpBackend
celu obsługi dowolnego użycia$http
usługi, w tym pobierania szablonu. System szablonów próbuje załadować szablon$http
i staje się to „nieoczekiwanym żądaniem” do makiety.Potrzebujesz sposobu, aby wstępnie załadować szablony do pliku, aby
$templateCache
były już dostępne, gdy Angular o nie poprosi, bez użycia$http
.Preferowane rozwiązanie: Karma
Jeśli używasz Karmy do uruchamiania testów (a powinieneś), możesz skonfigurować ją tak, aby ładowała szablony za pomocą preprocesora ng-html2js . Ng-html2js odczytuje określone pliki HTML i konwertuje je na moduł Angular, który wstępnie ładuje
$templateCache
.Krok 1: Włącz i skonfiguruj preprocesor w swoim
karma.conf.js
Jeśli używasz Yeoman do tworzenia szkieletów swojej aplikacji, ta konfiguracja będzie działać
Krok 2: Użyj modułu w swoich testach
Aby uzyskać pełny przykład, spójrz na ten kanoniczny przykład autorstwa guru testów Angulara, Vojty Jiny . Obejmuje całą konfigurację: konfigurację karmy, szablony i testy.
Rozwiązanie niezwiązane z karmą
Jeśli z jakiegoś powodu nie używasz Karmy (miałem nieelastyczny proces kompilacji w starszej aplikacji) i testujesz tylko w przeglądarce, odkryłem, że możesz obejść przejęcie ngMocka,
$httpBackend
używając surowego XHR, aby pobrać szablon naprawdę i włóż go do$templateCache
. To rozwiązanie jest znacznie mniej elastyczne, ale na razie wykonuje swoje zadanie.Ale naprawdę. Użyj Karmy . Konfiguracja wymaga trochę pracy, ale pozwala na uruchomienie wszystkich testów w wielu przeglądarkach jednocześnie z wiersza poleceń. Możesz więc mieć to jako część swojego systemu ciągłej integracji i / lub możesz uczynić z niego klawisz skrótu w swoim edytorze. Znacznie lepsze niż alt-tab-refresh-ad-infinitum.
źródło
preprocessors
wzorca pliku (np."path/to/templates/**/*.html"
) Dofiles
sekcji wkarma.conf.js
.false
parametruopen
wywołania XHR, aby uczynić go synchronicznym. Jeśli tego nie zrobisz, wykonanie będzie wesoło kontynuowane i rozpocznie wykonywanie testów, bez ładowania szablonu. To prowadzi z powrotem do tego samego problemu: 1) Żądanie szablonu zostaje wysłane. 2) Rozpocznie się wykonywanie testu. 3) Test kompiluje dyrektywę, a szablon nadal nie jest załadowany. 4) Angular żąda szablonu za pośrednictwem swojej$http
usługi, która jest wyszydzana. 5) Pozorowana$http
usługa narzeka: „nieoczekiwane żądanie”.npm install --save-dev karma-ng-html2js-preprocessor
) i dodać go do sekcji wtyczekkarma.conf.js
, zgodnie ze stackoverflow.com/a/19077966/859631 .Skończyło się na tym, że pobrałem pamięć podręczną szablonów i umieściłem tam widok. Nie mam kontroli nad tym, jak nie używam ngMock, okazuje się:
źródło
Ten początkowy problem można rozwiązać, dodając:
Dzieje się tak , ponieważ domyślnie próbuje znaleźć $ httpBackend w module ngMock i nie jest pełny.
źródło
Rozwiązanie, do którego doszedłem, wymaga jasmine-jquery.js i serwera proxy.
Wykonałem następujące kroki:
dodaj jasmine-jquery.js do swoich plików
dodaj serwer proxy, który będzie obsługiwał twoje urządzenia
W twojej specyfikacji
opisać ('MySpec', function () {var $ scope, template; jasmine.getFixtures (). fixturesPath = 'public / parts /'; // niestandardowa ścieżka, dzięki czemu możesz podać rzeczywisty szablon, którego używasz w aplikacji beforeEach (function () {szablon = angular.element ('');
});
Uruchom serwer w katalogu głównym aplikacji
python -m SimpleHTTPServer 3502
Uruchom karmę.
Zajęło mi trochę czasu, zanim to rozgryzłem, przeszukując wiele postów, myślę, że dokumentacja na ten temat powinna być bardziej przejrzysta, ponieważ jest to tak ważna kwestia.
źródło
localhost/base/specs
i dodaniem serwera proxy popython -m SimpleHTTPServer 3502
uruchomieniu go. Pan jest geniuszem!Moje rozwiązanie:
test/karma-utils.js
:karma.config.js
:test:
źródło
static
, np.beforeEach(preloadTemplate(static_url +'seed/partials/beChartDropdown.html'));
Dzięki!Jeśli używasz Grunt, możesz użyć szablonów grunt-kątowych. Ładuje szablony w templateCache i jest przejrzysty dla konfiguracji specyfikacji.
Moja przykładowa konfiguracja:
źródło
Ten sam problem rozwiązałem w nieco inny sposób niż wybrane rozwiązanie.
Najpierw zainstalowałem i skonfigurowałem wtyczkę ng-html2js dla karmy. W pliku karma.conf.js:
Następnie załadowałem moduł utworzony w beforeEach. W pliku Spec.js:
Następnie użyłem $ templateCache.get, aby zapisać go w zmiennej. W pliku Spec.js:
Wreszcie przetestowałem to w ten sposób. W pliku Spec.js:
źródło
Aby dynamicznie załadować szablon html do $ templateCache, możesz po prostu użyć preprocesora karmy html2js, jak wyjaśniono tutaj
sprowadza się to do dodania szablonów „ .html” do plików w pliku conf.js, a także preprocessors = {' .html': 'html2js'};
I użyć
do pliku testowego js
źródło
Uncaught SyntaxError: Unexpected token <
jeśli używasz Karmy, rozważ użycie preprocesora karma-ng-html2js do wstępnej kompilacji zewnętrznych szablonów HTML i unikaj próbowania przez Angulara pobierania ich przez HTTP podczas wykonywania testu. Miałem z tym problem przez kilka naszych - w moim przypadku częściowe ścieżki templateUrl rozwiązały się podczas normalnego wykonywania aplikacji, ale nie podczas testów - z powodu różnic w strukturach aplikacji i katalogu testowego.
źródło
Jeśli używasz wtyczki jasmine-maven-plugin razem z RequireJS, możesz użyć wtyczki tekstowej do załadowania zawartości szablonu do zmiennej, a następnie umieszczenia jej w pamięci podręcznej szablonów.
źródło
Jeśli używasz requirejs w swoich testach, możesz użyć wtyczki 'text', aby pobrać szablon html i umieścić go w $ templateCache.
źródło
Rozwiązuję ten problem, kompilując wszystkie szablony do templatecache. Używam łyka, podobne rozwiązanie można znaleźć też na chrząknięcie. Moje templateUrls w dyrektywach, wygląda jak modały
Dodaj nowy pakiet npm do mojego pliku package.json
"gulp-angular-templatecache": "1.*"
W pliku gulp dodaj szablon templatecache i nowe zadanie:
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')); });
Dodaj wszystkie pliki js w index.html
<script src="/assets/js/lib.js"></script> <script src="/assets/js/app.js"></script> <script src="/assets/js/templates.js"></script>
Cieszyć się!
źródło