【问题标题】:Angular 4 ngModel not updated after input change in tests测试中的输入更改后Angular 4 ngModel未更新
【发布时间】:2017-05-22 13:08:54
【问题描述】:

我有一个有 1 个输入的简单应用程序:

@Component({   selector: 'mycomponent',   styles: [

  ],   template: `
    <div class="new-stuff">
      <div>
        <div>
        Name: <input type="text" class="new-stuff-name" [(ngModel)]="stuff.name"/>
        </div>
        <div class="new-stuff-name-error" *ngIf="nameError != null">
          {{nameError}}
        </div>
      </div>

      <button class="new-stuff-save" (click)="checkStuff()">Add idea</button>
    </div>  `, }) 
export class StuffComponent implements OnInit {
   public stuff = {name: ''};
   public allStuff = [];
   public checkStuff() {
    if (this.stuff.name.length === 0) {
      this.nameError = 'The name field cannot be empty';
    }

    if (this.stuff.name.length > 0) {
      this.allStuff.push(this.stuff);
      this.stuff= { name: ''};
    }
  }
 }

当我运行应用程序时,我看到值发生了变化,一切看起来都捆绑在一起,但是当我尝试测试时,当我更改输入框中的值并单击按钮时,未显示错误消息,错误消息仍然存在显示,因为输入值没有改变。

这是我的茉莉花测试:

describe(`stuff`, () => {
  let comp: StuffComponent ;
  let fixture: ComponentFixture<StuffComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [StuffComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [FormsModule],
    }).compileComponents();
    fixture = TestBed.createComponent(StuffComponent );
    comp = fixture.componentInstance;
  }));

  describe('adding a new stuff', () => {
    let stuffNameInput;
    let saveButton;
    beforeEach(() => {
      stuffNameInput = fixture.nativeElement
        .querySelectorAll('.new-stuff-name')[0];
      saveButton = fixture.debugElement.nativeElement.querySelector(
        '.new-stuff-save');
    });

    describe('when is successfull', () => {
      beforeEach(async(() => {
        stuffNameInput.value = 'New Stuff';
        stuffNameInput.dispatchEvent(new Event('input'));
        saveButton.click();
        fixture.detectChanges();
      }));
      it('should display an error', () => {
        let errorDiv = fixture.nativeElement
          .querySelectorAll('.new-stuff-desc-error');
        expect(errorDiv.length)
          .toBe(0, 'Error message displayed');
      });
    });
  });
});

我尝试了多种方法,将 async 替换为 fakeAsync,调用 tick 函数,将 click 移动到 fixture.whenStable().then 块内,将 div 的检查移动到 fixture.whenStable().then 块。到目前为止没有任何效果。

我正在使用 Angular 的 4.1.3 版本

【问题讨论】:

    标签: angular jasmine testbed


    【解决方案1】:

    回答我自己的问题以记录问题。

    使用 stuff.name 作为 ngModel 效果不是很好。

    我将 stuff.name 更改为 name 并且它开始工作了

    【讨论】:

      【解决方案2】:

      在我的测试中,我发现 mousedown 比 click() 效果更好:

          const e: Event = document.createEvent('HTMLEvents');
          e.initEvent('mousedown', false, true);
          itemElements[1].nativeElement.dispatchEvent(e);
      

      【讨论】:

      • 我尝试了您的解决方案,但仍然遇到同样的问题。我的问题是,当我更改输入的值时,尽管我调度了事件,但它并没有触发 ngModel 上的更改
      • 您是否尝试过运行 ngOnChanges() 函数进行调试,如果您可以看到它以这种方式触发?缩小链条断裂的位置。
      • 好提示,我添加了 ngOnChanges 函数但没有运气,所以我尝试了 ngDoCheck 并手动更新变量,它可以工作。但要做到这一点,我必须添加 @ViewChild('inputId') 以从输入中获取值。看起来不是一个干净的解决方案
      猜你喜欢
      • 2018-07-15
      • 2017-07-18
      • 2021-09-12
      • 2021-10-16
      • 2018-06-18
      • 2019-06-29
      • 2017-12-26
      • 2017-11-20
      • 2023-04-02
      相关资源
      最近更新 更多