From fd9b5e4fefc3749c29ff33919be6aaa05c122464 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:16:30 +0100 Subject: [PATCH] feat: add LoginDialog modal wrapper component Co-Authored-By: Claude Opus 4.6 (1M context) --- .../composites/LoginForm/LoginDialog.test.tsx | 54 +++++++++++++++++++ .../composites/LoginForm/LoginDialog.tsx | 15 ++++++ 2 files changed, 69 insertions(+) create mode 100644 src/design-system/composites/LoginForm/LoginDialog.test.tsx create mode 100644 src/design-system/composites/LoginForm/LoginDialog.tsx diff --git a/src/design-system/composites/LoginForm/LoginDialog.test.tsx b/src/design-system/composites/LoginForm/LoginDialog.test.tsx new file mode 100644 index 0000000..6e486d0 --- /dev/null +++ b/src/design-system/composites/LoginForm/LoginDialog.test.tsx @@ -0,0 +1,54 @@ +import { describe, it, expect, vi } from 'vitest' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { LoginDialog } from './LoginDialog' + +const defaultProps = { + open: true, + onClose: vi.fn(), + onSubmit: vi.fn(), +} + +describe('LoginDialog', () => { + it('renders Modal with LoginForm when open', () => { + render() + expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('heading', { name: 'Sign in' })).toBeInTheDocument() + expect(screen.getByLabelText(/email/i)).toBeInTheDocument() + }) + + it('does not render when closed', () => { + render() + expect(screen.queryByRole('dialog')).not.toBeInTheDocument() + }) + + it('calls onClose on Esc', async () => { + const onClose = vi.fn() + const user = userEvent.setup() + render() + await user.keyboard('{Escape}') + expect(onClose).toHaveBeenCalled() + }) + + it('calls onClose on backdrop click', async () => { + const onClose = vi.fn() + const user = userEvent.setup() + render() + await user.click(screen.getByTestId('modal-backdrop')) + expect(onClose).toHaveBeenCalled() + }) + + it('passes LoginForm props through', () => { + render( + , + ) + expect(screen.getByText('Welcome')).toBeInTheDocument() + expect(screen.getByText('Continue with Google')).toBeInTheDocument() + expect(screen.getByText('Bad credentials')).toBeInTheDocument() + }) +}) diff --git a/src/design-system/composites/LoginForm/LoginDialog.tsx b/src/design-system/composites/LoginForm/LoginDialog.tsx new file mode 100644 index 0000000..cffd740 --- /dev/null +++ b/src/design-system/composites/LoginForm/LoginDialog.tsx @@ -0,0 +1,15 @@ +import { Modal } from '../Modal/Modal' +import { LoginForm, type LoginFormProps } from './LoginForm' + +export interface LoginDialogProps extends LoginFormProps { + open: boolean + onClose: () => void +} + +export function LoginDialog({ open, onClose, className, ...formProps }: LoginDialogProps) { + return ( + + + + ) +}