0

I have the following code to invoke angular2

import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { AppModule } from "./src/app";
export function runAngular2App(legacyModel: any) {
       platformBrowserDynamic([
           { provide: "legacyModel", useValue: model }
       ]).bootstrapModule(AppModule)
       .then(success => console.log("Ng2 Bootstrap success"))
       .catch(err => console.error(err));
}

And somewhere I am invoking it like in this manner -

    var legacyModel = {}; // some data
    require(["myAngular2App"], function(app) {
       app.runAngular2App(legacyModel); // Input to your APP
    });

header.component.ts And in my component I use the legacy model -

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

@Component({
  selector: 'app-header',
  encapsulation: ViewEncapsulation.Emulated,
  styleUrls: [ './header.less' ],
  templateUrl: './header.html'
})
export class HeaderComponent {
    public eventTitle;

    constructor(@Inject("appModel") private appModel) {
        this.eventTitle = this.appModel.get("eventTitle");
    }
}

Now the problem is when I am testing this component -

header.component.spec.ts

import {} from 'jasmine';

import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By }              from '@angular/platform-browser';
import { DebugElement }    from '@angular/core';

import { HeaderComponent } from './header.component';



describe('HeaderComponent', () => {

    let comp:    HeaderComponent;
    let fixture: ComponentFixture<HeaderComponent>;
    let de:      DebugElement;
    let el:      HTMLElement;

    // async beforeEach
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ HeaderComponent ] 

        })
        .compileComponents();  // compile template and css
    }));

    // synchronous beforeEach
    beforeEach(() => {
        fixture = TestBed.createComponent(HeaderComponent);

        comp = fixture.componentInstance; // HeaderComponent test instance

        de = fixture.debugElement.query(By.css('.title'));
        el = de.nativeElement;
    });

    it('should display event title', () => {
        fixture.detectChanges();
        expect(el.textContent).toContain(comp.eventTitle);
    });

    it('should display a different event title', () => {
        comp.eventTitle = "Angular2 moderator dashboard";
        fixture.detectChanges();
        expect(el.textContent).toContain("Angular2 moderator dashboard");
    });

});

I get the following error -

Error: No provider for appModel! in spec.bundle.ts (line 4110)

Since appModel is not service I am not able to inject it.

How do I inject appModel so my tests can run?

Ajey
  • 7,924
  • 12
  • 62
  • 86

1 Answers1

0

Behind your implementation question appears to be an architecture question. I see the term "legacy model" -- are you trying to test a new version of a model? Does the component know how to handle both model versions? The Angular service injection pattern is not intended for models, because two different models typically have different interfaces, and thus are ineligible for dependency injection, which requires different implementations to have the same interface.

Depending on the answers to the above questions, I could imagine at least two reasonable paths forward for you:

(1) If you are indeed trying to test two versions of a model, then you should probably forget dependency injection and just use standard imports like:

import { AppModel } from './path/to/appModel';
import { LegacyModel } from './path/to/legacyModel';

Then you can test how the component responds to both model implementations.

(2) If, however, your "models" both really have the same interface, perhaps the single function I can see from your snippets:

get(eventTitle: string)

...then in that case I would introduce a new service here, and have the component invoke the service instead of the model directly. A service is an appropriate level of abstraction when you have multiple implementations, and you can have both a new and a legacy implementation of the service, injected as appropriate for your app or tests (your tests should probably test both implementations until you are ready to retire the legacy version).

Will
  • 6,601
  • 3
  • 31
  • 42