mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-02 05:33:49 +00:00
fix reloading of user profile page on edit action perform (#15673)
* fix reloading of user profile page on data change * supported unit test update handler in UserPage
This commit is contained in:
parent
8073a80989
commit
024e19f97b
@ -74,9 +74,14 @@ jest.mock(
|
|||||||
jest.mock(
|
jest.mock(
|
||||||
'../../MyData/Persona/PersonaSelectableList/PersonaSelectableList.component',
|
'../../MyData/Persona/PersonaSelectableList/PersonaSelectableList.component',
|
||||||
() => ({
|
() => ({
|
||||||
PersonaSelectableList: jest
|
PersonaSelectableList: jest.fn().mockImplementation(({ onUpdate }) => (
|
||||||
.fn()
|
<div>
|
||||||
.mockReturnValue(<p>PersonaSelectableList</p>),
|
<p>PersonaSelectableList</p>
|
||||||
|
<button onClick={() => onUpdate([])}>
|
||||||
|
SavePersonaSelectableListButton
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -133,16 +138,22 @@ jest.mock('../../PageLayoutV1/PageLayoutV1', () =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
jest.mock('../../common/EntityDescription/DescriptionV1', () => {
|
jest.mock('../../common/EntityDescription/DescriptionV1', () => {
|
||||||
return jest.fn().mockReturnValue(<p>Description</p>);
|
return jest.fn().mockImplementation(({ onDescriptionUpdate }) => (
|
||||||
|
<div>
|
||||||
|
<span>Description</span>
|
||||||
|
<button onClick={() => onDescriptionUpdate('testDescription')}>
|
||||||
|
SaveDescriptionButton
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
});
|
});
|
||||||
const updateUserDetails = jest.fn();
|
|
||||||
|
|
||||||
const mockProp = {
|
const mockProp = {
|
||||||
queryFilters: {
|
queryFilters: {
|
||||||
myData: 'my-data',
|
myData: 'my-data',
|
||||||
following: 'following',
|
following: 'following',
|
||||||
},
|
},
|
||||||
updateUserDetails,
|
updateUserDetails: jest.fn(),
|
||||||
handlePaginate: jest.fn(),
|
handlePaginate: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -190,14 +201,69 @@ describe('Test User Component', () => {
|
|||||||
'UserProfileInheritedRoles'
|
'UserProfileInheritedRoles'
|
||||||
);
|
);
|
||||||
const UserProfileRoles = await findByText(container, 'UserProfileRoles');
|
const UserProfileRoles = await findByText(container, 'UserProfileRoles');
|
||||||
|
|
||||||
const UserProfileTeams = await findByText(container, 'UserProfileTeams');
|
const UserProfileTeams = await findByText(container, 'UserProfileTeams');
|
||||||
|
const description = await findByText(container, 'Description');
|
||||||
|
|
||||||
|
expect(description).toBeInTheDocument();
|
||||||
expect(UserProfileRoles).toBeInTheDocument();
|
expect(UserProfileRoles).toBeInTheDocument();
|
||||||
expect(UserProfileTeams).toBeInTheDocument();
|
expect(UserProfileTeams).toBeInTheDocument();
|
||||||
expect(UserProfileInheritedRoles).toBeInTheDocument();
|
expect(UserProfileInheritedRoles).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click of SaveDescriptionButton', async () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Users userData={mockUserData} {...mockProp} />,
|
||||||
|
{
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const collapsibleButton = await findByRole(container, 'img');
|
||||||
|
|
||||||
|
userEvent.click(collapsibleButton);
|
||||||
|
|
||||||
|
const saveDescriptionButton = await findByText(
|
||||||
|
container,
|
||||||
|
'SaveDescriptionButton'
|
||||||
|
);
|
||||||
|
|
||||||
|
userEvent.click(saveDescriptionButton);
|
||||||
|
|
||||||
|
expect(mockProp.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
description: 'testDescription',
|
||||||
|
},
|
||||||
|
'description'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click of SavePersonaSelectableListButton', async () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Users userData={mockUserData} {...mockProp} />,
|
||||||
|
{
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const collapsibleButton = await findByRole(container, 'img');
|
||||||
|
|
||||||
|
userEvent.click(collapsibleButton);
|
||||||
|
|
||||||
|
const savePersonaSelectableListButton = await findByText(
|
||||||
|
container,
|
||||||
|
'SavePersonaSelectableListButton'
|
||||||
|
);
|
||||||
|
|
||||||
|
userEvent.click(savePersonaSelectableListButton);
|
||||||
|
|
||||||
|
expect(mockProp.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
personas: [],
|
||||||
|
},
|
||||||
|
'personas'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('Tab should not visible to normal user', async () => {
|
it('Tab should not visible to normal user', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Users userData={mockUserData} {...mockProp} />,
|
<Users userData={mockUserData} {...mockProp} />,
|
||||||
|
@ -115,9 +115,9 @@ const Users = ({ userData, queryFilters, updateUserDetails }: Props) => {
|
|||||||
|
|
||||||
const handlePersonaUpdate = useCallback(
|
const handlePersonaUpdate = useCallback(
|
||||||
async (personas: EntityReference[]) => {
|
async (personas: EntityReference[]) => {
|
||||||
await updateUserDetails({ ...userData, personas });
|
await updateUserDetails({ personas }, 'personas');
|
||||||
},
|
},
|
||||||
[updateUserDetails, userData]
|
[updateUserDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
const tabDataRender = useCallback(
|
const tabDataRender = useCallback(
|
||||||
@ -232,7 +232,7 @@ const Users = ({ userData, queryFilters, updateUserDetails }: Props) => {
|
|||||||
|
|
||||||
const handleDescriptionChange = useCallback(
|
const handleDescriptionChange = useCallback(
|
||||||
async (description: string) => {
|
async (description: string) => {
|
||||||
await updateUserDetails({ description });
|
await updateUserDetails({ description }, 'description');
|
||||||
|
|
||||||
setIsDescriptionEdit(false);
|
setIsDescriptionEdit(false);
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ export interface Props {
|
|||||||
following: string;
|
following: string;
|
||||||
};
|
};
|
||||||
handlePaginate: (page: string | number) => void;
|
handlePaginate: (page: string | number) => void;
|
||||||
updateUserDetails: (data: Partial<User>) => Promise<void>;
|
updateUserDetails: (data: Partial<User>, key: keyof User) => Promise<void>;
|
||||||
authenticationMechanism?: PersonalAccessToken;
|
authenticationMechanism?: PersonalAccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,10 @@ const UserProfileDetails = ({
|
|||||||
const handleDisplayNameSave = useCallback(async () => {
|
const handleDisplayNameSave = useCallback(async () => {
|
||||||
if (displayName !== userData.displayName) {
|
if (displayName !== userData.displayName) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await updateUserDetails({ displayName: displayName ?? '' });
|
await updateUserDetails(
|
||||||
|
{ displayName: displayName ?? '' },
|
||||||
|
'displayName'
|
||||||
|
);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
setIsDisplayNameEdit(false);
|
setIsDisplayNameEdit(false);
|
||||||
@ -260,9 +263,9 @@ const UserProfileDetails = ({
|
|||||||
|
|
||||||
const handleDefaultPersonaUpdate = useCallback(
|
const handleDefaultPersonaUpdate = useCallback(
|
||||||
async (defaultPersona?: EntityReference) => {
|
async (defaultPersona?: EntityReference) => {
|
||||||
await updateUserDetails({ ...userData, defaultPersona });
|
await updateUserDetails({ defaultPersona }, 'defaultPersona');
|
||||||
},
|
},
|
||||||
[updateUserDetails, userData]
|
[updateUserDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
const defaultPersonaRender = useMemo(
|
const defaultPersonaRender = useMemo(
|
||||||
|
@ -15,5 +15,5 @@ import { User } from '../../../../../generated/entity/teams/user';
|
|||||||
|
|
||||||
export interface UserProfileDetailsProps {
|
export interface UserProfileDetailsProps {
|
||||||
userData: User;
|
userData: User;
|
||||||
updateUserDetails: (data: Partial<User>) => Promise<void>;
|
updateUserDetails: (data: Partial<User>, key: keyof User) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { AuthProvider } from '../../../../../generated/settings/settings';
|
import { AuthProvider } from '../../../../../generated/settings/settings';
|
||||||
@ -63,7 +63,15 @@ jest.mock('../UserProfileImage/UserProfileImage.component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
||||||
return jest.fn().mockReturnValue(<p>InlineEdit</p>);
|
return jest.fn().mockImplementation(({ onSave, children }) => (
|
||||||
|
<div data-testid="inline-edit">
|
||||||
|
<span>InlineEdit</span>
|
||||||
|
{children}
|
||||||
|
<button data-testid="display-name-save-button" onClick={onSave}>
|
||||||
|
DisplayNameButton
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../ChangePasswordForm', () => {
|
jest.mock('../../ChangePasswordForm', () => {
|
||||||
@ -73,9 +81,16 @@ jest.mock('../../ChangePasswordForm', () => {
|
|||||||
jest.mock(
|
jest.mock(
|
||||||
'../../../../MyData/Persona/PersonaSelectableList/PersonaSelectableList.component',
|
'../../../../MyData/Persona/PersonaSelectableList/PersonaSelectableList.component',
|
||||||
() => ({
|
() => ({
|
||||||
PersonaSelectableList: jest
|
PersonaSelectableList: jest.fn().mockImplementation(({ onUpdate }) => (
|
||||||
.fn()
|
<div>
|
||||||
.mockReturnValue(<p>PersonaSelectableList</p>),
|
<span>PersonaSelectableList</span>
|
||||||
|
<button
|
||||||
|
data-testid="persona-save-button"
|
||||||
|
onClick={() => onUpdate(USER_DATA.defaultPersona)}>
|
||||||
|
PersonaSaveButton
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -208,4 +223,44 @@ describe('Test User Profile Details Component', () => {
|
|||||||
|
|
||||||
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click of DisplayNameButton', async () => {
|
||||||
|
render(<UserProfileDetails {...mockPropsData} />, {
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByTestId('edit-displayName'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.change(screen.getByTestId('displayName'), {
|
||||||
|
target: { value: 'test' },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByTestId('display-name-save-button'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockPropsData.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{ displayName: 'test' },
|
||||||
|
'displayName'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click of PersonaSaveButton', async () => {
|
||||||
|
render(<UserProfileDetails {...mockPropsData} />, {
|
||||||
|
wrapper: MemoryRouter,
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId('persona-save-button'));
|
||||||
|
|
||||||
|
expect(mockPropsData.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{ defaultPersona: USER_DATA.defaultPersona },
|
||||||
|
'defaultPersona'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -98,14 +98,17 @@ const UserProfileRoles = ({
|
|||||||
const isAdmin = selectedRoles.find(
|
const isAdmin = selectedRoles.find(
|
||||||
(roleId) => roleId === toLower(TERM_ADMIN)
|
(roleId) => roleId === toLower(TERM_ADMIN)
|
||||||
);
|
);
|
||||||
await updateUserDetails({
|
await updateUserDetails(
|
||||||
roles: updatedRoles.map((roleId) => {
|
{
|
||||||
const role = roles.find((r) => r.id === roleId);
|
roles: updatedRoles.map((roleId) => {
|
||||||
|
const role = roles.find((r) => r.id === roleId);
|
||||||
|
|
||||||
return { id: roleId, type: 'role', name: role?.name ?? '' };
|
return { id: roleId, type: 'role', name: role?.name ?? '' };
|
||||||
}),
|
}),
|
||||||
isAdmin: Boolean(isAdmin),
|
isAdmin: Boolean(isAdmin),
|
||||||
});
|
},
|
||||||
|
'roles'
|
||||||
|
);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsRolesEdit(false);
|
setIsRolesEdit(false);
|
||||||
};
|
};
|
||||||
|
@ -15,5 +15,5 @@ import { User } from '../../../../../generated/entity/teams/user';
|
|||||||
export interface UserProfileRolesProps {
|
export interface UserProfileRolesProps {
|
||||||
isUserAdmin?: boolean;
|
isUserAdmin?: boolean;
|
||||||
userRoles: User['roles'];
|
userRoles: User['roles'];
|
||||||
updateUserDetails: (data: Partial<User>) => Promise<void>;
|
updateUserDetails: (data: Partial<User>, key: keyof User) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useAuth } from '../../../../../hooks/authHooks';
|
import { useAuth } from '../../../../../hooks/authHooks';
|
||||||
import { getRoles } from '../../../../../rest/rolesAPIV1';
|
import { getRoles } from '../../../../../rest/rolesAPIV1';
|
||||||
@ -29,7 +29,14 @@ jest.mock('../../../../../hooks/authHooks', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
||||||
return jest.fn().mockReturnValue(<p>InlineEdit</p>);
|
return jest.fn().mockImplementation(({ onSave }) => (
|
||||||
|
<div data-testid="inline-edit">
|
||||||
|
<span>InlineEdit</span>
|
||||||
|
<button data-testid="save" onClick={onSave}>
|
||||||
|
save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../../../common/Chip/Chip.component', () => {
|
jest.mock('../../../../common/Chip/Chip.component', () => {
|
||||||
@ -101,6 +108,26 @@ describe('Test User Profile Roles Component', () => {
|
|||||||
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click save', async () => {
|
||||||
|
(useAuth as jest.Mock).mockImplementation(() => ({
|
||||||
|
isAdminUser: true,
|
||||||
|
}));
|
||||||
|
render(<UserProfileRoles {...mockPropsData} />);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId('edit-roles-button'));
|
||||||
|
|
||||||
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByTestId('save'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockPropsData.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{ roles: [], isAdmin: false },
|
||||||
|
'roles'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should call roles api on edit button action', async () => {
|
it('should call roles api on edit button action', async () => {
|
||||||
(useAuth as jest.Mock).mockImplementation(() => ({
|
(useAuth as jest.Mock).mockImplementation(() => ({
|
||||||
isAdminUser: true,
|
isAdminUser: true,
|
||||||
|
@ -40,9 +40,12 @@ const UserProfileTeams = ({
|
|||||||
|
|
||||||
const handleTeamsSave = async () => {
|
const handleTeamsSave = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await updateUserDetails({
|
await updateUserDetails(
|
||||||
teams: selectedTeams.map((teamId) => ({ id: teamId.id, type: 'team' })),
|
{
|
||||||
});
|
teams: selectedTeams.map((teamId) => ({ id: teamId.id, type: 'team' })),
|
||||||
|
},
|
||||||
|
'teams'
|
||||||
|
);
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsTeamsEdit(false);
|
setIsTeamsEdit(false);
|
||||||
|
@ -14,5 +14,5 @@ import { User } from '../../../../../generated/entity/teams/user';
|
|||||||
|
|
||||||
export interface UserProfileTeamsProps {
|
export interface UserProfileTeamsProps {
|
||||||
teams: User['teams'];
|
teams: User['teams'];
|
||||||
updateUserDetails: (data: Partial<User>) => Promise<void>;
|
updateUserDetails: (data: Partial<User>, key: keyof User) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useAuth } from '../../../../../hooks/authHooks';
|
import { useAuth } from '../../../../../hooks/authHooks';
|
||||||
import { USER_DATA, USER_TEAMS } from '../../../../../mocks/User.mock';
|
import { USER_DATA, USER_TEAMS } from '../../../../../mocks/User.mock';
|
||||||
@ -28,11 +28,18 @@ jest.mock('../../../../../hooks/authHooks', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../../../utils/CommonUtils', () => ({
|
jest.mock('../../../../../utils/CommonUtils', () => ({
|
||||||
getNonDeletedTeams: jest.fn(),
|
getNonDeletedTeams: jest.fn().mockReturnValue([]),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
jest.mock('../../../../common/InlineEdit/InlineEdit.component', () => {
|
||||||
return jest.fn().mockReturnValue(<p>InlineEdit</p>);
|
return jest.fn().mockImplementation(({ onSave }) => (
|
||||||
|
<div data-testid="inline-edit">
|
||||||
|
<span>InlineEdit</span>
|
||||||
|
<button data-testid="save" onClick={onSave}>
|
||||||
|
save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../../../common/Chip/Chip.component', () => {
|
jest.mock('../../../../common/Chip/Chip.component', () => {
|
||||||
@ -74,6 +81,25 @@ describe('Test User Profile Teams Component', () => {
|
|||||||
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call updateUserDetails on click save', async () => {
|
||||||
|
render(<UserProfileTeams {...mockPropsData} teams={USER_DATA.teams} />);
|
||||||
|
|
||||||
|
const editButton = screen.getByTestId('edit-teams-button');
|
||||||
|
|
||||||
|
fireEvent.click(editButton);
|
||||||
|
|
||||||
|
expect(screen.getByText('InlineEdit')).toBeInTheDocument();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(screen.getByTestId('save'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockPropsData.updateUserDetails).toHaveBeenCalledWith(
|
||||||
|
{ teams: [] },
|
||||||
|
'teams'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not render edit button to non admin user', async () => {
|
it('should not render edit button to non admin user', async () => {
|
||||||
(useAuth as jest.Mock).mockImplementation(() => ({
|
(useAuth as jest.Mock).mockImplementation(() => ({
|
||||||
isAdminUser: false,
|
isAdminUser: false,
|
||||||
|
@ -180,7 +180,7 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
if (isEmpty(currentUser)) {
|
if (isEmpty(currentUser)) {
|
||||||
resetPermissions();
|
resetPermissions();
|
||||||
}
|
}
|
||||||
}, [currentUser]);
|
}, [currentUser?.teams, currentUser?.roles]);
|
||||||
|
|
||||||
const contextValues = useMemo(
|
const contextValues = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
import { Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty, isUndefined } from 'lodash';
|
||||||
import Qs from 'qs';
|
import Qs from 'qs';
|
||||||
import {
|
import {
|
||||||
default as React,
|
default as React,
|
||||||
@ -104,17 +104,30 @@ const UserPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateUserDetails = useCallback(
|
const updateUserDetails = useCallback(
|
||||||
async (data: Partial<User>) => {
|
async (data: Partial<User>, key: keyof User) => {
|
||||||
const updatedDetails = { ...userData, ...data };
|
const updatedDetails = { ...userData, ...data };
|
||||||
const jsonPatch = compare(userData, updatedDetails);
|
const jsonPatch = compare(userData, updatedDetails);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await updateUserDetail(userData.id, jsonPatch);
|
const response = await updateUserDetail(userData.id, jsonPatch);
|
||||||
if (response) {
|
if (response) {
|
||||||
if (userData.id === currentUser?.id) {
|
const newCurrentUserData = {
|
||||||
updateCurrentUser(response);
|
...currentUser,
|
||||||
|
[key]: response[key],
|
||||||
|
};
|
||||||
|
const newUserData = { ...userData, [key]: response[key] };
|
||||||
|
|
||||||
|
if (key === 'defaultPersona') {
|
||||||
|
if (isUndefined(response.defaultPersona)) {
|
||||||
|
// remove key from object if value is undefined
|
||||||
|
delete newCurrentUserData[key];
|
||||||
|
delete newUserData[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setUserData((prev) => ({ ...prev, ...response }));
|
if (userData.id === currentUser?.id) {
|
||||||
|
updateCurrentUser(newCurrentUserData as User);
|
||||||
|
}
|
||||||
|
setUserData(newUserData);
|
||||||
} else {
|
} else {
|
||||||
throw t('message.unexpected-error');
|
throw t('message.unexpected-error');
|
||||||
}
|
}
|
||||||
|
@ -11,104 +11,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { findByTestId, findByText, render } from '@testing-library/react';
|
import {
|
||||||
|
act,
|
||||||
|
findByTestId,
|
||||||
|
findByText,
|
||||||
|
fireEvent,
|
||||||
|
render,
|
||||||
|
screen,
|
||||||
|
} from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { EntityType } from '../../enums/entity.enum';
|
import { useApplicationStore } from '../../hooks/useApplicationStore';
|
||||||
import { getUserByName } from '../../rest/userAPI';
|
import { USER_DATA } from '../../mocks/User.mock';
|
||||||
|
import { getUserByName, updateUserDetail } from '../../rest/userAPI';
|
||||||
import UserPage from './UserPage.component';
|
import UserPage from './UserPage.component';
|
||||||
|
|
||||||
const mockUserData = {
|
|
||||||
id: 'd6764107-e8b4-4748-b256-c86fecc66064',
|
|
||||||
name: 'xyz',
|
|
||||||
displayName: 'XYZ',
|
|
||||||
version: 0.1,
|
|
||||||
updatedAt: 1648704499857,
|
|
||||||
updatedBy: 'xyz',
|
|
||||||
email: 'xyz@gmail.com',
|
|
||||||
href: 'http://localhost:8585/api/v1/users/d6764107-e8b4-4748-b256-c86fecc66064',
|
|
||||||
isAdmin: false,
|
|
||||||
domain: {
|
|
||||||
id: '303ca53b-5050-4caa-9c4e-d4fdada76a53',
|
|
||||||
type: EntityType.DOMAIN,
|
|
||||||
name: 'Engineering',
|
|
||||||
fullyQualifiedName: 'Engineering',
|
|
||||||
description: 'description',
|
|
||||||
inherited: true,
|
|
||||||
href: 'http://localhost:8585/api/v1/domains/303ca53b-5050-4caa-9c4e-d4fdada76a53',
|
|
||||||
},
|
|
||||||
profile: {
|
|
||||||
images: {
|
|
||||||
image:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s96-c',
|
|
||||||
image24:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s24-c',
|
|
||||||
image32:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s32-c',
|
|
||||||
image48:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s48-c',
|
|
||||||
image72:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s72-c',
|
|
||||||
image192:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s192-c',
|
|
||||||
image512:
|
|
||||||
'https://lh3.googleusercontent.com/a-/AOh14Gh8NPux8jEPIuyPWOxAB1od9fGN188Kcp5HeXgc=s512-c',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
teams: [
|
|
||||||
{
|
|
||||||
id: '3362fe18-05ad-4457-9632-84f22887dda6',
|
|
||||||
type: 'team',
|
|
||||||
name: 'Finance',
|
|
||||||
description: 'This is Finance description.',
|
|
||||||
displayName: 'Finance',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/teams/3362fe18-05ad-4457-9632-84f22887dda6',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5069ddd4-d47e-4b2c-a4c4-4c849b97b7f9',
|
|
||||||
type: 'team',
|
|
||||||
name: 'Data_Platform',
|
|
||||||
description: 'This is Data_Platform description.',
|
|
||||||
displayName: 'Data_Platform',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/teams/5069ddd4-d47e-4b2c-a4c4-4c849b97b7f9',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7182cc43-aebc-419d-9452-ddbe2fc4e640',
|
|
||||||
type: 'team',
|
|
||||||
name: 'Customer_Support',
|
|
||||||
description: 'This is Customer_Support description.',
|
|
||||||
displayName: 'Customer_Support',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/teams/7182cc43-aebc-419d-9452-ddbe2fc4e640',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
owns: [],
|
|
||||||
follows: [],
|
|
||||||
deleted: false,
|
|
||||||
roles: [
|
|
||||||
{
|
|
||||||
id: 'ce4df2a5-aaf5-4580-8556-254f42574aa7',
|
|
||||||
type: 'role',
|
|
||||||
name: 'DataConsumer',
|
|
||||||
description:
|
|
||||||
'Users with Data Consumer role use different data assets for their day to day work.',
|
|
||||||
displayName: 'Data Consumer',
|
|
||||||
deleted: false,
|
|
||||||
href: 'http://localhost:8585/api/v1/roles/ce4df2a5-aaf5-4580-8556-254f42574aa7',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
jest.mock('../../components/MyData/LeftSidebar/LeftSidebar.component', () =>
|
jest.mock('../../components/MyData/LeftSidebar/LeftSidebar.component', () =>
|
||||||
jest.fn().mockReturnValue(<p>Sidebar</p>)
|
jest.fn().mockReturnValue(<p>Sidebar</p>)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const mockUpdateCurrentUser = jest.fn();
|
||||||
|
|
||||||
jest.mock('../../hooks/useApplicationStore', () => {
|
jest.mock('../../hooks/useApplicationStore', () => {
|
||||||
return {
|
return {
|
||||||
useApplicationStore: jest.fn(() => ({
|
useApplicationStore: jest.fn(() => ({
|
||||||
isAuthDisabled: true,
|
currentUser: USER_DATA,
|
||||||
|
updateCurrentUser: mockUpdateCurrentUser,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -124,20 +52,26 @@ jest.mock('../../components/common/Loader/Loader', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../components/Settings/Users/Users.component', () => {
|
jest.mock('../../components/Settings/Users/Users.component', () => {
|
||||||
return jest.fn().mockReturnValue(<p>User Component</p>);
|
return jest.fn().mockImplementation(({ updateUserDetails }) => (
|
||||||
|
<div>
|
||||||
|
<p>User Component</p>
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
updateUserDetails({ defaultPersona: undefined }, 'defaultPersona')
|
||||||
|
}>
|
||||||
|
UserComponentSaveButton
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../../rest/userAPI', () => ({
|
jest.mock('../../rest/userAPI', () => ({
|
||||||
getUserByName: jest
|
getUserByName: jest.fn().mockImplementation(() => Promise.resolve(USER_DATA)),
|
||||||
|
updateUserDetail: jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => Promise.resolve({ data: mockUserData })),
|
.mockImplementation(() =>
|
||||||
}));
|
Promise.resolve({ ...USER_DATA, defaultPersona: undefined })
|
||||||
|
),
|
||||||
jest.mock('../../rest/userAPI', () => ({
|
|
||||||
getUserByName: jest
|
|
||||||
.fn()
|
|
||||||
.mockImplementation(() => Promise.resolve({ data: mockUserData })),
|
|
||||||
updateUserDetail: jest.fn(),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../rest/feedsAPI', () => ({
|
jest.mock('../../rest/feedsAPI', () => ({
|
||||||
@ -176,4 +110,55 @@ describe('Test the User Page', () => {
|
|||||||
|
|
||||||
expect(errorPlaceholder).toBeInTheDocument();
|
expect(errorPlaceholder).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should call and update state data with patch api for defaultPersona', async () => {
|
||||||
|
const userData = { ...USER_DATA };
|
||||||
|
delete userData.defaultPersona;
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
render(<UserPage />, { wrapper: MemoryRouter });
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByText('UserComponentSaveButton'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(updateUserDetail).toHaveBeenCalledWith(USER_DATA.id, [
|
||||||
|
{
|
||||||
|
op: 'remove',
|
||||||
|
path: '/defaultPersona',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(mockUpdateCurrentUser).toHaveBeenCalledWith(userData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should call updateCurrentUser if user is currentUser logged in', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(<UserPage />, { wrapper: MemoryRouter });
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByText('UserComponentSaveButton'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockUpdateCurrentUser).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not call updateCurrentUser if user is not currentUser logged in', async () => {
|
||||||
|
(useApplicationStore as unknown as jest.Mock).mockImplementation(() => ({
|
||||||
|
currentUser: { ...USER_DATA, id: '123' },
|
||||||
|
updateCurrentUser: mockUpdateCurrentUser,
|
||||||
|
}));
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
render(<UserPage />, { wrapper: MemoryRouter });
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByText('UserComponentSaveButton'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockUpdateCurrentUser).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user