diff --git a/package-lock.json b/package-lock.json
index 4f41eba048..822badbe33 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2386,6 +2386,25 @@
"prop-types": "15.6.2"
},
"dependencies": {
+ "@edx/frontend-enterprise-utils": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-utils/-/frontend-enterprise-utils-0.1.7.tgz",
+ "integrity": "sha512-rLS/Fmq+TQPFhy1yMli4e9DsCxGAKcpZp55HvjdiiIbuMpUrWqXuP/UFemL8w45yo9osw6vH0vKhqb14RX8y4A==",
+ "requires": {
+ "@testing-library/react": "11.2.6",
+ "history": "4.10.1",
+ "query-string": "5.1.1"
+ }
+ },
+ "@testing-library/react": {
+ "version": "11.2.6",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz",
+ "integrity": "sha512-TXMCg0jT8xmuU8BkKMtp8l7Z50Ykew5WNX8UoIKTaLFwKkP2+1YDhOLA2Ga3wY4x29jyntk7EWfum0kjlYiSjQ==",
+ "requires": {
+ "@babel/runtime": "^7.12.5",
+ "@testing-library/dom": "^7.28.1"
+ }
+ },
"classnames": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz",
@@ -2410,12 +2429,33 @@
"@edx/frontend-enterprise-utils": "^0.1.7",
"prop-types": "15.7.2",
"query-string": "5.1.1"
+ },
+ "dependencies": {
+ "@edx/frontend-enterprise-utils": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-utils/-/frontend-enterprise-utils-0.1.7.tgz",
+ "integrity": "sha512-rLS/Fmq+TQPFhy1yMli4e9DsCxGAKcpZp55HvjdiiIbuMpUrWqXuP/UFemL8w45yo9osw6vH0vKhqb14RX8y4A==",
+ "requires": {
+ "@testing-library/react": "11.2.6",
+ "history": "4.10.1",
+ "query-string": "5.1.1"
+ }
+ },
+ "@testing-library/react": {
+ "version": "11.2.6",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.6.tgz",
+ "integrity": "sha512-TXMCg0jT8xmuU8BkKMtp8l7Z50Ykew5WNX8UoIKTaLFwKkP2+1YDhOLA2Ga3wY4x29jyntk7EWfum0kjlYiSjQ==",
+ "requires": {
+ "@babel/runtime": "^7.12.5",
+ "@testing-library/dom": "^7.28.1"
+ }
+ }
}
},
"@edx/frontend-enterprise-utils": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-utils/-/frontend-enterprise-utils-0.1.7.tgz",
- "integrity": "sha512-rLS/Fmq+TQPFhy1yMli4e9DsCxGAKcpZp55HvjdiiIbuMpUrWqXuP/UFemL8w45yo9osw6vH0vKhqb14RX8y4A==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@edx/frontend-enterprise-utils/-/frontend-enterprise-utils-1.1.0.tgz",
+ "integrity": "sha512-Km0WspRcFZ6VlnXLNq8VGzHgFRcB3n3TDqLYlnfdANR+ZszYMH6aEhNgQ2DQW9HKRO5geMOUVEDXjqpmuCkw8Q==",
"requires": {
"@testing-library/react": "11.2.6",
"history": "4.10.1",
diff --git a/package.json b/package.json
index 05dfaf229c..9b09d1f4ae 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"@edx/brand": "npm:@edx/brand-edx.org@^2.0.3",
"@edx/frontend-enterprise-catalog-search": "0.1.10",
"@edx/frontend-enterprise-logistration": "0.1.11",
- "@edx/frontend-enterprise-utils": "0.1.7",
+ "@edx/frontend-enterprise-utils": "1.1.0",
"@edx/frontend-platform": "1.11.0",
"@edx/paragon": "^16.8.0",
"@fortawesome/fontawesome-svg-core": "1.2.35",
diff --git a/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx b/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
index 0928b2a1e9..ac52376bd7 100644
--- a/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
+++ b/src/components/subscriptions/expiration/SubscriptionExpirationBanner.jsx
@@ -1,7 +1,7 @@
import React, { useContext, useState } from 'react';
import { Alert } from '@edx/paragon';
import PropTypes from 'prop-types';
-import { sendTrackEvent } from '@edx/frontend-platform/analytics';
+import { sendEnterpriseTrackEvent } from '@edx/frontend-enterprise-utils';
import {
SUBSCRIPTION_DAYS_REMAINING_MODERATE,
@@ -20,6 +20,7 @@ const SubscriptionExpirationBanner = ({ isSubscriptionPlanDetails }) => {
daysUntilExpiration: daysUntilPlanExpiration,
expirationDate,
showExpirationNotifications,
+ enterpriseCustomerUuid,
},
} = useContext(SubscriptionDetailContext);
const [showBanner, setShowBanner] = useState(true);
@@ -82,17 +83,25 @@ const SubscriptionExpirationBanner = ({ isSubscriptionPlanDetails }) => {
}
const emitAlertActionEvent = () => {
- sendTrackEvent('edx.ui.admin_portal.subscriptions.expiration.alert.support_cta.clicked', {
- expiration_threshold: subscriptionExpirationThreshold,
- days_until_expiration: daysUntilExpiration,
- });
+ sendEnterpriseTrackEvent(
+ enterpriseCustomerUuid,
+ 'edx.ui.admin_portal.subscriptions.expiration.alert.support_cta.clicked',
+ {
+ expiration_threshold: subscriptionExpirationThreshold,
+ days_until_expiration: daysUntilExpiration,
+ },
+ );
};
const emitAlertDismissedEvent = () => {
- sendTrackEvent('edx.ui.admin_portal.subscriptions.expiration.alert.dismissed', {
- expiration_threshold: subscriptionExpirationThreshold,
- days_until_expiration: daysUntilExpiration,
- });
+ sendEnterpriseTrackEvent(
+ enterpriseCustomerUuid,
+ 'edx.ui.admin_portal.subscriptions.expiration.alert.dismissed',
+ {
+ expiration_threshold: subscriptionExpirationThreshold,
+ days_until_expiration: daysUntilExpiration,
+ },
+ );
};
const actions = [];
diff --git a/src/components/subscriptions/expiration/SubscriptionExpirationModals.jsx b/src/components/subscriptions/expiration/SubscriptionExpirationModals.jsx
index b4a68b526e..86d22d7fce 100644
--- a/src/components/subscriptions/expiration/SubscriptionExpirationModals.jsx
+++ b/src/components/subscriptions/expiration/SubscriptionExpirationModals.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Cookies from 'universal-cookie';
import { useToggle } from '@edx/paragon';
-import { sendTrackEvent } from '@edx/frontend-platform/analytics';
+import { sendEnterpriseTrackEvent } from '@edx/frontend-enterprise-utils';
import SubscriptionExpiredModal from './SubscriptionExpiredModal';
import SubscriptionExpiringModal from './SubscriptionExpiringModal';
@@ -30,6 +30,7 @@ const SubscriptionExpirationModals = ({ enterpriseId }) => {
const {
subscription: {
agreementNetDaysUntilExpiration, showExpirationNotifications,
+ enterpriseCustomerUuid,
},
} = useContext(SubscriptionDetailContext);
const isSubscriptionExpired = agreementNetDaysUntilExpiration <= 0;
@@ -96,17 +97,25 @@ const SubscriptionExpirationModals = ({ enterpriseId }) => {
}, [isSubscriptionExpired]);
const emitAlertActionEvent = () => {
- sendTrackEvent('edx.ui.admin_portal.subscriptions.expiration.modal.support_cta.clicked', {
- expiration_threshold: subscriptionExpirationThreshold,
- days_until_expiration: agreementNetDaysUntilExpiration,
- });
+ sendEnterpriseTrackEvent(
+ enterpriseCustomerUuid,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.support_cta.clicked',
+ {
+ expiration_threshold: subscriptionExpirationThreshold,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
};
const emitAlertDismissedEvent = () => {
- sendTrackEvent('edx.ui.admin_portal.subscriptions.expiration.modal.dismissed', {
- expiration_threshold: subscriptionExpirationThreshold,
- days_until_expiration: agreementNetDaysUntilExpiration,
- });
+ sendEnterpriseTrackEvent(
+ enterpriseCustomerUuid,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.dismissed',
+ {
+ expiration_threshold: subscriptionExpirationThreshold,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
};
const handleCloseModal = (closeModal) => {
diff --git a/src/components/subscriptions/tests/TestUtilities.jsx b/src/components/subscriptions/tests/TestUtilities.jsx
index 925691ea62..c1fbae058d 100644
--- a/src/components/subscriptions/tests/TestUtilities.jsx
+++ b/src/components/subscriptions/tests/TestUtilities.jsx
@@ -13,10 +13,10 @@ import SubscriptionDetailContextProvider from '../SubscriptionDetailContextProvi
import * as hooks from '../data/hooks';
export const TEST_ENTERPRISE_CUSTOMER_SLUG = 'test-enterprise';
-const TEST_ENTERPRISE_CUSTOMER_UUID = 'b5f07fee-1b34-458f-b672-19b55fc1bd10';
-const TEST_ENTERPRISE_CUSTOMER_CATALOG_UUID = 'ff7acb5e-584a-4e5f-bacc-33a9995794f9';
-const TEST_SUBSCRIPTION_PLAN_TITLE = 'Test Subscription Plan';
-const TEST_SUBSCRIPTION_PLAN_UUID = '28d4dcdc-c026-4c02-a263-82dd9c0d8b43';
+export const TEST_ENTERPRISE_CUSTOMER_UUID = 'b5f07fee-1b34-458f-b672-19b55fc1bd10';
+export const TEST_ENTERPRISE_CUSTOMER_CATALOG_UUID = 'ff7acb5e-584a-4e5f-bacc-33a9995794f9';
+export const TEST_SUBSCRIPTION_PLAN_TITLE = 'Test Subscription Plan';
+export const TEST_SUBSCRIPTION_PLAN_UUID = '28d4dcdc-c026-4c02-a263-82dd9c0d8b43';
export const SUBSCRIPTION_PLAN_ZERO_STATE = {
daysUntilExpiration: 240,
diff --git a/src/components/subscriptions/tests/expiration/SubscriptionExpirationBanner.test.jsx b/src/components/subscriptions/tests/expiration/SubscriptionExpirationBanner.test.jsx
index 0038ffb3e5..8494add79c 100644
--- a/src/components/subscriptions/tests/expiration/SubscriptionExpirationBanner.test.jsx
+++ b/src/components/subscriptions/tests/expiration/SubscriptionExpirationBanner.test.jsx
@@ -4,6 +4,7 @@ import {
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
+import * as enterpriseUtils from '@edx/frontend-enterprise-utils';
import SubscriptionExpirationBanner from '../../expiration/SubscriptionExpirationBanner';
import {
SUBSCRIPTION_DAYS_REMAINING_MODERATE,
@@ -13,10 +14,11 @@ import {
import {
SUBSCRIPTION_PLAN_ZERO_STATE,
SubscriptionManagementContext,
+ TEST_ENTERPRISE_CUSTOMER_UUID,
} from '../TestUtilities';
-jest.mock('@edx/frontend-platform/analytics', () => ({
- sendTrackEvent: jest.fn(),
+jest.mock('@edx/frontend-enterprise-utils', () => ({
+ sendEnterpriseTrackEvent: jest.fn(),
}));
// PropType validation for state is done by SubscriptionManagementContext
@@ -28,6 +30,8 @@ const ExpirationBannerWithContext = ({ detailState, isSubscriptionPlanDetails =
);
describe('', () => {
+ afterEach(() => jest.clearAllMocks());
+
test('does not render an alert before the "moderate" days until expiration threshold', () => {
const detailStateCopy = {
...SUBSCRIPTION_PLAN_ZERO_STATE,
@@ -63,6 +67,14 @@ describe('', () => {
userEvent.click(screen.getByText('Dismiss'));
await waitForElementToBeRemoved(screen.queryByRole('alert'));
expect(screen.queryByRole('alert')).toBeNull();
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.alert.dismissed',
+ {
+ expiration_threshold: threshold,
+ days_until_expiration: threshold,
+ },
+ );
});
test('does not render an alert when subscription expiration notifications are disabled', () => {
@@ -97,4 +109,23 @@ describe('', () => {
expect(screen.queryByText("This subscription plan's end date has passed")).toBeNull();
}
});
+
+ test('handles customer support button click', () => {
+ const agreementNetDaysUntilExpiration = 0;
+ const detailStateCopy = {
+ ...SUBSCRIPTION_PLAN_ZERO_STATE,
+ agreementNetDaysUntilExpiration,
+ };
+
+ render();
+ userEvent.click(screen.getByText('Contact customer support'));
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.alert.support_cta.clicked',
+ {
+ expiration_threshold: SUBSCRIPTION_DAYS_REMAINING_EXCEPTIONAL,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
+ });
});
diff --git a/src/components/subscriptions/tests/expiration/SubscriptionExpirationModals.test.jsx b/src/components/subscriptions/tests/expiration/SubscriptionExpirationModals.test.jsx
index 7d34026a77..faebb8be10 100644
--- a/src/components/subscriptions/tests/expiration/SubscriptionExpirationModals.test.jsx
+++ b/src/components/subscriptions/tests/expiration/SubscriptionExpirationModals.test.jsx
@@ -5,6 +5,7 @@ import {
import '@testing-library/jest-dom/extend-expect';
import userEvent from '@testing-library/user-event';
+import * as enterpriseUtils from '@edx/frontend-enterprise-utils';
import SubscriptionExpirationModals from '../../expiration/SubscriptionExpirationModals';
import { EXPIRED_MODAL_TITLE } from '../../expiration/SubscriptionExpiredModal';
import { EXPIRING_MODAL_TITLE } from '../../expiration/SubscriptionExpiringModal';
@@ -14,12 +15,13 @@ import {
SUBSCRIPTION_DAYS_REMAINING_EXCEPTIONAL,
} from '../../data/constants';
import {
+ TEST_ENTERPRISE_CUSTOMER_UUID,
SUBSCRIPTION_PLAN_ZERO_STATE,
SubscriptionManagementContext,
} from '../TestUtilities';
-jest.mock('@edx/frontend-platform/analytics', () => ({
- sendTrackEvent: jest.fn(),
+jest.mock('@edx/frontend-enterprise-utils', () => ({
+ sendEnterpriseTrackEvent: jest.fn(),
}));
// PropType validation for state is done by SubscriptionManagementContext
@@ -31,6 +33,8 @@ const ExpirationModalsWithContext = ({ detailState }) => (
);
describe('', () => {
+ afterEach(() => jest.clearAllMocks());
+
describe('non-expired and non-expiring', () => {
test('does not render any expiration modals', () => {
render();
@@ -62,14 +66,42 @@ describe('', () => {
});
test('expired modal is dismissible', () => {
+ const agreementNetDaysUntilExpiration = 0;
const detailStateCopy = {
...SUBSCRIPTION_PLAN_ZERO_STATE,
- agreementNetDaysUntilExpiration: 0,
+ agreementNetDaysUntilExpiration,
};
render();
expect(screen.queryByLabelText(EXPIRED_MODAL_TITLE)).toBeTruthy();
userEvent.click(screen.getByText('Dismiss'));
expect(screen.queryByLabelText(EXPIRED_MODAL_TITLE)).toBeFalsy();
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.dismissed',
+ {
+ expiration_threshold: SUBSCRIPTION_DAYS_REMAINING_EXCEPTIONAL,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
+ });
+
+ test('handles customer support button click', () => {
+ const agreementNetDaysUntilExpiration = 0;
+ const detailStateCopy = {
+ ...SUBSCRIPTION_PLAN_ZERO_STATE,
+ agreementNetDaysUntilExpiration,
+ };
+
+ render();
+ userEvent.click(screen.getByText('Contact customer support'));
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.support_cta.clicked',
+ {
+ expiration_threshold: SUBSCRIPTION_DAYS_REMAINING_EXCEPTIONAL,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
});
});
@@ -112,6 +144,33 @@ describe('', () => {
expect(screen.queryByLabelText(EXPIRING_MODAL_TITLE)).toBeTruthy();
userEvent.click(screen.getByText('Dismiss'));
expect(screen.queryByLabelText(EXPIRING_MODAL_TITLE)).toBeFalsy();
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.dismissed',
+ {
+ expiration_threshold: threshold,
+ days_until_expiration: threshold,
+ },
+ );
+ });
+
+ test('handles customer support button click', () => {
+ const agreementNetDaysUntilExpiration = 0;
+ const detailStateCopy = {
+ ...SUBSCRIPTION_PLAN_ZERO_STATE,
+ agreementNetDaysUntilExpiration,
+ };
+
+ render();
+ userEvent.click(screen.getByText('Contact customer support'));
+ expect(enterpriseUtils.sendEnterpriseTrackEvent).toHaveBeenCalledWith(
+ TEST_ENTERPRISE_CUSTOMER_UUID,
+ 'edx.ui.admin_portal.subscriptions.expiration.modal.support_cta.clicked',
+ {
+ expiration_threshold: SUBSCRIPTION_DAYS_REMAINING_EXCEPTIONAL,
+ days_until_expiration: agreementNetDaysUntilExpiration,
+ },
+ );
});
});
});