jestjsstenciljsstencil-component

Stenciljs having troubles testing emitted event with Jest


I'm writing an input component using stencil and I'm having troubles testing the emitted event which is fired on a click or enter key press.
The component:

    export class Input {
    .
    .
      private inputRef?: HTMLInputElement;
      @Event() inputEvent: EventEmitter<{}>;
    .
    .
    render() {
     return (
      <div class="status">
          <div class="input-wrapper">
            <input onKeyUp = {event => this.handleKeyDown(event)} ref={el => this.inputRef = el as HTMLInputElement}/>
          </div>
      </div>);
     }
      private handleKeyDown(e: KeyboardEvent): void {
        this.dispatchSearchEvent(e);
      }

      private dispatchSearchEvent(e){
        this.inputEvent.emit({type: "event-name", event: e, data: (this.inputRef as HTMLInputElement).value});
      }
    }

conponent.spec.jsx:

  it('fires an event upon enter key press', async () => {
    const component = new InputFields();
    jest.spyOn(component, 'event-name');

      const keyUpEvent = new Event("keyup", {
        key: "enter",
        keyCode: 13,
        which: 13,
        shiftKey: false,
        ctrlKey: false,
        metaKey: false
      });

      keyUpEvent.target = {value: "some input value"}
      component.handleKeyDown(keyUpEvent);
  
      component.inputEvent = { emit: jest.fn().mockReturnValue(Promise.resolve()), };

      expect(component.inputEvent.emit).toHaveBeenCalled();
  });

Having an error:

Cannot spy the event-name property because it is not a function; undefined given instead

  356 |   it('fires an event upon enter key press', async () => {
  357 |     const component = new Input();
> 358 |     jest.spyOn(component, 'event-name');
      |          ^
  359 |
  360 |       const keyUpEvent = new Event("keyup", {
  361 |         key: "enter",

Solution

  • The error message is trying to tell you that your Input component does not have a function named event-name. spyOn is for spying on functions not events.

    In E2E testing you can use E2EElement.spyOnEvent for events:

    const page = await newE2EPage({html: '<my-input></my-input>'});
    const component = await page.find('my-input');
    const spy = await component.spyOnEvent('inputEvent');
    await component.type('x');
    expect(spy).toHaveReceivedEventTimes(1);
    expect(spy.firstEvent.detail.data).toBe('x');