From bb36aeb272acd66715a8b7e292b751e8626f0be8 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Wed, 11 Mar 2026 20:56:04 +0100 Subject: [PATCH] test(01-02): add failing tests for InlineEditCell - renders formatted currency in display mode - enters edit mode on click - calls onSave with parsed number on blur/Enter - does not call onSave when value unchanged --- .../src/components/InlineEditCell.test.tsx | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 frontend/src/components/InlineEditCell.test.tsx diff --git a/frontend/src/components/InlineEditCell.test.tsx b/frontend/src/components/InlineEditCell.test.tsx new file mode 100644 index 0000000..3b43af3 --- /dev/null +++ b/frontend/src/components/InlineEditCell.test.tsx @@ -0,0 +1,106 @@ +import { render, screen, fireEvent } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { describe, it, expect, vi, beforeEach } from 'vitest' +import { InlineEditCell } from './InlineEditCell' + +// Wrap in a table/row to satisfy semantic HTML for TableCell +function Wrapper({ children }: { children: React.ReactNode }) { + return ( + + + {children} + +
+ ) +} + +describe('InlineEditCell', () => { + const defaultProps = { + value: 42.5, + currency: 'EUR', + onSave: vi.fn().mockResolvedValue(undefined), + } + + beforeEach(() => { + vi.clearAllMocks() + }) + + it('renders formatted currency value in display mode', () => { + render( + + + + ) + // Should show formatted value (42.5 in EUR → some formatted string containing 42) + expect(screen.getByText(/42/)).toBeInTheDocument() + }) + + it('enters edit mode on click', async () => { + const user = userEvent.setup() + render( + + + + ) + const span = screen.getByText(/42/) + await user.click(span) + // After click, an input should be visible + expect(screen.getByRole('spinbutton')).toBeInTheDocument() + }) + + it('calls onSave with parsed number on blur', async () => { + const user = userEvent.setup() + const onSave = vi.fn().mockResolvedValue(undefined) + render( + + + + ) + const span = screen.getByText(/42/) + await user.click(span) + + const input = screen.getByRole('spinbutton') + await user.clear(input) + await user.type(input, '100') + fireEvent.blur(input) + + expect(onSave).toHaveBeenCalledWith(100) + }) + + it('does not call onSave when value unchanged', async () => { + const user = userEvent.setup() + const onSave = vi.fn().mockResolvedValue(undefined) + render( + + + + ) + const span = screen.getByText(/42/) + await user.click(span) + + // Don't change the value, just blur + const input = screen.getByRole('spinbutton') + fireEvent.blur(input) + + expect(onSave).not.toHaveBeenCalled() + }) + + it('calls onSave on Enter key', async () => { + const user = userEvent.setup() + const onSave = vi.fn().mockResolvedValue(undefined) + render( + + + + ) + const span = screen.getByText(/42/) + await user.click(span) + + const input = screen.getByRole('spinbutton') + await user.clear(input) + await user.type(input, '99') + await user.keyboard('{Enter}') + + expect(onSave).toHaveBeenCalledWith(99) + }) +})