Skip to content
Merged
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
38 changes: 38 additions & 0 deletions src/app/[lang]/internal/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { render, within } from '@testing-library/react';
import { describe, expect, it } from 'vitest';

import InternalPage, { generateMetadata, generateStaticParams } from './page';

describe('/[lang]/internal page', () => {
it('generates locale params for internal test pages', () => {
expect(generateStaticParams()).toEqual([{ lang: 'en' }, { lang: 'ja' }, { lang: 'ko' }]);
});

it('renders the Korean internal page title and description only', async () => {
const container = document.createElement('div');
const result = render(await InternalPage({ params: Promise.resolve({ lang: 'ko' }) }), {
baseElement: container,
container,
});

expect(within(result.container).getByRole('heading', { level: 1, name: '내부 페이지' })).toBeTruthy();
expect(
within(result.container).getByText('검토와 구현 참고를 위해 유지 중인 내부 컴포넌트 및 페이지 예시 목록입니다.'),
).toBeTruthy();
expect(within(result.container).queryByRole('list')).not.toBeInTheDocument();
});

it('uses the same copy for route metadata', async () => {
await expect(generateMetadata({ params: Promise.resolve({ lang: 'ko' }) })).resolves.toMatchObject({
description: '검토와 구현 참고를 위해 유지 중인 내부 컴포넌트 및 페이지 예시 목록입니다.',
title: '내부 페이지',
});
});

it('falls back to English metadata when static generation omits params', async () => {
await expect(generateMetadata({})).resolves.toMatchObject({
description: 'A list of internal component and page examples maintained for review and implementation reference.',
title: 'Internal Pages',
});
});
});
94 changes: 94 additions & 0 deletions src/app/[lang]/internal/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { Metadata } from 'next';

type InternalPageParams = {
lang: string;
};

type InternalPageProps = {
params?: Promise<InternalPageParams | undefined>;
};

type InternalPageCopy = {
description: string;
title: string;
};

const internalPageCopy: Record<string, InternalPageCopy> = {
en: {
description: 'A list of internal component and page examples maintained for review and implementation reference.',
title: 'Internal Pages',
},
ja: {
description: 'レビューと実装参考のために維持している内部コンポーネントおよびページ例の一覧です。',
title: '内部ページ',
},
ko: {
description: '검토와 구현 참고를 위해 유지 중인 내부 컴포넌트 및 페이지 예시 목록입니다.',
title: '내부 페이지',
},
};

const locales = Object.keys(internalPageCopy);

function getInternalPageCopy(lang: string) {
return internalPageCopy[lang] ?? internalPageCopy.en;
}

async function getInternalPageLang(params: InternalPageProps['params']) {
const resolvedParams = await params;

return resolvedParams?.lang ?? 'en';
}

export function generateStaticParams() {
return locales.map(lang => ({ lang }));
}

export async function generateMetadata({ params }: InternalPageProps): Promise<Metadata> {
const lang = await getInternalPageLang(params);
const copy = getInternalPageCopy(lang);

return {
description: copy.description,
title: copy.title,
};
}

export default async function InternalPage({ params }: InternalPageProps) {
const lang = await getInternalPageLang(params);
const copy = getInternalPageCopy(lang);

return (
<section
style={{
margin: '0 auto',
maxWidth: '768px',
padding: '64px 24px',
}}
>
<h1
style={{
color: '#111318',
fontSize: '36px',
fontWeight: 700,
letterSpacing: '0',
lineHeight: 1.2,
margin: '0 0 16px',
}}
>
{copy.title}
</h1>
<p
style={{
color: '#454a53',
fontSize: '17px',
letterSpacing: '0',
lineHeight: 1.7,
margin: 0,
}}
>
{copy.description}
</p>
</section>
);
}
Loading