fix: refactor best practices checklist logic (#2038)
The Best Practices Checklist behavior was wrong for some cases: * Video: if duration is null it shouldn't be marked as completed * Video: if there are no videos it shouldn't be marked as completed * Unit depth: if course doesn't have units it shouldn't be marked as completed * Diverse learning sequence: description mentions that 80% should contain multiple content types, so if it is exactly 80% it should be marked as completed
This commit is contained in:
committed by
GitHub
parent
7274316eb8
commit
5df4cd941d
@@ -71,16 +71,6 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Learners engage best with short videos followed by opportunities to practice. Ensure that 80% or more of course videos are less than 10 minutes long.',
|
||||
description: 'Description for a section that prompts a user to follow best practices for video length',
|
||||
},
|
||||
mobileFriendlyVideoShortDescription: {
|
||||
id: 'mobileFriendlyVideoShortDescription',
|
||||
defaultMessage: 'Create mobile-friendly video',
|
||||
description: 'Label for a section that describes mobile friendly videos',
|
||||
},
|
||||
mobileFriendlyVideoLongDescription: {
|
||||
id: 'mobileFriendlyVideoLongDescription',
|
||||
defaultMessage: 'Mobile-friendly videos can be viewed across all supported devices. Ensure that at least 90% of course videos are mobile friendly by uploading course videos to the edX video pipeline.',
|
||||
description: 'Description for a section that prompts a user to follow best practices for mobile friendly videos',
|
||||
},
|
||||
diverseSequencesShortDescription: {
|
||||
id: 'diverseSequencesShortDescription',
|
||||
defaultMessage: 'Build diverse learning sequences',
|
||||
|
||||
@@ -36,10 +36,6 @@ export const checklistItems = {
|
||||
id: 'videoDuration',
|
||||
pacingTypeFilter: filters.ALL,
|
||||
},
|
||||
{
|
||||
id: 'mobileFriendlyVideo',
|
||||
pacingTypeFilter: filters.ALL,
|
||||
},
|
||||
{
|
||||
id: 'diverseSequences',
|
||||
pacingTypeFilter: filters.ALL,
|
||||
|
||||
@@ -35,18 +35,8 @@ export const hasAssignmentDeadlines = (assignments, dates) => {
|
||||
|
||||
export const hasShortVideoDuration = (videos) => {
|
||||
if (videos.totalNumber === 0) {
|
||||
return true;
|
||||
} if (videos.totalNumber > 0 && videos.durations.median <= 600) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const hasMobileFriendlyVideos = (videos) => {
|
||||
if (videos.totalNumber === 0) {
|
||||
return true;
|
||||
} if (videos.totalNumber > 0 && (videos.numMobileEncoded / videos.totalNumber) >= 0.9) {
|
||||
return false;
|
||||
} if (videos.totalNumber > 0 && videos.durations.median !== null && videos.durations.median <= 600) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -57,7 +47,7 @@ export const hasDiverseSequences = (subsections) => {
|
||||
if (subsections.totalVisible === 0) {
|
||||
return false;
|
||||
} if (subsections.totalVisible > 0) {
|
||||
return ((subsections.numWithOneBlockType / subsections.totalVisible) < 0.2);
|
||||
return ((subsections.numWithOneBlockType / subsections.totalVisible) <= 0.2);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -68,7 +58,7 @@ export const hasWeeklyHighlights = sections => (
|
||||
);
|
||||
|
||||
export const hasShortUnitDepth = units => (
|
||||
units.numBlocks.median <= 3
|
||||
units.numBlocks.median <= 3 && units.totalVisible > 0
|
||||
);
|
||||
|
||||
export const hasProctoringEscalationEmail = proctoring => (
|
||||
|
||||
@@ -189,8 +189,8 @@ describe('courseCheckValidators utility functions', () => {
|
||||
);
|
||||
|
||||
describe('hasShortVideoDuration', () => {
|
||||
it('returns true if course run has no videos', () => {
|
||||
expect(validators.hasShortVideoDuration({ totalNumber: 0 })).toEqual(true);
|
||||
it('returns false if course run has no videos', () => {
|
||||
expect(validators.hasShortVideoDuration({ totalNumber: 0 })).toEqual(false);
|
||||
});
|
||||
|
||||
it('returns true if course run videos have a median duration <= to 600', () => {
|
||||
@@ -204,22 +204,6 @@ describe('courseCheckValidators utility functions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasMobileFriendlyVideos', () => {
|
||||
it('returns true if course run has no videos', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 0 })).toEqual(true);
|
||||
});
|
||||
|
||||
it('returns true if course run videos are >= 90% mobile friendly', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 9 }))
|
||||
.toEqual(true);
|
||||
});
|
||||
|
||||
it('returns true if course run videos are < 90% mobile friendly', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 8 }))
|
||||
.toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDiverseSequences', () => {
|
||||
it('returns true if < 20% of visible subsections have more than one block type', () => {
|
||||
expect(validators.hasDiverseSequences({ totalVisible: 10, numWithOneBlockType: 1 }))
|
||||
@@ -264,6 +248,7 @@ describe('courseCheckValidators utility functions', () => {
|
||||
describe('hasShortUnitDepth', () => {
|
||||
it('returns true when course run has median number of blocks <= 3', () => {
|
||||
const units = {
|
||||
totalVisible: 2,
|
||||
numBlocks: {
|
||||
median: 3,
|
||||
},
|
||||
@@ -274,6 +259,7 @@ describe('courseCheckValidators utility functions', () => {
|
||||
|
||||
it('returns false when course run has median number of blocks > 3', () => {
|
||||
const units = {
|
||||
totalVisible: 2,
|
||||
numBlocks: {
|
||||
median: 4,
|
||||
},
|
||||
|
||||
@@ -14,8 +14,6 @@ const getValidatedValue = (data, id) => {
|
||||
return healthValidators.hasAssignmentDeadlines(data.assignments, data.dates);
|
||||
case 'videoDuration':
|
||||
return healthValidators.hasShortVideoDuration(data.videos);
|
||||
case 'mobileFriendlyVideo':
|
||||
return healthValidators.hasMobileFriendlyVideos(data.videos);
|
||||
case 'diverseSequences':
|
||||
return healthValidators.hasDiverseSequences(data.subsections);
|
||||
case 'weeklyHighlights':
|
||||
|
||||
@@ -88,20 +88,6 @@ describe('getValidatedValue utility function', () => {
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('mobile friendly video', () => {
|
||||
const spy = jest.fn();
|
||||
localValidators.hasMobileFriendlyVideos = spy;
|
||||
|
||||
const props = {
|
||||
data: {
|
||||
videos: {},
|
||||
},
|
||||
};
|
||||
|
||||
getValidatedValue(props, 'mobileFriendlyVideo');
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('diverse sequences', () => {
|
||||
const spy = jest.fn();
|
||||
localValidators.hasDiverseSequences = spy;
|
||||
|
||||
@@ -481,7 +481,7 @@ describe('<CourseOutline />', () => {
|
||||
courseId, excludeGraded: true, all: true,
|
||||
}), store.dispatch);
|
||||
|
||||
expect(getByText('4/9 completed')).toBeInTheDocument();
|
||||
expect(getByText('3/8 completed')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('render alerts if checklist api fails', async () => {
|
||||
|
||||
@@ -58,10 +58,6 @@ export const BEST_PRACTICES_CHECKLIST = /** @type {const} */ ({
|
||||
id: 'videoDuration',
|
||||
pacingTypeFilter: CHECKLIST_FILTERS.ALL,
|
||||
},
|
||||
{
|
||||
id: 'mobileFriendlyVideo',
|
||||
pacingTypeFilter: CHECKLIST_FILTERS.ALL,
|
||||
},
|
||||
{
|
||||
id: 'diverseSequences',
|
||||
pacingTypeFilter: CHECKLIST_FILTERS.ALL,
|
||||
|
||||
@@ -62,20 +62,7 @@ export const hasShortVideoDuration = (videos) => {
|
||||
if (totalNumber === 0) {
|
||||
return true;
|
||||
}
|
||||
if (totalNumber > 0 && durations.median <= 600) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const hasMobileFriendlyVideos = (videos) => {
|
||||
const { totalNumber, numMobileEncoded } = videos;
|
||||
|
||||
if (totalNumber === 0) {
|
||||
return true;
|
||||
}
|
||||
if (totalNumber > 0 && (numMobileEncoded / totalNumber) >= 0.9) {
|
||||
if (totalNumber > 0 && durations.median !== null && durations.median <= 600) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -89,7 +76,7 @@ export const hasDiverseSequences = (subsections) => {
|
||||
return false;
|
||||
}
|
||||
if (totalVisible > 0) {
|
||||
return ((numWithOneBlockType / totalVisible) < 0.2);
|
||||
return ((numWithOneBlockType / totalVisible) <= 0.2);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -101,6 +88,6 @@ export const hasWeeklyHighlights = (sections) => {
|
||||
return highlightsActiveForCourse && highlightsEnabled;
|
||||
};
|
||||
|
||||
export const hasShortUnitDepth = (units) => units.numBlocks.median <= 3;
|
||||
export const hasShortUnitDepth = (units) => units.numBlocks.median <= 3 && units.totalVisible > 0;
|
||||
|
||||
export const hasProctoringEscalationEmail = (proctoring) => proctoring.hasProctoringEscalationEmail;
|
||||
|
||||
@@ -204,22 +204,6 @@ describe('courseCheckValidators utility functions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasMobileFriendlyVideos', () => {
|
||||
it('returns true if course run has no videos', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 0 })).toEqual(true);
|
||||
});
|
||||
|
||||
it('returns true if course run videos are >= 90% mobile friendly', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 9 }))
|
||||
.toEqual(true);
|
||||
});
|
||||
|
||||
it('returns true if course run videos are < 90% mobile friendly', () => {
|
||||
expect(validators.hasMobileFriendlyVideos({ totalNumber: 10, numMobileEncoded: 8 }))
|
||||
.toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasDiverseSequences', () => {
|
||||
it('returns true if < 20% of visible subsections have more than one block type', () => {
|
||||
expect(validators.hasDiverseSequences({ totalVisible: 10, numWithOneBlockType: 1 }))
|
||||
@@ -264,6 +248,7 @@ describe('courseCheckValidators utility functions', () => {
|
||||
describe('hasShortUnitDepth', () => {
|
||||
it('returns true when course run has median number of blocks <= 3', () => {
|
||||
const units = {
|
||||
totalVisible: 2,
|
||||
numBlocks: {
|
||||
median: 3,
|
||||
},
|
||||
@@ -274,6 +259,7 @@ describe('courseCheckValidators utility functions', () => {
|
||||
|
||||
it('returns false when course run has median number of blocks > 3', () => {
|
||||
const units = {
|
||||
totalVisible: 2,
|
||||
numBlocks: {
|
||||
median: 4,
|
||||
},
|
||||
|
||||
@@ -89,8 +89,8 @@ describe('getChecklistForStatusBar util functions', () => {
|
||||
};
|
||||
|
||||
expect(getCourseBestPracticesChecklist(data)).toEqual({
|
||||
totalCourseBestPracticesChecks: 4,
|
||||
completedCourseBestPracticesChecks: 2,
|
||||
totalCourseBestPracticesChecks: 3,
|
||||
completedCourseBestPracticesChecks: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,8 +32,6 @@ const getChecklistValidatedValue = (data, id) => {
|
||||
return healthValidators.hasAssignmentDeadlines(assignments, dates);
|
||||
case 'videoDuration':
|
||||
return healthValidators.hasShortVideoDuration(videos);
|
||||
case 'mobileFriendlyVideo':
|
||||
return healthValidators.hasMobileFriendlyVideos(videos);
|
||||
case 'diverseSequences':
|
||||
return healthValidators.hasDiverseSequences(subsections);
|
||||
case 'weeklyHighlights':
|
||||
|
||||
Reference in New Issue
Block a user