* 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
281 lines
10 KiB
TypeScript
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');
|
|
});
|
|
});
|