Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import type { Preview } from "@storybook/nextjs-vite";
import { sb } from "storybook/test";
import { Theme } from "@radix-ui/themes";
import { IBM_Plex_Sans } from "next/font/google";
import { NextIntlClientProvider } from "next-intl";
import en from "../src/i18n/messages/en.json";
import ja from "../src/i18n/messages/ja.json";
import "@radix-ui/themes/styles.css";
import "../src/styles/globals.css";

Expand Down Expand Up @@ -101,6 +104,19 @@ const preview: Preview = {
},
},
globalTypes: {
locale: {
description: "Display language",
defaultValue: "en",
toolbar: {
title: "Language",
icon: "globe",
items: [
{ value: "en", title: "English" },
{ value: "ja", title: "日本語" },
],
dynamicTitle: true,
},
},
appearance: {
description: "Radix theme appearance",
defaultValue: "light",
Expand All @@ -115,6 +131,7 @@ const preview: Preview = {
decorators: [
(Story, context) => {
const appearance = context.globals.appearance as "light" | "dark";
const locale = context.globals.locale === "ja" ? "ja" : "en";
// .radix-themes is min-height:100vh -- right for one story to a frame,
// but a docs page stacks them into screens of whitespace.
const fillsFrame = context.viewMode !== "docs";
Expand All @@ -124,9 +141,15 @@ const preview: Preview = {
appearance={appearance}
style={fillsFrame ? undefined : { minHeight: 0 }}
>
<div style={{ padding: 24, maxWidth: 720 }}>
<Story />
</div>
<NextIntlClientProvider
locale={locale}
messages={locale === "ja" ? ja : en}
timeZone="UTC"
>
<div style={{ padding: 24, maxWidth: 720 }}>
<Story />
</div>
</NextIntlClientProvider>
</Theme>
);
},
Expand Down
2 changes: 1 addition & 1 deletion jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const customJestConfig = {
"^.+\\.(js|jsx|ts|tsx|mjs)$": ["babel-jest", { presets: ["next/babel"] }],
},
transformIgnorePatterns: [
"/node_modules/(?!(@storybook/[^/]+|storybook|react-markdown|bright|vfile|vfile-.*|unist-.*|unified|bail|is-plain-obj|trough|remark-.*|devlop|markdown-table|longest-streak|mdast-util-.*|micromark.*|decode-named-character-reference|character-entities|property-information|hast-util-.*|html-url-attributes|style-to-js|estree-util-is-identifier-name|zwitch|ccount|escape-string-regexp|trim-lines|space-separated-tokens|comma-separated-tokens|pretty-bytes|aws-sdk-client-mock|sinon|jose|@apidevtools)/)",
"/node_modules/(?!(@storybook/[^/]+|storybook|react-markdown|bright|vfile|vfile-.*|unist-.*|unified|bail|is-plain-obj|trough|remark-.*|devlop|markdown-table|longest-streak|mdast-util-.*|micromark.*|decode-named-character-reference|character-entities|property-information|hast-util-.*|html-url-attributes|style-to-js|estree-util-is-identifier-name|zwitch|ccount|escape-string-regexp|trim-lines|space-separated-tokens|comma-separated-tokens|pretty-bytes|aws-sdk-client-mock|sinon|jose|next-intl|use-intl|@formatjs|intl-messageformat|icu-minify|@schummar|@apidevtools)/)",
],
collectCoverageFrom: [
"src/**/*.{js,jsx,ts,tsx}",
Expand Down
41 changes: 41 additions & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,47 @@ jest.mock("next/navigation", () => ({
usePathname: () => "/",
}));

// Components read their strings through next-intl, which needs a provider on
// the client and a request on the server. Tests have neither, so both resolve
// against the real English catalog, and assertions match the text users see.
const intl = () => {
const { createTranslator, createFormatter } = jest.requireActual<
typeof import("use-intl/core")
>("use-intl/core");
const messages = jest.requireActual("@/i18n/messages/en.json") as Record<
string,
never
>;
const config = { locale: "en", timeZone: "UTC", messages } as const;
return {
t: (namespace?: string) =>
createTranslator({ ...config, namespace: namespace as never }),
format: () => createFormatter(config),
};
};
jest.mock("next-intl", () => {
const { t, format } = intl();
return {
useTranslations: t,
useFormatter: format,
useLocale: () => "en",
useTimeZone: () => "UTC",
useNow: () => new Date(),
NextIntlClientProvider: ({ children }: { children: unknown }) => children,
};
});
jest.mock("next-intl/server", () => {
const { t, format } = intl();
return {
getTranslations: async (
arg?: string | { namespace?: string }
) => t(typeof arg === "string" ? arg : arg?.namespace),
getFormatter: async () => format(),
getLocale: async () => "en",
getRequestConfig: (fn: unknown) => fn,
};
});

// @ts-ignore
global.Request = Request;
// @ts-ignore
Expand Down
6 changes: 5 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import createNextIntlPlugin from "next-intl/plugin";

const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts");

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
Expand Down Expand Up @@ -42,4 +46,4 @@ const nextConfig = {
},
};

export default nextConfig;
export default withNextIntl(nextConfig);
1 change: 1 addition & 0 deletions next.config.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @jest-environment node */
import nextConfig from "./next.config.js";

describe("next.config headers()", () => {
Expand Down
Loading
Loading