Skip to content

Commit 991c71a

Browse files
committed
Add test cases for all changes
1 parent 218da23 commit 991c71a

10 files changed

Lines changed: 792 additions & 27 deletions
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
2+
3+
import { Dropdown, DropdownOption } from './Dropdown'
4+
5+
const mockOnSelect = jest.fn()
6+
7+
const options: DropdownOption[] = [
8+
{ label: 'GPT-4o', name: 'gpt-4o' },
9+
{ label: 'Claude 3', name: 'claude-3' },
10+
{ label: 'Gemini', name: 'gemini', description: 'Google model', imageSrc: 'http://test/gemini.png' }
11+
]
12+
13+
beforeEach(() => {
14+
jest.clearAllMocks()
15+
})
16+
17+
describe('Dropdown', () => {
18+
it('renders without crashing', () => {
19+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} />)
20+
21+
expect(screen.getByRole('combobox')).toBeInTheDocument()
22+
})
23+
24+
it('displays options when opened', async () => {
25+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} />)
26+
27+
fireEvent.mouseDown(screen.getByRole('combobox'))
28+
await waitFor(() => {
29+
expect(screen.getByText('GPT-4o')).toBeInTheDocument()
30+
expect(screen.getByText('Claude 3')).toBeInTheDocument()
31+
expect(screen.getByText('Gemini')).toBeInTheDocument()
32+
})
33+
})
34+
35+
it('calls onSelect with option name when option is clicked', async () => {
36+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} />)
37+
38+
const input = screen.getByRole('combobox')
39+
fireEvent.change(input, { target: { value: 'GPT' } })
40+
await waitFor(() => screen.getByText('GPT-4o'))
41+
fireEvent.click(screen.getByText('GPT-4o'))
42+
43+
expect(mockOnSelect).toHaveBeenCalledWith('gpt-4o')
44+
})
45+
46+
it('shows image in option when imageSrc is present', async () => {
47+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} />)
48+
49+
fireEvent.mouseDown(screen.getByRole('combobox'))
50+
await waitFor(() => {
51+
const img = screen.getByAltText('Google model')
52+
expect(img).toBeInTheDocument()
53+
expect(img).toHaveAttribute('src', 'http://test/gemini.png')
54+
})
55+
})
56+
57+
it('shows description in option when present', async () => {
58+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} />)
59+
60+
fireEvent.mouseDown(screen.getByRole('combobox'))
61+
await waitFor(() => {
62+
expect(screen.getByText('Google model')).toBeInTheDocument()
63+
})
64+
})
65+
66+
it('renders in disabled state', () => {
67+
render(<Dropdown value='' options={options} onSelect={mockOnSelect} disabled />)
68+
69+
expect(screen.getByRole('combobox')).toBeDisabled()
70+
})
71+
72+
it('shows selected value label', () => {
73+
render(<Dropdown value='gpt-4o' options={options} onSelect={mockOnSelect} />)
74+
75+
expect(screen.getByRole('combobox')).toHaveValue('GPT-4o')
76+
})
77+
})

packages/agentflow/src/atoms/ScenariosInput.test.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ jest.mock('./NodeInputHandler', () => ({
2525
}))
2626

2727
jest.mock('@tabler/icons-react', () => ({
28-
IconInfoCircle: () => <span data-testid='icon-info' />,
2928
IconPlus: () => <span data-testid='icon-plus' />,
3029
IconTrash: () => <span data-testid='icon-trash' />
3130
}))
3231

