marcoturi / ionic-boilerplate

✨ An Ionic Starter kit featuring Tests, E2E, Karma, Protractor, Jasmine, Istanbul, Gitlab CI, Automatic IPA and APK, TypeScript 2, TsLint, Codelyzer, Typedoc, Yarn, Rollup, and Webpack 2
MIT License
318 stars 107 forks source link

Unit test: 404 on template urls #17

Closed NelsonBrandao closed 8 years ago

NelsonBrandao commented 8 years ago

Hi,

I integrated the unit test with my project but I keep getting 404 on all component templateUrls. This then fails to compile the component making all test fail.

Any idea why?

marcoturi commented 8 years ago

Could you provide a repo to reproduce the bug? Or at least same code example ?

NelsonBrandao commented 8 years ago

So this are the error messages:

1 11 2016 11:05:21.145:WARN [web-server]: 404: /st-error-message.component.html
(...)

This is the spec:

import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { TestUtils } from '../../../test/test-util';
import { StErrorMessageComponent } from './st-error-message.component';

@Component({
  template: `
    <st-error-message
        [message]="message"
    ></st-error-message>`
})
class TestHostComponent {
    message = "This is a test message";
}

let fixture: ComponentFixture<TestHostComponent> = null;
let element: DebugElement;
let hostInstance: any = null;
let componentInstance: any = null;

describe('Component: StErrorMessage', () => {
    beforeEach(async(() => {
        TestUtils.configureIonicTestingModule([
            TestHostComponent,
            StErrorMessageComponent
        ])
        .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(TestHostComponent);
        hostInstance = fixture.componentInstance;
        element = fixture.debugElement.query(By.css('st-error-message'));
        componentInstance = element.componentInstance;

        fixture.detectChanges();
    });

    it('should instanciate', () => {
        expect(hostInstance).toBeDefined();
    });
});

And the component:

import {
    Component,
    Input
} from '@angular/core';

@Component({
  selector: 'st-error-message',
  templateUrl: 'st-error-message.component.html'
})
export class StErrorMessageComponent {
    @Input() message;
}

The unit test setup is exactly like yours. I was looking at the webpack.test.js and notice that the html rule is a raw-loader, does this load template correctly? Since I'm using templateUrl on the component st-error-message.component.html never gets matched.

marcoturi commented 8 years ago

Ok try this. Do: npm i --save-dev angular2-template-loader

and replace in wepack.test.ts the snippet about awesome-typescript-loader with this:


                /**
                 * Typescript loader support for .ts and Angular 2 async routes via .async.ts
                 *
                 * See: https://github.com/s-panferov/awesome-typescript-loader
                 */
                {
                    test: /\.ts$/,

                    loaders: [
                        `awesome-typescript-loader?sourceMap=${!coverageEnabled},inlineSourceMap=${coverageEnabled},module=commonjs,noEmitHelpers=true,compilerOptions{}=removeComments:true`,
                        'angular2-template-loader'
                    ],
                    // query: {
                    //     // use inline sourcemaps for "karma-remap-coverage" reporter
                    //     sourceMap: !coverageEnabled,
                    //     inlineSourceMap: coverageEnabled,
                    //     module: 'commonjs',
                    //     noEmitHelpers: true,
                    //     compilerOptions: {
                    //         removeComments: true
                    //     }
                    // },
                    exclude: [/\.e2e\.ts$/]
                },

Please, let me know if it fix the issue.

NelsonBrandao commented 8 years ago

Doesn't work, it gives me the same error

marcoturi commented 8 years ago

Ok, so the issue is on the test spec i think. I'm not able to reproduce your issue, so the best I could do for you is to provide same test example I used in my project (based on this boilerplate). NOTE: I'm not testing css/html in my unit tests, as i prefer to test them with protractor.

1° Template:

import { NavMock } from '../../app/app.mocks.spec';
import { MyService } from '../../services/my.service';
import { HomePage } from './home.page';

describe('Home Page:', () => {
    let homePageFixture: HomePage;
  beforeEach(fakeAsync(() => {
        //Notice that I'm using <any> to prevent TS errors
        homePageFixture = new HomePage(<any> MyService, <any> new NavMock());
    }));

    it('Should be defined', () => {
        expect(homePageFixture).toBeDefined();
    });
});

2° Template

import { HelpPage } from './help.page';
import { TestBed, inject} from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { NavParams } from 'ionic-angular';

describe('Help Page:', () => {

    const mockParams: any = new NavParams('myparam');

    beforeEach(() => TestBed.configureTestingModule({
        schemas: [CUSTOM_ELEMENTS_SCHEMA],
        providers: [
            {provide: NavParams, useValue: mockParams},
            HelpPage,
        ],
    }));

    it('Should be defined', inject([HelpPage], (help: HelpPage) => {
        expect(help).toBeDefined();
    }));
});

Hope it helps.

NelsonBrandao commented 8 years ago

It doesn't appears to be related to the spec since it works with the other setup based on rollup

marcoturi commented 8 years ago

Please fork this repo and provide an example, so i could debug the issue.

wh33ler commented 7 years ago

I am interessted in this too. The following test doesn't fail but produces an error in your home.page.spec.ts when added

it('should create register Component', () => 
        TestBed.compileComponents().then(() => {
            var fixture = TestBed.createComponent(HomePage);
            fixture.detectChanges();
            var compiled = fixture.debugElement.componentInstance;
            expect(compiled).toBeTruthy();    
        })        
    );

ERROR: 'Unhandled Promise rejection:', 'Cannot create the component HomePage as it was not imported into the testing module!', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', Error{line: 13311, sourceURL: 'http://localhost:9880/base/config/karma-shim.js?ad71ec8f54dc5e81691ee14fa6222281346227e3', stack: 'createComponent@http://localhost:9880/base/config/karma-shim.js?ad71ec8f54dc5e81691ee14fa6222281346227e3:13311:140...

marcoturi commented 7 years ago

@wh33ler Use this template instead:

    let comp: HomePage;
    let fixture: ComponentFixture<HomePage>;
    let de: DebugElement;

    beforeEach(() => {
        TestBed.configureTestingModule({
            schemas: [CUSTOM_ELEMENTS_SCHEMA],
            declarations: [HomePage],
            providers: [
                {provide: NavController, useValue: NavController},
            ],
        });
        fixture = TestBed.createComponent(HomePage);
        // #trick
        // fixture.componentInstance.ionViewWillEnter();
        fixture.detectChanges();
        comp = fixture.componentInstance;
        de = fixture.debugElement;
    });

Than in your "it" statements use "comp" to access to the component.

wh33ler commented 7 years ago

thanks for the quick reply: If I use your suggestion I get the following error Error: This test module uses the component HomePage which is using a "templateUrl", but they were never compiled. Please call "TestBed.compileComponents" before your test. in config/karma-shim.js (line 13231).....

marcoturi commented 7 years ago

@wh33ler Latest commit fix the issue about templateUrl not compiled. I also added a working example in home.page.spec.ts

wh33ler commented 7 years ago

thanks a lot for the quick help. This fixed my problem I am having for a day now. Just one adjustment I had to do in my more complex Page is to remove the detectChanges call on the fixture at that time. Just wanted to let you know. Btw thanks a lot for the great boilerplate. Made our project structure a lot better. Keep it up 👍