ngParty / ng-metadata

Angular 2 decorators and utils for Angular 1.x

Home Page:https://hotell.gitbooks.io/ng-metadata/content/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[$compile:tpload] Failed to load template

ptomaszi opened this issue · comments

The component I am testing is using the "templateUrl" to provide a template:

import { Component, Inject, Input, Output, EventEmitter, OnChanges } from 'ng-metadata/core';

@Component({
    selector: 'diContactList',
    templateUrl: 'src/app/portal/parties/contacts/list/contact-list.component.html'
})
export class ContactListComponent implements OnChanges {

Then I have a corresponding unit test:

import { bundle, getInjectableName, NgModule, Component } from 'ng-metadata/core';

describe('ContactListComponent', () => {
    @Component({
        selector: 'test-component',
        template: `
            <di-contact-list>
            </di-contact-list>`
    })
    class TestComponent {
        constructor() {}
    }
    @NgModule({
        declarations: [TestComponent, ContactListComponent]     
    })
    class TestNgModule { } 
    
    let $compile: ng.ICompileService;
    let $rootScope: ng.IRootScopeService;
    let $scope: ng.IScope;
    let render: IRender<TestComponent>;
    let sut: ContactListComponent;
    
    beforeEach(() => {
        const TestModule: string = bundle(TestNgModule).name;
        ng.mock.module(TestModule);
    });

    beforeEach(ng.mock.inject(function($injector: ng.auto.IInjectorService) {
        $compile = $injector.get<ng.ICompileService>('$compile');
        $rootScope = $injector.get<ng.IRootScopeService>('$rootScope');
        $scope = $rootScope.$new();
        
        render = renderFactory($compile, $scope);
        sut = render(ContactListComponent).ctrl;
    }));

When run I am getting the following error:

Error: [$compile:tpload] Failed to load template: src/app/portal/parties/contacts/list/contact-list.component.html (HTTP status: undefined undefined)
http://errors.angularjs.org/1.6.5/$compile/tpload?p0=src%2Fapp%2Fportal%2Fparties%2Fcontacts%2Flist%2Fcontact-list.component.html&p1=undefined&p2=undefined

When I remove templateUrl or replace with template in the component, unit tests run correctly.

Hello, this shouldn't be any different than testing normal AngularJS components. If you want to test the component template you will need to populate the template cache with the template for that path. Depending on your build system there are several ways you can do that.

https://blog.logentries.com/2015/03/template-caching-in-angular-how-to-avoid-the-storm/

I have found where the issue was. If my component is using the "templateUrl" instead of "template", the render function returns "undefined" for the "ctrl". I have fixed it by modifying "src/testing/utils.js" file and adding "$scope.$digest();" after the $compile:

function renderFactory($compile, $scope) {
    return _compileAndDigest;
    function _compileAndDigest(Directive, _a) {
        var _b = _a === void 0 ? {} : _a, jqHost = _b.jqHost, attrs = _b.attrs, jqChildren = _b.jqChildren;
        var ctrlName = provider_1.getInjectableName(Directive);
        var selector = primitives_1.StringWrapper.kebabCase(ctrlName);
        // is Directive
        if (jqHost) {
            jqHost.attr(selector, '');
        }
        else {
            // is Component
            var hostElement = "<" + selector + "></" + selector + ">";
            jqHost = lang_1.global.angular.element(hostElement);
        }
        // since attributes can be undefined we check them
        if (attrs) {
            jqHost.attr(attrs);
        }
        if (jqChildren) {
            jqHost.append(jqChildren);
        }
        // angular api
        var compiledElement = $compile(jqHost)($scope);
        $scope.$digest();
        var ctrl = compiledElement.controller(ctrlName);
        $scope.$apply();
        return { compiledElement: compiledElement, ctrl: ctrl };
    }
}