1

I am unable to test for the right dispatch of an event after an error returned from a mocked wire service.

This is the component

import { api, LightningElement, wire, track } from "lwc";
import myMethod from "@salesforce/apex/MyController.MyMethod";
import { ShowToastEvent } from "lightning/platformShowToastEvent";

export default class MyComponent extends LightningElement {

  @api recordId = "who-cares";

  @track
  data;

  @wire(myMethod, { myObjId: "$recordId" })
  wiredRecord({ data, error }) {
    if (data) {
      this.data = data;
    } else {
      if (error) {
        let errorMessage = "Unknown error";

        if (Array.isArray(error.body.message)) {
          errorMessage = error.body.message.map((e) => e.message).join(", ");
        } else if (typeof error.body.message === "string") {
          errorMessage = error.body.message;
        }
        this.dispatchEvent(
          new ShowToastEvent({
            title: "Error when invoking the Controller API",
            message: errorMessage,
            variant: "error",
          })
        );
      }
    }
  }
}

and this is the test:

import MyComponent from "c/myComponent";
import { registerLdsTestWireAdapter } from "@salesforce/sfdx-lwc-jest";
import myMethod from "@salesforce/apex/MyController.MyMethod";
import { ShowToastEventName } from "lightning/platformShowToastEvent";
import { createElement } from "lwc";

const mockMyMethod = registerLdsTestWireAdapter(
  myMethod
);

const mockErrorResponse = require("./data/errorResponse.json");

describe("My Component", () => {
  afterEach(() => {
    while (document.body.firstChild) {
      document.body.removeChild(document.body.firstChild);
    }
  });
  
  it("should correctly show a toast when the API returns an error", () => {
    const element = createElement("c-my-component", {
      is: MyComponent,
    });
    const handler = jest.fn();
    document.body.appendChild(element);
    element.addEventListener(ShowToastEventName, handler);
    myMethod.error(
      mockErrorResponse.body,
      mockErrorResponse.status
    );
    return Promise.resolve().then(() => {
      expect(handler).toHaveBeenCalled();     
    });
  });
});
   

I do not see anything wrong in my test, is there a problem with testing dispatching of events from inside the component?

3
  • Try adding the event listener to the document, not the LWC itself. Remember to remove it again afterwards. – Phil W Nov 16 '20 at 21:52
  • What are the contents of the errorResponse.json? – adriancg Nov 16 '20 at 22:17
  • { "status": 500, "body": { "message": [ { "message": "Value provided is invalid for action parameter 'myId' of type 'Id'" } ] }, "headers": {} } – Edmondo1984 Nov 17 '20 at 7:30
1

The issue is that you are using registerLdsTestWireAdapter instead of registerApexTestWireAdapter for your test, and also need to fire the error,so you're missing this line

mockMyMethod.error(mockErrorResponse);

//can also have no arguments and sfdx-lwc-jest adds a default message
mockMyMethod.error();

See the Apex Wire Adapter Example

Regarding your follow-up about the event detail being empty. Looking at the sfdx-lwc-jest source, the ShowToastEvent is stubbed in a way that the event detail doesn't get set.

You can make your own custom stub at the project level so that it adds the toast as event.detail. Here is an example in the lwc-recipes repo. Be aware that for this to work you also need to update your projects jest config so that the module is resolved to your custom stub. See moduleNameMapper in the lwc-recipes jest.config.js

3
  • Should I switch the import or instead of using .error using .emit on the registerLdsTestWireAdapter? Because I tried switching the import to registerApexTestWireAdapter and my test stil fail – Edmondo1984 Nov 17 '20 at 7:31
  • This works except that the custom event detail is null :( – Edmondo1984 Nov 17 '20 at 14:53
  • @Edmondo1984 you are right you should use .error(). I have updated my answer, and also provided a workaround for your issue of the event detail not being set. – adriancg Nov 17 '20 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.