首页 > 解决方案 > Angular 6,如何在子组件上测试父发射器?

问题描述

我有一个选项卡组件作为其子组件的包装器,包装器组件发出状态(打开或关闭)和每个选项卡的索引,在每个子组件上我注入包装器组件以访问发射器。

所以基本上我正在尝试从我的子组件测试文件上的包装器组件订阅发射器:

it(`it should have a 'toggle()' function that close/open the tab and then emits the tab status`, (emitted) => {

    fixture = TestBed.createComponent(AccordionTabComponent);
    const compiled = fixture.componentInstance;

    compiled.toggle(); // -> toggle function trigger the emit

    const data = {
      tabIndex: compiled.tabIndex,
      isOpen: compiled.isOpen
    }; // -> I get the current data from the child component to compare it with the emitted data.

    compiled.accordionRef.open.subscribe(tabEmmited => {
      console.log('tabEmmited: ', tabEmmited);
      expect(JSON.stringify(data)).toBe(JSON.stringify(tabEmmited));
      emitted();
    });

    fixture.detectChanges();    
});

但看起来订阅永远不会发生,因为“订阅”中的“日志”从不打印任何内容,这也会导致此错误:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

这是我的组件中的一些代码,以获得更多上下文:

包装器组件:

 export class AccordionComponent implements OnInit {

  @ContentChildren(forwardRef(() => AccordionTabComponent)) public childrenTabs: QueryList<AccordionTabComponent>;
  @Output() open: EventEmitter<{}> = new EventEmitter(); // -> Parent emitter.
 }

选项卡组件:

    export class AccordionTabComponent implements OnInit {
        accordionRef: AccordionComponent; -> Wrapper Component Ref
        tabIndex: number;
        isOpen: boolean;

        constructor(
          @Inject(AccordionComponent) accordionContainer: AccordionComponent -> Wrapper component injected
      ) {
            this.accordionRef = accordionContainer;
          }

      // Show/Hide tab
        toggle(): void {
          this.isOpen = !this.isOpen;
          this.accordionRef.open.emit({tabIndex: this.tabIndex, isOpen: this.isOpen});
        }
     }

标签: angularunit-testingjasminesubscriptioneventemitter

解决方案


在您的代码实际发出它之前,您应该订阅事件发射器。以免错过活动。

it(`it should have a 'toggle()' function that close/open the tab and then emits the tab status`, (emitted) => {
    fixture = TestBed.createComponent(AccordionTabComponent);
    const compiled = fixture.componentInstance;

    //subscribe before emitting
    compiled.accordionRef.open.subscribe(tabEmmited => {
          expect(JSON.stringify(data)).toBe(JSON.stringify(tabEmmited));
    });

    compiled.toggle(); // -> Call the method that actually emits it

    ..........

    fixture.detectChanges();    
});

推荐阅读