admin/components/paginated-list/paginatedListUtils.test.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

76 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { buildListParams, getColumnFilterConfig, serializeFilters, withRowKeys } from '@/components/paginated-list/paginatedListUtils'
import type { PaginationListColumnType } from '@/types'
describe('paginatedListUtils', () => {
it('serializes scalar and range filters without mutating the input', () => {
const filters = { status: 'active', price: { from: '10', to: '20' }, ignored: '' }
expect(serializeFilters(filters)).toEqual({ status: 'active', price: '10,20' })
expect(filters.price).toEqual({ from: '10', to: '20' })
})
it('merges inherited filters and applies an optional API prefix', () => {
expect(
buildListParams({
filterPrefix: 'booking',
filters: { status: 'paid' },
page: 2,
rowsPerPage: 30,
sort: '-createdAt',
urlParams: { page: 1, pageSize: 20, filters: { owner: 'me' } },
})
).toEqual({
'booking.page': 2,
'booking.pageSize': 30,
'booking.filters': { owner: 'me', status: 'paid' },
'booking.sort': '-createdAt',
})
})
it('creates stable row keys from row id, customer id, or index', () => {
expect(withRowKeys([{ id: 7 }, { customer: { id: 'customer-1' } }, { title: 'fallback' }])).toEqual([
{ id: '7' },
{ customer: { id: 'customer-1' }, id: 'customer-1' },
{ title: 'fallback', id: 'row-2' },
])
})
// getColumnFilterConfig is the single source of truth both
// PaginatedListColumnFilter (inline) and PaginatedListFilterModal (modal)
// dispatch off of via PaginatedListFilterField (FE-4-T1) — locking down
// this mapping is what keeps the two call sites structurally unable to
// diverge for a new column type, in place of testing each consumer
// separately.
describe('getColumnFilterConfig', () => {
const column = (type?: PaginationListColumnType['type'], filterItems?: unknown[]) =>
({ field: 'f', label: 'F', type, filterItems }) as PaginationListColumnType
it('maps text, number, and untyped columns to scalar', () => {
expect(getColumnFilterConfig(column(undefined))).toBe('scalar')
expect(getColumnFilterConfig(column('text'))).toBe('scalar')
expect(getColumnFilterConfig(column('number'))).toBe('scalar')
})
it('maps inputFromTo to range', () => {
expect(getColumnFilterConfig(column('inputFromTo'))).toBe('range')
})
it('maps select to select only when filterItems are present, else none', () => {
expect(getColumnFilterConfig(column('select', [{ code: '1', name: 'One' }]))).toBe('select')
expect(getColumnFilterConfig(column('select', []))).toBe('none')
expect(getColumnFilterConfig(column('select'))).toBe('none')
})
it('maps date to date and dateFromTo to dateRange', () => {
expect(getColumnFilterConfig(column('date'))).toBe('date')
expect(getColumnFilterConfig(column('dateFromTo'))).toBe('dateRange')
})
it('falls back to none for an unrecognized type', () => {
expect(getColumnFilterConfig(column('somethingNew' as never))).toBe('none')
})
})
})