diff --git a/src/course-home/data/__factories__/progressTabData.factory.js b/src/course-home/data/__factories__/progressTabData.factory.js
index e8321d12..1ca91f06 100644
--- a/src/course-home/data/__factories__/progressTabData.factory.js
+++ b/src/course-home/data/__factories__/progressTabData.factory.js
@@ -12,9 +12,9 @@ Factory.define('progressTabData')
locked_count: 0,
},
course_grade: {
- letter_grade: null,
- percent: 0,
- is_passing: false,
+ letter_grade: 'pass',
+ percent: 1,
+ is_passing: true,
},
section_scores: [
{
@@ -55,6 +55,7 @@ Factory.define('progressTabData')
assignment_policies: [
{
num_droppable: 1,
+ num_total: 2,
short_label: 'HW',
type: 'Homework',
weight: 1,
diff --git a/src/course-home/data/__snapshots__/redux.test.js.snap b/src/course-home/data/__snapshots__/redux.test.js.snap
index eb3ff448..e342bb7a 100644
--- a/src/course-home/data/__snapshots__/redux.test.js.snap
+++ b/src/course-home/data/__snapshots__/redux.test.js.snap
@@ -536,9 +536,9 @@ Object {
"lockedCount": 0,
},
"courseGrade": Object {
- "isPassing": false,
- "letterGrade": null,
- "percent": 0,
+ "isPassing": true,
+ "letterGrade": "pass",
+ "percent": 1,
},
"courseId": "course-v1:edX+DemoX+Demo_Course_1",
"end": "3027-03-31T00:00:00Z",
@@ -547,6 +547,7 @@ Object {
"assignmentPolicies": Array [
Object {
"numDroppable": 1,
+ "numTotal": 2,
"shortLabel": "HW",
"type": "Homework",
"weight": 1,
diff --git a/src/course-home/progress-tab/ProgressTab.test.jsx b/src/course-home/progress-tab/ProgressTab.test.jsx
index d2a46e49..4284f259 100644
--- a/src/course-home/progress-tab/ProgressTab.test.jsx
+++ b/src/course-home/progress-tab/ProgressTab.test.jsx
@@ -60,19 +60,19 @@ describe('Progress Tab', () => {
});
it('renders correct copy for non-passing', async () => {
+ setTabData({
+ course_grade: {
+ is_passing: false,
+ letter_grade: null,
+ percent: 0.5,
+ },
+ });
await fetchAndRender();
expect(screen.queryByRole('button', { name: 'Grade range tooltip' })).not.toBeInTheDocument();
expect(screen.getByText('A weighted grade of 75% is required to pass in this course')).toBeInTheDocument();
});
it('renders correct copy for passing with pass/fail grade range', async () => {
- setTabData({
- course_grade: {
- is_passing: true,
- letter_grade: 'Pass',
- percent: 0.9,
- },
- });
await fetchAndRender();
expect(screen.queryByRole('button', { name: 'Grade range tooltip' })).not.toBeInTheDocument();
expect(screen.getByText('You’re currently passing this course')).toBeInTheDocument();
@@ -194,6 +194,131 @@ describe('Progress Tab', () => {
await fetchAndRender();
expect(screen.queryByText('Grade summary')).not.toBeInTheDocument();
});
+
+ it('calculates grades correctly when number of droppable assignments equals total number of assignments', async () => {
+ setTabData({
+ grading_policy: {
+ assignment_policies: [
+ {
+ num_droppable: 2,
+ num_total: 2,
+ short_label: 'HW',
+ type: 'Homework',
+ weight: 1,
+ },
+ ],
+ grade_range: {
+ pass: 0.75,
+ },
+ },
+ });
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {footnote - optional} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 1 100% 0% 0%' })).toBeInTheDocument();
+ });
+ it('calculates grades correctly when number of droppable assignments is less than total number of assignments', async () => {
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {footnote - optional} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 1 100% 100% 100%' })).toBeInTheDocument();
+ });
+ it('calculates grades correctly when number of droppable assignments is zero', async () => {
+ setTabData({
+ grading_policy: {
+ assignment_policies: [
+ {
+ num_droppable: 0,
+ num_total: 2,
+ short_label: 'HW',
+ type: 'Homework',
+ weight: 1,
+ },
+ ],
+ grade_range: {
+ pass: 0.75,
+ },
+ },
+ });
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 100% 50% 50%' })).toBeInTheDocument();
+ });
+ it('calculates grades correctly when number of total assignments is less than the number of assignments created', async () => {
+ setTabData({
+ grading_policy: {
+ assignment_policies: [
+ {
+ num_droppable: 1,
+ num_total: 1, // two assignments created in the factory, but 1 is expected per Studio settings
+ short_label: 'HW',
+ type: 'Homework',
+ weight: 1,
+ },
+ ],
+ grade_range: {
+ pass: 0.75,
+ },
+ },
+ });
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {footnote - optional} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 1 100% 100% 100%' })).toBeInTheDocument();
+ });
+ it('calculates grades correctly when number of total assignments is greater than the number of assignments created', async () => {
+ setTabData({
+ grading_policy: {
+ assignment_policies: [
+ {
+ num_droppable: 0,
+ num_total: 5, // two assignments created in the factory, but 5 are expected per Studio settings
+ short_label: 'HW',
+ type: 'Homework',
+ weight: 1,
+ },
+ ],
+ grade_range: {
+ pass: 0.75,
+ },
+ },
+ });
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 100% 20% 20%' })).toBeInTheDocument();
+ });
+ it('calculates weighted grades correctly', async () => {
+ setTabData({
+ grading_policy: {
+ assignment_policies: [
+ {
+ num_droppable: 1,
+ num_total: 2,
+ short_label: 'HW',
+ type: 'Homework',
+ weight: 0.5,
+ },
+ {
+ num_droppable: 0,
+ num_total: 1,
+ short_label: 'Ex',
+ type: 'Exam',
+ weight: 0.5,
+ },
+ ],
+ grade_range: {
+ pass: 0.75,
+ },
+ },
+ });
+ await fetchAndRender();
+ expect(screen.getByText('Grade summary')).toBeInTheDocument();
+ // The row is comprised of "{Assignment type} {footnote - optional} {weight} {grade} {weighted grade}"
+ expect(screen.getByRole('row', { name: 'Homework 1 50% 100% 50%' })).toBeInTheDocument();
+ expect(screen.getByRole('row', { name: 'Exam 50% 0% 0%' })).toBeInTheDocument();
+ });
});
describe('Detailed Grades', () => {
diff --git a/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx b/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
index 7a608ac0..f897b892 100644
--- a/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
+++ b/src/course-home/progress-tab/grades/grade-summary/DroppableAssignmentFootnote.jsx
@@ -15,7 +15,7 @@ function DroppableAssignmentFootnote({ footnotes, intl }) {
{index + 1}