Skip to content

Commit e46d4cc

Browse files
authored
feat: add tracking event in upgrade notifications tray (openedx#1323)
1 parent 92d8f63 commit e46d4cc

File tree

6 files changed

+110
-40
lines changed

6 files changed

+110
-40
lines changed

src/courseware/course/new-sidebar/sidebars/discussions-notifications/DiscussionsNotificationsSidebar.jsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ const DiscussionsNotificationsSidebar = () => {
1414
const { hideNotificationbar } = useContext(SidebarContext);
1515

1616
return (
17-
<SidebarBase
18-
ariaLabel={intl.formatMessage(messages.discussionNotificationTray)}
19-
sidebarId={ID}
20-
className="d-flex flex-column flex-fill sticky-top vh-100"
21-
showTitleBar={false}
22-
showBorder={false}
23-
>
24-
<NotificationTray />
25-
{!hideNotificationbar && <div className="my-1.5" />}
26-
<DiscussionsSidebar />
27-
</SidebarBase>
17+
<div className="sticky-top vh-100">
18+
<SidebarBase
19+
ariaLabel={intl.formatMessage(messages.discussionNotificationTray)}
20+
sidebarId={ID}
21+
className="d-flex flex-column flex-fill"
22+
showTitleBar={false}
23+
showBorder={false}
24+
>
25+
<NotificationTray />
26+
{!hideNotificationbar && <div className="my-1.5" />}
27+
<DiscussionsSidebar />
28+
</SidebarBase>
29+
</div>
2830
);
2931
};
3032

src/courseware/course/new-sidebar/sidebars/discussions-notifications/discussions/DiscussionsWidget.test.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import MockAdapter from 'axios-mock-adapter';
44

55
import { getConfig } from '@edx/frontend-platform';
66
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
7+
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
78

89
import {
910
initializeMockApp, initializeTestStore, render, screen,
@@ -16,6 +17,7 @@ import DiscussionsNotificationsSidebar from '../DiscussionsNotificationsSidebar'
1617
import DiscussionsWidget from './DiscussionsWidget';
1718

1819
initializeMockApp();
20+
jest.mock('@edx/frontend-platform/analytics');
1921

2022
describe('DiscussionsWidget', () => {
2123
let axiosMock;
@@ -74,7 +76,9 @@ describe('DiscussionsWidget', () => {
7476
});
7577

7678
it('should display the Back to course button on small screens.', async () => {
79+
sendTrackEvent.mockClear();
7780
renderWithProvider(DiscussionsNotificationsSidebar, { shouldDisplayFullScreen: true });
7881
expect(screen.queryByText('Back to course')).toBeInTheDocument();
82+
expect(sendTrackEvent).toHaveBeenCalledTimes(1);
7983
});
8084
});

src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.jsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { useContext, useEffect } from 'react';
1+
import React, { useContext, useEffect, useMemo } from 'react';
22

3+
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
34
import { useModel } from '../../../../../../generic/model-store';
45
import UpgradeNotification from '../../../../../../generic/upgrade-notification/UpgradeNotification';
56
import WIDGETS from '../../../constants';
@@ -21,19 +22,47 @@ const NotificationsWidget = () => {
2122
const {
2223
accessExpiration,
2324
contentTypeGatingEnabled,
25+
end,
26+
enrollmentEnd,
27+
enrollmentMode,
28+
enrollmentStart,
2429
marketingUrl,
2530
offer,
31+
start,
2632
timeOffsetMillis,
2733
userTimezone,
34+
verificationStatus,
2835
} = course;
2936

3037
const {
38+
courseModes,
3139
org,
3240
verifiedMode,
41+
username,
3342
} = useModel('courseHomeMeta', courseId);
3443

44+
const activeCourseModes = useMemo(() => courseModes?.map(mode => mode.slug), [courseModes]);
45+
46+
const notificationTrayEventProperties = {
47+
course_end: end,
48+
course_modes: activeCourseModes,
49+
course_start: start,
50+
courserun_key: courseId,
51+
enrollment_end: enrollmentEnd,
52+
enrollment_mode: enrollmentMode,
53+
enrollment_start: enrollmentStart,
54+
is_upgrade_notification_visible: !!verifiedMode,
55+
name: 'New Sidebar Notification Tray',
56+
org_key: org,
57+
username,
58+
verification_status: verificationStatus,
59+
};
60+
3561
// After three seconds, update notificationSeen (to hide red dot)
36-
useEffect(() => { setTimeout(onNotificationSeen, 3000); }, []);
62+
useEffect(() => {
63+
setTimeout(onNotificationSeen, 3000);
64+
sendTrackEvent('edx.ui.course.upgrade.new_sidebar.notifications', notificationTrayEventProperties);
65+
}, []);
3766

3867
if (hideNotificationbar || !isNotificationbarAvailable) { return null; }
3968

src/courseware/course/new-sidebar/sidebars/discussions-notifications/notifications/NotificationsWidget.test.jsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,9 @@ describe('NotificationsWidget', () => {
9494
);
9595
const UpgradeNotification = document.querySelector('.upgrade-notification');
9696

97-
expect(UpgradeNotification)
98-
.toBeInTheDocument();
99-
expect(screen.getByRole('link', { name: 'Upgrade for $149' }))
100-
.toBeInTheDocument();
101-
expect(screen.queryByText('You have no new notifications at this time.'))
102-
.not
103-
.toBeInTheDocument();
97+
expect(UpgradeNotification).toBeInTheDocument();
98+
expect(screen.getByRole('link', { name: 'Upgrade for $149' })).toBeInTheDocument();
99+
expect(screen.queryByText('You have no new notifications at this time.')).not.toBeInTheDocument();
104100
});
105101

106102
it('renders no notifications bar if no verified mode', async () => {
@@ -116,17 +112,14 @@ describe('NotificationsWidget', () => {
116112
<NotificationsWidget />
117113
</SidebarContext.Provider>,
118114
);
119-
expect(screen.queryByText('Notifications'))
120-
.not
121-
.toBeInTheDocument();
115+
expect(screen.queryByText('Notifications')).not.toBeInTheDocument();
122116
});
123117

124118
it.each([
125119
{
126120
description: 'close the notification widget.',
127121
enabledInContext: true,
128-
testId:
129-
'notification-widget',
122+
testId: 'notification-widget',
130123
},
131124
{
132125
description: 'close the sidebar when the notification widget is closed, and the discussion widget is unavailable.',

src/courseware/course/sequence/Sequence.test.jsx

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ describe('Sequence', () => {
180180
const sequencePreviousButton = screen.getByRole('link', { name: /previous/i });
181181
fireEvent.click(sequencePreviousButton);
182182
expect(testData.previousSequenceHandler).toHaveBeenCalledTimes(1);
183-
expect(sendTrackEvent).toHaveBeenCalledTimes(1);
183+
expect(sendTrackEvent).toHaveBeenCalledTimes(2);
184184
expect(sendTrackEvent).toHaveBeenCalledWith('edx.ui.lms.sequence.previous_selected', {
185185
current_tab: 1,
186186
id: testData.unitId,
@@ -194,8 +194,8 @@ describe('Sequence', () => {
194194
.filter(button => button !== sequencePreviousButton)[0];
195195
fireEvent.click(unitPreviousButton);
196196
expect(testData.previousSequenceHandler).toHaveBeenCalledTimes(2);
197-
expect(sendTrackEvent).toHaveBeenCalledTimes(2);
198-
expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.previous_selected', {
197+
expect(sendTrackEvent).toHaveBeenCalledTimes(3);
198+
expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.previous_selected', {
199199
current_tab: 1,
200200
id: testData.unitId,
201201
tab_count: unitBlocks.length,
@@ -229,8 +229,8 @@ describe('Sequence', () => {
229229
.filter(button => button !== sequenceNextButton)[0];
230230
fireEvent.click(unitNextButton);
231231
expect(testData.nextSequenceHandler).toHaveBeenCalledTimes(2);
232-
expect(sendTrackEvent).toHaveBeenCalledTimes(2);
233-
expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.next_selected', {
232+
expect(sendTrackEvent).toHaveBeenCalledTimes(3);
233+
expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.next_selected', {
234234
current_tab: unitBlocks.length,
235235
id: testData.unitId,
236236
tab_count: unitBlocks.length,
@@ -261,7 +261,7 @@ describe('Sequence', () => {
261261
// Therefore the next unit will still be `the initial one + 1`.
262262
expect(testData.unitNavigationHandler).toHaveBeenNthCalledWith(2, unitBlocks[unitNumber + 1].id);
263263

264-
expect(sendTrackEvent).toHaveBeenCalledTimes(2);
264+
expect(sendTrackEvent).toHaveBeenCalledTimes(3);
265265
});
266266

267267
it('handles the `Previous` buttons for the first unit in the first sequence', async () => {
@@ -280,7 +280,7 @@ describe('Sequence', () => {
280280

281281
expect(testData.previousSequenceHandler).not.toHaveBeenCalled();
282282
expect(testData.unitNavigationHandler).not.toHaveBeenCalled();
283-
expect(sendTrackEvent).not.toHaveBeenCalled();
283+
expect(sendTrackEvent).toHaveBeenCalled();
284284
});
285285

286286
it('handles the `Next` buttons for the last unit in the last sequence', async () => {
@@ -299,7 +299,7 @@ describe('Sequence', () => {
299299

300300
expect(testData.nextSequenceHandler).not.toHaveBeenCalled();
301301
expect(testData.unitNavigationHandler).not.toHaveBeenCalled();
302-
expect(sendTrackEvent).not.toHaveBeenCalled();
302+
expect(sendTrackEvent).toHaveBeenCalled();
303303
});
304304

305305
it('handles the navigation buttons for empty sequence', async () => {
@@ -345,25 +345,39 @@ describe('Sequence', () => {
345345
expect(testData.nextSequenceHandler).toHaveBeenCalledTimes(2);
346346
expect(testData.unitNavigationHandler).not.toHaveBeenCalled();
347347

348-
expect(sendTrackEvent).toHaveBeenNthCalledWith(1, 'edx.ui.lms.sequence.previous_selected', {
348+
expect(sendTrackEvent).toHaveBeenNthCalledWith(1, 'edx.ui.course.upgrade.old_sidebar.notifications', {
349+
course_end: undefined,
350+
course_modes: undefined,
351+
course_start: undefined,
352+
courserun_key: undefined,
353+
enrollment_end: undefined,
354+
enrollment_mode: undefined,
355+
enrollment_start: undefined,
356+
is_upgrade_notification_visible: false,
357+
name: 'Old Sidebar Notification Tray',
358+
org_key: undefined,
359+
username: undefined,
360+
verification_status: undefined,
361+
});
362+
expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.previous_selected', {
349363
current_tab: 1,
350364
id: testData.unitId,
351365
tab_count: 0,
352366
widget_placement: 'top',
353367
});
354-
expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'edx.ui.lms.sequence.previous_selected', {
368+
expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.previous_selected', {
355369
current_tab: 1,
356370
id: testData.unitId,
357371
tab_count: 0,
358372
widget_placement: 'bottom',
359373
});
360-
expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.ui.lms.sequence.next_selected', {
374+
expect(sendTrackEvent).toHaveBeenNthCalledWith(4, 'edx.ui.lms.sequence.next_selected', {
361375
current_tab: 1,
362376
id: testData.unitId,
363377
tab_count: 0,
364378
widget_placement: 'top',
365379
});
366-
expect(sendTrackEvent).toHaveBeenNthCalledWith(4, 'edx.ui.lms.sequence.next_selected', {
380+
expect(sendTrackEvent).toHaveBeenNthCalledWith(5, 'edx.ui.lms.sequence.next_selected', {
367381
current_tab: 1,
368382
id: testData.unitId,
369383
tab_count: 0,

src/courseware/course/sidebar/sidebars/notifications/NotificationTray.jsx

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
22
import classNames from 'classnames';
3-
import React, { useContext, useEffect } from 'react';
3+
import React, { useContext, useEffect, useMemo } from 'react';
4+
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
45
import { useModel } from '../../../../../generic/model-store';
56
import UpgradeNotification from '../../../../../generic/upgrade-notification/UpgradeNotification';
67

@@ -22,20 +23,47 @@ const NotificationTray = ({ intl }) => {
2223
const {
2324
accessExpiration,
2425
contentTypeGatingEnabled,
26+
end,
27+
enrollmentEnd,
28+
enrollmentMode,
29+
enrollmentStart,
2530
marketingUrl,
2631
offer,
32+
start,
2733
timeOffsetMillis,
2834
userTimezone,
35+
verificationStatus,
2936
} = course;
3037

3138
const {
39+
courseModes,
3240
org,
3341
verifiedMode,
42+
username,
3443
} = useModel('courseHomeMeta', courseId);
3544

45+
const activeCourseModes = useMemo(() => courseModes?.map(mode => mode.slug), [courseModes]);
46+
47+
const notificationTrayEventProperties = {
48+
course_end: end,
49+
course_modes: activeCourseModes,
50+
course_start: start,
51+
courserun_key: courseId,
52+
enrollment_end: enrollmentEnd,
53+
enrollment_mode: enrollmentMode,
54+
enrollment_start: enrollmentStart,
55+
is_upgrade_notification_visible: !!verifiedMode,
56+
name: 'Old Sidebar Notification Tray',
57+
org_key: org,
58+
username,
59+
verification_status: verificationStatus,
60+
};
61+
3662
// After three seconds, update notificationSeen (to hide red dot)
37-
// eslint-disable-next-line react-hooks/exhaustive-deps
38-
useEffect(() => { setTimeout(onNotificationSeen, 3000); }, []);
63+
useEffect(() => {
64+
setTimeout(onNotificationSeen, 3000);
65+
sendTrackEvent('edx.ui.course.upgrade.old_sidebar.notifications', notificationTrayEventProperties);
66+
}, []);
3967

4068
return (
4169
<SidebarBase

0 commit comments

Comments
 (0)