-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b631eff
commit 7be92c9
Showing
59 changed files
with
1,335 additions
and
4,848 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
packages/ui/src/common/utils/check-if-date-is-valid/check-if-date-is-valid.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const checkIfDateIsValid = (inputDate: string | Date | number): boolean => { | ||
const date = new Date(inputDate); | ||
|
||
if (date.getFullYear() < 1000) return false; | ||
|
||
return true; | ||
}; |
29 changes: 29 additions & 0 deletions
29
packages/ui/src/common/utils/check-if-date-is-valid/check-if-date-is-valid.unit.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { checkIfDateIsValid } from './check-if-date-is-valid'; | ||
|
||
describe('checkIfDateIsValid', () => { | ||
it('should return false for dates before year 1000', () => { | ||
expect(checkIfDateIsValid('0999-12-31')).toBe(false); | ||
expect(checkIfDateIsValid('0001-01-01')).toBe(false); | ||
expect(checkIfDateIsValid(new Date('0500-06-15'))).toBe(false); | ||
}); | ||
|
||
it('should return true for valid dates after year 1000', () => { | ||
expect(checkIfDateIsValid('2023-01-01')).toBe(true); | ||
expect(checkIfDateIsValid('1000-01-01')).toBe(true); | ||
expect(checkIfDateIsValid('3000-12-31')).toBe(true); | ||
}); | ||
|
||
it('should handle different input types', () => { | ||
const currentDate = new Date(); | ||
expect(checkIfDateIsValid(currentDate)).toBe(true); | ||
expect(checkIfDateIsValid(currentDate.toISOString())).toBe(true); | ||
expect(checkIfDateIsValid(currentDate.getTime())).toBe(true); | ||
}); | ||
|
||
it('should handle edge cases', () => { | ||
expect(checkIfDateIsValid('1000-01-01')).toBe(true); | ||
expect(checkIfDateIsValid('999-12-31')).toBe(false); | ||
expect(checkIfDateIsValid('9999-12-31')).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './check-if-date-is-valid'; |
6 changes: 3 additions & 3 deletions
6
packages/ui/src/components/atoms/inputs/Checkbox/Checkbox.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
packages/ui/src/components/molecules/ErrorsList/ErrorsList.unit.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { describe, expect, it, vi } from 'vitest'; | ||
import { ErrorsList } from './ErrorsList'; | ||
|
||
// Mock ErrorMessage component | ||
vi.mock('@/components/atoms', () => ({ | ||
ErrorMessage: ({ text, className }: { text: string; className?: string }) => ( | ||
<div className={className}>{text}</div> | ||
), | ||
})); | ||
|
||
describe('ErrorsList', () => { | ||
it('renders empty list when no errors provided', () => { | ||
render(<ErrorsList errors={[]} />); | ||
expect(screen.queryByRole('listitem')).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('renders list of errors', () => { | ||
const errors = ['Error 1', 'Error 2', 'Error 3']; | ||
render(<ErrorsList errors={errors} />); | ||
|
||
errors.forEach(error => { | ||
expect(screen.getByText(error)).toBeInTheDocument(); | ||
}); | ||
expect(screen.getAllByRole('listitem')).toHaveLength(3); | ||
}); | ||
|
||
it('applies custom className when provided', () => { | ||
render(<ErrorsList errors={['Error']} className="custom-class" />); | ||
const list = screen.getByRole('list'); | ||
expect(list.className).toContain('custom-class'); | ||
expect(list.className).toContain('pl-1'); | ||
}); | ||
|
||
it('applies testId to list and list items when provided', () => { | ||
const errors = ['Error 1', 'Error 2']; | ||
render(<ErrorsList errors={errors} testId="test" />); | ||
|
||
expect(screen.getByTestId('test-errors-list')).toBeInTheDocument(); | ||
expect(screen.getByTestId('test-error-list-item-0')).toBeInTheDocument(); | ||
expect(screen.getByTestId('test-error-list-item-1')).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders error type styling by default', () => { | ||
render(<ErrorsList errors={['Error']} />); | ||
// Default error type should not have warning class | ||
expect(screen.getByText('Error').className).not.toContain('text-amber-400'); | ||
}); | ||
|
||
it('renders warning type styling when specified', () => { | ||
render(<ErrorsList errors={['Warning']} type="warning" />); | ||
expect(screen.getByText('Warning').className).toContain('text-amber-400'); | ||
}); | ||
|
||
it('does not apply testId attributes when testId is not provided', () => { | ||
render(<ErrorsList errors={['Error']} />); | ||
expect(screen.queryByTestId(/errors-list/)).not.toBeInTheDocument(); | ||
expect(screen.queryByTestId(/error-list-item-/)).not.toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 16 additions & 12 deletions
28
.../src/components/organisms/Form/DynamicForm/fields/AutocompleteField/AutocompleteField.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
...nents/organisms/Form/DynamicForm/fields/AutocompleteField/AutocompleteField.unit.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { createTestId } from '@/components/organisms/Renderer'; | ||
import { cleanup, render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
import { useField } from '../../hooks/external'; | ||
import { IFormElement, TBaseFormElements } from '../../types'; | ||
import { useStack } from '../FieldList/providers/StackProvider'; | ||
import { AutocompleteField, IAutocompleteFieldParams } from './AutocompleteField'; | ||
|
||
// Mock dependencies | ||
vi.mock('@ballerine/ui', () => ({ | ||
AutocompleteInput: ({ children, options, ...props }: any) => ( | ||
<input {...props} options={JSON.stringify(options)} type="text" /> | ||
), | ||
})); | ||
|
||
vi.mock('../../hooks/external', () => ({ | ||
useField: vi.fn(), | ||
})); | ||
|
||
vi.mock('../FieldList/providers/StackProvider', () => ({ | ||
useStack: vi.fn(), | ||
})); | ||
|
||
vi.mock('@/components/organisms/Renderer', () => ({ | ||
createTestId: vi.fn(), | ||
})); | ||
|
||
vi.mock('../../layouts/FieldLayout', () => ({ | ||
FieldLayout: ({ children }: any) => <div>{children}</div>, | ||
})); | ||
|
||
describe('AutocompleteField', () => { | ||
const mockStack = [0]; | ||
const mockOptions = [ | ||
{ label: 'Option 1', value: 'opt1' }, | ||
{ label: 'Option 2', value: 'opt2' }, | ||
]; | ||
|
||
const mockElement = { | ||
id: 'test-autocomplete', | ||
params: { | ||
placeholder: 'Select an option', | ||
options: mockOptions, | ||
}, | ||
} as IFormElement<TBaseFormElements, IAutocompleteFieldParams>; | ||
|
||
const mockFieldProps = { | ||
value: '', | ||
onChange: vi.fn(), | ||
onBlur: vi.fn(), | ||
disabled: false, | ||
touched: false, | ||
} as ReturnType<typeof useField>; | ||
|
||
beforeEach(() => { | ||
cleanup(); | ||
vi.clearAllMocks(); | ||
vi.mocked(useStack).mockReturnValue({ stack: mockStack }); | ||
vi.mocked(useField).mockReturnValue(mockFieldProps); | ||
vi.mocked(createTestId).mockReturnValue('test-id'); | ||
}); | ||
|
||
it('should render AutocompleteInput component', () => { | ||
render(<AutocompleteField element={mockElement} />); | ||
expect(screen.getByTestId('test-id')).toBeInTheDocument(); | ||
}); | ||
|
||
it('should pass correct props to AutocompleteInput', () => { | ||
render(<AutocompleteField element={mockElement} />); | ||
const input = screen.getByTestId('test-id'); | ||
|
||
expect(input).toHaveAttribute('placeholder', 'Select an option'); | ||
expect(input).not.toBeDisabled(); | ||
}); | ||
|
||
it('should handle value changes', async () => { | ||
const user = userEvent.setup(); | ||
render(<AutocompleteField element={mockElement} />); | ||
|
||
const input = screen.getByTestId('test-id'); | ||
await user.type(input, 'test value'); | ||
|
||
expect(mockFieldProps.onChange).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle blur events', async () => { | ||
const user = userEvent.setup(); | ||
render(<AutocompleteField element={mockElement} />); | ||
|
||
const input = screen.getByTestId('test-id'); | ||
await user.click(input); | ||
await user.tab(); | ||
|
||
expect(mockFieldProps.onBlur).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should respect disabled state', () => { | ||
vi.mocked(useField).mockReturnValue({ | ||
...mockFieldProps, | ||
disabled: true, | ||
}); | ||
|
||
render(<AutocompleteField element={mockElement} />); | ||
expect(screen.getByTestId('test-id')).toBeDisabled(); | ||
}); | ||
|
||
it('should use default params when none provided', () => { | ||
const elementWithoutParams = { | ||
id: 'test-autocomplete', | ||
} as unknown as IFormElement<TBaseFormElements, IAutocompleteFieldParams>; | ||
|
||
render(<AutocompleteField element={elementWithoutParams} />); | ||
|
||
const input = screen.getByTestId('test-id'); | ||
expect(input).toHaveAttribute('placeholder', ''); | ||
}); | ||
|
||
it('should pass options from element params to AutocompleteInput', () => { | ||
const elementWithOptions = { | ||
...mockElement, | ||
params: { | ||
options: mockOptions, | ||
placeholder: 'Select an option', | ||
}, | ||
}; | ||
|
||
render(<AutocompleteField element={elementWithOptions} />); | ||
|
||
expect(screen.getByTestId('test-id')).toHaveAttribute('options', JSON.stringify(mockOptions)); | ||
}); | ||
}); |
40 changes: 8 additions & 32 deletions
40
packages/ui/src/components/organisms/Form/DynamicForm/fields/CheckboxField/CheckboxField.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,11 @@ | ||
import { FieldLayout } from '@/pages/CollectionFlowV2/components/ui/field-parts/FieldLayout'; | ||
import { IFieldComponentProps } from '@/pages/CollectionFlowV2/types'; | ||
import { Checkbox, createTestId } from '@ballerine/ui'; | ||
import { FunctionComponent } from 'react'; | ||
import { Checkbox } from '@/components/atoms'; | ||
import { useField } from '../../hooks/external'; | ||
import { TDynamicFormField } from '../../types'; | ||
import { useStack } from '../FieldList/providers/StackProvider'; | ||
|
||
export interface ICheckboxFieldOptions { | ||
label: string; | ||
} | ||
export const CheckboxField: TDynamicFormField = ({ element }) => { | ||
const { stack } = useStack(); | ||
const { value, onChange, disabled } = useField<boolean | undefined>(element, stack); | ||
|
||
export const CheckboxField: FunctionComponent< | ||
IFieldComponentProps<boolean, ICheckboxFieldOptions> | ||
> = ({ fieldProps, definition, options, stack }) => { | ||
const { value, onChange, onBlur, disabled } = fieldProps; | ||
const { label } = options; | ||
|
||
return ( | ||
<FieldLayout | ||
definition={definition} | ||
stack={stack} | ||
className="flex-row flex-row-reverse items-center justify-end" | ||
> | ||
<Checkbox | ||
className="border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground bg-white" | ||
color="primary" | ||
checked={value} | ||
disabled={disabled} | ||
data-testid={createTestId(definition, stack)} | ||
onCheckedChange={e => { | ||
onChange(Boolean(e)); | ||
}} | ||
onBlur={onBlur} | ||
/> | ||
</FieldLayout> | ||
); | ||
return <Checkbox checked={Boolean(value)} onChange={onChange} disabled={disabled} />; | ||
}; |
Oops, something went wrong.