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

问题描述 投票:34回答:3

我想在Angular 2单元测试中改变一个输入字段的值。

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

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

 private abc: Abc = new Abc();

在Angular 2测试中,我是否可以模拟用户在输入栏中输入,使 ngModel 将会根据用户在单元测试中输入的内容进行更新?

我可以在单元测试中抓取 DebugElementnativeElement 的输入字段没有问题。(只要设置一个 value 上的财产 nativeElement 的输入字段似乎并不奏效,因为它没有更新 ngModel 与我所设置的值)。)

也许 inputDebugEl.triggerEventHandler 可以被调用,但我不知道该给它什么参数,以便它能模拟用户输入了一个特定的输入字符串。

unit-testing testing angular jasmine
3个回答
50
投票

你是对的,你不能只设置输入,你还需要派遣 'input' 事件。这是我今天晚上早些时候写的一个输入文字的函数。

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

这里 fixtureComponentFixtureinputElement 是相关的 HTTPInputElement 从夹具的 nativeElement. 这将返回一个承诺,所以你可能需要解决它的问题。sendInput('whatever').then(...).

在上下文中。https:/github.comtextbookknown-for-webblob52c8aec4c2699c2f146a33c07786e1e32891c8b6srcappactoractor.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();
}

15
投票

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

我让它工作的方法是设置我的测试如下。

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();
  }
});

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

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


4
投票

我也很难让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...
    });
}));
© www.soinside.com 2019 - 2024. All rights reserved.