5

I have a problem with TestBed in Angular 2.0.0

    beforeEach( async(() => {
        TestBed.configureTestingModule({
            declarations: [
                SomethingComponent
            ]
        }).compileComponents(); // compile template
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SomethingComponent);
        comp = fixture.componentInstance;
    });

    it('test', async(() => {
        fixture.detectChanges();
        expect(true)
    }));

Given the component:

@Component({
    templateUrl: 'app/components/something/something.component.html'
})

I get the error:

Firefox 48.0.0 (Mac OS X 10.11.0)
Failed: Uncaught (in promise): Failed to load app/components/something/something.component.html
resolvePromise@node_modules/zone.js/dist/zone.js:429:31
resolvePromise@node_modules/zone.js/dist/zone.js:414:17
scheduleResolveOrReject/<@node_modules/zone.js/dist/zone.js:462:17
ZoneDelegate.prototype.invokeTask@node_modules/zone.js/dist/zone.js:236:23
ProxyZoneSpec.prototype.onInvokeTask@node_modules/zone.js/dist/proxy.js:96:20
ZoneDelegate.prototype.invokeTask@node_modules/zone.js/dist/zone.js:235:23
Zone.prototype.runTask@node_modules/zone.js/dist/zone.js:136:28
drainMicroTaskQueue@node_modules/zone.js/dist/zone.js:368:25
ZoneTask/this.invoke@node_modules/zone.js/dist/zone.js:308:25

I think it might be because the configuration isnt set up right. I am using gulp to precompile TypeScript into JavaScript, and I have the following project structure:

|_ grails-app
|_ frontend
  |_ angular
    |_ app
    |    |_ components
    |    |     |_ something
    |    |          |_ something.component.ts
    |    |          |_ something.component.html
    |    |_ model
    |    |_ test
    |    |_ app.module.ts
    |    |_ app.routing.ts
    |    |_ main.ts
    |_ assets
    |_ build
    |    |_ app
    |        |_ components
    |        |      |_ something
    |        |          |_ something.component.html
    |        |          |_ something.component.js
    |        |          |_ something.component.js.map
    |        |_      
    |        |_      
    |        |      
    |_ node_modules
    |_ gulpfile.js
    |_ karma.conf.js
    |_ karma-test-shim.js
    |_ systemjs.config
    |_
    |_
    |

But if I assume that the html file is precompiled, and remove the command .compileComponents() from the test, I get the following error:

Firefox 48.0.0 (Mac OS X 10.11.0)
Error: Cannot create the component SomethingComponent as it was not imported into the testing module! 

And if I remove the async, I get this error:

Firefox 48.0.0 (Mac OS X 10.11.0)
Error: This test module uses the component SomethingComponent which is using a "templateUrl", but they were never compiled. Please call "TestBed.compileComponents" before your test. 

In karma-test-shim.js, I have:

System.config({
baseURL: '/base/',
paths: {
    // paths serve as alias
    'npm:': 'node_modules/'
},
map: {
    'app': '/base/build/app/',
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',

    // angular testing umd bundles
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',

    // other libraries
    'rxjs': 'npm:rxjs'
},
packages: {
    'app': {
        defaultExtension: 'js'
    },
    'rxjs': {
        defaultExtension: 'js'
    }
}
});

I hope someone can help me figure out, what Im doing wrong in configuration.

Jarl
  • 2,831
  • 4
  • 24
  • 31
Janett Holst
  • 146
  • 1
  • 5

3 Answers3

4

You can define the base path i karma.conf.js as a proxy:

// Proxied base paths for loading assets
proxies: {
  // required for component assets fetched by Angular's compiler
  "/app/": '/base/build/app/'
},

Source: https://github.com/angular/quickstart

  • For Karma 1.1.2 I had to specify full proxy path, i.e. '/base/app/': '/base/build/app'. – s-f Nov 14 '16 at 10:02
2

I found a solution myself.

beforeEach( async(() => {
    TestBed.configureTestingModule({
        declarations: [
            SomethingComponent
        ]
    })
    .overrideComponent(SomethingComponent, {
        set: {
            templateUrl: '/base/build/app/components/something/something.component.html'
        }}
    )
   .compileComponents(); // compile template
}));

You would think, that you should be able to define the prefix '/base/build/' somewhere. However, I have not been able to locate it yet.

Janett Holst
  • 146
  • 1
  • 5
0

try this . works fine for me. no need to override template and haven't setup any path in karma.

describe('test something', () => {
//mock service if need to or ignore it
    class MockService  {

        getActionOutput(body: string) {
            return Observable.from(['something']);
        }
    }
    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                SomethingComponent
            ],
            imports: [
                // HttpModule, etc.
            ],
            providers: [
                BaseRequestOptions,
                MockBackend,
                {
                    provide: Http,
                    useFactory: function(backend: ConnectionBackend, defaultOptions: BaseRequestOptions) {
                        return new Http(backend, defaultOptions);
                    },
                    deps: [MockBackend, BaseRequestOptions]
                },
                //Mock service if need to or ignore it
                 {provide: SomeService, useClass: MockService}
        ]
        });
        fixture = TestBed.createComponent(SomeComponent);
        component = fixture.componentInstance;
    });
    it('should work something', async(() => {
        expect(component).toBeDefined();
    }));
});

for me it doesnt matter where ur template html is .. unless u want to override it

Anagh Verma
  • 133
  • 10