diff --git a/apps/client/composables/main/summary.ts b/apps/client/composables/main/summary.ts index 5a8c6c9cf..e4517e3c3 100644 --- a/apps/client/composables/main/summary.ts +++ b/apps/client/composables/main/summary.ts @@ -18,19 +18,29 @@ export function useSummary() { }; } -const enSentence = ref("To be, or not to be, that is the question."); -const zhSentence = ref("生存还是毁灭,这是一个问题。"); -const setenceLoading = ref(false); +export const defaultEnSentence = 'To be, or not to be, that is the question.' +export const defaultZhSentence = '生存还是毁灭,这是一个问题。' + +const enSentence = ref(defaultEnSentence); +const zhSentence = ref(defaultZhSentence); +const hasLoadingDailySentence = ref(false); + +export const resetSentenceLoading = () => (hasLoadingDailySentence.value = false) + export function useDailySentence() { const getDailySentence = async () => { - if (!setenceLoading.value) { - const { en, zh } = await fetchDailySentence(); + if (!hasLoadingDailySentence.value) { + hasLoadingDailySentence.value = true; + const { en, zh } = await fetchDailySentence().catch((err) => { + hasLoadingDailySentence.value = false + return Promise.reject(err) + }); enSentence.value = en; zhSentence.value = zh; - setenceLoading.value = true; } }; + onMounted(() => { getDailySentence(); }); @@ -38,5 +48,6 @@ export function useDailySentence() { return { enSentence, zhSentence, + getDailySentence, }; } diff --git a/apps/client/composables/main/tests/summary.spec.ts b/apps/client/composables/main/tests/summary.spec.ts new file mode 100644 index 000000000..b05abf4ed --- /dev/null +++ b/apps/client/composables/main/tests/summary.spec.ts @@ -0,0 +1,78 @@ +import { it, expect, describe, vi, beforeEach } from "vitest"; +import { resetSentenceLoading, useDailySentence, useSummary } from "../summary"; +import * as toolApi from "~/api/tool"; +import { useSetup } from "~/tests/helper/component"; +import { flushPromises } from "@vue/test-utils"; + +vi.mock("~/api/tool"); + +describe("summary", () => { + describe("summary sentence", () => { + const dummyRes = { + en: "en", + zh: "zh", + }; + beforeEach(() => { + vi.mocked(toolApi.fetchDailySentence).mockResolvedValue(dummyRes); + return () => { + resetSentenceLoading(); + vi.resetAllMocks(); + }; + }); + + it("should load the daily sentence", async () => { + const { wrapper } = useSetup(() => { + const { zhSentence, enSentence } = useDailySentence(); + return { + zhSentence, + enSentence, + }; + }); + + await flushPromises(); + + const { zhSentence, enSentence } = wrapper.vm; + + expect(toolApi.fetchDailySentence).toBeCalled(); + expect(zhSentence).toBe(dummyRes.zh); + expect(enSentence).toBe(dummyRes.en); + }); + + it("should only load sentence once", async () => { + useSetup(() => { + useDailySentence(); + }); + + await flushPromises(); + + useSetup(() => { + useDailySentence(); + }); + + await flushPromises(); + + expect(toolApi.fetchDailySentence).toBeCalledTimes(1); + }); + }); + + describe("summary modal control", () => { + it("should show summary modal", () => { + const { showModal, showSummary } = useSummary(); + showSummary(); + expect(showModal.value).toBeTruthy(); + }); + + it("should hide summary modal", () => { + const { showModal, hideSummary } = useSummary(); + hideSummary(); + expect(showModal.value).toBeFalsy(); + }); + + it("should return a same value in different hook", () => { + const { showSummary } = useSummary(); + showSummary(); + const { showModal: anotherShowModal } = useSummary(); + expect(anotherShowModal.value).toBeTruthy(); + }); + }); +});