从Angular 2测试中更新输入html字段

Dan*_*iel 31 testing unit-testing jasmine angular

我想在Angular 2单元测试中更改输入字段的值.

<input type="text" class="form-control" [(ngModel)]="abc.value" />
Run Code Online (Sandbox Code Playgroud)

我不能只改变ngModel因为abc对象是私有的:

 private abc: Abc = new Abc();
Run Code Online (Sandbox Code Playgroud)

在Angular 2测试中,我可以模拟用户在输入字段ngModel中键入内容,以便使用用户在单元测试中输入的内容进行更新吗?

我可以毫无问题地抓住输入字段DebugElementnativeElement输入字段.(只是设置了value对房地产nativeElement的输入域的似乎并没有工作,因为它不更新ngModel什么我为值设置).

也许inputDebugEl.triggerEventHandler可以被调用,但是我不确定给它的参数是什么它将模拟用户输入特定的输入字符串.

jon*_*rpe 44

你是对的,不仅可以设置输入,还需要调度'input'事件.这是我今晚早些时候写的一个输入文字的函数:

function sendInput(text: string) {
  inputElement.value = text;
  inputElement.dispatchEvent(new Event('input'));
  fixture.detectChanges();
  return fixture.whenStable();
}
Run Code Online (Sandbox Code Playgroud)

fixtureComponentFixture和夹具inputElement相关HTTPInputElementnativeElement.这会返回一个承诺,因此您可能需要解决它sendInput('whatever').then(...).

在上下文中:https://github.com/textbook/known-for-web/blob/52c8aec4c2699c2f146a33c07786e1e32891c8b6/src/app/actor/actor.component.spec.ts#L134


更新:

我们有一些问题让它在Angular 2.1中工作,它不喜欢创建一个new Event(...),所以我们改为:

import { dispatchEvent } from '@angular/platform-browser/testing/browser-util';

...

function sendInput(text: string) {
  inputElement.value = text;
  dispatchEvent(fixture.nativeElement, 'input');
  fixture.detectChanges();
  return fixture.whenStable();
}
Run Code Online (Sandbox Code Playgroud)

  • 实施此功能时,您还有其他陷阱吗?我正在尝试使该解决方案起作用,但是到目前为止,还没有能够更新模型。我使用的是Angular 2.1.2,因此不确定自从这篇文章以来是否发生了故障/更改。 (2认同)

小智 13

在Angular 2.4中,我接受的解决方案并不适合我.即使在调用了detectChanges()之后,我设置的值也没有出现在(测试)UI中.

我开始工作的方式是设置我的测试如下:

describe('TemplateComponent', function () {
  let comp: TemplateComponent;
  let fixture: ComponentFixture<TemplateComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ FormsModule ],
      declarations: [ TemplateComponent ]
    })
    .compileComponents();
  }));

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

  it('should allow us to set a bound input field', fakeAsync(() => {
    setInputValue('#test2', 'Tommy');

    expect(comp.personName).toEqual('Tommy');
  }));

  // must be called from within fakeAsync due to use of tick()
  function setInputValue(selector: string, value: string) {
    fixture.detectChanges();
    tick();

    let input = fixture.debugElement.query(By.css(selector)).nativeElement;
    input.value = value;
    input.dispatchEvent(new Event('input'));
    tick();
  }
});
Run Code Online (Sandbox Code Playgroud)

我的TemplateComponent组件有一个personName在这个例子中命名的属性,它是我在模板中绑定的模型属性:

<input id="test2" type="text" [(ngModel)]="personName" />


Phi*_*ber 5

我也很难得到 jonrsharpe 的答案以使用 Angular 2.4。我发现调用fixture.detectChanges()fixture.whenStable()导致表单组件重置。测试开始时,似乎某些初始化函数仍在等待中。我通过在每次测试之前添加对这些方法的额外调用来解决这个问题。这是我的代码片段:

beforeEach(() => {
    TestBed.configureTestingModule({
        // ...etc...
    });
    fixture = TestBed.createComponent(LoginComponent);
    comp = fixture.componentInstance;
    usernameBox = fixture.debugElement.query(By.css('input[name="username"]'));
    passwordBox = fixture.debugElement.query(By.css('input[type="password"]'));
    loginButton = fixture.debugElement.query(By.css('.btn-primary'));
    formElement = fixture.debugElement.query(By.css('form'));
});

beforeEach(async(() => {
    // The magic sauce!!
    // Because this is in an async wrapper it will automatically wait
    // for the call to whenStable() to complete
    fixture.detectChanges();
    fixture.whenStable();
}));

function sendInput(inputElement: any, text: string) {
    inputElement.value = text;
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    return fixture.whenStable();
}

it('should log in correctly', async(() => {

    sendInput(usernameBox.nativeElement, 'User1')
    .then(() => {
        return sendInput(passwordBox.nativeElement, 'Password1')
    }).then(() => {
        formElement.triggerEventHandler('submit', null);
        fixture.detectChanges();

        let spinner = fixture.debugElement.query(By.css('img'));
        expect(Helper.isHidden(spinner)).toBeFalsy('Spinner should be visible');

        // ...etc...
    });
}));
Run Code Online (Sandbox Code Playgroud)

  • 即使我不使用 `whenStable`,_magic sauce_ 提示帮助我摆脱了痛苦:我的输入字段在测试期间神秘地保持为空。将 `async` 添加到 `beforeEach(async(() =&gt; { ... component = fixture.componentInstance; fixture.detectChanges(); }));` 使该字段最终被填充。 (2认同)