是否可以在Angular中模拟属性指令?

jen*_*ent 12 jasmine angular

我有以下指令应用于输入标记.当在主机组件上运行jasmine规范时,我希望它忽略(模拟)这个指令,因为它依赖于我对测试不感兴趣的jquery.

我试图创建一个MockDirective类,但没有成功.谁知道怎么做到这一点?

@Directive({
    selector: '[skinColorPicker]'
})
export class ColorPickerDirective implements OnInit {

    @Input('skinColorPicker') initialColor;

    @Output() colorSelected: EventEmitter<string> = new EventEmitter<string>();

    constructor(private el: ElementRef) {}

    ngOnInit() {

       // legacy jQuery blah blah
    }
}
Run Code Online (Sandbox Code Playgroud)

在主持人内:

<input skinColorPicker="'#555'" (colorSelected)="onPageBackgroundColorSelected($event)" 
 />
Run Code Online (Sandbox Code Playgroud)

规格:

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
          PrintSidebarComponent,
          MockDirective({ selector: '[skinColorPicker]' }) // does not work
      ]
    })
    .compileComponents();
  }));

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

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

export function MockDirective(options: Component): Component {
    let metadata: Directive = {
        selector: options.selector,
        inputs: options.inputs,
        outputs: options.outputs
    };
    return Directive(metadata)(class _ { });
}
Run Code Online (Sandbox Code Playgroud)

无法绑定到'skinColorPicker',因为它不是'input'的已知属性.

我看到了这个overrideDirective方法,但还没有找到一个像样的例子.

一个解决方案 原来是一个缺少该@Input('skinColorPicker')属性的模拟声明:

MockDirective({selector: '[skinColorPicker]', inputs: ['skinColorPicker']})
Run Code Online (Sandbox Code Playgroud)

我仍然认为看一个内置Testbed.overrideDirective函数的例子会更好.

Plunkr

jen*_*ent 6

MockDirective做的工作,但它是配置错误。

export function MockDirective(options: Component): Directive {
    const metadata: Directive = {
        selector: options.selector,
        inputs: options.inputs,
        outputs: options.outputs
    };
    return Directive(metadata)(class _ { });
}
Run Code Online (Sandbox Code Playgroud)

原来是该@Input('skinColorPicker')属性缺少的模拟声明:

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: ['skinColorPicker'] }) // does work
  ]
})
Run Code Online (Sandbox Code Playgroud)


mai*_*aia 6

我的解决方案与@ jenson-button-event的解决方案相同,但有一些小的更改,因此可以在TypeScript中进行编译。

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>
}

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: []  // <--- empty, unless the directive has inputs
      })
  ]
})
Run Code Online (Sandbox Code Playgroud)


Mar*_*ijk 6

该解决方案与 @jenson-button-event 和 @maia 的解决方案完全相同,只是改进了 Typescript 的正确性。如果没有改进,它对我不起作用。

export function MockDirective(options: Component): Type<Directive> {
  const metadata: Directive = {
    selector: options.selector,
    inputs: options.inputs,
    outputs: options.outputs,
  };
  return Directive(metadata)(class MockDirectiveClass {
  });
}

TestBed.configureTestingModule({
  declarations: [
      PrintSidebarComponent,
      MockDirective({ 
        selector: '[skinColorPicker]', 
        inputs: []  // <--- empty, unless the directive has inputs
      })
  ]
})
Run Code Online (Sandbox Code Playgroud)