Is it possible to mock the attribute directive in Angular?

I have the following directive that applies to input tags. When running the jasmine spec on a host component, I want it to ignore (mock) this directive as it has a jquery dependency which I am not interested in testing.

I tried to create a class MockDirective

but was not successful. Does anyone know how to achieve this?

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

      

inside the host:

<input skinColorPicker="'#555'" (colorSelected)="onPageBackgroundColorSelected($event)" 
 />

      

specification:

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 _ { });
}

      

Cannot bind to 'skinColorPicker' as it is not a known Input property.

I've seen this overrideDirective method but couldn't find a decent example.

One solution Turned out to be the missing declaration for the property @Input('skinColorPicker')

:

MockDirective({selector: '[skinColorPicker]', inputs: ['skinColorPicker']})

      

I still think it's better to see an example with an inline function Testbed.overrideDirective

.

Plunkr

+3


source to share


3 answers


MockDirective

works, but it has been misconfigured.

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

      



Thrown out by a missing mock declaration for a property @Input('skinColorPicker')

:

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

      

+1


source


Since the component is a directive without a template, we can use the MockComponent directly . I think MockDirective is also inspired by this.

The way to use MockComponent to forge a directive is as follows:



MockComponent({
  selector: '[skinColorPicker]',
  inputs: ['skinColorPicker']
}),

      

0


source


My solution is identical to @ jenson-button-event's solution with some minor changes, so it compiles to 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
      })
  ]
})

      

0


source







All Articles