为@View Child

时间:2019-03-30 06:59:03

标签: angular

我有一个Angular6组件,可以动态加载另一个Angular组件:

import { Component, OnInit, OnDestroy, Input, ViewChild, ComponentFactoryResolver, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';

import { CompItem } from '../../../core/pages/servicecatalog/models/comp.item.model';
import { CompComponent } from '../../../core/pages/servicecatalog/models/comp.compoent.model';
import { CompDirective } from '../../directive/comp-directive.directive';
import { CompService } from '../../services/comp.service';

import * as _ from 'lodash';



@Component({
  selector: 'app-dynamic-component-holder',
  templateUrl: './dynamic-component-holder.component.html',
  styleUrls: ['./dynamic-component-holder.component.css']
})
export class DynamicComponentHolderComponent implements OnInit {

  comp: CompItem;
  @ViewChild(CompDirective) compHost: CompDirective;

  customUiList: Array<CompItem> = [];

  componentRef: any;

  constructor(
    public dialog: MatDialogRef<DynamicComponentHolderComponent>,
    @Inject(MAT_DIALOG_DATA) public receivedData: any,
    private componentFactoryResolver: ComponentFactoryResolver,
    private _componentService: CompService
  ) {
  }

  ngOnInit() {
    this.getCustomComponentList();
  }

  loadComponent() {
    const dynamicItem = this.comp;

    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(dynamicItem.component);

    const viewContainerRef = this.compHost.viewContainerRef;
    viewContainerRef.clear();

    this.componentRef = viewContainerRef.createComponent(componentFactory);
    (<CompComponent>this.componentRef.instance).data = this.receivedData.data;


    <CompComponent>this.componentRef.instance.
    updateEmitter.subscribe((response) => {
    this.dialog.close({ confirm: true, orderid: response.orderNumber, orderNumber: response.orderNumber });
    });

    // Default Close Emitter
    <CompComponent>this.componentRef.instance.
      closeEmitter.subscribe((response) => {
        this.closeDialog('close');
      });

  }

  getCustomComponentList() {
    this._componentService.getComponents()
      .subscribe(
        (response) => {
          if (response.length > 0) {
            response.forEach((comp) => {
              this.customUiList.push(comp);
            });
            const classNameIndex = _.findIndex(this.customUiList, (o) => {
              return o.data.displayName == this.receivedData.data.customComponent;
            });
            if (classNameIndex > -1) {
              this.comp = this.customUiList[classNameIndex];
              this.loadComponent();
            }
          }
        }
      );
  }

  ngOnDestroy() {
  }

  closeDialog(param: any) {
    <CompComponent>this.componentRef.destroy();
    this.dialog.close({ confirm: false });
  }


}


<ng-template comp-host></ng-template>

我正在尝试为此编写UT,但出现错误:

  

未捕获的TypeError:无法读取未定义的属性“ subscribe”       在DynamicComponentHolderComponent.subscribe [作为loadComponent](:9876 / _karma_webpack_ / webpack:/src/app/service-catalog/custom-ui-components/dynamic-component-holder/dynamic-component-holder.component.ts:40)< / p>

如何为动态Angular component.subscribe做UT?

请帮助。

SPECT.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { DynamicComponentHolderComponent } from './dynamic-component-holder.component';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { CompService } from '../../services/comp.service';
import { NO_ERRORS_SCHEMA, Component, Directive } from '@angular/core';
import { of } from 'rxjs';
import { CompItem } from '../../../core/pages/servicecatalog/models/comp.item.model';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { CompDirective } from '../../directive/comp-directive.directive';

@Component({
  selector: 'product-settings',
  template: '<p>Mock Product Settings Component</p>'
})
class MockRefreshComponent {}


describe('DynamicComponentHolderComponent', () => {
  let component: DynamicComponentHolderComponent;
  let fixture: ComponentFixture<DynamicComponentHolderComponent>;

  const MatDialogRefMock = {
    close: jasmine.createSpy('close')
  };

  // tslint:disable-next-line:quotemark
  const passedData = {"data":{"categoryIds":[{"parentId":"5c3f08a7dc57c0002e3e8506","status":"Active","_id":"5c3f08b5dc57c0002e3e8507","name":"userCat-2","description":"userCat-2","createdAt":"2019-01-16T10:34:29.280Z","updatedAt":"2019-01-16T10:34:29.280Z","__v":0}],"tags":["refresh"],"status":"Active","orderFormKey":[],"headers":[],"userGroup":[{"id":"377c866e-7b43-4c5f-87fd-461c296412df","group":"service-catalog","description":"service catalog group","isAdmin":false,"created_at":"2018-12-27T04:56:57.493Z"}],"workflow":[],"_id":"5c4662df0042bc008aa1acb7","name":"Refresh Cisco Ip Phone","description":"Refresh Cisco Ip Phone","orderFormType":"customComponent","customComponent":"Refresh Cisco IP Phone","createdAt":"2019-01-22T00:25:03.626Z","updatedAt":"2019-01-22T00:25:03.626Z","__v":0,"favourite":true,"favouriteId":"5c46b56b11d3e50064cc41f5"}};

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        DynamicComponentHolderComponent,
        MockRefreshComponent,
        CompDirective
      ],
      imports: [
        MatDialogModule
      ],
      providers: [
        { provide: MAT_DIALOG_DATA, useValue: passedData },
        { provide: MatDialogRef, useValue: MatDialogRefMock },
        { provide: CompService, useClass: MockComponentService}
      ],
      schemas: [NO_ERRORS_SCHEMA]
    });

    TestBed.overrideModule(BrowserDynamicTestingModule, {
      set: {
        entryComponents: [MockRefreshComponent]
      }
    })
    .compileComponents();
  }));

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('will have the  `ViewChild`s defined', () => {
    expect(fixture.componentInstance.compHost).toBeDefined();
  });

  it('expect close Dialog to be called', () => {
    const closeDialog = spyOn(component, 'closeDialog').and.callThrough();
    component.closeDialog('close');
    expect(closeDialog).toHaveBeenCalled();
  });

});

class MockComponentService {
  getComponents() {
    return of([
      new CompItem(MockRefreshComponent, {
        'displayName': 'Refresh Cisco IP Phone',
        'name': 'refreshCiscoIpPhone',
        'componentName': 'refresh-cisco',
        'classname': 'RefreshCiscoComponent',
        'width': '90%',
        'height': '95vh',
        'maxWidth': '95vw',
        'maxHeight': '95vh',
      })
    ]);
  }
}

export function MockDirective(options: Component): Directive {
  const metadata: Directive = {
    selector: options.selector,
    inputs: options.inputs,
    outputs: options.outputs
  };
  return <any>Directive(metadata)(class _ {}); // <----- add <any>
}

0 个答案:

没有答案