mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
fix lint issues
This commit is contained in:
@@ -72,14 +72,14 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
header: 'Dec lat',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'dec_long',
|
||||
header: 'Dec long',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'altitude',
|
||||
@@ -462,7 +462,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'dc13_n',
|
||||
@@ -477,7 +477,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'dc13_min',
|
||||
@@ -485,7 +485,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'dc13_stdev',
|
||||
@@ -493,7 +493,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'do18_mean',
|
||||
@@ -501,7 +501,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'do18_n',
|
||||
@@ -516,7 +516,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'do18_min',
|
||||
@@ -524,7 +524,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'do18_stdev',
|
||||
@@ -532,7 +532,7 @@ export const CrossSearchTable = ({ selectorFn }: { selectorFn?: (newObject: Cros
|
||||
size: 20,
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
id: 'microwear_now_ls',
|
||||
|
||||
@@ -184,7 +184,7 @@ const NewReferenceDialog = ({
|
||||
data: emptyReference,
|
||||
mode: modeOptionToMode.new,
|
||||
setMode: () => undefined,
|
||||
editData: emptyReference as EditDataType<ReferenceDetailsType>,
|
||||
editData: emptyReference,
|
||||
textField,
|
||||
dropdown,
|
||||
dropdownWithSearch,
|
||||
|
||||
@@ -38,7 +38,7 @@ const createMockDetailContext = (reference: ReferenceDetailsType): DetailContext
|
||||
data: reference,
|
||||
mode: readMode,
|
||||
setMode,
|
||||
editData: reference as EditDataType<ReferenceDetailsType>,
|
||||
editData: reference,
|
||||
setEditData,
|
||||
isDirty: false,
|
||||
resetEditData,
|
||||
|
||||
@@ -92,8 +92,8 @@ export const applyDefaultSpeciesOrdering = <T extends MRT_RowData>(
|
||||
|
||||
return [...rows].sort((leftRow, rightRow) => {
|
||||
for (const field of fields) {
|
||||
const left = normalizeSortValue(getNestedValue(leftRow as MRT_RowData, field))
|
||||
const right = normalizeSortValue(getNestedValue(rightRow as MRT_RowData, field))
|
||||
const left = normalizeSortValue(getNestedValue(leftRow, field))
|
||||
const right = normalizeSortValue(getNestedValue(rightRow, field))
|
||||
|
||||
const compared = left.localeCompare(right)
|
||||
if (compared !== 0) {
|
||||
|
||||
@@ -73,7 +73,7 @@ export const UpdateTab = <T, UpdateType extends MRT_RowData & { updates: UpdateL
|
||||
authorizer={row.original[`${prefix}_authorizer`] as string}
|
||||
coordinator={row.original[`${prefix}_coordinator`] as string}
|
||||
updates={row.original.updates}
|
||||
comment={row.original[`${prefix}_comment` as keyof UpdateType] as string}
|
||||
comment={row.original[`${prefix}_comment` as keyof UpdateType]}
|
||||
references={row.original[refFieldName]}
|
||||
/>
|
||||
),
|
||||
|
||||
@@ -278,9 +278,9 @@ const MultiSelector = <T extends object>({
|
||||
export const EditableTextField = <T extends object>(props: EditableTextFieldProps<T>) => {
|
||||
const { field, disabled = false, big = false, readonly = false, handleSetEditData } = props
|
||||
const type = props.type ?? 'text'
|
||||
const trim = type === 'text' ? (props as EditableTextFieldTextProps<T>).trim ?? false : false
|
||||
const trim = type === 'text' ? ((props as EditableTextFieldTextProps<T>).trim ?? false) : false
|
||||
const round = type === 'number' ? (props as EditableTextFieldNumberProps<T>).round : undefined
|
||||
const integerOnly = type === 'number' ? (props as EditableTextFieldNumberProps<T>).integerOnly ?? false : false
|
||||
const integerOnly = type === 'number' ? ((props as EditableTextFieldNumberProps<T>).integerOnly ?? false) : false
|
||||
const min = type === 'number' ? (props as EditableTextFieldNumberProps<T>).min : undefined
|
||||
const { setEditData, editData, validator, fieldsWithErrors, setFieldsWithErrors } = useDetailContext<T>()
|
||||
const errorObject = validator(editData, field)
|
||||
@@ -402,7 +402,7 @@ export const EditableTextField = <T extends object>(props: EditableTextFieldProp
|
||||
if (integerOnly && event.key === '.') event.preventDefault()
|
||||
}}
|
||||
id={`${String(field)}-textfield`}
|
||||
value={type === 'number' ? numberInputValue : editData[field] ?? ''}
|
||||
value={type === 'number' ? numberInputValue : (editData[field] ?? '')}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
error={!!error}
|
||||
@@ -458,9 +458,7 @@ type EditableTextFieldDateProps<T extends object> = EditableTextFieldCommonProps
|
||||
}
|
||||
|
||||
export type EditableTextFieldProps<T extends object> =
|
||||
| EditableTextFieldTextProps<T>
|
||||
| EditableTextFieldNumberProps<T>
|
||||
| EditableTextFieldDateProps<T>
|
||||
EditableTextFieldTextProps<T> | EditableTextFieldNumberProps<T> | EditableTextFieldDateProps<T>
|
||||
|
||||
export const FieldWithTableSelection = <T extends object, ParentType extends object>({
|
||||
targetField,
|
||||
|
||||
@@ -41,7 +41,7 @@ export const LocalityTable = ({ selectorFn }: { selectorFn?: (newObject: Localit
|
||||
|
||||
if (validIds.length > 0)
|
||||
setFilteredLocalities(localitiesQueryData?.filter(locality => validIds.includes(locality.lid)))
|
||||
else setFilteredLocalities(localitiesQueryData as SimplifiedLocality[])
|
||||
else setFilteredLocalities(localitiesQueryData)
|
||||
}, [columnFilters, localitiesQueryData])
|
||||
|
||||
const columns = useMemo<MRT_ColumnDef<Locality>[]>(
|
||||
@@ -87,14 +87,14 @@ export const LocalityTable = ({ selectorFn }: { selectorFn?: (newObject: Localit
|
||||
header: 'Dec lat',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'dec_long',
|
||||
header: 'Dec long',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
accessorKey: 'altitude',
|
||||
@@ -106,7 +106,7 @@ export const LocalityTable = ({ selectorFn }: { selectorFn?: (newObject: Localit
|
||||
header: 'Max age',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
id: 'bfa_max',
|
||||
@@ -130,7 +130,7 @@ export const LocalityTable = ({ selectorFn }: { selectorFn?: (newObject: Localit
|
||||
header: 'Min age',
|
||||
filterVariant: 'range',
|
||||
enableColumnFilterModes: false,
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue() as number),
|
||||
Cell: ({ cell }) => formatWithMaxThreeDecimals(cell.getValue()),
|
||||
},
|
||||
{
|
||||
id: 'bfa_min',
|
||||
|
||||
@@ -93,19 +93,17 @@ export const MuseumTab = () => {
|
||||
alt_int_name: normalized.alt_int_name || null,
|
||||
state: normalized.state || null,
|
||||
state_code: normalized.state_code || null,
|
||||
} as Museum).unwrap()
|
||||
}).unwrap()
|
||||
|
||||
const refetchResult = await refetchMuseums()
|
||||
const refreshedMuseums = refetchResult.data ?? museumData ?? []
|
||||
const resolvedMuseum =
|
||||
refreshedMuseums.find(museum => museum.museum === museumId) ??
|
||||
({
|
||||
...normalized,
|
||||
museum: museumId,
|
||||
alt_int_name: normalized.alt_int_name || null,
|
||||
state: normalized.state || null,
|
||||
state_code: normalized.state_code || null,
|
||||
} as Museum)
|
||||
const resolvedMuseum = refreshedMuseums.find(museum => museum.museum === museumId) ?? {
|
||||
...normalized,
|
||||
museum: museumId,
|
||||
alt_int_name: normalized.alt_int_name || null,
|
||||
state: normalized.state || null,
|
||||
state_code: normalized.state_code || null,
|
||||
}
|
||||
|
||||
if (editData.now_mus.some(link => link.museum === museumId)) {
|
||||
notify('Museum already linked to this locality.', 'warning')
|
||||
|
||||
@@ -15,7 +15,7 @@ const validateOccurrenceDetail = (
|
||||
editData: EditDataType<OccurrenceDetailsType>,
|
||||
fieldName: keyof EditDataType<OccurrenceDetailsType>
|
||||
): ValidationObject => {
|
||||
return validateOccurrence(editData as EditableOccurrenceData, fieldName as keyof EditableOccurrenceData)
|
||||
return validateOccurrence(editData, fieldName as keyof EditableOccurrenceData)
|
||||
}
|
||||
|
||||
const emptyOccurrence: OccurrenceDetailsType = {
|
||||
|
||||
@@ -134,10 +134,7 @@ export const ReferenceTab = () => {
|
||||
}),
|
||||
])
|
||||
} else if (field.field_name == 'exact_date') {
|
||||
nonAuthorFieldsArray.push([
|
||||
field.ref_field_name,
|
||||
textField(field.field_name as keyof ReferenceDetailsType, { type: 'date' }),
|
||||
])
|
||||
nonAuthorFieldsArray.push([field.ref_field_name, textField(field.field_name, { type: 'date' })])
|
||||
} else {
|
||||
nonAuthorFieldsArray.push([field.ref_field_name, fieldComponent])
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ jest.mock('@/redux/timeUnitReducer', () => {
|
||||
|
||||
// Handle edge case when offset exceeds totalItems
|
||||
const clampedPageIndex = Math.min(derivedPageIndex, sequencesByPage.length - 1)
|
||||
const pageData = clampedPageIndex >= 0 ? sequencesByPage[clampedPageIndex] ?? [] : []
|
||||
const pageData = clampedPageIndex >= 0 ? (sequencesByPage[clampedPageIndex] ?? []) : []
|
||||
|
||||
return {
|
||||
data: {
|
||||
|
||||
@@ -50,7 +50,7 @@ export const SpeciesDetails = ({
|
||||
// this should be removed if validators are improved in the future
|
||||
if (data) {
|
||||
const fixedSpeciesData = fixNullValuesInTaxonomyFields(data)
|
||||
setModifiedData(fixedSpeciesData as SpeciesDetailsType)
|
||||
setModifiedData(fixedSpeciesData)
|
||||
}
|
||||
}, [data])
|
||||
|
||||
|
||||
@@ -20,10 +20,7 @@ export const SynonymTab = () => {
|
||||
const convertAndCheckNewSynonymTaxonomy = (newSynonym: EditDataType<SpeciesSynonym>) => {
|
||||
const errors = []
|
||||
for (const field in newSynonym) {
|
||||
const errorObject = validateSynonym(
|
||||
newSynonym as unknown as EditDataType<SpeciesSynonym>,
|
||||
field as unknown as keyof EditDataType<SpeciesSynonym>
|
||||
)
|
||||
const errorObject = validateSynonym(newSynonym, field as unknown as keyof EditDataType<SpeciesSynonym>)
|
||||
const { error } = errorObject
|
||||
if (error) errors.push(errorObject)
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ const applyColumnFilterModeDefaults = <T extends MRT_RowData>(
|
||||
columnFilterFns[columnId] = 'equals'
|
||||
return {
|
||||
...column,
|
||||
filterFn: typeof column.filterFn === 'function' ? column.filterFn : column.filterFn ?? 'equals',
|
||||
filterFn: typeof column.filterFn === 'function' ? column.filterFn : (column.filterFn ?? 'equals'),
|
||||
enableColumnFilterModes: false,
|
||||
columnFilterModeOptions: ['equals'],
|
||||
}
|
||||
@@ -150,7 +150,7 @@ const applyColumnFilterModeDefaults = <T extends MRT_RowData>(
|
||||
columnFilterFns[columnId] = 'equals'
|
||||
return {
|
||||
...column,
|
||||
filterFn: typeof column.filterFn === 'function' ? column.filterFn : column.filterFn ?? 'equals',
|
||||
filterFn: typeof column.filterFn === 'function' ? column.filterFn : (column.filterFn ?? 'equals'),
|
||||
enableColumnFilterModes: false,
|
||||
columnFilterModeOptions: ['equals'],
|
||||
}
|
||||
|
||||
@@ -22,49 +22,47 @@ jest.mock('@/shared/types', () => ({}))
|
||||
|
||||
type TestPageContext = PageContextType<unknown>
|
||||
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext =>
|
||||
({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
}) as TestPageContext
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext => ({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
})
|
||||
|
||||
type TestDetailContext = DetailContextType<unknown>
|
||||
|
||||
const createDetailContextValue = (overrides: Partial<TestDetailContext> = {}): TestDetailContext =>
|
||||
({
|
||||
data: {},
|
||||
mode: modeOptionToMode.read,
|
||||
setMode: () => {},
|
||||
editData: {} as TestDetailContext['editData'],
|
||||
setEditData: (() => {}) as TestDetailContext['setEditData'],
|
||||
isDirty: false,
|
||||
resetEditData: () => {},
|
||||
textField: (() => <></>) as TestDetailContext['textField'],
|
||||
bigTextField: (() => <></>) as TestDetailContext['bigTextField'],
|
||||
dropdown: (() => <></>) as TestDetailContext['dropdown'],
|
||||
dropdownWithSearch: (() => <></>) as TestDetailContext['dropdownWithSearch'],
|
||||
radioSelection: (() => <></>) as TestDetailContext['radioSelection'],
|
||||
validator: () => ({ name: 'field', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
...overrides,
|
||||
}) as TestDetailContext
|
||||
const createDetailContextValue = (overrides: Partial<TestDetailContext> = {}): TestDetailContext => ({
|
||||
data: {},
|
||||
mode: modeOptionToMode.read,
|
||||
setMode: () => {},
|
||||
editData: {},
|
||||
setEditData: () => {},
|
||||
isDirty: false,
|
||||
resetEditData: () => {},
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
dropdownWithSearch: () => <></>,
|
||||
radioSelection: () => <></>,
|
||||
validator: () => ({ name: 'field', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const pageContextValue: TestPageContext = createPageContextValue()
|
||||
|
||||
|
||||
@@ -190,13 +190,13 @@ export const usePaginatedQuery = <
|
||||
}, [rows, envelope])
|
||||
|
||||
const transformedRows = useMemo(() => {
|
||||
if (!rows) return rows as unknown as TMapped[] | undefined
|
||||
if (!rows) return rows
|
||||
if (!selectorFn) return rows as unknown as TMapped[]
|
||||
|
||||
return rows.map((item, index) => {
|
||||
const mapped = selectorFn(item)
|
||||
if (index === 0 && typeof fullCount === 'number' && isObject(mapped) && !('full_count' in mapped)) {
|
||||
return { ...mapped, full_count: fullCount } as TMapped
|
||||
return { ...mapped, full_count: fullCount }
|
||||
}
|
||||
return mapped
|
||||
})
|
||||
|
||||
@@ -117,8 +117,9 @@ const taxonomyFields = new Set([
|
||||
])
|
||||
|
||||
const isEmptyValue = (value: unknown) => value === null || value === undefined || value === ''
|
||||
const normalizeValue = (value: unknown) => (isEmptyValue(value) ? '' : String(value))
|
||||
const isSameValue = (left: unknown, right: unknown) => normalizeValue(left) === normalizeValue(right)
|
||||
const normalizeValue = (value: string | number | boolean | null) => (isEmptyValue(value) ? '' : String(value))
|
||||
const isSameValue = (left: string | number | boolean | null, right: string | number | boolean | null) =>
|
||||
normalizeValue(left) === normalizeValue(right)
|
||||
|
||||
const resolveMergeErrorMessage = (error: unknown): string => {
|
||||
if (error && typeof error === 'object' && 'data' in error) {
|
||||
|
||||
@@ -50,21 +50,21 @@ const authorCheck: (data: ReferenceAuthorType[]) => ValidationError = (data: Ref
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
return ('Authors gave the following errors: ' + errors.join(', ')) as ValidationError
|
||||
return 'Authors gave the following errors: ' + errors.join(', ')
|
||||
}
|
||||
return null as ValidationError
|
||||
}
|
||||
|
||||
const journalCheck: (journal: ReferenceJournalType) => ValidationError = (journal: ReferenceJournalType) => {
|
||||
if (!journal) {
|
||||
return 'You must select or create a new journal' as ValidationError
|
||||
return 'You must select or create a new journal'
|
||||
}
|
||||
//Existing journal can't have rowState 'removed' if journal is mandatory
|
||||
if (journal.rowState && journal.rowState == 'removed') {
|
||||
return 'You must select or create a new journal' as ValidationError
|
||||
return 'You must select or create a new journal'
|
||||
}
|
||||
if (typeof journal.journal_title !== 'string' || journal.journal_title?.length < 1) {
|
||||
return 'Journal must have a title' as ValidationError
|
||||
return 'Journal must have a title'
|
||||
}
|
||||
return null as ValidationError
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const createProvider = (state: TestContextState) => (
|
||||
<DetailContextProvider
|
||||
contextState={{
|
||||
...state,
|
||||
editData: state.data as EditDataType<TestData>,
|
||||
editData: state.data,
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
|
||||
@@ -62,7 +62,7 @@ const TimeUnitTabContent = () => {
|
||||
onClick={() =>
|
||||
setEditData({
|
||||
...editData,
|
||||
up_bound: { ...(editData.up_bound ?? {}), age: 99 } as TimeUnitDetailsType['up_bound'],
|
||||
up_bound: { ...(editData.up_bound ?? {}), age: 99 },
|
||||
})
|
||||
}
|
||||
>
|
||||
|
||||
@@ -63,7 +63,7 @@ const TimeUnitTabContent = () => {
|
||||
onClick={() =>
|
||||
setEditData({
|
||||
...editData,
|
||||
up_bound: { ...(editData.up_bound ?? {}), age: 99 } as TimeUnitDetailsType['up_bound'],
|
||||
up_bound: { ...(editData.up_bound ?? {}), age: 99 },
|
||||
})
|
||||
}
|
||||
>
|
||||
|
||||
@@ -29,14 +29,14 @@ const createContextValue = (): DetailContextType<ParentType> => ({
|
||||
data: { species: [] },
|
||||
mode: modeOptionToMode.edit,
|
||||
setMode: jest.fn(),
|
||||
editData: { species: [] } as EditDataType<ParentType>,
|
||||
editData: { species: [] },
|
||||
setEditData: jest.fn(),
|
||||
textField: (() => <span />) as DetailContextType<ParentType>['textField'],
|
||||
bigTextField: (() => <span />) as DetailContextType<ParentType>['bigTextField'],
|
||||
dropdown: (() => <span />) as DetailContextType<ParentType>['dropdown'],
|
||||
dropdownWithSearch: (() => <span />) as DetailContextType<ParentType>['dropdownWithSearch'],
|
||||
radioSelection: (() => <span />) as DetailContextType<ParentType>['radioSelection'],
|
||||
validator: (() => ({ name: '', error: null })) as DetailContextType<ParentType>['validator'],
|
||||
textField: () => <span />,
|
||||
bigTextField: () => <span />,
|
||||
dropdown: () => <span />,
|
||||
dropdownWithSearch: () => <span />,
|
||||
radioSelection: () => <span />,
|
||||
validator: () => ({ name: '', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: jest.fn(),
|
||||
isDirty: false,
|
||||
|
||||
@@ -202,12 +202,12 @@ const createContextValue = (): DetailContextType<LocalityDetailsType> => ({
|
||||
setMode: jest.fn(),
|
||||
editData: { lid: 1, now_ls: [] } as unknown as EditDataType<LocalityDetailsType>,
|
||||
setEditData,
|
||||
textField: (() => <span />) as DetailContextType<LocalityDetailsType>['textField'],
|
||||
bigTextField: (() => <span />) as DetailContextType<LocalityDetailsType>['bigTextField'],
|
||||
dropdown: (() => <span />) as DetailContextType<LocalityDetailsType>['dropdown'],
|
||||
dropdownWithSearch: (() => <span />) as DetailContextType<LocalityDetailsType>['dropdownWithSearch'],
|
||||
radioSelection: (() => <span />) as DetailContextType<LocalityDetailsType>['radioSelection'],
|
||||
validator: (() => ({ name: '', error: null })) as DetailContextType<LocalityDetailsType>['validator'],
|
||||
textField: () => <span />,
|
||||
bigTextField: () => <span />,
|
||||
dropdown: () => <span />,
|
||||
dropdownWithSearch: () => <span />,
|
||||
radioSelection: () => <span />,
|
||||
validator: () => ({ name: '', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: jest.fn(),
|
||||
isDirty: false,
|
||||
|
||||
@@ -128,7 +128,7 @@ describe('ProjectDetails', () => {
|
||||
mockUseUsersApi.mockReturnValue({ users: [], isLoading: false, isError: false })
|
||||
mockNotify.mockReset()
|
||||
mockNavigate.mockReset()
|
||||
window.confirm = jest.fn(() => true) as unknown as typeof window.confirm
|
||||
window.confirm = jest.fn(() => true)
|
||||
})
|
||||
|
||||
it('deletes the project and navigates back to the list', async () => {
|
||||
|
||||
@@ -147,7 +147,7 @@ describe('WriteButton taxonomy handling', () => {
|
||||
const onWrite = jest.fn(() => Promise.resolve())
|
||||
mockCheckSpeciesTaxonomy.mockReturnValue(new Set(['The taxon already exists in the database.']))
|
||||
|
||||
renderButton({ ...baseSpecies, sp_comment: 'Updated comment' } as EditDataType<Species>, onWrite)
|
||||
renderButton({ ...baseSpecies, sp_comment: 'Updated comment' }, onWrite)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /save changes/i }))
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('WriteButton taxonomy handling', () => {
|
||||
const onWrite = jest.fn(() => Promise.resolve())
|
||||
mockCheckSpeciesTaxonomy.mockReturnValue(new Set(['The taxon already exists in the database.']))
|
||||
|
||||
renderButton({ ...baseSpecies, genus_name: 'Gorilla' } as EditDataType<Species>, onWrite)
|
||||
renderButton({ ...baseSpecies, genus_name: 'Gorilla' }, onWrite)
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /save changes/i }))
|
||||
|
||||
@@ -177,7 +177,7 @@ describe('WriteButton taxonomy handling', () => {
|
||||
const onWrite = jest.fn(() => Promise.resolve())
|
||||
const setEditData = jest.fn()
|
||||
|
||||
renderButton({ ...baseSpecies, sp_comment: '' } as EditDataType<Species>, onWrite, { setEditData })
|
||||
renderButton({ ...baseSpecies, sp_comment: '' }, onWrite, { setEditData })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /save changes/i }))
|
||||
|
||||
@@ -190,14 +190,14 @@ describe('WriteButton taxonomy handling', () => {
|
||||
})
|
||||
|
||||
it('disables the button when no edits have been made', () => {
|
||||
renderButton(baseSpecies as EditDataType<Species>, jest.fn(), { isDirty: false })
|
||||
renderButton(baseSpecies, jest.fn(), { isDirty: false })
|
||||
|
||||
const button = screen.getByRole('button', { name: /save changes/i })
|
||||
expect((button as HTMLButtonElement).disabled).toBe(true)
|
||||
})
|
||||
|
||||
it('shows helper tooltip when hovering the disabled button', async () => {
|
||||
renderButton(baseSpecies as EditDataType<Species>, jest.fn(), { isDirty: false })
|
||||
renderButton(baseSpecies, jest.fn(), { isDirty: false })
|
||||
|
||||
const button = screen.getByRole('button', { name: /save changes/i })
|
||||
const tooltipTrigger = button.parentElement
|
||||
@@ -211,7 +211,7 @@ describe('WriteButton taxonomy handling', () => {
|
||||
})
|
||||
|
||||
it('enables the button after edits have been made', () => {
|
||||
renderButton(baseSpecies as EditDataType<Species>, jest.fn(), { isDirty: true })
|
||||
renderButton(baseSpecies, jest.fn(), { isDirty: true })
|
||||
|
||||
const button = screen.getByRole('button', { name: /save changes/i })
|
||||
expect((button as HTMLButtonElement).disabled).toBe(false)
|
||||
@@ -220,7 +220,7 @@ describe('WriteButton taxonomy handling', () => {
|
||||
it('disables the button in staging mode when no edits have been made', () => {
|
||||
const onWrite = jest.fn(() => Promise.resolve())
|
||||
|
||||
renderButton(baseSpecies as EditDataType<Species>, onWrite, {
|
||||
renderButton(baseSpecies, onWrite, {
|
||||
isDirty: false,
|
||||
mode: modeStagingEdit,
|
||||
})
|
||||
|
||||
@@ -63,7 +63,7 @@ jest.mock('@/components/Reference/Tabs/ReferenceTab', () => ({
|
||||
},
|
||||
],
|
||||
ref_journal: undefined,
|
||||
} as unknown as EditDataType<ReferenceDetailsType>)
|
||||
})
|
||||
}
|
||||
>
|
||||
Fill reference
|
||||
@@ -117,7 +117,7 @@ const renderStagingView = () => {
|
||||
data: { references: [], comment: '' },
|
||||
mode: modeOptionToMode['staging-new'],
|
||||
setMode: jest.fn(),
|
||||
editData: { references: [], comment: '' } as EditDataType<StagingData>,
|
||||
editData: { references: [], comment: '' },
|
||||
textField: jest.fn(() => <input aria-label="field" />),
|
||||
bigTextField: jest.fn(() => <textarea aria-label="comment" />),
|
||||
dropdown: jest.fn(() => <select aria-label="dropdown" />),
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('useUnsavedChangesPrompt', () => {
|
||||
proceed: undefined,
|
||||
reset: undefined,
|
||||
location: undefined,
|
||||
} as ReturnType<typeof useBlocker>)
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
// Polyfill for React Router's data router in Jest environment
|
||||
// See: https://github.com/remix-run/react-router/discussions/9851
|
||||
import '@testing-library/jest-dom'
|
||||
import { TextDecoder, TextEncoder } from 'util'
|
||||
|
||||
if (typeof global.TextEncoder === 'undefined') {
|
||||
global.TextEncoder = TextEncoder
|
||||
}
|
||||
|
||||
if (typeof global.TextDecoder === 'undefined') {
|
||||
global.TextDecoder = TextDecoder
|
||||
}
|
||||
|
||||
if (typeof global.Request === 'undefined') {
|
||||
global.Request = class Request {
|
||||
@@ -49,5 +58,5 @@ if (typeof global.fetch === 'undefined') {
|
||||
}
|
||||
|
||||
if (typeof global.structuredClone === 'undefined') {
|
||||
global.structuredClone = (<T>(value: T) => JSON.parse(JSON.stringify(value)) as T) as typeof structuredClone
|
||||
global.structuredClone = <T>(value: T) => JSON.parse(JSON.stringify(value)) as T
|
||||
}
|
||||
|
||||
@@ -13,12 +13,7 @@ type ApiErrorResult = {
|
||||
}
|
||||
|
||||
const isApiErrorShape = (error: unknown): error is ApiErrorShape => {
|
||||
return (
|
||||
typeof error === 'object' &&
|
||||
error !== null &&
|
||||
'status' in error &&
|
||||
typeof (error as { status: unknown }).status === 'number'
|
||||
)
|
||||
return typeof error === 'object' && error !== null && 'status' in error && typeof error.status === 'number'
|
||||
}
|
||||
|
||||
const isSerializedError = (error: unknown): error is SerializedError => {
|
||||
|
||||
@@ -61,7 +61,7 @@ const createContextValue = (overrides: ContextOverrides = {}): TestDetailContext
|
||||
data,
|
||||
mode: overrides.mode ?? modeOptionToMode.read,
|
||||
setMode: jest.fn(),
|
||||
editData: overrides.editData ?? (data as EditDataType<LocalityDetailsType>),
|
||||
editData: overrides.editData ?? data,
|
||||
setEditData: overrides.setEditData ?? jest.fn(),
|
||||
textField: () => <input aria-label="text-field" readOnly />,
|
||||
bigTextField: () => <textarea aria-label="big-text-field" readOnly />,
|
||||
|
||||
@@ -48,32 +48,30 @@ jest.mock('@/components/DetailView/Context/DetailContext', () => ({
|
||||
|
||||
const createDetailContextValue = (
|
||||
overrides: Partial<DetailContextType<ReferenceDetailsType>> = {}
|
||||
): DetailContextType<ReferenceDetailsType> =>
|
||||
({
|
||||
data: {} as ReferenceDetailsType,
|
||||
mode: modeOptionToMode.edit,
|
||||
setMode: () => {},
|
||||
editData: { rid: 1, ref_authors: [] } as unknown as EditDataType<ReferenceDetailsType>,
|
||||
setEditData: () => {},
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
dropdownWithSearch: () => <></>,
|
||||
radioSelection: () => <></>,
|
||||
validator: () => ({ name: '', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
isDirty: false,
|
||||
resetEditData: () => {},
|
||||
...overrides,
|
||||
}) as DetailContextType<ReferenceDetailsType>
|
||||
): DetailContextType<ReferenceDetailsType> => ({
|
||||
data: {} as ReferenceDetailsType,
|
||||
mode: modeOptionToMode.edit,
|
||||
setMode: () => {},
|
||||
editData: { rid: 1, ref_authors: [] },
|
||||
setEditData: () => {},
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
dropdownWithSearch: () => <></>,
|
||||
radioSelection: () => <></>,
|
||||
validator: () => ({ name: '', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
isDirty: false,
|
||||
resetEditData: () => {},
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const buildAuthor = (overrides: Partial<ReferenceAuthorType> = {}): ReferenceAuthorType =>
|
||||
({
|
||||
author_surname: 'Cande',
|
||||
author_initials: 'S.C.',
|
||||
...overrides,
|
||||
}) as ReferenceAuthorType
|
||||
const buildAuthor = (overrides: Partial<ReferenceAuthorType> = {}): ReferenceAuthorType => ({
|
||||
author_surname: 'Cande',
|
||||
author_initials: 'S.C.',
|
||||
...overrides,
|
||||
})
|
||||
|
||||
describe('AuthorTab', () => {
|
||||
it('filters out already-selected authors from the selector list', () => {
|
||||
|
||||
@@ -207,8 +207,8 @@ describe('SpeciesTable synonym filtering', () => {
|
||||
expect(speciesWithSynonyms).toBeDefined()
|
||||
const row = { original: speciesWithSynonyms! }
|
||||
|
||||
expect(genusFilter!(row as { original: Species }, 'genus_name', 'lupus')).toBe(true)
|
||||
expect(genusFilter!(row as { original: Species }, 'genus_name', 'unknown')).toBe(false)
|
||||
expect(genusFilter!(row, 'genus_name', 'lupus')).toBe(true)
|
||||
expect(genusFilter!(row, 'genus_name', 'unknown')).toBe(false)
|
||||
})
|
||||
|
||||
it('matches rows when the species filter value appears in a synonym', () => {
|
||||
@@ -223,8 +223,8 @@ describe('SpeciesTable synonym filtering', () => {
|
||||
expect(speciesWithSynonyms).toBeDefined()
|
||||
const row = { original: speciesWithSynonyms! }
|
||||
|
||||
expect(speciesFilter!(row as { original: Species }, 'species_name', 'fami')).toBe(true)
|
||||
expect(speciesFilter!(row as { original: Species }, 'species_name', 'absent')).toBe(false)
|
||||
expect(speciesFilter!(row, 'species_name', 'fami')).toBe(true)
|
||||
expect(speciesFilter!(row, 'species_name', 'absent')).toBe(false)
|
||||
})
|
||||
|
||||
it('provides unique column identifiers', () => {
|
||||
|
||||
@@ -177,7 +177,7 @@ describe('project mapping helpers', () => {
|
||||
})
|
||||
|
||||
it('returns null when coordinator cannot be matched to a user', () => {
|
||||
const payload = mapProjectEditDataToUpdatePayload(baseProject as EditDataType<ProjectDetailsType>, [
|
||||
const payload = mapProjectEditDataToUpdatePayload(baseProject, [
|
||||
{ userId: 99, label: 'Other, Person', initials: 'XX' },
|
||||
])
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ const conflictError = Object.assign(new Error('The Reference with associated upd
|
||||
})
|
||||
|
||||
describe('ReferenceDetails deletion', () => {
|
||||
const originalConfirm = window.confirm
|
||||
const originalConfirm = window.confirm.bind(window)
|
||||
const mockDeleteTrigger = jest.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -40,7 +40,7 @@ const baseTimeBound: TimeBoundDetailsType = {
|
||||
age: 12,
|
||||
b_comment: '',
|
||||
now_bau: [],
|
||||
} as unknown as TimeBoundDetailsType
|
||||
}
|
||||
|
||||
const createDetailContextValue = (overrides: Partial<DetailContextType<TimeBoundDetailsType>> = {}) =>
|
||||
({
|
||||
|
||||
@@ -23,27 +23,26 @@ jest.mock('@/shared/types', () => ({}))
|
||||
|
||||
type TestPageContext = PageContextType<unknown>
|
||||
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext =>
|
||||
({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
}) as TestPageContext
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext => ({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
})
|
||||
|
||||
type TestDetailContext = DetailContextType<unknown>
|
||||
|
||||
@@ -52,13 +51,13 @@ const createDetailContextValue = (overrides: Partial<TestDetailContext> = {}): T
|
||||
data: {},
|
||||
mode: modeOptionToMode.read,
|
||||
setMode: () => {},
|
||||
editData: {} as TestDetailContext['editData'],
|
||||
setEditData: (() => {}) as TestDetailContext['setEditData'],
|
||||
textField: (() => <></>) as TestDetailContext['textField'],
|
||||
bigTextField: (() => <></>) as TestDetailContext['bigTextField'],
|
||||
dropdown: (() => <></>) as TestDetailContext['dropdown'],
|
||||
dropdownWithSearch: (() => <></>) as TestDetailContext['dropdownWithSearch'],
|
||||
radioSelection: (() => <></>) as TestDetailContext['radioSelection'],
|
||||
editData: {},
|
||||
setEditData: () => {},
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
dropdownWithSearch: () => <></>,
|
||||
radioSelection: () => <></>,
|
||||
validator: () => ({ name: 'field', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
|
||||
@@ -69,27 +69,26 @@ const createReference = (overrides: ReferenceOverride = {}): ReferenceMock => ({
|
||||
|
||||
type TestPageContext = PageContextType<unknown>
|
||||
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext =>
|
||||
({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
}) as TestPageContext
|
||||
const createPageContextValue = (overrides: Partial<TestPageContext> = {}): TestPageContext => ({
|
||||
idList: [],
|
||||
setIdList: () => {},
|
||||
idFieldName: 'rid',
|
||||
viewName: 'reference',
|
||||
previousTableUrls: [],
|
||||
setPreviousTableUrls: () => {},
|
||||
createTitle: () => '',
|
||||
createSubtitle: () => '',
|
||||
editRights: {},
|
||||
sqlLimit: 25,
|
||||
sqlOffset: 0,
|
||||
sqlColumnFilters: [],
|
||||
sqlOrderBy: [],
|
||||
setSqlLimit: () => {},
|
||||
setSqlOffset: () => {},
|
||||
setSqlColumnFilters: () => {},
|
||||
setSqlOrderBy: () => {},
|
||||
...overrides,
|
||||
})
|
||||
|
||||
type TestDetailContext = DetailContextType<unknown>
|
||||
|
||||
@@ -98,13 +97,13 @@ const createDetailContextValue = (overrides: Partial<TestDetailContext> = {}): T
|
||||
data: {},
|
||||
mode: modeOptionToMode.read,
|
||||
setMode: () => {},
|
||||
editData: {} as TestDetailContext['editData'],
|
||||
setEditData: (() => {}) as TestDetailContext['setEditData'],
|
||||
textField: (() => <></>) as TestDetailContext['textField'],
|
||||
bigTextField: (() => <></>) as TestDetailContext['bigTextField'],
|
||||
dropdown: (() => <></>) as TestDetailContext['dropdown'],
|
||||
dropdownWithSearch: (() => <></>) as TestDetailContext['dropdownWithSearch'],
|
||||
radioSelection: (() => <></>) as TestDetailContext['radioSelection'],
|
||||
editData: {},
|
||||
setEditData: () => {},
|
||||
textField: () => <></>,
|
||||
bigTextField: () => <></>,
|
||||
dropdown: () => <></>,
|
||||
dropdownWithSearch: () => <></>,
|
||||
radioSelection: () => <></>,
|
||||
validator: () => ({ name: 'field', error: null }),
|
||||
fieldsWithErrors: {},
|
||||
setFieldsWithErrors: () => {},
|
||||
|
||||
Reference in New Issue
Block a user