From d760be1a533ff3da305dd1a59f962911671a354c Mon Sep 17 00:00:00 2001 From: Ahtisham Shahid Date: Fri, 4 Jul 2025 17:00:09 +0500 Subject: [PATCH] feat: integrated notification preferences v2 API (#1280) --- .env | 1 + .env.development | 1 + .env.test | 1 + src/index.jsx | 1 + .../NotificationPreferences.test.jsx | 71 +++++++++++++++++++ src/notification-preferences/data/service.js | 11 ++- 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/.env b/.env index 2cb38af..89430a4 100644 --- a/.env +++ b/.env @@ -37,3 +37,4 @@ SUPPORT_URL_TO_UNLINK_SOCIAL_MEDIA_ACCOUNT='https://help.edx.org/edxlearner/s/ar COUNTRIES_WITH_DELETE_ACCOUNT_DISABLED='[]' # Fallback in local style files PARAGON_THEME_URLS={} +ENABLE_PREFERENCES_V2='false' diff --git a/.env.development b/.env.development index 9b6218d..1c3d711 100644 --- a/.env.development +++ b/.env.development @@ -38,3 +38,4 @@ SUPPORT_URL_TO_UNLINK_SOCIAL_MEDIA_ACCOUNT='https://help.edx.org/edxlearner/s/ar COUNTRIES_WITH_DELETE_ACCOUNT_DISABLED='[]' # Fallback in local style files PARAGON_THEME_URLS={} +ENABLE_PREFERENCES_V2='false' diff --git a/.env.test b/.env.test index 25d9962..d05ed4a 100644 --- a/.env.test +++ b/.env.test @@ -34,3 +34,4 @@ LEARNER_FEEDBACK_URL='' SUPPORT_URL_TO_UNLINK_SOCIAL_MEDIA_ACCOUNT='https://help.edx.org/edxlearner/s/article/How-do-I-link-or-unlink-my-edX-account-to-a-social-media-account' COUNTRIES_WITH_DELETE_ACCOUNT_DISABLED='[]' PARAGON_THEME_URLS={} +ENABLE_PREFERENCES_V2='false' diff --git a/src/index.jsx b/src/index.jsx index da2a3d1..be14a3d 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -74,6 +74,7 @@ initialize({ MARKETING_EMAILS_OPT_IN: (process.env.MARKETING_EMAILS_OPT_IN || false), PASSWORD_RESET_SUPPORT_LINK: process.env.PASSWORD_RESET_SUPPORT_LINK, LEARNER_FEEDBACK_URL: process.env.LEARNER_FEEDBACK_URL, + ENABLE_PREFERENCES_V2: process.env.ENABLE_PREFERENCES_V2 || false, }, 'App loadConfig override handler'); }, }, diff --git a/src/notification-preferences/NotificationPreferences.test.jsx b/src/notification-preferences/NotificationPreferences.test.jsx index 46f443d..aa9e173 100644 --- a/src/notification-preferences/NotificationPreferences.test.jsx +++ b/src/notification-preferences/NotificationPreferences.test.jsx @@ -11,6 +11,10 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { defaultState } from './data/reducers'; import NotificationPreferences from './NotificationPreferences'; import { LOADING_STATUS, SUCCESS_STATUS } from '../constants'; +import { + getCourseNotificationPreferences, + postPreferenceToggle, +} from './data/service'; const courseId = 'selected-course-id'; @@ -191,3 +195,70 @@ describe('Notification Preferences', () => { } }); }); + +describe('Notification Preferences API v2 Logic', () => { + const LMS_BASE_URL = 'https://lms.example.com'; + let mockHttpClient; + + beforeEach(() => { + jest.clearAllMocks(); + + mockHttpClient = { + get: jest.fn().mockResolvedValue({ data: {} }), + put: jest.fn().mockResolvedValue({ data: {} }), + post: jest.fn().mockResolvedValue({ data: {} }), + patch: jest.fn().mockResolvedValue({ data: {} }), + }; + auth.getAuthenticatedHttpClient.mockReturnValue(mockHttpClient); + + setConfig({ LMS_BASE_URL }); + }); + + describe('getCourseNotificationPreferences', () => { + it('should call the v2 configurations URL when ENABLE_PREFERENCES_V2 is true', async () => { + setConfig({ LMS_BASE_URL, ENABLE_PREFERENCES_V2: 'true' }); + const expectedUrl = `${LMS_BASE_URL}/api/notifications/v2/configurations/`; + + await getCourseNotificationPreferences('any-course-id'); + + expect(mockHttpClient.get).toHaveBeenCalledWith(expectedUrl); + expect(mockHttpClient.get).toHaveBeenCalledTimes(1); + }); + + it('should call the original (v1) configurations URL when ENABLE_PREFERENCES_V2 is not true', async () => { + setConfig({ LMS_BASE_URL, ENABLE_PREFERENCES_V2: 'false' }); + const expectedUrl = `${LMS_BASE_URL}/api/notifications/configurations/${courseId}`; + + await getCourseNotificationPreferences(courseId); + + expect(mockHttpClient.get).toHaveBeenCalledWith(expectedUrl); + expect(mockHttpClient.get).toHaveBeenCalledTimes(1); + }); + }); + + describe('postPreferenceToggle', () => { + it('should call the v2 configurations URL with PUT method when ENABLE_PREFERENCES_V2 is true', async () => { + setConfig({ LMS_BASE_URL, ENABLE_PREFERENCES_V2: 'true' }); + const expectedUrl = `${LMS_BASE_URL}/api/notifications/v2/configurations/`; + const testArgs = ['app_name', 'notification_type', 'web', true, 'daily']; + + await postPreferenceToggle(...testArgs); + + expect(mockHttpClient.put).toHaveBeenCalledWith(expectedUrl, expect.any(Object)); + expect(mockHttpClient.put).toHaveBeenCalledTimes(1); + expect(mockHttpClient.post).not.toHaveBeenCalled(); + }); + + it('should call the original (v1) update-all URL with POST method when ENABLE_PREFERENCES_V2 is not true', async () => { + setConfig({ LMS_BASE_URL, ENABLE_PREFERENCES_V2: 'false' }); + const expectedUrl = `${LMS_BASE_URL}/api/notifications/preferences/update-all/`; + const testArgs = ['app_name', 'notification_type', 'web', true, 'daily']; + + await postPreferenceToggle(...testArgs); + + expect(mockHttpClient.post).toHaveBeenCalledWith(expectedUrl, expect.any(Object)); + expect(mockHttpClient.post).toHaveBeenCalledTimes(1); + expect(mockHttpClient.put).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/src/notification-preferences/data/service.js b/src/notification-preferences/data/service.js index 98b18fe..d9dbc88 100644 --- a/src/notification-preferences/data/service.js +++ b/src/notification-preferences/data/service.js @@ -3,7 +3,10 @@ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import snakeCase from 'lodash.snakecase'; export const getCourseNotificationPreferences = async (courseId) => { - const url = `${getConfig().LMS_BASE_URL}/api/notifications/configurations/${courseId}`; + let url = `${getConfig().LMS_BASE_URL}/api/notifications/configurations/${courseId}`; + if (getConfig().ENABLE_PREFERENCES_V2 === 'true') { + url = `${getConfig().LMS_BASE_URL}/api/notifications/v2/configurations/`; + } const { data } = await getAuthenticatedHttpClient().get(url); return data; }; @@ -47,6 +50,12 @@ export const postPreferenceToggle = async ( value, emailCadence, }); + if (getConfig().ENABLE_PREFERENCES_V2 === 'true') { + const url = `${getConfig().LMS_BASE_URL}/api/notifications/v2/configurations/`; + const { data } = await getAuthenticatedHttpClient().put(url, patchData); + return data; + } + const url = `${getConfig().LMS_BASE_URL}/api/notifications/preferences/update-all/`; const { data } = await getAuthenticatedHttpClient().post(url, patchData); return data;