如何在Angular 2单元测试中触发ngModel模型更新?

Nic*_*ers 7 unit-testing angular

我试图测试包含文本输入元素的组件.我想验证当文本输入的值更改时组件的状态按预期更改.当然,文本输入使用ngModel指令(双向绑定).

虽然组件在运行时工作正常,但我在创建有效的传递测试时遇到了麻烦.我发布了我认为应该在下面工作的内容,以及之后的测试结果.

我究竟做错了什么?

测试:

import {Component} from 'angular2/core';
import {describe, it, injectAsync, TestComponentBuilder} from 'angular2/testing';
import {FORM_DIRECTIVES} from 'angular2/common';
import {By} from 'angular2/platform/common_dom';

class TestComponent {
    static get annotations() {
        return [
            new Component({
                template: '<input type="text" [(ngModel)]="name" /><p>Hello {{name}}</p>',
                directives: [FORM_DIRECTIVES]
            })
        ]
    }
}

describe('NgModel', () => {
    it('should update the model', injectAsync([TestComponentBuilder], tcb => {
        return tcb
            .createAsync(TestComponent)
            .then(fixture => {
                fixture.nativeElement.querySelector('input').value = 'John';
                const inputElement = fixture.debugElement.query(By.css('input'));
                inputElement.triggerEventHandler('input', { target: inputElement.nativeElement });
                fixture.detectChanges();
                expect(fixture.componentInstance.name).toEqual('John');
            });
    }));
});
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Chrome 45.0.2454 (Mac OS X 10.10.5) NgModel should update the model FAILED
    Expected undefined to equal 'John'.
        at /Users/nsaunders/Projects/ng2-esnext-seed/src/test/ngmodel.spec.js!transpiled:41:52
        at ZoneDelegate.invoke (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:322:29)
        at Zone.run (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:218:44)
        at /Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:567:58
        at ZoneDelegate.invokeTask (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:355:38)
        at Zone.runTask (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:254:48)
        at drainMicroTaskQueue (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:473:36)
        at XMLHttpRequest.ZoneTask.invoke (/Users/nsaunders/Projects/ng2-esnext-seed/node_modules/angular2/bundles/angular2-polyfills.js:425:22)
Run Code Online (Sandbox Code Playgroud)

Nic*_*ers 10

这是一种方法:

import {Component} from 'angular2/core';
import {describe, it, inject, fakeAsync, tick, TestComponentBuilder} from 'angular2/testing';
import {FORM_DIRECTIVES} from 'angular2/common';

class TestComponent {
    static get annotations() {
        return [
            new Component({
                template: '<input type="text" [(ngModel)]="name" /><p>Hello {{name}}</p>',
                directives: [FORM_DIRECTIVES]
            })
        ]
    }
}

describe('NgModel', () => {
    it('should update the model', inject([TestComponentBuilder], fakeAsync(tcb => {
        let fixture = null;
        tcb.createAsync(TestComponent).then(f => fixture = f);
        tick();

        fixture.detectChanges();
        let input = fixture.nativeElement.querySelector('input');
        input.value = 'John';
        let evt = document.createEvent('Event');
        evt.initEvent('input', true, false);
        input.dispatchEvent(evt);
        tick(50);

        expect(fixture.componentInstance.name).toEqual('John');
    })));
});
Run Code Online (Sandbox Code Playgroud)

  • 注意:不推荐使用Event.initEvent;您可能想改用Event构造函数。由于PhantomJS,我不得不使用不推荐使用的API。有关更多信息,请参见https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent和https://developer.mozilla.org/en-US/docs/Web/API/Event/Event信息。 (2认同)

Gün*_*uer 3

NgModel 监听该input事件以获取有关更改的通知:

dispatchEvent(inputElement, "input");
tick();
Run Code Online (Sandbox Code Playgroud)

对于其他输入元素,可能会使用其他事件(复选框、单选、选项……)。