Skip to content

Commit

Permalink
refactor: fixed issues of review
Browse files Browse the repository at this point in the history
  • Loading branch information
SundasNoreen committed Jun 19, 2023
1 parent 6efa310 commit 683a582
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 100 deletions.
22 changes: 12 additions & 10 deletions src/Notifications/data/api.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { camelCaseObject, getConfig, snakeCaseObject } from '@edx/frontend-platform';
import { getConfig, snakeCaseObject } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

export const getNotificationsCountApiUrl = () => `${getConfig().LMS_BASE_URL}/api/notifications/count/`;
export const getNotificationsApiUrl = () => `${getConfig().LMS_BASE_URL}/api/notifications/`;
export const markNotificationsSeenApiUrl = (appName) => `${getConfig().LMS_BASE_URL}/api/notifications/mark-notifications-unseen/${appName}/`;
export const markAllNotificationsAsReadpiUrl = (appName, id) => `${getConfig().LMS_BASE_URL}/api/notifications/mark-notifications-read/${appName}/${id}`;
export const markAllNotificationsAsReadpiUrl = () => `${getConfig().LMS_BASE_URL}/api/notifications/read/`;

export async function getNotifications(appName, page, pageSize) {
const params = snakeCaseObject({ page, pageSize });
Expand All @@ -14,29 +14,31 @@ export async function getNotifications(appName, page, pageSize) {
const endIndex = startIndex + pageSize;

const notifications = data.slice(startIndex, endIndex);
return { notifications: camelCaseObject(notifications), numPages: 2, currentPage: page };
return { notifications, numPages: 2, currentPage: page };
}

export async function getNotificationCounts() {
const { data } = await getAuthenticatedHttpClient().get(getNotificationsCountApiUrl());

return camelCaseObject(data);
return data;
}

export async function markNotificationSeen(appName) {
const { data } = await getAuthenticatedHttpClient().put(`${markNotificationsSeenApiUrl(appName)}`);

return camelCaseObject(data);
return data;
}

export async function markAllNotificationRead(appName) {
const { data } = await getAuthenticatedHttpClient().put(`${markAllNotificationsAsReadpiUrl(appName)}`);
const params = snakeCaseObject({ appName });
const { data } = await getAuthenticatedHttpClient().put(markAllNotificationsAsReadpiUrl(), { params });

return camelCaseObject(data);
return data;
}

export async function markNotificationRead(appName, notificationId) {
const { data } = await getAuthenticatedHttpClient().put(`${markAllNotificationsAsReadpiUrl(appName, notificationId)}`);
export async function markNotificationRead(notificationId) {
const params = snakeCaseObject({ notificationId });
const { data } = await getAuthenticatedHttpClient().put(markAllNotificationsAsReadpiUrl(), { params });

return camelCaseObject({ data, id: notificationId });
return { data, id: notificationId };
}
126 changes: 73 additions & 53 deletions src/Notifications/data/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,19 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { initializeMockApp } from '@edx/frontend-platform/testing';

import { initializeStore } from '../../store';
import executeThunk from '../../test-utils';
import {
getNotificationsApiUrl, getNotificationsCountApiUrl, markAllNotificationsAsReadpiUrl, markNotificationsSeenApiUrl,
getNotificationCounts, getNotifications, markNotificationSeen, markAllNotificationRead, markNotificationRead,
} from './api';
import {
fetchAppsNotificationCount,
fetchNotificationList,
markAllNotificationsAsRead,
markNotificationsAsRead,
markNotificationsAsSeen,
} from './thunks';

import './__factories__';

const notificationCountsApiUrl = getNotificationsCountApiUrl();
const notificationsApiUrl = getNotificationsApiUrl();
const markedAllNotificationsAsSeenApiUrl = markNotificationsSeenApiUrl('discussions');
const markedAllNotificationsAsReadApiUrl = markAllNotificationsAsReadpiUrl('discussions');
const markedNotificationAsReadApiUrl = markAllNotificationsAsReadpiUrl('discussions', 1);
const markedAllNotificationsAsReadApiUrl = markAllNotificationsAsReadpiUrl();

let axiosMock = null;
let store;

describe('Notifications API', () => {
beforeEach(async () => {
Expand Down Expand Up @@ -61,17 +51,23 @@ describe('Notifications API', () => {
});

it('failed to get notification counts.', async () => {
axiosMock.onGet(notificationCountsApiUrl).reply(404);
await executeThunk(fetchAppsNotificationCount(), store.dispatch, store.getState);

expect(store.getState().notifications.notificationStatus).toEqual('failed');
axiosMock.onGet(notificationCountsApiUrl).reply(404, { message: 'Failed to get notification counts.' });
try {
await getNotificationCounts();
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual('Failed to get notification counts.');
}
});

it('denied to get notification counts.', async () => {
axiosMock.onGet(notificationCountsApiUrl).reply(403, {});
await executeThunk(fetchAppsNotificationCount(), store.dispatch);

expect(store.getState().notifications.notificationStatus).toEqual('denied');
axiosMock.onGet(notificationCountsApiUrl).reply(403, { message: 'Denied to get notification counts.' });
try {
await getNotificationCounts();
} catch (error) {
expect(error.response.status).toEqual(403);
expect(error.response.data.message).toEqual('Denied to get notification counts.');
}
});

it('successfully get notifications.', async () => {
Expand All @@ -86,17 +82,23 @@ describe('Notifications API', () => {
});

it('failed to get notifications.', async () => {
axiosMock.onGet(notificationsApiUrl).reply(404);
await executeThunk(fetchNotificationList({ page: 1, pageSize: 10 }), store.dispatch, store.getState);

expect(store.getState().notifications.notificationStatus).toEqual('failed');
axiosMock.onGet(notificationsApiUrl).reply(404, { message: 'Failed to get notifications.' });
try {
await getNotifications({ page: 1, pageSize: 10 });
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual('Failed to get notifications.');
}
});

it('denied to get notifications.', async () => {
axiosMock.onGet(notificationsApiUrl).reply(403, {});
await executeThunk(fetchNotificationList({ page: 1, pageSize: 10 }), store.dispatch);

expect(store.getState().notifications.notificationStatus).toEqual('denied');
axiosMock.onGet(notificationsApiUrl).reply(403, { message: 'Denied to get notifications.' });
try {
await getNotifications({ page: 1, pageSize: 10 });
} catch (error) {
expect(error.response.status).toEqual(403);
expect(error.response.data.message).toEqual('Denied to get notifications.');
}
});

it('successfully marked all notifications as seen for selected app.', async () => {
Expand All @@ -108,17 +110,23 @@ describe('Notifications API', () => {
});

it('failed to mark all notifications as seen for selected app.', async () => {
axiosMock.onPut(markedAllNotificationsAsSeenApiUrl).reply(404);
await executeThunk(markNotificationsAsSeen('discussions'), store.dispatch, store.getState);

expect(store.getState().notifications.notificationStatus).toEqual('failed');
axiosMock.onPut(markedAllNotificationsAsSeenApiUrl).reply(404, { message: 'Failed to mark notifications seen.' });
try {
await markNotificationSeen('discussions');
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual('Failed to mark notifications seen.');
}
});

it('denied to mark all notifications as seen for selected app.', async () => {
axiosMock.onPut(markedAllNotificationsAsSeenApiUrl).reply(403, {});
await executeThunk(markNotificationsAsSeen('discussions'), store.dispatch);

expect(store.getState().notifications.notificationStatus).toEqual('denied');
axiosMock.onPut(markedAllNotificationsAsSeenApiUrl).reply(403, { message: 'Denied to mark notifications seen.' });
try {
await markNotificationSeen('discussions');
} catch (error) {
expect(error.response.status).toEqual(403);
expect(error.response.data.message).toEqual('Denied to mark notifications seen.');
}
});

it('successfully marked all notifications as read for selected app.', async () => {
Expand All @@ -130,38 +138,50 @@ describe('Notifications API', () => {
});

it('failed to mark all notifications as read for selected app.', async () => {
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(404);
await executeThunk(markAllNotificationsAsRead('discussions'), store.dispatch, store.getState);

expect(store.getState().notifications.notificationStatus).toEqual('failed');
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(404, { message: 'Failed to mark notifications read.' });
try {
await markAllNotificationRead('discussions');
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual('Failed to mark notifications read.');
}
});

it('denied to mark all notifications as read for selected app.', async () => {
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(403, {});
await executeThunk(markAllNotificationsAsRead('discussions'), store.dispatch);

expect(store.getState().notifications.notificationStatus).toEqual('denied');
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(403, { message: 'Denied to mark notifications read.' });
try {
await markAllNotificationRead('discussions');
} catch (error) {
expect(error.response.status).toEqual(403);
expect(error.response.data.message).toEqual('Denied to mark notifications read.');
}
});

it('successfully marked notification as read.', async () => {
axiosMock.onPut(markedNotificationAsReadApiUrl).reply(200, { message: 'Notification marked read.' });
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(200, { message: 'Notification marked read.' });

const { data } = await markNotificationRead('discussions', 1);
const { data } = await markNotificationRead(1);

expect(data.message).toEqual('Notification marked read.');
});

it('failed to mark notification as read .', async () => {
axiosMock.onPut(markedNotificationAsReadApiUrl).reply(404);
await executeThunk(markNotificationsAsRead('discussions', 1), store.dispatch, store.getState);

expect(store.getState().notifications.notificationStatus).toEqual('failed');
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(404, { message: 'Failed to mark notification read.' });
try {
await markNotificationRead(1);
} catch (error) {
expect(error.response.status).toEqual(404);
expect(error.response.data.message).toEqual('Failed to mark notification read.');
}
});

it('denied to mark notification as read.', async () => {
axiosMock.onPut(markedNotificationAsReadApiUrl).reply(403, {});
await executeThunk(markNotificationsAsRead('discussions', 1), store.dispatch);

expect(store.getState().notifications.notificationStatus).toEqual('denied');
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(403, { message: 'Denied to mark notification read.' });
try {
await markNotificationRead(1);
} catch (error) {
expect(error.response.status).toEqual(403);
expect(error.response.data.message).toEqual('Denied to mark notification read.');
}
});
});
33 changes: 3 additions & 30 deletions src/Notifications/data/redux.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import './__factories__';

const notificationCountsApiUrl = getNotificationsCountApiUrl();
const notificationsApiUrl = getNotificationsApiUrl();
const markedNotificationAsReadApiUrl = markAllNotificationsAsReadpiUrl('discussions', 1);
const markedAllNotificationsAsReadApiUrl = markAllNotificationsAsReadpiUrl('discussions');
const markedAllNotificationsAsReadApiUrl = markAllNotificationsAsReadpiUrl();
const markedAllNotificationsAsSeenApiUrl = markNotificationsSeenApiUrl('discussions');

let axiosMock;
Expand Down Expand Up @@ -86,32 +85,6 @@ describe('Notification Redux', () => {
expect(tabsCount.authoring).toEqual(5);
});

it('successfully loaded showNotificationTray status in the redux based on api.', async () => {
const { notifications: { showNotificationTray } } = store.getState();

expect(showNotificationTray).toEqual(true);
});

it('successfully store the count, numPages, currentPage, and nextPage data in redux.', async () => {
const { notifications: { pagination } } = store.getState();

expect(pagination.count).toEqual(10);
expect(pagination.currentPage).toEqual(1);
expect(pagination.numPages).toEqual(2);
});

it('successfully updated the selected app name in redux.', async () => {
const { notifications: { appName } } = store.getState();

expect(appName).toEqual('discussions');
});

it('successfully store notification ids in the selected app in apps.', async () => {
const { notifications: { apps } } = store.getState();

expect(apps.discussions).toHaveLength(2);
});

it('successfully marked all notifications as seen for selected app.', async () => {
axiosMock.onPut(markedAllNotificationsAsSeenApiUrl).reply(200);
await executeThunk(markNotificationsAsSeen('discussions'), store.dispatch, store.getState);
Expand All @@ -131,8 +104,8 @@ describe('Notification Redux', () => {
});

it('successfully marked notification as read in the redux.', async () => {
axiosMock.onPut(markedNotificationAsReadApiUrl).reply(200);
await executeThunk(markNotificationsAsRead('discussions', 1), store.dispatch, store.getState);
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(200);
await executeThunk(markNotificationsAsRead(1), store.dispatch, store.getState);

const { notifications: { notificationStatus, notifications } } = store.getState();
const firstNotification = Object.values(notifications)[0];
Expand Down
15 changes: 8 additions & 7 deletions src/Notifications/data/thunks.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { camelCaseObject } from '@edx/frontend-platform';
import {
fetchNotificationSuccess,
fetchNotificationRequest,
Expand Down Expand Up @@ -47,7 +48,7 @@ export const fetchNotificationList = ({ appName, page, pageSize }) => (
try {
dispatch(fetchNotificationRequest({ appName }));
const data = await getNotifications(appName, page, pageSize);
const normalisedData = normalizeNotifications((data));
const normalisedData = normalizeNotifications((camelCaseObject(data)));
dispatch(fetchNotificationSuccess({ ...normalisedData, numPages: data.numPages, currentPage: data.currentPage }));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
Expand All @@ -64,7 +65,7 @@ export const fetchAppsNotificationCount = () => (
try {
dispatch(fetchNotificationsCountRequest());
const data = await getNotificationCounts();
const normalisedData = normalizeNotificationCounts((data));
const normalisedData = normalizeNotificationCounts((camelCaseObject(data)));
dispatch(fetchNotificationsCountSuccess({
...normalisedData,
countByAppName: data.countByAppName,
Expand All @@ -86,7 +87,7 @@ export const markAllNotificationsAsRead = (appName) => (
try {
dispatch(markAllNotificationsAsReadRequest({ appName }));
const data = await markAllNotificationRead(appName);
dispatch(markAllNotificationsAsReadSuccess(data));
dispatch(markAllNotificationsAsReadSuccess(camelCaseObject(data)));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(markAllNotificationsAsReadDenied());
Expand All @@ -97,12 +98,12 @@ export const markAllNotificationsAsRead = (appName) => (
}
);

export const markNotificationsAsRead = (appName, notificationId) => (
export const markNotificationsAsRead = (notificationId) => (
async (dispatch) => {
try {
dispatch(markNotificationsAsReadRequest({ notificationId }));
const data = await markNotificationRead(appName, notificationId);
dispatch(markNotificationsAsReadSuccess(data));
const data = await markNotificationRead(notificationId);
dispatch(markNotificationsAsReadSuccess(camelCaseObject(data)));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(markNotificationsAsReadDenied());
Expand All @@ -118,7 +119,7 @@ export const markNotificationsAsSeen = (appName) => (
try {
dispatch(markNotificationsAsSeenRequest({ appName }));
const data = await markNotificationSeen(appName);
dispatch(markNotificationsAsSeenSuccess(data));
dispatch(markNotificationsAsSeenSuccess(camelCaseObject(data)));
} catch (error) {
if (getHttpErrorStatus(error) === 403) {
dispatch(markNotificationsAsSeenDenied());
Expand Down

0 comments on commit 683a582

Please sign in to comment.