feat: implement fallback recommendations (#758)

This commit is contained in:
Zainab Amir
2023-02-27 20:30:41 +05:00
committed by GitHub
parent 6c72e9dad4
commit 3d10cea137
7 changed files with 118 additions and 10 deletions

View File

@@ -20,6 +20,7 @@ const configuration = {
TOS_AND_HONOR_CODE: process.env.TOS_AND_HONOR_CODE || null,
TOS_LINK: process.env.TOS_LINK || null,
// Miscellaneous
GENERAL_RECOMMENDATIONS: process.env.GENERAL_RECOMMENDATIONS || [],
INFO_EMAIL: process.env.INFO_EMAIL || '',
};

View File

@@ -29,6 +29,7 @@ const RecommendationCard = (props) => {
position + 1,
userId,
recommendation.marketingUrl,
recommendation.recommendationType || 'algolia',
);
};
@@ -71,6 +72,7 @@ RecommendationCard.propTypes = {
logoImageUrl: PropTypes.string.isRequired,
})),
marketingUrl: PropTypes.string.isRequired,
recommendationType: PropTypes.string,
}).isRequired,
position: PropTypes.number.isRequired,
userId: PropTypes.number,

View File

@@ -43,6 +43,7 @@ RecommendationsList.propTypes = {
logoImageUrl: PropTypes.string.isRequired,
})),
marketingUrl: PropTypes.string.isRequired,
recommendationType: PropTypes.string,
})),
userId: PropTypes.number,
};

View File

