Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Add the ability to send ad-hoc text messages from a user's record. Refs UIU-3572.
* Update Reset button style and conditional clear icons. Refs UIU-3232.
* Show renew confirmation popup after multi-item renewal. Refs UIU-3625.
* Fix crash when opening the Version history pane on the user detail view. Fixes UIU-3630.

## [13.0.2] (https://github.com/folio-org/ui-users/tree/v13.0.2) (2026-06-12)
[Full Changelog](https://github.com/folio-org/ui-users/compare/v13.0.1...v13.0.2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ const useUserVersionHistoryFormatters = () => {
);

const contactTypesMap = useMemo(
() => Object.fromEntries(contactTypes.map(type => [type.id, formatMessage({ id: type.desc })])),
[formatMessage],
() => Object.fromEntries(contactTypes.map(type => [type.value, type.label])),
[],
);

const fieldLabelsMap = useMemo(
Expand All @@ -131,7 +131,7 @@ const useUserVersionHistoryFormatters = () => {
? formatMessage({ id: 'ui-users.active' })
: formatMessage({ id: 'ui-users.inactive' })),
patronGroup: value => patronGroupsMap[value] || value,
preferredContactTypeIds: value => formatList(value.map(v => contactTypesMap[v])),
preferredContactTypeIds: value => formatList([value ?? []].flat().map(v => contactTypesMap[v] ?? v)),
expirationDate: renderDate,
dateOfBirth: renderDate,
enrollmentDate: renderDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ jest.mock('../../../../hooks/usePatronGroups', () => jest.fn());
const renderFormatters = () => renderHook(() => useUserVersionHistoryFormatters()).result.current;

const isNoValue = node => node?.type === NoValue;
// contactTypes labels are <FormattedMessage> elements; unmatched codes stay raw strings.
const contactTypeIds = (fieldFormatter, value) => fieldFormatter
.preferredContactTypeIds(value)
.map(item => item?.props?.id ?? item);

describe('useUserVersionHistoryFormatters', () => {
beforeEach(() => {
Expand All @@ -36,6 +40,35 @@ describe('useUserVersionHistoryFormatters', () => {
expect(fieldFormatter.departments('dept-missing')).toBe('dept-missing');
});

it('resolves preferred contact type ids to their labels', () => {
const { fieldFormatter } = renderFormatters();

expect(contactTypeIds(fieldFormatter, ['002', '003'])).toEqual([
'ui-users.data.contactTypes.email',
'ui-users.data.contactTypes.textMessage',
]);
});

it('accepts a preferred contact type id that is not wrapped in an array', () => {
const { fieldFormatter } = renderFormatters();

expect(contactTypeIds(fieldFormatter, '001')).toEqual(['ui-users.data.contactTypes.mail']);
});

it('falls back to the raw value for an unknown preferred contact type id', () => {
const { fieldFormatter } = renderFormatters();

expect(contactTypeIds(fieldFormatter, ['999'])).toEqual(['999']);
});

it('renders an empty list when no preferred contact type is set', () => {
const { fieldFormatter } = renderFormatters();

expect(fieldFormatter.preferredContactTypeIds(null)).toEqual([]);
expect(fieldFormatter.preferredContactTypeIds(undefined)).toEqual([]);
expect(fieldFormatter.preferredContactTypeIds([])).toEqual([]);
});

it('renders NoValue for an empty proxyFor value', () => {
const { fieldFormatter } = renderFormatters();

Expand Down
3 changes: 3 additions & 0 deletions test/jest/__mock__/intl.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import React from 'react';
jest.mock('react-intl', () => {
const intl = {
formatMessage: ({ id }) => id,
// Real formatList interleaves separators and returns a node array for
// non-string values; returning the list as-is keeps assertions readable.
formatList: (values) => values,
formatNumber: (value) => value,
formatTime: (value) => value,
formatDisplayName: (value) => value,
Expand Down
Loading