-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ feat: Implemented hook to check for value errors
- Loading branch information
1 parent
981c3cb
commit 73b897d
Showing
2 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
97 changes: 97 additions & 0 deletions
97
src/app/(routes)/ledgers/[id]/transactions/create/use-transaction-form-errors.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,97 @@ | ||
import { renderHook, act } from '@testing-library/react' | ||
import { useIntl } from 'react-intl' | ||
import { useTransactionFormErrors } from './use-transaction-form-errors' | ||
import { TransactionFormSchema } from './schemas' | ||
|
||
jest.mock('react-intl', () => ({ | ||
useIntl: jest.fn() | ||
})) | ||
|
||
describe('useTransactionFormErrors', () => { | ||
const intlMock = { | ||
formatMessage: jest.fn(({ defaultMessage }) => defaultMessage) | ||
} | ||
|
||
beforeEach(() => { | ||
;(useIntl as jest.Mock).mockReturnValue(intlMock) | ||
}) | ||
|
||
it('should return no errors initially', () => { | ||
const { result } = renderHook(() => | ||
useTransactionFormErrors({ | ||
value: 0, | ||
source: [], | ||
destination: [] | ||
} as any) | ||
) | ||
expect(result.current.errors).toEqual({}) | ||
}) | ||
|
||
it('should add debit error if source sum does not match value', () => { | ||
const { result } = renderHook(() => | ||
useTransactionFormErrors({ | ||
value: 100, | ||
source: [{ value: 50 }], | ||
destination: [] | ||
} as any) | ||
) | ||
|
||
act(() => { | ||
result.current.errors | ||
}) | ||
|
||
expect(result.current.errors.debit).toBe( | ||
'Total Debits do not match total Credits' | ||
) | ||
}) | ||
|
||
it('should add credit error if destination sum does not match value', () => { | ||
const { result } = renderHook(() => | ||
useTransactionFormErrors({ | ||
value: '100', | ||
source: [], | ||
destination: [{ value: '50' }] | ||
} as any) | ||
) | ||
|
||
act(() => { | ||
result.current.errors | ||
}) | ||
|
||
expect(result.current.errors.credit).toBe( | ||
'Total Debits do not match total Credits' | ||
) | ||
}) | ||
|
||
it('should remove debit error if source sum matches value', () => { | ||
const { result } = renderHook(() => | ||
useTransactionFormErrors({ | ||
value: '100', | ||
source: [{ value: '100' }], | ||
destination: [] | ||
} as any) | ||
) | ||
|
||
act(() => { | ||
result.current.errors | ||
}) | ||
|
||
expect(result.current.errors.debit).toBeUndefined() | ||
}) | ||
|
||
it('should remove credit error if destination sum matches value', () => { | ||
const { result } = renderHook(() => | ||
useTransactionFormErrors({ | ||
value: '100', | ||
source: [], | ||
destination: [{ value: '100' }] | ||
} as any) | ||
) | ||
|
||
act(() => { | ||
result.current.errors | ||
}) | ||
|
||
expect(result.current.errors.credit).toBeUndefined() | ||
}) | ||
}) |
55 changes: 55 additions & 0 deletions
55
src/app/(routes)/ledgers/[id]/transactions/create/use-transaction-form-errors.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,55 @@ | ||
import { useEffect, useState } from 'react' | ||
import { useIntl } from 'react-intl' | ||
import { TransactionFormSchema, TransactionSourceFormSchema } from './schemas' | ||
|
||
export type TransactionFormErrors = Record<string, string> | ||
|
||
export const useTransactionFormErrors = (values: TransactionFormSchema) => { | ||
const intl = useIntl() | ||
const [errors, setErrors] = useState<TransactionFormErrors>({}) | ||
const { value, source, destination } = values | ||
|
||
const sum = (source: TransactionSourceFormSchema) => | ||
source.reduce((acc, curr) => acc + Number(curr.value), 0) | ||
|
||
const addError = (key: string, value: string) => { | ||
setErrors((prev) => ({ ...prev, [key]: value })) | ||
} | ||
|
||
const removeError = (key: string) => { | ||
setErrors((prev) => { | ||
const { [key]: _, ...rest } = prev | ||
return rest | ||
}) | ||
} | ||
|
||
useEffect(() => { | ||
const v = Number(value) | ||
|
||
if (v !== sum(source)) { | ||
addError( | ||
'debit', | ||
intl.formatMessage({ | ||
id: 'transactions.errors.debit', | ||
defaultMessage: 'Total Debits do not match total Credits' | ||
}) | ||
) | ||
} else { | ||
removeError('debit') | ||
} | ||
|
||
if (v !== sum(destination)) { | ||
addError( | ||
'credit', | ||
intl.formatMessage({ | ||
id: 'transactions.errors.debit', | ||
defaultMessage: 'Total Debits do not match total Credits' | ||
}) | ||
) | ||
} else { | ||
removeError('credit') | ||
} | ||
}, [value, sum(source), sum(destination)]) | ||
|
||
return { errors } | ||
} |