@@ -29,14 +29,26 @@ const RecommendationsPage = (props) => {
if (registrationResponse) {
let coursesWithKeys = [];
getPersonalizedRecommendations(educationLevel).then((response) => {
if (response.length) {
coursesWithKeys = response.map(course => ({
...course,
courseKey: convertCourseRunKeytoCourseKey(course.activeRunKey),
}));
coursesWithKeys = response.map(course => ({
...course,
courseKey: convertCourseRunKeytoCourseKey(course.activeRunKey),
}));
if (coursesWithKeys.length >= RECOMMENDATIONS_COUNT) {
setRecommendations(coursesWithKeys.slice(0, RECOMMENDATIONS_COUNT));
} else {
const courseRecommendations = coursesWithKeys.concat(getConfig().GENERAL_RECOMMENDATIONS);
// Remove duplicate recommendations
const uniqueRecommendations = courseRecommendations.filter(
(recommendation, index, self) => index === self.findIndex((existingRecommendation) => (
existingRecommendation.courseKey === recommendation.courseKey
)),
);
setRecommendations(uniqueRecommendations.slice(0, RECOMMENDATIONS_COUNT));
}
setIsLoading(false);
// We only want to track the recommendations returned by Algolia
const courseKeys = coursesWithKeys.map(course => course.courseKey);
trackRecommendationsViewed(courseKeys, false, userId);
})

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Provider } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';
import { getConfig, mergeConfig } from '@edx/frontend-platform';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
@@ -10,7 +10,7 @@ import configureStore from 'redux-mock-store';
import { DEFAULT_REDIRECT_URL } from '../../data/constants';
import * as getPersonalizedRecommendations from '../data/service';
import RecommendationsPage from '../RecommendationsPage';
import mockedResponse from './mockedData';
import { mockedGeneralRecommendations, mockedResponse } from './mockedData';
const IntlRecommendationsPage = injectIntl(RecommendationsPage);
const mockStore = configureStore();
@@ -100,6 +100,16 @@ describe('RecommendationsPageTests', () => {
expect(window.location.href).toEqual(registrationResult.redirectUrl);
});
it('should not redirect if fallback recommendations are enabled', async () => {
mergeConfig({
GENERAL_RECOMMENDATIONS: mockedGeneralRecommendations,
});
getPersonalizedRecommendations.default = jest.fn().mockImplementation(() => Promise.resolve([]));
const recommendationsPage = await getRecommendationsPage();
expect(recommendationsPage.find('#course-recommendations').exists()).toBeTruthy();
});
it('should display all owners for a course', async () => {
getPersonalizedRecommendations.default = jest.fn().mockImplementation(() => Promise.resolve(mockedResponse));
const recommendationsPage = await getRecommendationsPage();

View File

@@ -1,4 +1,4 @@
const mockedResponse = [
export const mockedResponse = [
{
title: 'How to Learn Online 1',
marketingUrl: 'https://test-recommendations.com/course/how-to-learn-online-1',
@@ -76,4 +76,85 @@ const mockedResponse = [
},
];
export default mockedResponse;
export const mockedGeneralRecommendations = [
{
courseKey: 'MITx+6.00.1x',
activeRunKey: 'course-v1:MITx+6.00.1x+1T2023',
cardImageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/956319ec-8665-4039-8bc6-32c9a9aea5e9-885268c71902.jpg',
marketingUrl: 'https://www.edx.org/course/introduction-to-computer-science-and-programming-7',
objectId: 'course-956319ec-8665-4039-8bc6-32c9a9aea5e9',
owners: [
{
key: 'MITx',
logoImageUrl: 'https://prod-discovery.edx-cdn.org/organization/logos/2a73d2ce-c34a-4e08-8223-83bca9d2f01d-2cc8854c6fee.png',
name: 'Massachusetts Institute of Technology',
},
],
title: 'Introduction to Computer Science and Programming Using Python',
recommendationType: 'general',
},
{
courseKey: 'IBM+PY0101EN',
activeRunKey: 'course-v1:IBM+PY0101EN+2T2021',
cardImageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/381a0046-5d78-4790-8776-74620d59f48e-e2e7f4677ce2.jpeg',
marketingUrl: 'https://www.edx.org/course/python-basics-for-data-science',
objectID: 'course-381a0046-5d78-4790-8776-74620d59f48e',
owners: [
{
key: 'IBM',
logoImageUrl: 'https://prod-discovery.edx-cdn.org/organization/logos/87b07564-d569-4cfd-bee6-8b0a407acb73-dc33e4b5f353.png',
name: 'IBM',
},
],
title: 'Python Basics for Data Science',
recommendationType: 'general',
},
{
courseKey: 'HarvardX+CS50P',
activeRunKey: 'course-v1:HarvardX+CS50P+Python',
cardImageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/2cc794d0-316d-42f7-bbfd-25c34e4cd5df-033e46d516c0.png',
marketingUrl: 'https://www.edx.org/course/cs50s-introduction-to-programming-with-python',
objectID: 'course-2cc794d0-316d-42f7-bbfd-25c34e4cd5df',
owners: [
{
key: 'HarvardX',
logoImageUrl: 'https://prod-discovery.edx-cdn.org/organization/logos/44022f13-20df-4666-9111-cede3e5dc5b6-2cc39992c67a.png',
name: 'Harvard University',
},
],
title: 'CS50\'s Introduction to Programming with Python',
recommendationType: 'general',
},
{
courseKey: 'UQx+IELTSx',
activeRunKey: 'course-v1:UQx+IELTSx+1T2022',
cardImageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/d61d7a1f-3333-4169-a786-92e2bf690c6f-fa8a6909baec.jpg',
marketingUrl: 'https://www.edx.org/course/ielts-academic-test-preparation',
objectID: 'course-d61d7a1f-3333-4169-a786-92e2bf690c6f',
owners: [
{
key: 'UQx',
logoImageUrl: 'https://prod-discovery.edx-cdn.org/organization/logos/8554749f-b920-4d7f-8986-af6bb95290aa-f336c6a2ca11.png',
name: 'The University of Queensland',
},
],
title: 'IELTS Academic Test Preparation',
recommendationType: 'general',
},
{
courseKey: 'HarvardX+CS50x',
activeRunKey: 'course-v1:HarvardX+CS50+X',
cardImageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/da1b2400-322b-459b-97b0-0c557f05d017-a3d1899c3344.png',
marketingUrl: 'https://www.edx.org/course/introduction-computer-science-harvardx-cs50x',
objectID: 'course-da1b2400-322b-459b-97b0-0c557f05d017',
owners: [
{
key: 'HarvardX',
logoImageUrl: 'https://prod-discovery.edx-cdn.org/organization/logos/44022f13-20df-4666-9111-cede3e5dc5b6-2cc39992c67a.png',
name: 'Harvard University',
},
],
title: 'CS50\'s Introduction to Computer Science',
recommendationType: 'general',
},
];

View File

@@ -16,11 +16,12 @@ export const createLinkTracker = (tracker, href, openInNewTab = false) => (e) =>
return setTimeout(() => { global.location.href = href; }, LINK_TIMEOUT);
};
export const trackRecommendationsClicked = (courseKey, isControl, position, userId, href) => {
export const trackRecommendationsClicked = (courseKey, isControl, position, userId, href, recommendationType) => {
createLinkTracker(
sendTrackEvent(eventNames.recommendedCourseClicked, {
page: 'authn_recommendations',
position,
recommendation_type: recommendationType,
course_key: courseKey,
is_control: isControl,
user_id: userId,