diff --git a/app/screens/edit_profile/edit_profile.test.tsx b/app/screens/edit_profile/edit_profile.test.tsx new file mode 100644 index 000000000..6a817d128 --- /dev/null +++ b/app/screens/edit_profile/edit_profile.test.tsx @@ -0,0 +1,113 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +import {act} from '@testing-library/react-hooks'; +import {fireEvent, waitFor} from '@testing-library/react-native'; +import React from 'react'; + +import AvailableScreens from '@constants/screens'; +import {renderWithIntlAndTheme} from '@test/intl-test-helper'; + +import EditProfile from './edit_profile'; + +import type {UserModel} from '@database/models/server'; + +jest.mock('@components/compass_icon', () => { + function CompassIcon() { + return null; + } + CompassIcon.getImageSourceSync = jest.fn().mockReturnValue({}); + return { + __esModule: true, + default: CompassIcon, + }; +}); + +jest.mock('@context/server', () => ({ + useServerUrl: jest.fn().mockReturnValue('http://localhost:8065'), +})); + +jest.mock('@actions/remote/user', () => ({ + fetchCustomAttributes: jest.fn().mockResolvedValue({ + attributes: { + attr1: { + id: 'attr1', + name: 'Custom Attribute 1', + value: 'original value 1', + sort_order: 1, + }, + attr3: { + id: 'attr3', + name: 'Custom Attribute 3', + value: 'original value 3', + sort_order: 3, + }, + attr2: { + id: 'attr2', + name: 'Custom Attribute 2', + value: 'original value 2', + sort_order: 2, + }, + }, + error: undefined, + }), + updateCustomAttributes: jest.fn().mockResolvedValue({}), + updateMe: jest.fn().mockResolvedValue({}), + uploadUserProfileImage: jest.fn().mockResolvedValue({}), + setDefaultProfileImage: jest.fn().mockResolvedValue({}), + buildProfileImageUrlFromUser: jest.fn().mockReturnValue('http://example.com/profile.jpg'), +})); + +describe('EditProfile', () => { + const mockCurrentUser = { + id: 'user1', + email: 'test@example.com', + firstName: 'John', + lastName: 'Doe', + nickname: 'Johnny', + position: 'Developer', + username: 'johndoe', + } as UserModel; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should update custom attribute value while preserving name and sort order', async () => { + const {findAllByTestId} = renderWithIntlAndTheme( + , + ); + + await waitFor(() => { + const {fetchCustomAttributes} = require('@actions/remote/user'); + expect(fetchCustomAttributes).toHaveBeenCalledWith('http://localhost:8065', 'user1'); + }); + + const customAttributeItems = await findAllByTestId(new RegExp('^edit_profile_form.customAttributes.attr[0-9]+.input$')); + expect(customAttributeItems.length).toBe(3); + + expect(customAttributeItems[0].props.value).toBe('original value 1'); + expect(customAttributeItems[1].props.value).toBe('original value 2'); + expect(customAttributeItems[2].props.value).toBe('original value 3'); + + await act(async () => { + fireEvent.changeText(customAttributeItems[1], 'new value'); + }); + + const newCustomAttributeItems = await findAllByTestId(new RegExp('^edit_profile_form.customAttributes.attr[0-9]+.input$')); + expect(newCustomAttributeItems.length).toBe(3); + expect(newCustomAttributeItems[0].props.value).toBe('original value 1'); + expect(newCustomAttributeItems[1].props.value).toBe('new value'); + expect(newCustomAttributeItems[2].props.value).toBe('original value 3'); + }); +}); diff --git a/app/screens/edit_profile/edit_profile.tsx b/app/screens/edit_profile/edit_profile.tsx index 7481d1a39..9c5172760 100644 --- a/app/screens/edit_profile/edit_profile.tsx +++ b/app/screens/edit_profile/edit_profile.tsx @@ -127,7 +127,7 @@ const EditProfile = ({ } const {error: fetchError, attributes} = await fetchCustomAttributes(serverUrl, currentUser.id); if (!fetchError && attributes) { - setUserInfo((prev) => ({...prev, customAttributes: attributes} as UserInfo)); + setUserInfo((prev: UserInfo) => ({...prev, customAttributes: attributes} as UserInfo)); } }; @@ -200,7 +200,7 @@ const EditProfile = ({ const update = {...userInfo}; if (fieldKey.startsWith(CUSTOM_ATTRS_PREFIX_NAME)) { const attrKey = fieldKey.slice(CUSTOM_ATTRS_PREFIX_NAME.length); - update.customAttributes = {...update.customAttributes, [attrKey]: {id: attrKey, name: userInfo.customAttributes[attrKey].name, value}}; + update.customAttributes = {...update.customAttributes, [attrKey]: {id: attrKey, name: userInfo.customAttributes[attrKey].name, value, sort_order: userInfo.customAttributes[attrKey].sort_order}}; } else { switch (fieldKey) { // typescript doesn't like to do update[fieldkey] as it might containg a customAttribute case