From e46d4cc54ddb921a71e15278cec7c7dbd45d6efb Mon Sep 17 00:00:00 2001 From: Awais Ansari <79941147+awais-ansari@users.noreply.github.com> Date: Thu, 14 Mar 2024 20:52:19 +0500 Subject: [PATCH] feat: add tracking event in upgrade notifications tray (#1323) --- .../DiscussionsNotificationsSidebar.jsx | 24 +++++----- .../discussions/DiscussionsWidget.test.jsx | 4 ++ .../notifications/NotificationsWidget.jsx | 33 +++++++++++++- .../NotificationsWidget.test.jsx | 17 +++---- .../course/sequence/Sequence.test.jsx | 44 ++++++++++++------- .../notifications/NotificationTray.jsx | 34 ++++++++++++-- 6 files changed, 113 insertions(+), 43 deletions(-) diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/DiscussionsNotificationsSidebar.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/DiscussionsNotificationsSidebar.jsx index 94168991..eabd7492 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/DiscussionsNotificationsSidebar.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/DiscussionsNotificationsSidebar.jsx @@ -14,17 +14,19 @@ const DiscussionsNotificationsSidebar = () => { const { hideNotificationbar } = useContext(SidebarContext); return ( - - - {!hideNotificationbar &&
} - - +
+ + + {!hideNotificationbar &&
} + + +
); }; diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.test.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.test.jsx index 84685bf7..cfae7106 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.test.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.test.jsx @@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter'; import { getConfig } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; +import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { initializeMockApp, initializeTestStore, render, screen, @@ -16,6 +17,7 @@ import DiscussionsNotificationsSidebar from '../DiscussionsNotificationsSidebar' import DiscussionsWidget from './DiscussionsWidget'; initializeMockApp(); +jest.mock('@edx/frontend-platform/analytics'); describe('DiscussionsWidget', () => { let axiosMock; @@ -74,7 +76,9 @@ describe('DiscussionsWidget', () => { }); it('should display the Back to course button on small screens.', async () => { + sendTrackEvent.mockClear(); renderWithProvider(DiscussionsNotificationsSidebar, { shouldDisplayFullScreen: true }); expect(screen.queryByText('Back to course')).toBeInTheDocument(); + expect(sendTrackEvent).toHaveBeenCalledTimes(1); }); }); diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx index e146fb7a..6d124481 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx @@ -1,5 +1,6 @@ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useMemo } from 'react'; +import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { useModel } from '../../../../../../generic/model-store'; import UpgradeNotification from '../../../../../../generic/upgrade-notification/UpgradeNotification'; import WIDGETS from '../../../constants'; @@ -21,19 +22,47 @@ const NotificationsWidget = () => { const { accessExpiration, contentTypeGatingEnabled, + end, + enrollmentEnd, + enrollmentMode, + enrollmentStart, marketingUrl, offer, + start, timeOffsetMillis, userTimezone, + verificationStatus, } = course; const { + courseModes, org, verifiedMode, + username, } = useModel('courseHomeMeta', courseId); + const activeCourseModes = useMemo(() => courseModes?.map(mode => mode.slug), [courseModes]); + + const notificationTrayEventProperties = { + course_end: end, + course_modes: activeCourseModes, + course_start: start, + courserun_key: courseId, + enrollment_end: enrollmentEnd, + enrollment_mode: enrollmentMode, + enrollment_start: enrollmentStart, + is_upgrade_notification_visible: !!verifiedMode, + name: 'New Sidebar Notification Tray', + org_key: org, + username, + verification_status: verificationStatus, + }; + // After three seconds, update notificationSeen (to hide red dot) - useEffect(() => { setTimeout(onNotificationSeen, 3000); }, []); + useEffect(() => { + setTimeout(onNotificationSeen, 3000); + sendTrackEvent('edx.ui.course.upgrade.new_sidebar.notifications', notificationTrayEventProperties); + }, []); if (hideNotificationbar || !isNotificationbarAvailable) { return null; } diff --git a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx index 2438e826..7b11d131 100644 --- a/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx +++ b/src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx @@ -94,13 +94,9 @@ describe('NotificationsWidget', () => { ); const UpgradeNotification = document.querySelector('.upgrade-notification'); - expect(UpgradeNotification) - .toBeInTheDocument(); - expect(screen.getByRole('link', { name: 'Upgrade for $149' })) - .toBeInTheDocument(); - expect(screen.queryByText('You have no new notifications at this time.')) - .not - .toBeInTheDocument(); + expect(UpgradeNotification).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'Upgrade for $149' })).toBeInTheDocument(); + expect(screen.queryByText('You have no new notifications at this time.')).not.toBeInTheDocument(); }); it('renders no notifications bar if no verified mode', async () => { @@ -116,17 +112,14 @@ describe('NotificationsWidget', () => { , ); - expect(screen.queryByText('Notifications')) - .not - .toBeInTheDocument(); + expect(screen.queryByText('Notifications')).not.toBeInTheDocument(); }); it.each([ { description: 'close the notification widget.', enabledInContext: true, - testId: - 'notification-widget', + testId: 'notification-widget', }, { description: 'close the sidebar when the notification widget is closed, and the discussion widget is unavailable.', diff --git a/src/courseware/course/sequence/Sequence.test.jsx b/src/courseware/course/sequence/Sequence.test.jsx index 2676fbef..50a8f7e1 100644 --- a/src/courseware/course/sequence/Sequence.test.jsx +++ b/src/courseware/course/sequence/Sequence.test.jsx @@ -180,7 +180,7 @@ describe('Sequence', () => { const sequencePreviousButton = screen.getByRole('link', { name: /previous/i }); fireEvent.click(sequencePreviousButton); expect(testData.previousSequenceHandler).toHaveBeenCalledTimes(1); - expect(sendTrackEvent).toHaveBeenCalledTimes(1); + expect(sendTrackEvent).toHaveBeenCalledTimes(2); expect(sendTrackEvent).toHaveBeenCalledWith('edx.ui.lms.sequence.previous_selected', { current_tab: 1, id: testData.unitId, @@ -194,8 +194,8 @@ describe('Sequence', () => { .filter(button => button !== sequencePreviousButton)[0]; fireEvent.click(unitPreviousButton); expect(testData.previousSequenceHandler).toHaveBeenCalledTimes(2); - expect(sendTrackEvent).toHaveBeenCalledTimes(2); - expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.previous_selected', { + expect(sendTrackEvent).toHaveBeenCalledTimes(3); + expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.previous_selected', { current_tab: 1, id: testData.unitId, tab_count: unitBlocks.length, @@ -229,8 +229,8 @@ describe('Sequence', () => { .filter(button => button !== sequenceNextButton)[0]; fireEvent.click(unitNextButton); expect(testData.nextSequenceHandler).toHaveBeenCalledTimes(2); - expect(sendTrackEvent).toHaveBeenCalledTimes(2); - expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.next_selected', { + expect(sendTrackEvent).toHaveBeenCalledTimes(3); + expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.next_selected', { current_tab: unitBlocks.length, id: testData.unitId, tab_count: unitBlocks.length, @@ -261,7 +261,7 @@ describe('Sequence', () => { // Therefore the next unit will still be `the initial one + 1`. expect(testData.unitNavigationHandler).toHaveBeenNthCalledWith(2, unitBlocks[unitNumber + 1].id); - expect(sendTrackEvent).toHaveBeenCalledTimes(2); + expect(sendTrackEvent).toHaveBeenCalledTimes(3); }); it('handles the `Previous` buttons for the first unit in the first sequence', async () => { @@ -280,7 +280,7 @@ describe('Sequence', () => { expect(testData.previousSequenceHandler).not.toHaveBeenCalled(); expect(testData.unitNavigationHandler).not.toHaveBeenCalled(); - expect(sendTrackEvent).not.toHaveBeenCalled(); + expect(sendTrackEvent).toHaveBeenCalled(); }); it('handles the `Next` buttons for the last unit in the last sequence', async () => { @@ -299,7 +299,7 @@ describe('Sequence', () => { expect(testData.nextSequenceHandler).not.toHaveBeenCalled(); expect(testData.unitNavigationHandler).not.toHaveBeenCalled(); - expect(sendTrackEvent).not.toHaveBeenCalled(); + expect(sendTrackEvent).toHaveBeenCalled(); }); it('handles the navigation buttons for empty sequence', async () => { @@ -345,25 +345,39 @@ describe('Sequence', () => { expect(testData.nextSequenceHandler).toHaveBeenCalledTimes(2); expect(testData.unitNavigationHandler).not.toHaveBeenCalled(); - expect(sendTrackEvent).toHaveBeenNthCalledWith(1, 'edx.ui.lms.sequence.previous_selected', { - current_tab: 1, - id: testData.unitId, - tab_count: 0, - widget_placement: 'top', + expect(sendTrackEvent).toHaveBeenNthCalledWith(1, 'edx.ui.course.upgrade.old_sidebar.notifications', { + course_end: undefined, + course_modes: undefined, + course_start: undefined, + courserun_key: undefined, + enrollment_end: undefined, + enrollment_mode: undefined, + enrollment_start: undefined, + is_upgrade_notification_visible: false, + name: 'Old Sidebar Notification Tray', + org_key: undefined, + username: undefined, + verification_status: undefined, }); expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.previous_selected', { + current_tab: 1, + id: testData.unitId, + tab_count: 0, + widget_placement: 'top', + }); + expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.previous_selected', { current_tab: 1, id: testData.unitId, tab_count: 0, widget_placement: 'bottom', }); - expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.next_selected', { + expect(sendTrackEvent).toHaveBeenNthCalledWith(4, 'edx.ui.lms.sequence.next_selected', { current_tab: 1, id: testData.unitId, tab_count: 0, widget_placement: 'top', }); - expect(sendTrackEvent).toHaveBeenNthCalledWith(4, 'edx.ui.lms.sequence.next_selected', { + expect(sendTrackEvent).toHaveBeenNthCalledWith(5, 'edx.ui.lms.sequence.next_selected', { current_tab: 1, id: testData.unitId, tab_count: 0, diff --git a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx index 409f3a92..76f1e38f 100644 --- a/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx +++ b/src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx @@ -1,6 +1,7 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import classNames from 'classnames'; -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useMemo } from 'react'; +import { sendTrackEvent } from '@edx/frontend-platform/analytics'; import { useModel } from '../../../../../generic/model-store'; import UpgradeNotification from '../../../../../generic/upgrade-notification/UpgradeNotification'; @@ -22,20 +23,47 @@ const NotificationTray = ({ intl }) => { const { accessExpiration, contentTypeGatingEnabled, + end, + enrollmentEnd, + enrollmentMode, + enrollmentStart, marketingUrl, offer, + start, timeOffsetMillis, userTimezone, + verificationStatus, } = course; const { + courseModes, org, verifiedMode, + username, } = useModel('courseHomeMeta', courseId); + const activeCourseModes = useMemo(() => courseModes?.map(mode => mode.slug), [courseModes]); + + const notificationTrayEventProperties = { + course_end: end, + course_modes: activeCourseModes, + course_start: start, + courserun_key: courseId, + enrollment_end: enrollmentEnd, + enrollment_mode: enrollmentMode, + enrollment_start: enrollmentStart, + is_upgrade_notification_visible: !!verifiedMode, + name: 'Old Sidebar Notification Tray', + org_key: org, + username, + verification_status: verificationStatus, + }; + // After three seconds, update notificationSeen (to hide red dot) - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(() => { setTimeout(onNotificationSeen, 3000); }, []); + useEffect(() => { + setTimeout(onNotificationSeen, 3000); + sendTrackEvent('edx.ui.course.upgrade.old_sidebar.notifications', notificationTrayEventProperties); + }, []); return (