diff --git a/src/components/NoteState.spec.ts b/src/components/NoteState.spec.ts new file mode 100644 index 0000000..5f88d27 --- /dev/null +++ b/src/components/NoteState.spec.ts @@ -0,0 +1,29 @@ +import { mount } from "@vue/test-utils" +import { describe, expect, it } from "vitest" + +import NoteState from "./NoteState.vue" + +describe("NoteState", () => { + it("shows a spinner while loading and no retry", () => { + const wrapper = mount(NoteState, { props: { status: "loading" } }) + + expect(wrapper.find(".loading-spinner").exists()).toBe(true) + expect(wrapper.find(".note-state-retry").exists()).toBe(false) + }) + + it("shows a message and retry button when failed", () => { + const wrapper = mount(NoteState, { props: { status: "failed" } }) + + expect(wrapper.find(".loading-spinner").exists()).toBe(false) + expect(wrapper.text()).toContain("Couldn't load this note") + expect(wrapper.find(".note-state-retry").exists()).toBe(true) + }) + + it("emits retry when the retry button is clicked", async () => { + const wrapper = mount(NoteState, { props: { status: "failed" } }) + + await wrapper.find(".note-state-retry").trigger("click") + + expect(wrapper.emitted("retry")).toHaveLength(1) + }) +}) diff --git a/src/components/NoteState.vue b/src/components/NoteState.vue new file mode 100644 index 0000000..02ff07f --- /dev/null +++ b/src/components/NoteState.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/StackedNote.vue b/src/components/StackedNote.vue index 59345b6..7ae3362 100644 --- a/src/components/StackedNote.vue +++ b/src/components/StackedNote.vue @@ -40,6 +40,10 @@ const EditNote = defineAsyncComponent( () => import("@/modules/note/components/EditNote.vue") ) +const NoteState = defineAsyncComponent( + () => import("@/components/NoteState.vue") +) + const props = defineProps<{ user: string repo: string @@ -154,10 +158,21 @@ const { }) const conflictOpen = ref(false) +const loadStatus = ref<"loading" | "ready" | "failed">("loading") -onMounted(async () => { - initialRawContent.value = await getRawContent() -}) +const loadNote = async () => { + loadStatus.value = "loading" + const raw = await getRawContent() + if (raw === null) { + loadStatus.value = "failed" + return + } + rawContent.value = raw + initialRawContent.value = raw + loadStatus.value = "ready" +} + +onMounted(loadNote) watch( path, @@ -412,11 +427,18 @@ const onBadgeClick = async () => {
-
+