Add AuthLayoutClient component and unit tests for authentication layout
- Implemented `AuthLayoutClient` with theme toggle and responsive layout. - Replaced legacy layout implementation in `layout.tsx` with `AuthLayoutClient` for improved modularity and styling consistency. - Added comprehensive Jest tests to verify layout structure, theme toggle placement, and responsive rendering.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
import { AuthLayoutClient } from '@/components/auth/AuthLayoutClient';
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Authentication',
|
title: 'Authentication',
|
||||||
@@ -9,11 +10,5 @@ export default function AuthLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return <AuthLayoutClient>{children}</AuthLayoutClient>;
|
||||||
<div className="flex min-h-screen items-center justify-center bg-gray-50 dark:bg-gray-900 px-4 py-12 sm:px-6 lg:px-8">
|
|
||||||
<div className="w-full max-w-md space-y-8">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
30
frontend/src/components/auth/AuthLayoutClient.tsx
Normal file
30
frontend/src/components/auth/AuthLayoutClient.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* AuthLayoutClient Component
|
||||||
|
* Client-side wrapper for auth layout with theme toggle
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { ThemeToggle } from '@/components/theme/ThemeToggle';
|
||||||
|
|
||||||
|
interface AuthLayoutClientProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AuthLayoutClient({ children }: AuthLayoutClientProps) {
|
||||||
|
return (
|
||||||
|
<div className="relative flex min-h-screen items-center justify-center bg-muted/30 px-4 py-12 sm:px-6 lg:px-8">
|
||||||
|
{/* Theme toggle in top-right corner */}
|
||||||
|
<div className="absolute right-4 top-4">
|
||||||
|
<ThemeToggle />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Auth card */}
|
||||||
|
<div className="w-full max-w-md">
|
||||||
|
<div className="rounded-lg border bg-card p-8 shadow-sm">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
79
frontend/tests/components/auth/AuthLayoutClient.test.tsx
Normal file
79
frontend/tests/components/auth/AuthLayoutClient.test.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { AuthLayoutClient } from '@/components/auth/AuthLayoutClient';
|
||||||
|
import { useTheme } from '@/components/theme/ThemeProvider';
|
||||||
|
|
||||||
|
// Mock ThemeProvider
|
||||||
|
jest.mock('@/components/theme/ThemeProvider', () => ({
|
||||||
|
useTheme: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('AuthLayoutClient', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
(useTheme as jest.Mock).mockReturnValue({
|
||||||
|
theme: 'light',
|
||||||
|
setTheme: jest.fn(),
|
||||||
|
resolvedTheme: 'light',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render children', () => {
|
||||||
|
render(
|
||||||
|
<AuthLayoutClient>
|
||||||
|
<div>Test Content</div>
|
||||||
|
</AuthLayoutClient>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('Test Content')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render theme toggle', () => {
|
||||||
|
render(
|
||||||
|
<AuthLayoutClient>
|
||||||
|
<div>Test Content</div>
|
||||||
|
</AuthLayoutClient>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Theme toggle is rendered as a button with aria-label
|
||||||
|
const themeToggle = screen.getByRole('button', { name: /toggle theme/i });
|
||||||
|
expect(themeToggle).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have proper layout structure', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<AuthLayoutClient>
|
||||||
|
<div>Test Content</div>
|
||||||
|
</AuthLayoutClient>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for main container with proper classes
|
||||||
|
const mainContainer = container.querySelector('.relative.flex.min-h-screen');
|
||||||
|
expect(mainContainer).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Check for card container
|
||||||
|
const cardContainer = container.querySelector('.rounded-lg.border.bg-card');
|
||||||
|
expect(cardContainer).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should position theme toggle in top-right corner', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<AuthLayoutClient>
|
||||||
|
<div>Test Content</div>
|
||||||
|
</AuthLayoutClient>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for theme toggle container with absolute positioning
|
||||||
|
const toggleContainer = container.querySelector('.absolute.right-4.top-4');
|
||||||
|
expect(toggleContainer).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render card with proper padding and styling', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<AuthLayoutClient>
|
||||||
|
<div>Test Content</div>
|
||||||
|
</AuthLayoutClient>
|
||||||
|
);
|
||||||
|
|
||||||
|
const card = container.querySelector('.p-8.shadow-sm');
|
||||||
|
expect(card).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user