4

My problem is exactly same as How do I trigger a ngModel model update in an Angular 2 unit test?

I must be doing something silly in my test. Could anyone point out any obvious errors that I'm overlooking

component

    @Component({
  moduleId: module.id,
  selector: 'od-tree',
  templateUrl: 'tree.component.html',
  styleUrls: ['tree.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TreeComponent implements OnInit, OnChanges, AfterViewChecked {
  @Input() allResources: { items: {} };
  @Input() resourceGroups = { items: {} };
  @Input() selectedNodes: ITree.SelectedNode[];
  @Input() showIcons: boolean;
  @Input() showCheckboxes: boolean;
  @Input() omitAncillaryDBs: boolean;

  @Output() selectNode = new EventEmitter<any>();

  searchResource$ = new Subject<string>();
  searchField = '';
  tabs = [
    { title: TABS.ALL_RESOURCES, active: true },
    { title: TABS.RESOURCE_GROUPS, active: false }
  ];
  inSearchMode = false;
  trees = {
    ALL_RESOURCES: {
      searchText: null,
      tree: []
    },
    RESOURCE_GROUPS: {
      searchText: null,
      tree: []
    }
  };

  private _allResourcesTreeState = [];
  private _resourceGroupsTreeState = [];
  private ancillaryDBList = ['App-Services', 'Documents', 'Extensions', 'Fab', 'Last-Login',
    'Meters', 'Modules', 'Schemas', 'Security', 'Triggers'];

  constructor(private _cd: ChangeDetectorRef) { }
...
...
...
}

template

<div class="input-with-icon">
        <i class="icon-search"></i>
        <input type="text" [(ngModel)]="searchField" name="searchField" class="form-control" id="search-resources" placeholder="Search" (ngModelChange)="searchResource$.next(searchField)">
      </div>
... (truncated)
....
....

unit test

 describe('tree component', () => {
    //let activatedRoute: ActivatedRouteStub;
    let comp: TreeComponent;
    let fixture: ComponentFixture<TreeComponent>;
    let de: DebugElement;
    let el: HTMLElement;


    beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [TreeModule],
      })
        .compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(TreeComponent);
      comp = fixture.componentInstance;
      de = fixture.debugElement;
      el = de.nativeElement;
      comp.ngOnInit();
      fixture.detectChanges();
    });


    it('should bind value to ngmodel',() => {
         let inputEl = de.query(By.css('input#search-resources'))
         inputEl.nativeElement.value = 'node';
         inputEl.triggerEventHandler('input', {target: inputEl.nativeElement});
         fixture.detectChanges();
         expect(comp.searchField).toEqual('node');
      });  

 // another approach 
   it('should filter resources when used in host component',fakeAsync(() => {
       let inputEl = de.query(By.css('input#search-resources'));
       inputEl.nativeElement.value = 'node';
       dispatchEvent('input', inputEl.nativeElement);
       tick();
       fixture.detectChanges();
       expect(de.queryAll(By.css('li.host-leaf:not([hidden])')).length).toEqual(2, 'should show filtered hosts');
    }));

    }
1
  • update your post with TreeComponent Commented Jan 27, 2017 at 2:06

2 Answers 2

4

This is a known bug with current Testbed implementation detectChanges() when use in conjunction with OnPush change detection strategy. You can read more about it here. Very annoying indeed.

It turns out @Input changes is triggered not from the current component itself but from the parent-component.

Here is what i did to make my tests work with angular v2.4

fixture.changeDetectorRef['internalView']['compView_0'].markAsCheckOnce();
fixture.detectChanges();

https://github.com/angular/angular/issues/12313

Sign up to request clarification or add additional context in comments.

1 Comment

huh! thank you very much. I haven't tried but i'll accept that answer.
0

You will need to import the FormsModule into the testing module to get ngModel bindings working.

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [
    TreeModule
    FormsModule
    ]
  })
    .compileComponents();
}));

1 Comment

FormsModule is already imported in TreeModule. I tried your suggestion as well but did not help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.