import { describe, it, expect, vi } from "vitest"; import { mount, flushPromises } from "@vue/test-utils"; import { defineComponent, h, nextTick, ref } from "vue"; import ErrorBoundary from "../ErrorBoundary.vue"; describe("ErrorBoundary", () => { it("renders children when nothing throws", () => { const Child = defineComponent({ template: "

hello

" }); const wrapper = mount(ErrorBoundary, { slots: { default: Child } }); expect(wrapper.find("[data-testid=ok]").text()).toBe("hello"); expect(wrapper.find("[data-testid=error-boundary]").exists()).toBe(false); }); it("catches a render-time error and renders the fallback", async () => { const consoleError = vi.spyOn(console, "error").mockImplementation(() => {}); const Boom = defineComponent({ render() { throw new Error("kaboom"); }, }); const wrapper = mount(ErrorBoundary, { slots: { default: () => h(Boom) } }); await nextTick(); expect(wrapper.find("[data-testid=error-boundary]").exists()).toBe(true); expect(wrapper.find("[data-testid=error-boundary]").text()).toContain("kaboom"); consoleError.mockRestore(); }); it("reset clears the captured error", async () => { const consoleError = vi.spyOn(console, "error").mockImplementation(() => {}); const shouldThrow = ref(true); const Maybe = defineComponent({ render() { if (shouldThrow.value) throw new Error("once"); return h("p", { "data-testid": "ok" }, "fine"); }, }); const wrapper = mount(ErrorBoundary, { slots: { default: () => h(Maybe) } }); await nextTick(); expect(wrapper.find("[data-testid=error-boundary]").exists()).toBe(true); shouldThrow.value = false; await wrapper.get("button").trigger("click"); await flushPromises(); await nextTick(); expect(wrapper.find("[data-testid=error-boundary]").exists()).toBe(false); expect(wrapper.find("[data-testid=ok]").exists()).toBe(true); consoleError.mockRestore(); }); });