32+
jest.mock('./TooltipWithParser', () => ({
33+
TooltipWithParser: ({ title }: { title: string }) => <span data-testid='tooltip-with-parser'>{title}</span>
34+
}))
35+
3336
const scenarioInputParam: InputParam = {
3437
id: 'conditionAgentScenarios',
3538
name: 'conditionAgentScenarios',
@@ -61,7 +64,7 @@ describe('ScenariosInput', () => {
6164
const paramWithDesc: InputParam = { ...scenarioInputParam, description: 'Define scenarios for splitting' }
6265
render(<ScenariosInput inputParam={paramWithDesc} data={mockNodeData} onDataChange={mockOnDataChange} />)
6366

64-
expect(screen.getByTestId('icon-info')).toBeInTheDocument()
67+
expect(screen.getByTestId('tooltip-with-parser')).toBeInTheDocument()
6568
})
6669

6770
it('should render scenario items with "Scenario N" labels', () => {

packages/agentflow/src/atoms/StructuredOutputBuilder.test.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ const mockOnDataChange = jest.fn()
99

1010
jest.mock('@tabler/icons-react', () => ({
1111
IconArrowsMaximize: () => <span data-testid='icon-arrows-maximize' />,
12-
IconInfoCircle: () => <span data-testid='icon-info-circle' />,
1312
IconPlus: () => <span data-testid='icon-plus' />,
1413
IconTrash: () => <span data-testid='icon-trash' />
1514
}))
1615

16+
jest.mock('./TooltipWithParser', () => ({
17+
TooltipWithParser: ({ title }: { title: string }) => <span data-testid='tooltip-with-parser'>{title}</span>
18+
}))
19+
1720
jest.mock('./CodeInput', () => ({
1821
CodeInput: ({ value, onChange, language }: { value: string; onChange: (v: string) => void; language?: string }) => (
1922
<textarea data-testid='code-input' data-language={language} value={value} onChange={(e) => onChange(e.target.value)} />
@@ -366,7 +369,7 @@ describe('StructuredOutputBuilder', () => {
366369
render(<StructuredOutputBuilder inputParam={mockInputParam} data={dataWithEntries} onDataChange={mockOnDataChange} />)
367370

368371
expect(screen.getByText('Enum Values')).toBeInTheDocument()
369-
expect(screen.getByTestId('icon-info-circle')).toBeInTheDocument()
372+
expect(screen.getByTestId('tooltip-with-parser')).toBeInTheDocument()
370373
})
371374

372375
it('should render info icon and expand icon next to JSON Schema label', () => {
@@ -380,7 +383,7 @@ describe('StructuredOutputBuilder', () => {
380383
render(<StructuredOutputBuilder inputParam={mockInputParam} data={dataWithEntries} onDataChange={mockOnDataChange} />)
381384

382385
expect(screen.getByText('JSON Schema')).toBeInTheDocument()
383-
expect(screen.getByTestId('icon-info-circle')).toBeInTheDocument()
386+
expect(screen.getByTestId('tooltip-with-parser')).toBeInTheDocument()
384387
expect(screen.getByTitle('Expand')).toBeInTheDocument()
385388
})
386389

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { fireEvent, render, screen } from '@testing-library/react'
2+
3+
import { SwitchInput } from './SwitchInput'
4+
5+
const mockOnChange = jest.fn()
6+
7+
beforeEach(() => {
8+
jest.clearAllMocks()
9+
})
10+
11+
describe('SwitchInput', () => {
12+
it('renders switch element', () => {
13+
render(<SwitchInput value={false} onChange={mockOnChange} />)
14+
15+
expect(screen.getByRole('checkbox')).toBeInTheDocument()
16+
})
17+
18+
it('shows label when provided', () => {
19+
render(<SwitchInput label='Enable feature' value={false} onChange={mockOnChange} />)
20+
21+
expect(screen.getByText('Enable feature')).toBeInTheDocument()
22+
})
23+
24+
it('does not show label when not provided', () => {
25+
const { container } = render(<SwitchInput value={false} onChange={mockOnChange} />)
26+
27+
expect(container.querySelector('.MuiTypography-root')).not.toBeInTheDocument()
28+
})
29+
30+
it('switch is checked when value is true', () => {
31+
render(<SwitchInput value={true} onChange={mockOnChange} />)
32+
33+
expect(screen.getByRole('checkbox')).toBeChecked()
34+
})
35+
36+
it('switch is unchecked when value is false', () => {
37+
render(<SwitchInput value={false} onChange={mockOnChange} />)
38+
39+
expect(screen.getByRole('checkbox')).not.toBeChecked()
40+
})
41+
42+
it('calls onChange when toggled', () => {
43+
render(<SwitchInput value={false} onChange={mockOnChange} />)
44+
45+
fireEvent.click(screen.getByRole('checkbox'))
46+
47+
expect(mockOnChange).toHaveBeenCalledWith(true)
48+
})
49+
50+
it('switch is disabled when disabled prop is true', () => {
51+
render(<SwitchInput value={false} onChange={mockOnChange} disabled={true} />)
52+
53+
expect(screen.getByRole('checkbox')).toBeDisabled()
54+
})
55+
56+
it('handles string value coercion (truthy string → true)', () => {
57+
render(<SwitchInput value='hello' onChange={mockOnChange} />)
58+
59+
expect(screen.getByRole('checkbox')).toBeChecked()
60+
})
61+
62+
it('handles undefined value (defaults to false)', () => {
63+
render(<SwitchInput value={undefined} onChange={mockOnChange} />)
64+
65+
expect(screen.getByRole('checkbox')).not.toBeChecked()
66+
})
67+
})
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { render, screen } from '@testing-library/react'
2+
3+
import { TooltipWithParser } from './TooltipWithParser'
4+
5+
jest.mock('html-react-parser', () => {
6+
const mockParser = (html: string) => html
7+
mockParser.displayName = 'mockParser'
8+
return { __esModule: true, default: mockParser }
9+
})
10+
11+
describe('TooltipWithParser', () => {
12+
it('renders info icon button', () => {
13+
render(<TooltipWithParser title='Some tooltip' />)
14+
15+
expect(screen.getByRole('button')).toBeInTheDocument()
16+
expect(screen.getByTestId('InfoIcon')).toBeInTheDocument()
17+
})
18+
19+
it('renders tooltip with parsed HTML content', async () => {
20+
render(<TooltipWithParser title='<b>Bold</b> text' />)
21+
22+
// Hover over the button to trigger the tooltip
23+
const button = screen.getByRole('button')
24+
button.focus()
25+
26+
expect(await screen.findByRole('tooltip')).toHaveTextContent('<b>Bold</b> text')
27+
})
28+
29+
it('applies custom sx props', () => {
30+
render(<TooltipWithParser title='Tooltip' sx={{ color: 'red' }} />)
31+
32+
expect(screen.getByTestId('InfoIcon')).toBeInTheDocument()
33+
})
34+
})
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import type { CredentialSchemaInput } from '@/core/types'
2+
3+
import { getDefaultValueForType } from './credentialDefaults'
4+
5+
const makeInput = (overrides: Partial<CredentialSchemaInput> = {}): CredentialSchemaInput => ({
6+
label: 'Test',
7+
name: 'test',
8+
type: 'string',
9+
...overrides
10+
})
11+
12+
describe('getDefaultValueForType', () => {
13+
it('returns input.default when defined', () => {
14+
expect(getDefaultValueForType(makeInput({ type: 'string', default: 'custom' }))).toBe('custom')
15+
})
16+
17+
it('returns input.default even when it is a falsy value', () => {
18+
expect(getDefaultValueForType(makeInput({ type: 'number', default: 0 }))).toBe(0)
19+
expect(getDefaultValueForType(makeInput({ type: 'boolean', default: false }))).toBe(false)
20+
expect(getDefaultValueForType(makeInput({ type: 'string', default: '' }))).toBe('')
21+
})
22+
23+
it('returns false for boolean', () => {
24+
expect(getDefaultValueForType(makeInput({ type: 'boolean' }))).toBe(false)
25+
})
26+
27+
it('returns 0 for number', () => {
28+
expect(getDefaultValueForType(makeInput({ type: 'number' }))).toBe(0)
29+
})
30+
31+
it("returns '{}' for json", () => {
32+
expect(getDefaultValueForType(makeInput({ type: 'json' }))).toBe('{}')
33+
})
34+
35+
it('returns first option name for options with options present', () => {
36+
const input = makeInput({
37+
type: 'options',
38+
options: [
39+
{ label: 'First', name: 'first' },
40+
{ label: 'Second', name: 'second' }
41+
]
42+
})
43+
expect(getDefaultValueForType(input)).toBe('first')
44+
})
45+
46+
it("returns '' for options with no options", () => {
47+
expect(getDefaultValueForType(makeInput({ type: 'options' }))).toBe('')
48+
expect(getDefaultValueForType(makeInput({ type: 'options', options: [] }))).toBe('')
49+
})
50+
51+
it("returns '' for string", () => {
52+
expect(getDefaultValueForType(makeInput({ type: 'string' }))).toBe('')
53+
})
54+
55+
it("returns '' for password", () => {
56+
expect(getDefaultValueForType(makeInput({ type: 'password' }))).toBe('')
57+
})
58+
59+
it("returns '' for unknown type", () => {
60+
expect(getDefaultValueForType(makeInput({ type: 'unknown' as CredentialSchemaInput['type'] }))).toBe('')
61+
})
62+
})

0 commit comments

Comments
 (0)