Search code examples
vue.jsvuejs3vue-testing-library

Unit testing vue 3 onErrorCapture life cycle hook


import { onErrorCaptured } from "vue";
import { TheLayout } from "@/components";

const snackbar = useSnackbar();

onErrorCaptured((err) => {
  console.error(err);
  snackbar.send(err);
  return false;
});
</script>

<template>
  <the-layout>
    <router-view />
  </the-layout>
</template>

I have this SFC code in my App.vue. I want to test the onErrorCaptured behaviour such that it logs the error and sends the error to a the snackbar. So far i have come up with this:

  it("should catch errors and logs and send them to snackbar", async () => {
    const consoleErrorSpy = vi.spyOn(console, "error");
    const wrapper = mount(App, {
      global: {
        plugins: [
          styles,
          router,
          i18n,
          createTestingPinia({
            initialState: { snackbarStore: { show: false, message: "" } }
          })
        ]
      }
    });
    const error = new Error("error message");
    wrapper.someMagicMethodToTriggerAnError(error) ????
    await nextTick();
    const snackbar = useSnackbar();
    expect(consoleErrorSpy).toHaveBeenCalledWith(error);
    expect(snackbar.send).toHaveBeenCalledWith(error);
  });

What should i do to trigger an error in the component to test the behaviour ?


Solution

  • As estus-flask suggested the solution is to mock the child component and throw an error from it. Following code shows the approach for the component in question.

    test("should catch errors and logs and send them to snackbar", async () => {
      const consoleErrorSpy = vi.spyOn(console, "error");
      const error = new Error("error message");
      const errorComponent = {
        template: "<button @click='throwError'/>",
        methods: {
          throwError: () => {
            throw error;
          }
        }
      } as Component;
    
      const wrapper = mount(App, {
        global: {
          stubs: {
            TheLayout: errorComponent
          },
          plugins: [router, createTestingPinia()]
        }
      });
      await wrapper.get("button").trigger("click");
      expect(consoleErrorSpy).toHaveBeenCalledWith(error);
      expect(useSnackbar().send).toHaveBeenCalledWith(error);
      wrapper.unmount();
    });