简体   繁体   English

如何在断言之前将组件状态与 html-input 同步?

[英]how to synchronise component state with html-input before assertion?

I am trying to test interactions between a components internals and its HTML.我正在尝试测试组件内部与其 HTML 之间的交互。

In the following test code, I have an app-component with an input-field, which is linked to an attribute within the component using two-way binding.在下面的测试代码中,我有一个带有输入字段的应用程序组件,它使用双向绑定链接到组件内的一个属性。

Test1 passes with the use of fixture.detectChanges and waiting it to be stable. Test1 通过使用fixture.detectChanges并等待它稳定。 So, in this test the components test-attribute is synchronised with the input-field.因此,在此测试中,组件测试属性与输入字段同步。

However, test2 fails due to the fact that the compontent has not been updated with the new test-attribute value.但是,由于组件尚未使用新的 test-attribute 值更新,test2 失败。 So, what am I missing or doing wrong to synchronise the changes before entering into the assertion?那么,在进入断言之前,我错过了什么或做错了什么来同步更改?

 import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { test = 'hello'; } import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; import {BrowserModule, By} from '@angular/platform-browser'; import {FormsModule} from '@angular/forms'; import {ComponentFixture} from '../../node_modules/@angular/core/testing'; import {detectChanges} from '../../node_modules/@angular/core/src/render3'; describe('AppComponent', () => { let component: AppComponent; let fixture: ComponentFixture<AppComponent>; beforeEach(() => { TestBed.configureTestingModule({ imports: [ FormsModule ], declarations: [ AppComponent, ], }).compileComponents(); fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; }); it('test1', () => { const inputElement = fixture.debugElement.query(By.css('input')); const el = inputElement.nativeElement; fixture.detectChanges(); fixture.whenStable().then(() => { expect(el.value).toBe('hello'); }) }); it('test2', () => { const inputElement = fixture.debugElement.query(By.css('input')); const el = inputElement.nativeElement; el.value = 'test'; expect(el.value).toBe('test'); el.dispatchEvent(new Event('input')); fixture.detectChanges(); fixture.whenStable().then(() => { expect(component.test).toBe('test'); }) }); });
 <div> <input [(ngModel)]="test" type="text"> <p>{{test}}</p> </div>

I took the answer below and looked at the minimal from the answer to get my test to pass.我接受了下面的答案,并从答案中查看了最少的内容,以使我的测试通过。 The key seems to have been to move the fixture.detectChanges() to the beforeEach() function.关键似乎是将 fixture.detectChanges() 移动到 beforeEach() 函数。

I believe this was the minimum I needed to include for a passing test, in addition to adding the fixture.detectChanges in the beforeEach.除了在 beforeEach 中添加 fixture.detectChanges 之外,我相信这是通过测试所需的最低要求。 It seems that the done and the fixture.whenStable is not necessary.似乎不需要 done 和 fixture.whenStable 。

it('test2', () => {
   const inputElement = fixture.debugElement.query(By.css('input'));
   const el = inputElement.nativeElement;
   el.value = 'test';
   el.dispatchEvent(new Event('input'));
   expect(component.test).toBe('test');
});

I think the issue with your test is that you never initially call fixture.detectChanges() after you set up your fixture and component in your beforeEach .我认为您的测试的问题在于,在您在beforeEach设置fixturecomponent后,您最初从未调用过fixture.detectChanges()

Check this stackblitz for a working version of your test.检查stackblitz 以获取测试的工作版本。

I added a second beforeEach where fixture.detectChanges is called:我添加了第二个beforeEach其中fixture.detectChanges被称为:

beforeEach(() => {
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

And here is the failing (now working) test:这是失败的(现在工作)测试:

it('test2', (done) => {
  const inputElement = fixture.nativeElement.querySelector('input');
  inputElement.value = 'test';

  const inputEvent = document.createEvent('Event');
  inputEvent.initEvent('input', true, true);
  inputElement.dispatchEvent(inputEvent);

  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(component.test).toBe('test');
    done();
  });
});

In the second test, you have to add this:在第二个测试中,您必须添加以下内容:

el.dispatchEvent(new Event('input'));

before doing the expect, and not after在做期望之前,而不是之后

and then you have also to add然后你还必须添加

fixture.detectChanges(); before doing the expect as well在做期望之前

so write your second test like this:所以写你的第二个测试是这样的:

it('test2', async(() => {
    const inputElement = fixture.debugElement.query(By.css('input')).nativeElement;
    inputElement.value = 'test';
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(component.test).toBe('test');
    })
}));

You have to add async to your it function because ngModel is async.您必须将async添加到您的it函数中,因为ngModel是异步的。

Alternatively you can use fakeAsync as well或者,您也可以使用 fakeAsync

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在@input() 变量上使用类型断言? - How to use type assertion on @input() variable? Angular - 接收@Input 时,如何在执行@Input 逻辑之前等待子组件中的其他异步数据 - Angular - When receiving @Input, how to wait for other async data in the children component before executing the @Input logic 将 html 作为输入传递给 angular 组件 - Pass html as an input to an angular component 如何获取JSON数据并在Angular 8输入类型的组件HTML中显示 - How to get JSON data and show in component HTML with input type for Angular 8 如何使用属性绑定将数据传递给 angular html 组件中的输入 - How to pass data to the input in angular html component using property binding 如何在不订阅每个输入/组件角度变化的情况下更新数据更改的摘要状态? - How to update summary state of data changes without subscribing to every input/component change in angular? 子组件输入属性是否在 ngOnInit 之前解析? - Are child component input properties resolved before ngOnInit? 如何从祖父组件更改孙子组件内的 html 输入值 - How to change html input value inside a grandchild component from grandparent component 如何在Angular 6中更改组件的状态? - How to change the state of a component in Angular 6? Angular2 - 在模板之前获取组件html - Angular2 - Get component html before template
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM