fix: [AA-1207] Remove redundant API fields (#873)

Remove redundant fields from courseware API. These are all found in courseHome: 

- number
- org
- originalUserIsStaff
- isStaff
- verifiedMode
- isMasquerading (virtual field from isStaff and originalUserIsStaff)
This commit is contained in:
Chris Deery
2022-03-18 09:20:31 -04:00
committed by GitHub
parent 9436770620
commit 3cba1bbac4
31 changed files with 116 additions and 113 deletions

View File

@@ -8,6 +8,7 @@ Factory.define('courseHomeMetadata')
title: 'Demonstration Course',
is_self_paced: false,
is_enrolled: false,
is_staff: false,
can_load_courseware: true,
celebrations: null,
course_access: {
@@ -18,9 +19,20 @@ Factory.define('courseHomeMetadata')
user_fragment: null,
user_message: null,
},
number: 'DemoX',
original_user_is_staff: false,
org: 'edX',
start: '2013-02-05T05:00:00Z',
user_timezone: 'UTC',
username: 'MockUser',
verified_mode: {
access_expiration_date: null,
currency: 'USD',
upgrade_url: 'http://localhost:18130/basket/add/?sku=8CF08E5',
sku: '8CF08E5',
price: 149,
currency_symbol: '$',
},
})
.attr(
'tabs', ['id', 'host'], (id, host) => [

View File

@@ -76,9 +76,12 @@ Object {
"userTimezone": "UTC",
"username": "MockUser",
"verifiedMode": Object {
"accessExpirationDate": null,
"currency": "USD",
"currencySymbol": "$",
"price": 10,
"upgradeUrl": "test",
"price": 149,
"sku": "8CF08E5",
"upgradeUrl": "http://localhost:18130/basket/add/?sku=8CF08E5",
},
},
},
@@ -391,9 +394,12 @@ Object {
"userTimezone": "UTC",
"username": "MockUser",
"verifiedMode": Object {
"accessExpirationDate": null,
"currency": "USD",
"currencySymbol": "$",
"price": 10,
"upgradeUrl": "test",
"price": 149,
"sku": "8CF08E5",
"upgradeUrl": "http://localhost:18130/basket/add/?sku=8CF08E5",
},
},
},
@@ -586,9 +592,12 @@ Object {
"userTimezone": "UTC",
"username": "MockUser",
"verifiedMode": Object {
"accessExpirationDate": null,
"currency": "USD",
"currencySymbol": "$",
"price": 10,
"upgradeUrl": "test",
"price": 149,
"sku": "8CF08E5",
"upgradeUrl": "http://localhost:18130/basket/add/?sku=8CF08E5",
},
},
},

View File

@@ -72,7 +72,7 @@ describe('CoursewareContainer', () => {
sequenceBlocks: [defaultSequenceBlock],
} = buildSimpleCourseBlocks(
defaultCourseId,
defaultCourseMetadata.name,
defaultCourseHomeMetadata.title,
{ unitBlocks: defaultUnitBlocks },
);
@@ -173,15 +173,16 @@ describe('CoursewareContainer', () => {
describe('when receiving successful course data', () => {
const courseMetadata = defaultCourseMetadata;
const courseHomeMetadata = defaultCourseHomeMetadata;
const courseId = defaultCourseId;
function assertLoadedHeader(container) {
const courseHeader = container.querySelector('.learning-header');
// Ensure the course number and org appear - this proves we loaded course metadata properly.
expect(courseHeader).toHaveTextContent(courseMetadata.number);
expect(courseHeader).toHaveTextContent(courseMetadata.org);
expect(courseHeader).toHaveTextContent(courseHomeMetadata.number);
expect(courseHeader).toHaveTextContent(courseHomeMetadata.org);
// Ensure the course title is showing up in the header. This means we loaded course blocks properly.
expect(courseHeader.querySelector('.course-title')).toHaveTextContent(courseMetadata.name);
expect(courseHeader.querySelector('.course-title')).toHaveTextContent(courseHomeMetadata.title);
}
function assertSequenceNavigation(container, expectedUnitCount = 3) {
@@ -250,7 +251,7 @@ describe('CoursewareContainer', () => {
const {
courseBlocks, unitTree, sequenceTree, sectionTree,
} = buildBinaryCourseBlocks(
courseId, courseMetadata.name,
courseId, courseHomeMetadata.title,
);
function setUrl(urlSequenceId, urlUnitId = null) {

View File

@@ -31,6 +31,10 @@ function Course({
windowWidth,
}) {
const course = useModel('coursewareMeta', courseId);
const {
celebrations,
isStaff,
} = useModel('courseHomeMeta', courseId);
const sequence = useModel('sequences', sequenceId);
const section = useModel('sections', sequence ? sequence.sectionId : null);
@@ -40,11 +44,6 @@ function Course({
course,
].filter(element => element != null).map(element => element.title);
const {
celebrations,
courseGoals,
} = course;
// Below the tabs, above the breadcrumbs alerts (appearing in the order listed here)
const dispatch = useDispatch();
const celebrateFirstSection = celebrations && celebrations.firstSection;
@@ -57,7 +56,7 @@ function Course({
celebrations && !celebrations.streakLengthToCelebrate && celebrations.weeklyGoal,
);
const shouldDisplayTriggers = windowWidth >= breakpoints.small.minWidth;
const daysPerWeek = courseGoals?.selectedGoal?.daysPerWeek;
const daysPerWeek = course?.courseGoals?.selectedGoal?.daysPerWeek;
// Responsive breakpoints for showing the notification button/tray
const shouldDisplayNotificationTrayOpenOnLoad = windowWidth > breakpoints.medium.minWidth;
@@ -85,7 +84,7 @@ function Course({
courseId={courseId}
sectionId={section ? section.id : null}
sequenceId={sequenceId}
isStaff={course ? course.isStaff : null}
isStaff={isStaff}
unitId={unitId}
//* * [MM-P2P] Experiment */
mmp2p={MMP2P}

View File

@@ -64,8 +64,8 @@ describe('Course', () => {
});
it('displays first section celebration modal', async () => {
const courseMetadata = Factory.build('courseMetadata', { celebrations: { firstSection: true } });
const testStore = await initializeTestStore({ courseMetadata }, false);
const courseHomeMetadata = Factory.build('courseHomeMetadata', { celebrations: { firstSection: true } });
const testStore = await initializeTestStore({ courseHomeMetadata }, false);
const { courseware, models } = testStore.getState();
const { courseId, sequenceId } = courseware;
const testData = {
@@ -84,8 +84,8 @@ describe('Course', () => {
});
it('displays weekly goal celebration modal', async () => {
const courseMetadata = Factory.build('courseMetadata', { celebrations: { weeklyGoal: true } });
const testStore = await initializeTestStore({ courseMetadata }, false);
const courseHomeMetadata = Factory.build('courseHomeMetadata', { celebrations: { weeklyGoal: true } });
const testStore = await initializeTestStore({ courseHomeMetadata }, false);
const { courseware, models } = testStore.getState();
const { courseId, sequenceId } = courseware;
const testData = {

View File

@@ -19,7 +19,7 @@ import { useModel } from '../../../generic/model-store';
function CelebrationModal({
courseId, intl, isOpen, onClose, ...rest
}) {
const { org } = useModel('coursewareMeta', courseId);
const { org } = useModel('courseHomeMeta', courseId);
const wideScreen = useWindowSize().width >= breakpoints.small.minWidth;
useEffect(() => {

View File

@@ -14,7 +14,7 @@ import { useModel } from '../../../generic/model-store';
function WeeklyGoalCelebrationModal({
courseId, daysPerWeek, intl, isOpen, onClose, ...rest
}) {
const { org } = useModel('coursewareMeta', courseId);
const { org } = useModel('courseHomeMeta', courseId);
useEffect(() => {
if (isOpen) {

View File

@@ -71,7 +71,7 @@ function shouldCelebrateOnSectionLoad(courseId, sequenceId, celebrateFirstSectio
// Update our local copy of course data from LMS
dispatch(updateModel({
modelType: 'coursewareMeta',
modelType: 'courseHomeMeta',
model: {
id: courseId,
celebrations: {

View File

@@ -18,7 +18,7 @@ import { logClick } from './utils';
function CatalogSuggestion({ intl, variant }) {
const { courseId } = useSelector(state => state.courseware);
const { org } = useModel('coursewareMeta', courseId);
const { org } = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
const searchOurCatalogLink = (

View File

@@ -46,14 +46,17 @@ function CourseCelebration({ intl }) {
linkedinAddToProfileUrl,
marketingUrl,
offer,
org,
relatedPrograms,
title,
verifiedMode,
verifyIdentityUrl,
verificationStatus,
} = useModel('coursewareMeta', courseId);
const {
org,
verifiedMode,
} = useModel('courseHomeMeta', courseId);
const {
certStatus,
certWebViewUrl,

View File

@@ -24,10 +24,11 @@ function CourseExit({ intl }) {
enrollmentMode,
hasScheduledContent,
isEnrolled,
isMasquerading,
userHasPassingGrade,
} = useModel('coursewareMeta', courseId);
const { isMasquerading } = useModel('courseHomeMeta', courseId);
const mode = getCourseExitMode(
certificateData,
hasScheduledContent,

View File

@@ -30,7 +30,7 @@ describe('Course Exit Pages', () => {
});
const courseId = coursewareMetadata.id;
const courseHomeMetadata = Factory.build('courseHomeMetadata');
const { courseBlocks: defaultCourseBlocks } = buildSimpleCourseBlocks(courseId, coursewareMetadata.name);
const { courseBlocks: defaultCourseBlocks } = buildSimpleCourseBlocks(courseId, courseHomeMetadata.title);
let coursewareMetadataUrl = `${getConfig().LMS_BASE_URL}/api/courseware/course/${courseId}`;
coursewareMetadataUrl = appendBrowserTimezoneToUrl(coursewareMetadataUrl);
@@ -39,9 +39,11 @@ describe('Course Exit Pages', () => {
const enrollmentsUrl = new RegExp(`${getConfig().LMS_BASE_URL}/api/enrollment/v1/enrollment*`);
const learningSequencesUrlRegExp = new RegExp(`${getConfig().LMS_BASE_URL}/api/learning_sequences/v1/course_outline/*`);
function setMetadata(attributes) {
const courseMetadata = { ...coursewareMetadata, ...attributes };
axiosMock.onGet(coursewareMetadataUrl).reply(200, courseMetadata);
function setMetadata(coursewareAttributes, courseHomeAttributes = {}) {
const extendedCourseMetadata = { ...coursewareMetadata, ...coursewareAttributes };
axiosMock.onGet(coursewareMetadataUrl).reply(200, extendedCourseMetadata);
const extendedCourseHomeMetadata = { ...courseHomeMetadata, ...courseHomeAttributes };
axiosMock.onGet(courseHomeMetadataUrl).reply(200, extendedCourseHomeMetadata);
}
async function fetchAndRender(component) {
@@ -186,6 +188,8 @@ describe('Course Exit Pages', () => {
it('Displays upgrade link when available', async () => {
setMetadata({
certificate_data: { cert_status: 'audit_passing' },
},
{
verified_mode: {
access_expiration_date: '9999-08-06T12:00:00Z',
upgrade_url: 'http://localhost:18130/basket/add/?sku=8CF08E5',
@@ -206,6 +210,8 @@ describe('Course Exit Pages', () => {
it('Displays nothing if audit only', async () => {
setMetadata({
certificate_data: { cert_status: 'audit_passing' },
},
{
verified_mode: null,
});
await fetchAndRender(<CourseCelebration />);
@@ -371,7 +377,7 @@ describe('Course Exit Pages', () => {
describe('Course in progress experience', () => {
it('Displays link to dates tab', async () => {
setMetadata({ user_has_passing_grade: false });
const { courseBlocks } = buildSimpleCourseBlocks(courseId, coursewareMetadata.name,
const { courseBlocks } = buildSimpleCourseBlocks(courseId, courseHomeMetadata.title,
{ hasScheduledContent: true });
axiosMock.onGet(learningSequencesUrlRegExp).reply(200, buildOutlineFromBlocks(courseBlocks));

View File

@@ -16,8 +16,11 @@ import { logClick, logVisit } from './utils';
function CourseInProgress({ intl }) {
const { courseId } = useSelector(state => state.courseware);
const { org, title } = useModel('coursewareMeta', courseId);
const { tabs } = useModel('courseHomeMeta', courseId);
const {
org,
tabs,
title,
} = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
// Get dates tab link for 'view course schedule' button

View File

@@ -16,8 +16,11 @@ import { logClick, logVisit } from './utils';
function CourseNonPassing({ intl }) {
const { courseId } = useSelector(state => state.courseware);
const { org, title } = useModel('coursewareMeta', courseId);
const { tabs } = useModel('courseHomeMeta', courseId);
const {
org,
tabs,
title,
} = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
// Get progress tab link for 'view grades' button

View File

@@ -133,7 +133,8 @@ const IntlCard = injectIntl(CourseCard);
function CourseRecommendations({ intl, variant }) {
const { courseId, recommendationsStatus } = useSelector(state => ({ ...state.recommendations, ...state.courseware }));
const { org, number, recommendations } = useModel('coursewareMeta', courseId);
const { recommendations } = useModel('coursewareMeta', courseId);
const { org, number } = useModel('courseHomeMeta', courseId);
const dispatch = useDispatch();
const courseKey = `${org}+${number}`;

View File

@@ -18,7 +18,7 @@ import { logClick } from './utils';
function DashboardFootnote({ intl, variant }) {
const { courseId } = useSelector(state => state.courseware);
const { org } = useModel('coursewareMeta', courseId);
const { org } = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
const dashboardLink = (

View File

@@ -16,7 +16,7 @@ import { useModel } from '../../../generic/model-store';
function UpgradeFootnote({ deadline, href, intl }) {
const { courseId } = useSelector(state => state.courseware);
const { org } = useModel('coursewareMeta', courseId);
const { org } = useModel('courseHomeMeta', courseId);
const { administrator } = getAuthenticatedUser();
const upgradeLink = (

View File

@@ -41,6 +41,10 @@ function Sequence({
mmp2p,
}) {
const course = useModel('coursewareMeta', courseId);
const {
isStaff,
originalUserIsStaff,
} = useModel('courseHomeMeta', courseId);
const sequence = useModel('sequences', sequenceId);
const unit = useModel('units', unitId);
const sequenceStatus = useSelector(state => state.courseware.sequenceStatus);
@@ -215,8 +219,8 @@ function Sequence({
<SequenceExamWrapper
sequence={sequence}
courseId={courseId}
isStaff={course.isStaff}
originalUserIsStaff={course.originalUserIsStaff}
isStaff={isStaff}
originalUserIsStaff={originalUserIsStaff}
isIntegritySignatureEnabled={course.isIntegritySignatureEnabled}
canAccessProctoredExams={course.canAccessProctoredExams}
>

View File

@@ -29,10 +29,12 @@ function LockPaywall({
accessExpiration,
marketingUrl,
offer,
org,
verifiedMode,
} = course;
const {
org, verifiedMode,
} = useModel('courseHomeMeta', courseId);
// the following variables are set and used for resposive layout to work with
// whether the NotificationTray is open or not and if there's an offer with longer text
const shouldDisplayBulletPointsBelowCertificate = useWindowSize().width <= breakpoints.large.minWidth;

View File

@@ -26,7 +26,7 @@ describe('Lock Paywall', () => {
currencySymbol,
price,
upgradeUrl,
} = store.getState().models.coursewareMeta[mockData.courseId].verifiedMode;
} = store.getState().models.courseHomeMeta[mockData.courseId].verifiedMode;
render(<LockPaywall {...mockData} />);
const upgradeLink = screen.getByRole('link', { name: `Upgrade for ${currencySymbol}${price}` });
@@ -56,7 +56,7 @@ describe('Lock Paywall', () => {
const {
currencySymbol,
price,
} = store.getState().models.coursewareMeta[mockData.courseId].verifiedMode;
} = store.getState().models.courseHomeMeta[mockData.courseId].verifiedMode;
render(<LockPaywall {...mockData} />);
const upgradeLink = screen.getByRole('link', { name: `Upgrade for ${currencySymbol}${price}` });
@@ -74,9 +74,9 @@ describe('Lock Paywall', () => {
});
it('does not display anything if course does not have verified mode', async () => {
const courseMetadata = Factory.build('courseMetadata', { verified_mode: null });
const testStore = await initializeTestStore({ courseMetadata, excludeFetchSequence: true }, false);
const { container } = render(<LockPaywall {...mockData} courseId={courseMetadata.id} />, { store: testStore });
const courseHomeMetadata = Factory.build('courseHomeMetadata', { verified_mode: null });
const testStore = await initializeTestStore({ courseHomeMetadata, excludeFetchSequence: true }, false);
const { container } = render(<LockPaywall {...mockData} courseId={courseHomeMetadata.id} />, { store: testStore });
expect(container).toBeEmptyDOMElement();
});

View File

@@ -13,7 +13,7 @@ export default function SidebarProvider({
unitId,
children,
}) {
const { verifiedMode } = useModel('coursewareMeta', courseId);
const { verifiedMode } = useModel('courseHomeMeta', courseId);
const shouldDisplayFullScreen = useWindowSize().width < breakpoints.large.minWidth;
const shouldDisplaySidebarOpen = useWindowSize().width > breakpoints.medium.minWidth;
const showNotificationsOnLoad = getSessionStorage(`notificationTrayStatus.${courseId}`) !== 'closed';

View File

@@ -24,11 +24,15 @@ function NotificationTray({ intl }) {
contentTypeGatingEnabled,
marketingUrl,
offer,
org,
timeOffsetMillis,
userTimezone,
verifiedMode,
} = course;
const {
org,
verifiedMode,
} = useModel('courseHomeMeta', courseId);
// After three seconds, update notificationSeen (to hide red dot)
useEffect(() => { setTimeout(onNotificationSeen, 3000); }, []);

View File

@@ -32,8 +32,8 @@ describe('NotificationTray', () => {
const courseHomeMetadataUrl = appendBrowserTimezoneToUrl(`${getConfig().LMS_BASE_URL}/api/course_home/course_metadata/${courseId}`);
function setMetadata(attributes, options) {
const courseMetadata = Factory.build('courseMetadata', attributes, options);
axiosMock.onGet(courseMetadataUrl).reply(200, courseMetadata);
const updatedCourseHomeMetadata = Factory.build('courseHomeMetadata', attributes, options);
axiosMock.onGet(courseHomeMetadataUrl).reply(200, updatedCourseHomeMetadata);
}
async function fetchAndRender(component) {

View File

@@ -32,14 +32,6 @@ Factory.define('courseMetadata')
mode: null,
is_active: null,
},
verified_mode: {
access_expiration_date: null,
currency: 'USD',
upgrade_url: 'http://localhost:18130/basket/add/?sku=8CF08E5',
sku: '8CF08E5',
price: 149,
currency_symbol: '$',
},
show_calculator: false,
license: 'all-rights-reserved',
notes: {

View File

@@ -95,9 +95,7 @@ function normalizeMetadata(metadata) {
courseGoals: camelCaseObject(data.course_goals),
id: data.id,
title: data.name,
number: data.number,
offer: camelCaseObject(data.offer),
org: data.org,
enrollmentStart: data.enrollment_start,
enrollmentEnd: data.enrollment_end,
end: data.end,
@@ -105,10 +103,7 @@ function normalizeMetadata(metadata) {
enrollmentMode: data.enrollment.mode,
isEnrolled: data.enrollment.is_active,
canViewLegacyCourseware: data.can_view_legacy_courseware,
originalUserIsStaff: data.original_user_is_staff,
isStaff: data.is_staff,
license: data.license,
verifiedMode: camelCaseObject(data.verified_mode),
userTimezone: data.user_timezone,
showCalculator: data.show_calculator,
notes: camelCaseObject(data.notes),
@@ -125,7 +120,6 @@ function normalizeMetadata(metadata) {
relatedPrograms: camelCaseObject(data.related_programs),
isIntegritySignatureEnabled: data.is_integrity_signature_enabled,
userNeedsIntegritySignature: data.user_needs_integrity_signature,
isMasquerading: data.original_user_is_staff && !data.is_staff,
canAccessProctoredExams: data.can_access_proctored_exams,
};
}

View File

@@ -224,7 +224,6 @@ describe('Courseware Service', () => {
}),
license: string('all-rights-reserved'),
name: like('Demonstration Course'),
number: like('DemoX'),
offer: {
code: string('code'),
expiration_date: term({
@@ -236,7 +235,6 @@ describe('Courseware Service', () => {
percentage: integer(50),
upgrade_url: string('url'),
},
org: like('edX'),
related_programs: null,
short_description: like(''),
start: term({
@@ -269,11 +267,6 @@ describe('Courseware Service', () => {
}),
notes: { enabled: boolean(false), visible: boolean(true) },
marketing_url: null,
celebrations: {
first_section: boolean(false),
streak_length_to_celebrate: null,
streak_discount_enabled: boolean(false),
},
user_has_passing_grade: boolean(false),
course_exit_page_is_active: boolean(false),
certificate_data: {
@@ -298,7 +291,6 @@ describe('Courseware Service', () => {
contentTypeGatingEnabled: false,
id: 'course-v1:edX+DemoX+Demo_Course',
title: 'Demonstration Course',
number: 'DemoX',
offer: {
code: 'code',
discountedPrice: '$99',
@@ -307,7 +299,6 @@ describe('Courseware Service', () => {
percentage: 50,
upgradeUrl: 'url',
},
org: 'edX',
enrollmentStart: '2013-02-05T05:00:00Z',
enrollmentEnd: '2013-02-05T05:00:00Z',
end: '2013-02-05T05:00:00Z',
@@ -315,26 +306,11 @@ describe('Courseware Service', () => {
enrollmentMode: 'audit',
isEnrolled: true,
canViewLegacyCourseware: true,
originalUserIsStaff: true,
isStaff: true,
license: 'all-rights-reserved',
verifiedMode: {
accessExpirationDate: '2013-02-05T05:00:00Z',
currency: 'USD',
currencySymbol: '$',
price: 149,
sku: '8CF08E5',
upgradeUrl: `${getConfig().ECOMMERCE_BASE_URL}/basket/add/?sku=8CF08E5`,
},
userTimezone: null,
showCalculator: false,
notes: { enabled: false, visible: true },
marketingUrl: null,
celebrations: {
firstSection: false,
streakLengthToCelebrate: null,
streakDiscountEnabled: false,
},
userHasPassingGrade: false,
courseExitPageIsActive: false,
certificateData: {
@@ -349,7 +325,6 @@ describe('Courseware Service', () => {
linkedinAddToProfileUrl: null,
relatedPrograms: null,
userNeedsIntegritySignature: false,
isMasquerading: false,
};
const response = await getCourseMetadata(courseId);
expect(response).toBeTruthy();

View File

@@ -112,7 +112,7 @@ describe('Data layer integration tests', () => {
expect(state.courseware.sequenceId).toEqual(null);
// check that at least one key camel cased, thus course data normalized
expect(state.models.coursewareMeta[courseId].verifiedMode).not.toBeUndefined();
expect(state.models.coursewareMeta[courseId].marketingUrl).not.toBeUndefined();
});
it('Should fetch, normalize, and save metadata; filtering has no effect', async () => {
@@ -132,7 +132,7 @@ describe('Data layer integration tests', () => {
expect(state.courseware.sequenceId).toEqual(null);
// check that at least one key camel cased, thus course data normalized
expect(state.models.coursewareMeta[courseId].verifiedMode).not.toBeUndefined();
expect(state.models.coursewareMeta[courseId].marketingUrl).not.toBeUndefined();
expect(state.models.sequences.length === 1);
Object.values(state.models.sections).forEach(section => expect(section.sequenceIds.length === 1));
@@ -159,7 +159,7 @@ describe('Data layer integration tests', () => {
expect(state.courseware.sequenceId).toEqual(null);
// check that at least one key camel cased, thus course data normalized
expect(state.models.coursewareMeta[courseId].verifiedMode).not.toBeUndefined();
expect(state.models.coursewareMeta[courseId].marketingUrl).not.toBeUndefined();
expect(state.models.sequences === null);
Object.values(state.models.sections).forEach(section => expect(section.sequenceIds.length === 0));

View File

@@ -29,11 +29,12 @@ function SocialIcons({
intl,
socialMessage,
}) {
const { marketingUrl } = useModel('coursewareMeta', courseId);
const {
marketingUrl,
org,
title,
} = useModel('coursewareMeta', courseId);
} = useModel('courseHomeMeta', courseId);
if (!marketingUrl) {
return null;

View File

@@ -202,9 +202,11 @@ const initCoursewareMMP2P = (courseId, sequenceId, unitId) => {
const models = {
coursewareMeta: state.models.coursewareMeta[courseId],
courseHomeMeta: state.models.courseHomeMeta[courseId],
units: state.models.units[unitId],
};
const { accessExpiration, verifiedMode } = models.coursewareMeta;
const { accessExpiration } = models.coursewareMeta;
const { verifiedMode } = models.courseHomeMeta;
const graded = models.units !== undefined ? models.units.graded : false;
let access = {};

View File

@@ -8,13 +8,4 @@ export default new Factory()
.option('host')
.attrs({
id: 'course-v1:edX+DemoX+Demo_Course',
is_staff: false,
original_user_is_staff: false,
number: 'DemoX',
org: 'edX',
verified_mode: {
upgrade_url: 'test',
price: 10,
currency_symbol: '$',
},
});

View File

@@ -23,8 +23,8 @@ describe('Loaded Tab Page', () => {
let testStore;
let axiosMock;
const calculateUrl = `${getConfig().ECOMMERCE_BASE_URL}/api/v2/baskets/calculate/?code=ZGY11119949&sku=8CF08E5&username=MockUser`;
const courseMetadata = Factory.build('courseMetadata', { celebrations: { streak_length_to_celebrate: 3 } });
const courseHomeMetadata = Factory.build('courseHomeMetadata');
const courseMetadata = Factory.build('courseMetadata');
const courseHomeMetadata = Factory.build('courseHomeMetadata', { celebrations: { streak_length_to_celebrate: 3 } });
function setDiscount(percent) {
mockData.streakDiscountCouponEnabled = true;
@@ -50,7 +50,7 @@ describe('Loaded Tab Page', () => {
isStreakCelebrationOpen: true,
metadataModel: 'coursewareMeta',
streakLengthToCelebrate: 3,
verifiedMode: camelCaseObject(courseMetadata.verified_mode),
verifiedMode: camelCaseObject(courseHomeMetadata.verified_mode),
};
testStore = await initializeTestStore({ courseMetadata, courseHomeMetadata }, false);
@@ -68,7 +68,7 @@ describe('Loaded Tab Page', () => {
expect(screen.getByText('Keep it up, youre on a roll!')).toBeInTheDocument();
expect(sendTrackEvent).toHaveBeenCalledTimes(1);
expect(sendTrackEvent).toHaveBeenCalledWith('edx.ui.lms.celebration.streak.opened', {
org_key: courseMetadata.org,
org_key: courseHomeMetadata.org,
courserun_key: mockData.courseId,
is_staff: false,
});