import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { describe, it, expect, vi } from 'vitest' import { CreateViewDialog } from './CreateViewDialog' import type { ViewDefinition } from '../types' describe('CreateViewDialog', () => { const defaultProps = { open: true, onClose: vi.fn(), onCreate: vi.fn(), availableFields: ['type', 'status', 'title'], } function makeEditingView(overrides: Partial = {}): ViewDefinition { return { name: 'Active Projects', icon: 'rocket', color: null, sort: null, filters: { all: [{ field: 'type', op: 'equals', value: 'Project' }] }, ...overrides, } } it('shows "Create View" title in create mode', () => { render() expect(screen.getByText('Create View')).toBeInTheDocument() expect(screen.getByText('Create')).toBeInTheDocument() }) it('shows "Edit View" title when editingView is provided', () => { render() expect(screen.getByText('Edit View')).toBeInTheDocument() expect(screen.getByText('Save')).toBeInTheDocument() }) it('pre-populates name field in edit mode', () => { render() const input = screen.getByPlaceholderText(/Active Projects|Reading List/i) expect(input).toHaveValue('Active Projects') }) it('preserves existing icon and markdown-defined color when editing a view', async () => { const onCreate = vi.fn() const editingView = makeEditingView({ name: 'Monday', icon: 'folder', color: 'blue' }) render() // Submit the form without changing anything fireEvent.submit(screen.getByText('Save').closest('form')!) await waitFor(() => { expect(onCreate).toHaveBeenCalledWith( expect.objectContaining({ icon: 'folder', color: 'blue' }) ) }) }) it('passes selected icon and color when creating a view', async () => { const onCreate = vi.fn() render() const input = screen.getByPlaceholderText(/Active Projects|Reading List/i) fireEvent.change(input, { target: { value: 'Test View' } }) fireEvent.change(screen.getByPlaceholderText('Search icons…'), { target: { value: 'book' } }) fireEvent.click(screen.getByTitle('book')) fireEvent.click(screen.getByTitle('Blue')) fireEvent.click(screen.getByText('Create')) await waitFor(() => expect(onCreate).toHaveBeenCalledTimes(1)) const definition = onCreate.mock.calls[0][0] as ViewDefinition expect(definition.icon).toBe('book') expect(definition.color).toBe('blue') }) it('passes null icon and color when no appearance is selected', async () => { const onCreate = vi.fn() render() const input = screen.getByPlaceholderText(/Active Projects|Reading List/i) fireEvent.change(input, { target: { value: 'No Icon View' } }) fireEvent.submit(screen.getByText('Create').closest('form')!) await waitFor(() => { expect(onCreate).toHaveBeenCalledWith( expect.objectContaining({ icon: null, color: null }) ) }) }) it('keeps the dialog open when async save reports failure', async () => { const onClose = vi.fn() const onCreate = vi.fn(async () => false) render() const input = screen.getByPlaceholderText(/Active Projects|Reading List/i) fireEvent.change(input, { target: { value: 'Unsaveable View' } }) fireEvent.click(screen.getByText('Create')) await waitFor(() => expect(onCreate).toHaveBeenCalledTimes(1)) expect(onClose).not.toHaveBeenCalled() expect(screen.getByText('Create View')).toBeInTheDocument() }) })