test: added redux, selector and api cases
This commit is contained in:
57
package-lock.json
generated
57
package-lock.json
generated
@@ -16,6 +16,7 @@
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@reduxjs/toolkit": "1.9.5",
|
||||
"axios-mock-adapter": "1.21.4",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"classnames": "2.3.2",
|
||||
"lodash": "4.17.21",
|
||||
@@ -23,6 +24,7 @@
|
||||
"react-responsive": "8.2.0",
|
||||
"react-router-dom": "5.3.4",
|
||||
"react-transition-group": "4.4.5",
|
||||
"rosie": "2.1.0",
|
||||
"timeago.js": "4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -7709,8 +7711,7 @@
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/at-least-node": {
|
||||
"version": "1.0.0",
|
||||
@@ -7799,7 +7800,6 @@
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
|
||||
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.9",
|
||||
"form-data": "^4.0.0"
|
||||
@@ -7819,6 +7819,40 @@
|
||||
"url": "https://github.com/ArthurFiorette/axios-cache-interceptor?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/axios-mock-adapter": {
|
||||
"version": "1.21.4",
|
||||
"resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.21.4.tgz",
|
||||
"integrity": "sha512-ztnENm28ONAKeRXC/6SUW6pcsaXbThKq93MRDRAA47LYTzrGSDoO/DCr1NHz7jApEl95DrBoGPvZ0r9xtSbjqw==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"is-buffer": "^2.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"axios": ">= 0.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios-mock-adapter/node_modules/is-buffer": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
|
||||
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
|
||||
@@ -9166,7 +9200,6 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
@@ -9896,7 +9929,6 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
@@ -11774,8 +11806,7 @@
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fast-defer": {
|
||||
"version": "1.1.7",
|
||||
@@ -12052,7 +12083,6 @@
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -12283,7 +12313,6 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@@ -19203,7 +19232,6 @@
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@@ -19212,7 +19240,6 @@
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
@@ -22628,6 +22655,14 @@
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/rosie": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/rosie/-/rosie-2.1.0.tgz",
|
||||
"integrity": "sha512-Dbzdc+prLXZuB/suRptDnBUY29SdGvND3bLg6cll8n7PNqzuyCxSlRfrkn8PqjS9n4QVsiM7RCvxCkKAkTQRjA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/rst-selector-parser": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
|
||||
|
||||
@@ -62,14 +62,16 @@
|
||||
"@fortawesome/free-solid-svg-icons": "6.3.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@reduxjs/toolkit": "1.9.5",
|
||||
"axios-mock-adapter": "1.21.4",
|
||||
"babel-polyfill": "6.26.0",
|
||||
"classnames": "2.3.2",
|
||||
"lodash": "4.17.21",
|
||||
"react-redux": "7.2.9",
|
||||
"react-responsive": "8.2.0",
|
||||
"react-router-dom": "5.3.4",
|
||||
"react-transition-group": "4.4.5",
|
||||
"timeago.js": "4.0.2",
|
||||
"react-router-dom": "5.3.4"
|
||||
"rosie": "2.1.0",
|
||||
"timeago.js": "4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@edx/frontend-platform": "^4.0.0",
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import { camelCaseObject } from '@edx/frontend-platform';
|
||||
import notificationsList from './notifications.json';
|
||||
import { camelCaseObject, 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 async function getNotifications(appName, page, pageSize) {
|
||||
const { data } = notificationsList;
|
||||
const params = snakeCaseObject({ page, pageSize });
|
||||
const { data } = await getAuthenticatedHttpClient().get(getNotificationsApiUrl(), { params });
|
||||
|
||||
const startIndex = (page - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
|
||||
@@ -11,30 +18,25 @@ export async function getNotifications(appName, page, pageSize) {
|
||||
}
|
||||
|
||||
export async function getNotificationCounts() {
|
||||
const data = {
|
||||
count: 45,
|
||||
count_by_app_name: {
|
||||
reminders: 10,
|
||||
discussions: 20,
|
||||
grades: 10,
|
||||
authoring: 5,
|
||||
},
|
||||
show_notification_tray: false,
|
||||
};
|
||||
const { data } = await getAuthenticatedHttpClient().get(getNotificationsCountApiUrl());
|
||||
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function markNotificationSeen() {
|
||||
const data = [];
|
||||
export async function markNotificationSeen(appName) {
|
||||
const { data } = await getAuthenticatedHttpClient().put(`${markNotificationsSeenApiUrl(appName)}`);
|
||||
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function markAllNotificationRead() {
|
||||
const { data } = camelCaseObject(notificationsList);
|
||||
return data;
|
||||
export async function markAllNotificationRead(appName) {
|
||||
const { data } = await getAuthenticatedHttpClient().put(`${markAllNotificationsAsReadpiUrl(appName)}`);
|
||||
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function markNotificationRead(notificationId) {
|
||||
const { data } = camelCaseObject(notificationsList);
|
||||
return { data, id: notificationId };
|
||||
export async function markNotificationRead(appName, notificationId) {
|
||||
const { data } = await getAuthenticatedHttpClient().put(`${markAllNotificationsAsReadpiUrl(appName, notificationId)}`);
|
||||
|
||||
return camelCaseObject({ data, id: notificationId });
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ describe('Notification Redux', () => {
|
||||
store = initializeStore();
|
||||
|
||||
axiosMock.onGet(notificationCountsApiUrl).reply(200, (Factory.build('notificationsCount')));
|
||||
axiosMock.onGet(notificationsApiUrl).reply(200, (Factory.buildList('notification', 2, null)));
|
||||
axiosMock.onGet(notificationsApiUrl).reply(
|
||||
200,
|
||||
(Factory.buildList('notification', 2, null, { createdDate: new Date().toISOString() })),
|
||||
);
|
||||
await executeThunk(fetchAppsNotificationCount(), store.dispatch, store.getState);
|
||||
await executeThunk(fetchNotificationList({ page: 1, pageSize: 10 }), store.dispatch, store.getState);
|
||||
});
|
||||
@@ -68,9 +71,9 @@ describe('Notification Redux', () => {
|
||||
});
|
||||
|
||||
it('successfully loaded notifications list in the redux.', async () => {
|
||||
const state = store.getState();
|
||||
const { notifications: { notifications } } = store.getState();
|
||||
|
||||
expect(Object.keys(state.notifications.notifications)).toHaveLength(2);
|
||||
expect(Object.keys(notifications)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('successfully loaded notification counts in the redux.', async () => {
|
||||
@@ -84,9 +87,9 @@ describe('Notification Redux', () => {
|
||||
});
|
||||
|
||||
it('successfully loaded showNotificationTray status in the redux based on api.', async () => {
|
||||
const state = store.getState();
|
||||
const { notifications: { showNotificationTray } } = store.getState();
|
||||
|
||||
expect(state.notifications.showNotificationTray).toEqual(true);
|
||||
expect(showNotificationTray).toEqual(true);
|
||||
});
|
||||
|
||||
it('successfully store the count, numPages, currentPage, and nextPage data in redux.', async () => {
|
||||
@@ -98,15 +101,15 @@ describe('Notification Redux', () => {
|
||||
});
|
||||
|
||||
it('successfully updated the selected app name in redux.', async () => {
|
||||
const state = store.getState();
|
||||
const { notifications: { appName } } = store.getState();
|
||||
|
||||
expect(state.notifications.appName).toEqual('discussions');
|
||||
expect(appName).toEqual('discussions');
|
||||
});
|
||||
|
||||
it('successfully store notification ids in the selected app in apps.', async () => {
|
||||
const state = store.getState();
|
||||
const { notifications: { apps } } = store.getState();
|
||||
|
||||
expect(state.notifications.apps.discussions).toHaveLength(2);
|
||||
expect(apps.discussions).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('successfully marked all notifications as seen for selected app.', async () => {
|
||||
@@ -120,10 +123,10 @@ describe('Notification Redux', () => {
|
||||
axiosMock.onPut(markedAllNotificationsAsReadApiUrl).reply(200);
|
||||
await executeThunk(markAllNotificationsAsRead('discussions'), store.dispatch, store.getState);
|
||||
|
||||
const { notifications } = store.getState();
|
||||
const firstNotification = Object.values(notifications.notifications)[0];
|
||||
const { notifications: { notificationStatus, notifications } } = store.getState();
|
||||
const firstNotification = Object.values(notifications)[0];
|
||||
|
||||
expect(notifications.notificationStatus).toEqual('successful');
|
||||
expect(notificationStatus).toEqual('successful');
|
||||
expect(firstNotification.lastRead).not.toBeNull();
|
||||
});
|
||||
|
||||
@@ -131,10 +134,10 @@ describe('Notification Redux', () => {
|
||||
axiosMock.onPut(markedNotificationAsReadApiUrl).reply(200);
|
||||
await executeThunk(markNotificationsAsRead('discussions', 1), store.dispatch, store.getState);
|
||||
|
||||
const { notifications } = store.getState();
|
||||
const firstNotification = Object.values(notifications.notifications)[0];
|
||||
const { notifications: { notificationStatus, notifications } } = store.getState();
|
||||
const firstNotification = Object.values(notifications)[0];
|
||||
|
||||
expect(notifications.notificationStatus).toEqual('successful');
|
||||
expect(notificationStatus).toEqual('successful');
|
||||
expect(firstNotification.lastRead).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,7 +43,10 @@ describe('Notification Selectors', () => {
|
||||
store = initializeStore();
|
||||
|
||||
axiosMock.onGet(notificationCountsApiUrl).reply(200, (Factory.build('notificationsCount')));
|
||||
axiosMock.onGet(notificationsApiUrl).reply(200, (Factory.buildList('notification', 2, null)));
|
||||
axiosMock.onGet(notificationsApiUrl).reply(
|
||||
200,
|
||||
(Factory.buildList('notification', 2, null, { createdDate: new Date().toISOString() })),
|
||||
);
|
||||
await executeThunk(fetchAppsNotificationCount(), store.dispatch, store.getState);
|
||||
await executeThunk(fetchNotificationList({ page: 1, pageSize: 10 }), store.dispatch, store.getState);
|
||||
});
|
||||
|
||||
@@ -97,11 +97,11 @@ export const markAllNotificationsAsRead = (appName) => (
|
||||
}
|
||||
);
|
||||
|
||||
export const markNotificationsAsRead = (notificationId) => (
|
||||
export const markNotificationsAsRead = (appName, notificationId) => (
|
||||
async (dispatch) => {
|
||||
try {
|
||||
dispatch(markNotificationsAsReadRequest({ notificationId }));
|
||||
const data = await markNotificationRead(notificationId);
|
||||
const data = await markNotificationRead(appName, notificationId);
|
||||
dispatch(markNotificationsAsReadSuccess(data));
|
||||
} catch (error) {
|
||||
if (getHttpErrorStatus(error) === 403) {
|
||||
|
||||
Reference in New Issue
Block a user