Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Update error messages when adding user to library [FC-0062] #1543

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading