Skip to content

Commit

Permalink
fix: Update error messages when adding user to library [FC-0062] (#1543)
Browse files Browse the repository at this point in the history
Updates the message error when the user doesn't exist when adding a new team member to a library.
  • Loading branch information
ChrisChV authored Dec 6, 2024
1 parent 0e9025a commit d2d7532
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { capitalize } from 'lodash';
import userEvent from '@testing-library/user-event';
import { initializeMocks, render, screen } from '../../testUtils';
import { NOTIFICATION_MESSAGES } from '../../constants';
import ProcessingNotification from '.';

const mockUndo = jest.fn();

const props = {
title: NOTIFICATION_MESSAGES.saving,
title: 'ThIs IS a Test. OK?',
isShow: true,
action: {
label: 'Undo',
Expand All @@ -22,16 +20,16 @@ describe('<ProcessingNotification />', () => {

it('renders successfully', () => {
render(<ProcessingNotification {...props} close={() => {}} />);
expect(screen.getByText(capitalize(props.title))).toBeInTheDocument();
expect(screen.getByText(props.title)).toBeInTheDocument();
expect(screen.getByText('Undo')).toBeInTheDocument();
expect(screen.getByRole('alert').querySelector('.processing-notification-hide-close-button')).not.toBeInTheDocument();
userEvent.click(screen.getByText('Undo'));
expect(mockUndo).toBeCalled();
expect(mockUndo).toHaveBeenCalled();
});

it('add hide-close-button class if no close action is passed', () => {
render(<ProcessingNotification {...props} />);
expect(screen.getByText(capitalize(props.title))).toBeInTheDocument();
expect(screen.getByText(props.title)).toBeInTheDocument();
expect(screen.getByRole('alert').querySelector('.processing-notification-hide-close-button')).toBeInTheDocument();
});
});
3 changes: 1 addition & 2 deletions src/generic/processing-notification/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
Icon, Toast,
} from '@openedx/paragon';
import { Settings as IconSettings } from '@openedx/paragon/icons';
import { capitalize } from 'lodash';
import classNames from 'classnames';

const ProcessingNotification = ({
Expand All @@ -18,7 +17,7 @@ const ProcessingNotification = ({
>
<span className="d-flex align-items-center">
<Icon className="processing-notification-icon mb-0 mr-2" src={IconSettings} />
<span className="font-weight-bold h4 mb-0 text-white">{capitalize(title)}</span>
<span className="font-weight-bold h4 mb-0 text-white">{title}</span>
</span>
</Toast>
);
Expand Down
12 changes: 6 additions & 6 deletions src/generic/toast-context/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const TestComponentToShow = () => {
const { showToast } = React.useContext(ToastContext);

React.useEffect(() => {
showToast('This is the toast!');
showToast('This is the Toast!');
}, [showToast]);

return <div>Content</div>;
Expand All @@ -23,7 +23,7 @@ const TestComponentToClose = () => {
const { showToast, closeToast } = React.useContext(ToastContext);

React.useEffect(() => {
showToast('This is the toast!');
showToast('This is the Toast!');
closeToast();
}, [showToast]);

Expand Down Expand Up @@ -59,19 +59,19 @@ describe('<ToastProvider />', () => {

it('should show toast', async () => {
render(<RootWrapper><TestComponentToShow /></RootWrapper>);
expect(await screen.findByText('This is the toast!')).toBeInTheDocument();
expect(await screen.findByText('This is the Toast!')).toBeInTheDocument();
});

it('should close toast after 5000ms', async () => {
render(<RootWrapper><TestComponentToShow /></RootWrapper>);
expect(await screen.findByText('This is the toast!')).toBeInTheDocument();
expect(await screen.findByText('This is the Toast!')).toBeInTheDocument();
jest.advanceTimersByTime(6000);
expect(screen.queryByText('This is the toast!')).not.toBeInTheDocument();
expect(screen.queryByText('This is the Toast!')).not.toBeInTheDocument();
});

it('should close toast', async () => {
render(<RootWrapper><TestComponentToClose /></RootWrapper>);
expect(await screen.findByText('Content')).toBeInTheDocument();
expect(screen.queryByText('This is the toast!')).not.toBeInTheDocument();
expect(screen.queryByText('This is the Toast!')).not.toBeInTheDocument();
});
});
59 changes: 56 additions & 3 deletions src/library-authoring/library-team/LibraryTeam.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
getLibraryTeamMemberApiUrl,
} from '../data/api';
import { LibraryProvider } from '../common/context';
import { ToastProvider } from '../../generic/toast-context';
import LibraryTeam from './LibraryTeam';

mockContentLibrary.applyMock();
Expand All @@ -28,9 +29,11 @@ describe('<LibraryTeam />', () => {
const { libraryId } = mockContentLibrary;
const renderLibraryTeam = async () => {
render(
<LibraryProvider libraryId={libraryId}>
<LibraryTeam />
</LibraryProvider>,
<ToastProvider>
<LibraryProvider libraryId={libraryId}>
<LibraryTeam />
</LibraryProvider>
</ToastProvider>,
);

await waitFor(() => {
Expand Down Expand Up @@ -176,6 +179,56 @@ describe('<LibraryTeam />', () => {
`{"library_id":"${libraryId}","email":"[email protected]","access_level":"read"}`,
);
});

expect(await screen.findByText('Team Member added')).toBeInTheDocument();
});

it('shows error when user do not exist', async () => {
const url = getLibraryTeamApiUrl(libraryId);
const axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock.onPost(url).reply(400, { email: 'Error' });

await renderLibraryTeam();

const addButton = screen.getByRole('button', { name: 'New team member' });
userEvent.click(addButton);
const emailInput = screen.getByRole('textbox', { name: 'User\'s email address' });
userEvent.click(emailInput);
userEvent.type(emailInput, '[email protected]');

const saveButton = screen.getByRole('button', { name: /add member/i });
userEvent.click(saveButton);

await waitFor(() => {
expect(axiosMock.history.post.length).toEqual(1);
});

expect(await screen.findByText(
'Error adding Team Member. Please verify that the email is correct and belongs to a registered user.',
)).toBeInTheDocument();
});

it('shows error', async () => {
const url = getLibraryTeamApiUrl(libraryId);
const axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock.onPost(url).reply(400, {});

await renderLibraryTeam();

const addButton = screen.getByRole('button', { name: 'New team member' });
userEvent.click(addButton);
const emailInput = screen.getByRole('textbox', { name: 'User\'s email address' });
userEvent.click(emailInput);
userEvent.type(emailInput, '[email protected]');

const saveButton = screen.getByRole('button', { name: /add member/i });
userEvent.click(saveButton);

await waitFor(() => {
expect(axiosMock.history.post.length).toEqual(1);
});

expect(await screen.findByText('Error adding Team Member')).toBeInTheDocument();
});

it('allows library team member roles to be changed', async () => {
Expand Down
9 changes: 7 additions & 2 deletions src/library-authoring/library-team/LibraryTeam.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ const LibraryTeam: React.FC<Record<never, never>> = () => {
accessLevel: LibraryRole.Reader.toString() as LibraryAccessLevel,
}).then(() => {
showToast(intl.formatMessage(messages.addMemberSuccess));
}).catch(() => {
showToast(intl.formatMessage(messages.addMemberError));
}).catch((addMemberError) => {
const errorData = typeof addMemberError === 'object' ? addMemberError.response?.data : undefined;
if (errorData && 'email' in errorData) {
showToast(intl.formatMessage(messages.addMemberEmailError));
} else {
showToast(intl.formatMessage(messages.addMemberError));
}
});
closeAddLibraryTeamMember();
},
Expand Down
5 changes: 5 additions & 0 deletions src/library-authoring/library-team/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ const messages = defineMessages({
defaultMessage: 'Error adding Team Member',
description: 'Message shown when an error occurs while adding a Library Team member',
},
addMemberEmailError: {
id: 'course-authoring.library-authoring.library-team.add-member-email-error',
defaultMessage: 'Error adding Team Member. Please verify that the email is correct and belongs to a registered user.',
description: 'Message shown when an error occurs with email while adding a Library Team member.',
},
deleteMemberSuccess: {
id: 'course-authoring.library-authoring.library-team.delete-member-success',
defaultMessage: 'Team Member deleted',
Expand Down

0 comments on commit d2d7532

Please sign in to comment.