mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
Full-featured pastebin application with: - Next.js frontend with TypeScript - Express backend with SQLite/PostgreSQL - Syntax highlighting for 100+ languages - Code quality validation system - Comprehensive accessibility (WCAG compliance) - Docker deployment configuration - Playwright E2E tests - Jest unit tests This provides a standalone web application that can be integrated as a capability module in the Universal Platform. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
388 lines
13 KiB
TypeScript
388 lines
13 KiB
TypeScript
import React from 'react'
|
|
import { render, screen, fireEvent } from '@/test-utils'
|
|
import userEvent from '@testing-library/user-event'
|
|
import { CodeEditorSection } from '@/components/features/snippet-editor/CodeEditorSection'
|
|
import { InputParameter } from '@/lib/types'
|
|
|
|
// Mock the editor components
|
|
jest.mock('@/components/features/snippet-editor/MonacoEditor', () => ({
|
|
MonacoEditor: ({ value, onChange }: any) => (
|
|
<textarea
|
|
data-testid="monaco-editor"
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
placeholder="Code editor"
|
|
/>
|
|
),
|
|
}))
|
|
|
|
jest.mock('@/components/features/snippet-editor/SplitScreenEditor', () => ({
|
|
SplitScreenEditor: ({ value, onChange }: any) => (
|
|
<textarea
|
|
data-testid="split-screen-editor"
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
placeholder="Split screen editor"
|
|
/>
|
|
),
|
|
}))
|
|
|
|
describe('CodeEditorSection Component', () => {
|
|
const mockOnCodeChange = jest.fn()
|
|
const mockOnPreviewChange = jest.fn()
|
|
|
|
const defaultProps = {
|
|
code: 'const test = () => {}',
|
|
language: 'TSX',
|
|
hasPreview: false,
|
|
functionName: 'TestComponent',
|
|
inputParameters: [],
|
|
errors: {},
|
|
onCodeChange: mockOnCodeChange,
|
|
onPreviewChange: mockOnPreviewChange,
|
|
}
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
})
|
|
|
|
describe('Rendering', () => {
|
|
it('should render without crashing', () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
expect(screen.getByTestId('code-editor-container')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should display Code label', () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
expect(screen.getByText('Code *')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render code editor', () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
expect(screen.getByTestId('monaco-editor')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Preview Checkbox - Supported Languages', () => {
|
|
it('should render preview checkbox for TSX language', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="TSX" />)
|
|
expect(screen.getByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render preview checkbox for JSX language', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="JSX" />)
|
|
expect(screen.getByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render preview checkbox for JavaScript language', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="JavaScript" />)
|
|
expect(screen.getByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render preview checkbox for TypeScript language', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="TypeScript" />)
|
|
expect(screen.getByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should display preview label', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="TSX" />)
|
|
expect(screen.getByTestId('enable-preview-label')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should have correct label text for preview', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="TSX" />)
|
|
expect(screen.getByText('Enable live preview')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Preview Checkbox - Unsupported Languages', () => {
|
|
it('should render preview checkbox for Python (supported)', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="Python" />)
|
|
expect(screen.getByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should not render preview checkbox for HTML (unsupported)', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="HTML" />)
|
|
expect(screen.queryByTestId('enable-preview-checkbox')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Preview Checkbox Interaction', () => {
|
|
it('should call onPreviewChange when checkbox is clicked', async () => {
|
|
const user = userEvent.setup()
|
|
render(<CodeEditorSection {...defaultProps} language="TSX" />)
|
|
|
|
const checkbox = screen.getByTestId('enable-preview-checkbox')
|
|
await user.click(checkbox)
|
|
|
|
expect(mockOnPreviewChange).toHaveBeenCalledWith(true)
|
|
})
|
|
|
|
it('should toggle preview checkbox state', async () => {
|
|
const user = userEvent.setup()
|
|
const { rerender } = render(
|
|
<CodeEditorSection {...defaultProps} language="TSX" hasPreview={false} />
|
|
)
|
|
|
|
const checkbox = screen.getByTestId('enable-preview-checkbox') as HTMLInputElement
|
|
expect(checkbox.checked).toBe(false)
|
|
|
|
await user.click(checkbox)
|
|
expect(mockOnPreviewChange).toHaveBeenCalledWith(true)
|
|
|
|
rerender(
|
|
<CodeEditorSection {...defaultProps} language="TSX" hasPreview={true} />
|
|
)
|
|
|
|
expect(checkbox.checked).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('Editor Selection Based on Preview', () => {
|
|
it('should render MonacoEditor when preview is disabled', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={false}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('code-editor-container')).toBeInTheDocument()
|
|
expect(screen.getByTestId('monaco-editor')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render SplitScreenEditor when preview is enabled', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={true}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('split-screen-editor-container')).toBeInTheDocument()
|
|
expect(screen.getByTestId('split-screen-editor')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should render MonacoEditor if language is not supported even with hasPreview true', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="HTML"
|
|
hasPreview={true}
|
|
/>
|
|
)
|
|
// Should show Monaco editor for unsupported language, not split screen
|
|
expect(screen.getByTestId('code-editor-container')).toBeInTheDocument()
|
|
expect(screen.queryByTestId('split-screen-editor')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Code Input Handling', () => {
|
|
it('should call onCodeChange when code is modified in MonacoEditor', async () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
|
|
const editor = screen.getByTestId('monaco-editor') as HTMLTextAreaElement
|
|
fireEvent.change(editor, { target: { value: 'new code' } })
|
|
|
|
expect(mockOnCodeChange).toHaveBeenCalledWith('new code')
|
|
})
|
|
|
|
it('should pass code prop to editor', () => {
|
|
const customCode = 'console.log("test")'
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
code={customCode}
|
|
/>
|
|
)
|
|
const editor = screen.getByTestId('monaco-editor') as HTMLTextAreaElement
|
|
expect(editor.value).toBe(customCode)
|
|
})
|
|
})
|
|
|
|
describe('Error Handling', () => {
|
|
it('should display error message when code has error', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
errors={{ code: 'Syntax error on line 5' }}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('code-error-message')).toBeInTheDocument()
|
|
expect(screen.getByText('Syntax error on line 5')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should not display error message when there is no error', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
errors={{}}
|
|
/>
|
|
)
|
|
expect(screen.queryByTestId('code-error-message')).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('should apply error styling when error exists', () => {
|
|
const { container } = render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
errors={{ code: 'Error' }}
|
|
/>
|
|
)
|
|
const errorContainer = container.querySelector('[data-testid="code-editor-container"]')
|
|
expect(errorContainer?.className).toContain('destructive')
|
|
})
|
|
|
|
it('should apply error styling to split screen editor', () => {
|
|
const { container } = render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={true}
|
|
errors={{ code: 'Error' }}
|
|
/>
|
|
)
|
|
const splitScreenContainer = container.querySelector('[data-testid="split-screen-editor-container"]')
|
|
expect(splitScreenContainer?.className).toContain('ring-destructive')
|
|
})
|
|
})
|
|
|
|
describe('Props Validation', () => {
|
|
it('should accept all required props', () => {
|
|
expect(() => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
}).not.toThrow()
|
|
})
|
|
|
|
it('should handle empty code string', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
code=""
|
|
/>
|
|
)
|
|
const editor = screen.getByTestId('monaco-editor') as HTMLTextAreaElement
|
|
expect(editor.value).toBe('')
|
|
})
|
|
|
|
it('should handle empty input parameters', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
inputParameters={[]}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('code-editor-container')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should handle input parameters', () => {
|
|
const params: InputParameter[] = [
|
|
{ name: 'count', type: 'number', defaultValue: '0', description: '' },
|
|
]
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={true}
|
|
inputParameters={params}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('split-screen-editor-container')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Editor Container Styling', () => {
|
|
it('should render code editor container with proper classes', () => {
|
|
const { container } = render(<CodeEditorSection {...defaultProps} />)
|
|
const editorContainer = container.querySelector('[data-testid="code-editor-container"]')
|
|
expect(editorContainer?.className).toContain('rounded-md')
|
|
expect(editorContainer?.className).toContain('border')
|
|
})
|
|
|
|
it('should render code editor container with border styling', () => {
|
|
const { container } = render(<CodeEditorSection {...defaultProps} />)
|
|
const editorContainer = container.querySelector('[data-testid="code-editor-container"]')
|
|
expect(editorContainer?.className).toContain('border-border')
|
|
})
|
|
})
|
|
|
|
describe('Component Integration', () => {
|
|
it('should integrate with MonacoEditor component', () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
expect(screen.getByTestId('monaco-editor')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should integrate with SplitScreenEditor component', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={true}
|
|
/>
|
|
)
|
|
expect(screen.getByTestId('split-screen-editor')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should pass correct props to SplitScreenEditor', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
language="TSX"
|
|
hasPreview={true}
|
|
functionName="MyComponent"
|
|
/>
|
|
)
|
|
const splitScreenEditor = screen.getByTestId('split-screen-editor')
|
|
expect(splitScreenEditor).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('Accessibility', () => {
|
|
it('should have accessible label for preview checkbox', () => {
|
|
render(<CodeEditorSection {...defaultProps} language="TSX" />)
|
|
expect(screen.getByLabelText('Enable live preview')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should have accessible label for code input', () => {
|
|
render(<CodeEditorSection {...defaultProps} />)
|
|
expect(screen.getByText('Code *')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should have error message with proper id attribute', () => {
|
|
render(
|
|
<CodeEditorSection
|
|
{...defaultProps}
|
|
errors={{ code: 'Error' }}
|
|
/>
|
|
)
|
|
const errorMsg = screen.getByTestId('code-error-message')
|
|
expect(errorMsg.id).toBe('code-error')
|
|
})
|
|
})
|
|
|
|
describe('Language Support Verification', () => {
|
|
it('should verify supported languages show preview checkbox', () => {
|
|
const supportedLanguages = ['JSX', 'TSX', 'JavaScript', 'TypeScript']
|
|
supportedLanguages.forEach(lang => {
|
|
const { unmount } = render(
|
|
<CodeEditorSection {...defaultProps} language={lang} />
|
|
)
|
|
expect(screen.queryByTestId('enable-preview-checkbox')).toBeInTheDocument()
|
|
unmount()
|
|
})
|
|
})
|
|
|
|
it('should verify unsupported languages hide preview checkbox', () => {
|
|
// Use languages that are NOT in previewEnabledLanguages
|
|
const unsupportedLanguages = ['HTML', 'CSS', 'SQL', 'Go']
|
|
unsupportedLanguages.forEach(lang => {
|
|
const { unmount } = render(
|
|
<CodeEditorSection {...defaultProps} language={lang} />
|
|
)
|
|
expect(screen.queryByTestId('enable-preview-checkbox')).not.toBeInTheDocument()
|
|
unmount()
|
|
})
|
|
})
|
|
})
|
|
})
|