TimTheEnchanter
TimTheEnchanter

Reputation: 3671

How to test event in StencilJS component

I have a StencilJS component with an Event defined as:

@Event({eventName: 'focusEvent'}) focusEvent: EventEmitter<any>;

And the component looks like this:

<input type='text' 
    ... 
    onFocus={ (evt) => this.focusEvent.emit(evt)}>           
</input>

My test is as follows:

const mockEvent = jest.fn();
const page = await newE2EPage();
await page.setContent(`<my-textbox focusEvent=${mockEvent}></my-textbox>`);

await page.waitForSelector('input');
const el = await page.find('input');
expect(el).not.toBeNull();     // <-- this passes
       
const spy = el.spyOnEvent("focusEvent");
await el.focus();
expect(spy).toHaveBeenCalled();   // <-- this fails

The error is:

Matcher error: received value must be a mock or spy function

    Received has type:  object
    Received has value: {}

If I put the component in a test application and run it, I can see that the focus event fires when I click into the text box, but I can't figure out how to reproduce that in a test.

Upvotes: 2

Views: 3744

Answers (1)

Felipe Malara
Felipe Malara

Reputation: 1914

Try the following:

 const page = await newE2EPage();
 await page.setContent(`<my-textbox></my-textbox>`); // removed the focusEvent={...}
    
 const input = await page.find('input') // removed the waitForSelector + find, just find works 

 expect(input).not.toBeNull();     // <-- this passes

 const focusEventSpy = await page.spyOnEvent('focusEvent');

 await input.focus();

 await page.waitForChanges(); // introduced the wait for changes

 expect(focusEventSpy).toHaveReceivedEvent();   // <-- this now passes

Key points:

  • waitForChanges, from stenciljs docs:

Both Stencil and Puppeteer have an asynchronous architecture, which is a good thing for performance. Since all calls are async, it's required that await page.waitForChanges() is called when changes are made to components.

Upvotes: 3

Related Questions