mattermost-mobile/app/actions/remote/custom_profile.test.ts
Guillermo Vayá 972bd34da6
[MM-62700] User Attribute types (#8903)
* add basic types to user_profile

* fix storing multiselect in DB

* fix storing multi-select on db

* add tests

* add tests for select-multiselect

* imporove testing

* improve intl, add tests

* address comments and tests

* review comments

* more test refactoring

* remove styling tests

* remove styling tests

* small improvements

* nitpick

* improve messaging

* safer stringify

* fix tests
2025-06-12 10:59:13 +02:00

281 lines
10 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import NetworkManager from '@managers/network_manager';
import {
fetchCustomProfileAttributes,
updateCustomProfileAttributes,
} from './custom_profile';
jest.mock('@database/manager', () => ({
getServerDatabaseAndOperator: jest.fn().mockReturnValue({
operator: {
batchRecords: jest.fn(),
handleCustomProfileFields: jest.fn(),
handleCustomProfileAttributes: jest.fn(),
},
}),
}));
beforeAll(() => {
// @ts-ignore
NetworkManager.getClient = () => mockClient;
});
const mockClient = {
getCustomProfileAttributeFields: jest.fn(),
getCustomProfileAttributeValues: jest.fn(),
updateCustomProfileAttributeValues: jest.fn(),
};
const serverUrl = 'baseHandler.test.com';
describe('Custom Profile Attributes', () => {
it('fetchCustomProfileAttributes - base case without filter', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'field1', name: 'Field 1', attrs: {sort_order: 1}},
{id: 'field2', name: 'Field 2', attrs: {sort_order: 2}},
{id: 'field3', name: 'Field 3', attrs: {sort_order: 3}},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
field1: 'value1',
field2: '',
field3: 'value3',
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(Object.keys(result.attributes!)).toHaveLength(3);
expect(result.attributes!.field1).toEqual({
id: 'field1',
name: 'Field 1',
type: 'text',
value: 'value1',
sort_order: 1,
});
expect(result.attributes!.field2).toEqual({
id: 'field2',
name: 'Field 2',
type: 'text',
value: '',
sort_order: 2,
});
expect(result.attributes!.field3).toEqual({
id: 'field3',
name: 'Field 3',
type: 'text',
value: 'value3',
sort_order: 3,
});
});
it('fetchCustomProfileAttributes - with filter empty values', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'field1', name: 'Field 1'},
{id: 'field2', name: 'Field 2'},
{id: 'field3', name: 'Field 3'},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
field1: 'value1',
field2: '',
field3: 'value3',
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1', true);
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(Object.keys(result.attributes!)).toHaveLength(2);
expect(result.attributes!.field1).toEqual({
id: 'field1',
name: 'Field 1',
type: 'text',
value: 'value1',
sort_order: undefined,
});
expect(result.attributes!.field2).toBeUndefined();
expect(result.attributes!.field3).toEqual({
id: 'field3',
name: 'Field 3',
type: 'text',
value: 'value3',
sort_order: undefined,
});
});
it('fetchCustomProfileAttributes - no fields', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toEqual({});
});
it('fetchCustomProfileAttributes - error on fields', async () => {
const error = new Error('Sample error');
mockClient.getCustomProfileAttributeFields = jest.fn().mockRejectedValue(error);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
field1: 'value1',
field2: 'value2',
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeDefined();
});
it('fetchCustomProfileAttributes - error on values', async () => {
const error = new Error('Sample error');
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'field1', name: 'Field 1'},
{id: 'field2', name: 'Field 2'},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockRejectedValue(error);
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeDefined();
});
it('updateCustomProfileAttributes - base case', async () => {
mockClient.updateCustomProfileAttributeValues = jest.fn().mockResolvedValue({});
const attributes = {
field1: {
id: 'field1',
name: 'Field 1',
type: 'text',
value: 'new value 1',
},
field2: {
id: 'field2',
name: 'Field 2',
type: 'text',
value: 'new value 2',
},
};
const result = await updateCustomProfileAttributes(serverUrl, 'user1', attributes);
expect(result.error).toBeUndefined();
expect(result.success).toBe(true);
expect(mockClient.updateCustomProfileAttributeValues).toHaveBeenCalledWith({
field1: 'new value 1',
field2: 'new value 2',
});
});
it('updateCustomProfileAttributes - error', async () => {
const error = new Error('Test Error');
mockClient.updateCustomProfileAttributeValues = jest.fn().mockRejectedValue(error);
const attributes = {
field1: {
id: 'field1',
name: 'Field 1',
type: 'text',
value: 'new value 1',
},
};
const result = await updateCustomProfileAttributes(serverUrl, 'user1', attributes);
expect(result.error).toBeDefined();
expect(result.success).toBe(false);
});
// New tests for array handling functionality
it('fetchCustomProfileAttributes - handles multiselect array values correctly', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'multiselect1', name: 'Multiselect 1', type: 'multiselect', attrs: {sort_order: 1}},
{id: 'select1', name: 'Select 1', type: 'select', attrs: {sort_order: 2}},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
multiselect1: ['opt1', 'opt2', 'opt3'],
select1: 'single_opt',
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(Object.keys(result.attributes!)).toHaveLength(2);
// Array should be serialized to JSON string
expect(result.attributes!.multiselect1).toEqual({
id: 'multiselect1',
name: 'Multiselect 1',
type: 'multiselect',
value: '["opt1","opt2","opt3"]',
sort_order: 1,
});
// Single value should remain as string
expect(result.attributes!.select1).toEqual({
id: 'select1',
name: 'Select 1',
type: 'select',
value: 'single_opt',
sort_order: 2,
});
});
it('fetchCustomProfileAttributes - handles empty arrays correctly', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'multiselect1', name: 'Multiselect 1', type: 'multiselect'},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
multiselect1: [],
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(result.attributes!.multiselect1).toEqual({
id: 'multiselect1',
name: 'Multiselect 1',
type: 'multiselect',
value: '[]',
});
});
it('fetchCustomProfileAttributes - handles null and undefined values correctly', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'field1', name: 'Field 1', type: 'text'},
{id: 'field2', name: 'Field 2', type: 'multiselect'},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
field1: null,
field2: undefined,
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(result.attributes!.field1.value).toBe('');
expect(result.attributes!.field2.value).toBe('');
});
it('fetchCustomProfileAttributes - handles mixed data types correctly', async () => {
mockClient.getCustomProfileAttributeFields = jest.fn().mockResolvedValue([
{id: 'text_field', name: 'Text Field', type: 'text'},
{id: 'number_field', name: 'Number Field', type: 'number'},
{id: 'multiselect_field', name: 'Multiselect Field', type: 'multiselect'},
{id: 'select_field', name: 'Select Field', type: 'select'},
]);
mockClient.getCustomProfileAttributeValues = jest.fn().mockResolvedValue({
text_field: 'text value',
number_field: 42,
multiselect_field: ['opt1', 'opt2'],
select_field: 'single_opt',
});
const result = await fetchCustomProfileAttributes(serverUrl, 'user1');
expect(result.error).toBeUndefined();
expect(result.attributes).toBeDefined();
expect(result.attributes!.text_field.value).toBe('text value');
expect(result.attributes!.number_field.value).toBe('42');
expect(result.attributes!.multiselect_field.value).toBe('["opt1","opt2"]');
expect(result.attributes!.select_field.value).toBe('single_opt');
});
});