首页 > 解决方案 > Angular 单元测试 ControlValueAccessor 与 ngFor

问题描述

在 ControleValueAccessor 内部使用时如何测试 ngFor 元素。

@Component({
  selector: 'checkbox-group',
  templateUrl: `
<h3 class="tt">s</h3>
<ng-container *ngFor="let item of _model;let i = index" >  <h3>s</h3>
  <div>
      <input type="checkbox" id="c{{i}}"/>
  </div>
</ng-container>

`,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CheckboxGroupComponent),
      multi: true
    }
  ]
})

export class CheckboxGroupComponent implements ControlValueAccessor {
  constructor(private ref: ChangeDetectorRef) {
    ref.detach();
  }
  writeValue(value: any): void {
    this._model = value;
    if(value != null) { this.ref.detectChanges();
  }
}

并从父 settings.html 导入此控件值访问器:

<div>
  <checkbox-group [(ngModel)]="selectedItems"></checkbox-group>
</div>

现在当我想测试它时,它只有一个子元素。并且只知道标签是第一个和最后一个子元素

设置.spec.ts:

TestBed.configureTestingModule({
      declarations: [ SettingsPage, CheckboxGroupComponent ],
      imports: [IonicModule.forRoot()],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => CheckboxGroupComponent),
          multi: true
        }
        // other providers
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();

it('should get checkBoxGroup Childs', fakeAsync(() => {  
    let customComponent = fixture.nativeElement.querySelector('checkbox-group');
    component.selectedItems = [true,true,true];
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      customComponent.NgModule=[true,false,true];
      fixture.detectChanges();
      debugger;        
    }); 
}))

在 customComponent 上调试:

在 customComponent 上调试

标签: angularjestjsjasmineangular-testangular2-changedetection

解决方案


我不完全确定您要做什么,但试试这个:

注意标记的评论!

import { By } from '@angular/platform-browser';
....
TestBed.configureTestingModule({
      declarations: [ SettingsPage, CheckboxGroupComponent ],
      imports: [IonicModule.forRoot()],
      providers: [
      /* !! Get rid of these lines because CheckboxGroupComponent
         is already doing the providing !!
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => CheckboxGroupComponent),
          multi: true
        } */
        // other providers
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();

it('should get checkBoxGroup Childs', fakeAsync(() => {  
    component.selectedItems = [true,true,true];
    fixture.detectChanges();
    // !! We can queryAll of the CSS elements and expect the length to be 3
    let customComponents = fixture.debugElement.queryAll(By.css('checkbox-group'));
    expect(customComponents.length).toBe(3);
}))

!!编辑 !!

<h3 class="tt">s</h3> // <-- this is the h3 you're seeing
<h1>Model's value: </h1>
<pre>{{ _model | json }}</pre>
<ng-container *ngFor="let item of _model;let i = index" >  <h3>s</h3> // You want to see <h3>s</h3>
  <div>
      <input type="checkbox" id="c{{i}}"/>
  </div>
</ng-container>

所以你是说你只看到带有 classtt的 h3 而不是里面带有 s 的 h3?

我添加了一个h1和一个pre标签来显示_model. 查看它的值并确保它不是空数组。


推荐阅读