Browse Source
The app now starts I18nProvider in zh-CN when no saved language exists, while preserving explicit saved choices. The login-required Ant Design modal also uses the v6 mask.closable shape so the console no longer warns about maskClosable. Constraint: First-run locale should not override an existing saved language preference Constraint: Ant Design 6 deprecates maskClosable on Modal.confirm Rejected: Keep browser-language detection | first entry needs deterministic Simplified Chinese Confidence: high Scope-risk: narrow Directive: Keep provider-less useI18n fallback stable for isolated tests unless all callers are wrapped in I18nProvider Tested: npm run test:run -- src/i18n/__tests__/index.test.tsx src/components/__tests__/TemplateExplorerView.test.tsx src/components/__tests__/Header.test.tsx src/utils/__tests__/loginRequiredModal.test.ts src/utils/__tests__/authFetch.test.ts src/store/__tests__/userStore.test.ts Tested: npm run build Not-tested: npm run lint | existing Next 16 next lint script resolves to nonexistent /lint directoryfeature/gateway
4 changed files with 80 additions and 12 deletions
@ -0,0 +1,50 @@ |
|||
import { render, screen, waitFor } from "@testing-library/react"; |
|||
import { beforeEach, describe, expect, it } from "vitest"; |
|||
import { I18nProvider, useI18n } from "@/i18n"; |
|||
|
|||
function LanguageProbe() { |
|||
const { language, t } = useI18n(); |
|||
return ( |
|||
<div> |
|||
<span data-testid="language">{language}</span> |
|||
<span data-testid="label">{t("language.label")}</span> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
describe("I18nProvider", () => { |
|||
beforeEach(() => { |
|||
window.localStorage.clear(); |
|||
document.documentElement.lang = ""; |
|||
}); |
|||
|
|||
it("defaults first-time visitors to Simplified Chinese", async () => { |
|||
render( |
|||
<I18nProvider> |
|||
<LanguageProbe /> |
|||
</I18nProvider> |
|||
); |
|||
|
|||
expect(screen.getByTestId("language")).toHaveTextContent("zh-CN"); |
|||
expect(screen.getByTestId("label")).toHaveTextContent("语言"); |
|||
await waitFor(() => { |
|||
expect(window.localStorage.getItem("popiart-node-language")).toBe("zh-CN"); |
|||
expect(document.documentElement.lang).toBe("zh-CN"); |
|||
}); |
|||
}); |
|||
|
|||
it("keeps an existing saved language preference", async () => { |
|||
window.localStorage.setItem("popiart-node-language", "ja"); |
|||
|
|||
render( |
|||
<I18nProvider> |
|||
<LanguageProbe /> |
|||
</I18nProvider> |
|||
); |
|||
|
|||
await waitFor(() => { |
|||
expect(screen.getByTestId("language")).toHaveTextContent("ja"); |
|||
expect(screen.getByTestId("label")).toHaveTextContent("言語"); |
|||
}); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,26 @@ |
|||
import { beforeEach, describe, expect, it, vi } from "vitest"; |
|||
|
|||
describe("openLoginRequiredModal", () => { |
|||
beforeEach(() => { |
|||
vi.resetModules(); |
|||
}); |
|||
|
|||
it("uses the Ant Design 6 mask.closable option instead of deprecated maskClosable", async () => { |
|||
const confirm = vi.fn(() => ({ |
|||
destroy: vi.fn(), |
|||
update: vi.fn(), |
|||
})); |
|||
|
|||
vi.doMock("antd", () => ({ |
|||
Modal: { confirm }, |
|||
})); |
|||
|
|||
const { openLoginRequiredModal } = await import("@/utils/loginRequiredModal"); |
|||
openLoginRequiredModal(); |
|||
|
|||
expect(confirm).toHaveBeenCalledWith(expect.objectContaining({ |
|||
mask: { closable: false }, |
|||
})); |
|||
expect(confirm.mock.calls[0][0]).not.toHaveProperty("maskClosable"); |
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue