3

I am using the latest angular-cli with angular 2.1. The component test I want to write is simple: Get some data from a service and display it.

It works, when the data ist simply displayed in a paragraph, but it does not, when it is bound to a textarea.

Below is an excerpt from my template:

<p *ngIf="!isBusy" class="twain">
  <i>{{settings.blockLoginMessage}}</i>
</p>
<textarea  
  id="blockLoginMessage" 
  name="blockLoginMessage" 
  [(ngModel)]="settings.blockLoginMessage" 
  class="form-control">
</textarea>

and the corresponding tests:

describe('SettingsComponent', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [SharedModule, TranslateModule.forRoot()],
            declarations: [SettingsComponent],
            providers: [
                Overlay,
                ToastsManager,
                ViewContainerRef,
                TranslateService,
                SettingsService
            ]
        });

        fixture = TestBed.createComponent(SettingsComponent);
        comp = fixture.componentInstance;

        settingsService = fixture.debugElement.injector.get(SettingsService);

        getSettingsSpy = spyOn(settingsService, 'getSettings')
            .and.returnValue(Observable.of(new Settings(true, false, 'test')).delay(500).toPromise());

        setSettingsSpy = spyOn(settingsService, 'setSettings')
            .and.returnValue(Observable.of(true).delay(500));

        fixture.detectChanges(); 
    });

    it('should create the component', () => {
        expect(comp).toBeTruthy();
    });

    it('should show busy indicator as long as there are no settings', () => {
        let busyPanel = fixture.debugElement.query(By.css('#busyPanel'));
        expect(busyPanel).not.toBeNull('cant find busy');
    });

    it('should show loaded settings after observable finished (done)', done => {
        fixture.detectChanges();

        // get the spy promise and wait for it to resolve
        getSettingsSpy.calls.mostRecent().returnValue.then(() => {
            fixture.detectChanges();

            let de = fixture.debugElement.query(By.css('.twain'));
            let el = de.nativeElement;

            expect(el.textContent).toBe('test', 'show loaded settings');

            let de2 = fixture.debugElement.query(By.css('#blockLoginMessage'));
            let el2: HTMLTextAreaElement = de2.nativeElement;

            expect(el2.textContent).toBe('test', 'show loaded settings');

            done();
        });
    });
});

Does anyone have a hint why this does not work?

Furthermore, my attempts with async and fakeAsync fail completely, when I have a delay in my promises like above.

3
  • fixture.isStable() returns false btw Commented Oct 25, 2016 at 5:50
  • Can you post a complete example, preferably just using a dummy component, and service, all posted in one page we can copy and paste and test as is. And please include only what is necessary to reproduce the problem (i.e. no translate module) or anything else that doesn't involve solving the problem of how to test ngModel. This is what an MVCE is Commented Oct 25, 2016 at 6:12
  • pls check Angular 2 Testing: Get Value from ngModel Commented Jul 13, 2017 at 7:16

1 Answer 1

8

ngModel updates asynchronously since RC5. You should test it asynchronous way:

it('should check initial value of ngModel', async(() => {
  let fixture = TestBed.createComponent(TestComponent);
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    let el = fixture.debugElement.query(By.css('select your input'));
    let actual = selectElement.nativeElement.value;
    expect(expected).toBe(actual);
  });
}));
Sign up to request clarification or add additional context in comments.

2 Comments

BTW here is the link to CHANGELOG changes that describe it - github.com/angular/angular/commit/…
Thank you so much. This should be upvoted a thousand times more

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.