我想在Angular 2单元测试中改变一个输入字段的值。
<input type="text" class="form-control" [(ngModel)]="abc.value" />
我不能只改变 ngModel
因为 abc
对象是私有的。
private abc: Abc = new Abc();
在Angular 2测试中,我是否可以模拟用户在输入栏中输入,使 ngModel
将会根据用户在单元测试中输入的内容进行更新?
我可以在单元测试中抓取 DebugElement
和 nativeElement
的输入字段没有问题。(只要设置一个 value
上的财产 nativeElement
的输入字段似乎并不奏效,因为它没有更新 ngModel
与我所设置的值)。)
也许 inputDebugEl.triggerEventHandler
可以被调用,但我不知道该给它什么参数,以便它能模拟用户输入了一个特定的输入字符串。
你是对的,你不能只设置输入,你还需要派遣 'input'
事件。这是我今天晚上早些时候写的一个输入文字的函数。
function sendInput(text: string) {
inputElement.value = text;
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
return fixture.whenStable();
}
这里 fixture
是 ComponentFixture
和 inputElement
是相关的 HTTPInputElement
从夹具的 nativeElement
. 这将返回一个承诺,所以你可能需要解决它的问题。sendInput('whatever').then(...)
.
更新:
我们在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();
}
在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" />
我也很难让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...
});
}));