Compare commits
6 Commits
open-relea
...
jkantor/ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32be24cfe6 | ||
|
|
67789481fb | ||
|
|
543cd623e1 | ||
|
|
ba31b713e2 | ||
|
|
84fe2c6628 | ||
|
|
b87447b543 |
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -11,18 +11,22 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
node: [16]
|
||||
npm: [8.5.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Nodejs Env
|
||||
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Nodejs
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ env.NODE_VER }}
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Install npm 8.5.x
|
||||
run: npm install -g npm@${{ matrix.npm }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
2
.github/workflows/lockfileversion-check.yml
vendored
2
.github/workflows/lockfileversion-check.yml
vendored
@@ -10,4 +10,4 @@ on:
|
||||
|
||||
jobs:
|
||||
version-check:
|
||||
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master
|
||||
uses: openedx/.github/.github/workflows/lockfileversion-check.yml@master
|
||||
|
||||
5
.github/workflows/npm-publish.yml
vendored
5
.github/workflows/npm-publish.yml
vendored
@@ -15,13 +15,10 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Nodejs Env
|
||||
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ env.NODE_VER }}
|
||||
node-version: 12
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
28714
package-lock.json
generated
28714
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@
|
||||
"extends @edx/browserslist-config"
|
||||
],
|
||||
"dependencies": {
|
||||
"@edx/brand": "npm:@edx/brand-edx.org@^1.3.2",
|
||||
"@edx/brand": "npm:@edx/brand-openedx@^1.2.0",
|
||||
"@edx/frontend-component-footer": "^11.1.1",
|
||||
"@edx/frontend-component-header": "^3.1.1",
|
||||
"@edx/frontend-platform": "2.5.0",
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@edx/browserslist-config": "^1.1.1",
|
||||
"@edx/frontend-build": "12.8.27",
|
||||
"@edx/frontend-build": "^12.4.15",
|
||||
"@testing-library/react": "^12.1.0",
|
||||
"axios": "0.21.2",
|
||||
"axios-mock-adapter": "^1.17.0",
|
||||
|
||||
@@ -29,16 +29,16 @@ Username.propTypes = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Fields.Email
|
||||
* Simple label field for email value.
|
||||
* @param {string} email - email for display
|
||||
* Fields.Text
|
||||
* Simple label field for text value.
|
||||
* @param {string} value - value for display
|
||||
*/
|
||||
const Email = ({ email }) => <span className="wrap-text-in-cell">{email}</span>;
|
||||
Email.propTypes = {
|
||||
email: PropTypes.string.isRequired,
|
||||
const Text = ({ value }) => (<span className="wrap-text-in-cell">{value}</span>);
|
||||
Text.propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default StrictDict({
|
||||
Email,
|
||||
Text,
|
||||
Username,
|
||||
});
|
||||
|
||||
@@ -41,13 +41,13 @@ describe('Gradebook Table Fields', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Email', () => {
|
||||
const email = 'myTag@place.com';
|
||||
describe('Text', () => {
|
||||
const value = 'myTag@place.com';
|
||||
test('snapshot', () => {
|
||||
expect(shallow(<Fields.Email email={email} />)).toMatchSnapshot();
|
||||
expect(shallow(<Fields.Text value={value} />)).toMatchSnapshot();
|
||||
});
|
||||
test('wraps entry email', () => {
|
||||
expect(shallow(<Fields.Email email={email} />).text()).toEqual(email);
|
||||
test('wraps entry value', () => {
|
||||
expect(shallow(<Fields.Text value={value} />).text()).toEqual(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,6 +45,13 @@ const TotalGradeLabelReplacement = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* Asterisk to display next to heading labels that are only used for masters students
|
||||
*/
|
||||
const mastersOnlyFieldAsterisk = (
|
||||
<span className="font-weight-normal">*</span>
|
||||
);
|
||||
|
||||
/**
|
||||
* <UsernameLabelReplacement />
|
||||
* Username column header. Lists that Student Key is possibly available
|
||||
@@ -56,11 +63,24 @@ const UsernameLabelReplacement = () => (
|
||||
</div>
|
||||
<div className="font-weight-normal student-key">
|
||||
<FormattedMessage {...messages.studentKeyLabel} />
|
||||
{ mastersOnlyFieldAsterisk }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* <MastersOnlyLabelReplacement {message}>
|
||||
* Column header for fields that are only available for masters students
|
||||
*/
|
||||
const MastersOnlyLabelReplacement = (message) => (
|
||||
<div>
|
||||
<FormattedMessage {...message} />
|
||||
{ mastersOnlyFieldAsterisk }
|
||||
</div>
|
||||
);
|
||||
|
||||
export default StrictDict({
|
||||
TotalGradeLabelReplacement,
|
||||
UsernameLabelReplacement,
|
||||
MastersOnlyLabelReplacement,
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import LabelReplacements from './LabelReplacements';
|
||||
const {
|
||||
TotalGradeLabelReplacement,
|
||||
UsernameLabelReplacement,
|
||||
MastersOnlyLabelReplacement,
|
||||
} = LabelReplacements;
|
||||
|
||||
jest.mock('@edx/paragon', () => ({
|
||||
@@ -35,6 +36,16 @@ describe('LabelReplacements', () => {
|
||||
expect(shallow(<UsernameLabelReplacement />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('MastersOnlyLabelReplacement', () => {
|
||||
test('snapshot', () => {
|
||||
const message = {
|
||||
id: 'id',
|
||||
defaultMessage: 'defaultMessAge',
|
||||
description: 'desCripTion',
|
||||
};
|
||||
expect(shallow(<MastersOnlyLabelReplacement {...message} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapshot', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Gradebook Table Fields Email snapshot 1`] = `
|
||||
exports[`Gradebook Table Fields Text snapshot 1`] = `
|
||||
<span
|
||||
className="wrap-text-in-cell"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LabelReplacements MastersOnlyLabelReplacement snapshot 1`] = `
|
||||
<div>
|
||||
<FormattedMessage
|
||||
defaultMessage="defaultMessAge"
|
||||
description="desCripTion"
|
||||
id="id"
|
||||
/>
|
||||
<span
|
||||
className="font-weight-normal"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LabelReplacements TotalGradeLabelReplacement displays overlay tooltip 1`] = `
|
||||
<Tooltip
|
||||
id="course-grade-tooltip"
|
||||
@@ -73,10 +88,15 @@ exports[`LabelReplacements UsernameLabelReplacement snapshot 1`] = `
|
||||
className="font-weight-normal student-key"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Student Key*"
|
||||
defaultMessage="Student Key"
|
||||
description="Gradebook table Student Key label"
|
||||
id="gradebook.GradesView.table.labels.studentKey"
|
||||
/>
|
||||
<span
|
||||
className="font-weight-normal"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -13,8 +13,16 @@ exports[`GradebookTable component snapshot - fields1 and 2 between email and tot
|
||||
"accessor": "Username",
|
||||
},
|
||||
Object {
|
||||
"Header": <FormattedMessage
|
||||
defaultMessage="Email*"
|
||||
"Header": <MastersOnlyLabelReplacement
|
||||
defaultMessage="Full Name"
|
||||
description="Gradebook table full name column header"
|
||||
id="gradebook.GradesView.table.headings.fullName"
|
||||
/>,
|
||||
"accessor": "Full Name",
|
||||
},
|
||||
Object {
|
||||
"Header": <MastersOnlyLabelReplacement
|
||||
defaultMessage="Email"
|
||||
description="Gradebook table email column header"
|
||||
id="gradebook.GradesView.table.headings.email"
|
||||
/>,
|
||||
|
||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { DataTable } from '@edx/paragon';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { Headings } from 'data/constants/grades';
|
||||
@@ -38,7 +38,9 @@ export class GradebookTable extends React.Component {
|
||||
} else if (heading === Headings.username) {
|
||||
label = <LabelReplacements.UsernameLabelReplacement />;
|
||||
} else if (heading === Headings.email) {
|
||||
label = <FormattedMessage {...messages.emailHeading} />;
|
||||
label = <LabelReplacements.MastersOnlyLabelReplacement {...messages.emailHeading} />;
|
||||
} else if (heading === Headings.fullName) {
|
||||
label = <LabelReplacements.MastersOnlyLabelReplacement {...messages.fullNameHeading} />;
|
||||
} else {
|
||||
label = heading;
|
||||
}
|
||||
@@ -49,7 +51,8 @@ export class GradebookTable extends React.Component {
|
||||
[Headings.username]: (
|
||||
<Fields.Username username={entry.username} userKey={entry.external_user_key} />
|
||||
),
|
||||
[Headings.email]: (<Fields.Email email={entry.email} />),
|
||||
[Headings.fullName]: (<Fields.Text value={entry.full_name} />),
|
||||
[Headings.email]: (<Fields.Text value={entry.email} />),
|
||||
[Headings.totalGrade]: `${roundGrade(entry.percent * 100)}${getLocalizedPercentSign()}`,
|
||||
...entry.section_breakdown.reduce((acc, subsection) => ({
|
||||
...acc,
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
fullNameHeading: {
|
||||
id: 'gradebook.GradesView.table.headings.fullName',
|
||||
defaultMessage: 'Full Name',
|
||||
description: 'Gradebook table full name column header',
|
||||
},
|
||||
emailHeading: {
|
||||
id: 'gradebook.GradesView.table.headings.email',
|
||||
defaultMessage: 'Email*',
|
||||
defaultMessage: 'Email',
|
||||
description: 'Gradebook table email column header',
|
||||
},
|
||||
totalGradeHeading: {
|
||||
@@ -18,7 +23,7 @@ const messages = defineMessages({
|
||||
},
|
||||
studentKeyLabel: {
|
||||
id: 'gradebook.GradesView.table.labels.studentKey',
|
||||
defaultMessage: 'Student Key*',
|
||||
defaultMessage: 'Student Key',
|
||||
description: 'Gradebook table Student Key label',
|
||||
},
|
||||
usernameLabel: {
|
||||
|
||||
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { DataTable } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { Headings } from 'data/constants/grades';
|
||||
@@ -22,7 +21,7 @@ jest.mock('./Fields', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
Username: () => 'Fields.Username',
|
||||
Email: () => 'Fields.Email',
|
||||
Text: () => 'Fields.Text',
|
||||
},
|
||||
}));
|
||||
jest.mock('./LabelReplacements', () => ({
|
||||
@@ -30,6 +29,7 @@ jest.mock('./LabelReplacements', () => ({
|
||||
default: {
|
||||
TotalGradeLabelReplacement: () => 'TotalGradeLabelReplacement',
|
||||
UsernameLabelReplacement: () => 'UsernameLabelReplacement',
|
||||
MastersOnlyLabelReplacement: () => 'MastersOnlyLabelReplacement',
|
||||
},
|
||||
}));
|
||||
jest.mock('./GradeButton', () => 'GradeButton');
|
||||
@@ -75,6 +75,7 @@ describe('GradebookTable', () => {
|
||||
],
|
||||
headings: [
|
||||
Headings.username,
|
||||
Headings.fullName,
|
||||
Headings.email,
|
||||
fields.field1,
|
||||
fields.field2,
|
||||
@@ -104,17 +105,22 @@ describe('GradebookTable', () => {
|
||||
expect(heading.accessor).toEqual(Headings.username);
|
||||
expect(heading.Header.type).toEqual(LabelReplacements.UsernameLabelReplacement);
|
||||
});
|
||||
test('email sets key and Header from header', () => {
|
||||
test('full name sets key and Header from header', () => {
|
||||
const heading = headings[1];
|
||||
expect(heading.accessor).toEqual(Headings.fullName);
|
||||
expect(heading.Header).toEqual(<LabelReplacements.MastersOnlyLabelReplacement {...messages.fullNameHeading} />);
|
||||
});
|
||||
test('email sets key and Header from header', () => {
|
||||
const heading = headings[2];
|
||||
expect(heading.accessor).toEqual(Headings.email);
|
||||
expect(heading.Header).toEqual(<FormattedMessage {...messages.emailHeading} />);
|
||||
expect(heading.Header).toEqual(<LabelReplacements.MastersOnlyLabelReplacement {...messages.emailHeading} />);
|
||||
});
|
||||
test('subsections set key and Header from header', () => {
|
||||
expect(headings[2]).toEqual({ accessor: fields.field1, Header: fields.field1 });
|
||||
expect(headings[3]).toEqual({ accessor: fields.field2, Header: fields.field2 });
|
||||
expect(headings[3]).toEqual({ accessor: fields.field1, Header: fields.field1 });
|
||||
expect(headings[4]).toEqual({ accessor: fields.field2, Header: fields.field2 });
|
||||
});
|
||||
test('totalGrade sets key and replaces Header with component', () => {
|
||||
const heading = headings[4];
|
||||
const heading = headings[5];
|
||||
expect(heading.accessor).toEqual(Headings.totalGrade);
|
||||
expect(heading.Header.type).toEqual(LabelReplacements.TotalGradeLabelReplacement);
|
||||
});
|
||||
@@ -139,10 +145,15 @@ describe('GradebookTable', () => {
|
||||
userKey: entry.external_user_key,
|
||||
});
|
||||
});
|
||||
test('email set to Email Field', () => {
|
||||
test('fullName set to Text Field', () => {
|
||||
const field = row[Headings.fullName];
|
||||
expect(field.type).toEqual(Fields.Text);
|
||||
expect(field.props).toEqual({ value: entry.full_name });
|
||||
});
|
||||
test('email set to Text Field', () => {
|
||||
const field = row[Headings.email];
|
||||
expect(field.type).toEqual(Fields.Email);
|
||||
expect(field.props).toEqual({ email: entry.email });
|
||||
expect(field.type).toEqual(Fields.Text);
|
||||
expect(field.props).toEqual({ value: entry.email });
|
||||
});
|
||||
test('totalGrade set to rounded percent grade * 100', () => {
|
||||
expect(
|
||||
|
||||
@@ -6,11 +6,10 @@ export const useImportButtonData = () => {
|
||||
const submitImportGradesButtonData = thunkActions.grades.useSubmitImportGradesButtonData();
|
||||
|
||||
const fileInputRef = useRef();
|
||||
const hasFile = fileInputRef.current && fileInputRef.current.files[0];
|
||||
|
||||
const handleClickImportGrades = () => hasFile && fileInputRef.current.click();
|
||||
const handleClickImportGrades = () => fileInputRef.current?.click();
|
||||
const handleFileInputChange = () => {
|
||||
if (hasFile) {
|
||||
if (fileInputRef.current?.files[0]) {
|
||||
const clearInput = () => {
|
||||
fileInputRef.current.value = null;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { StrictDict } from 'utils';
|
||||
const EMAIL_HEADING = 'Email';
|
||||
const TOTAL_COURSE_GRADE_HEADING = 'Total Grade (%)';
|
||||
const USERNAME_HEADING = 'Username';
|
||||
const FULL_NAME_HEADING = 'Full Name';
|
||||
|
||||
const GradeFormats = StrictDict({
|
||||
absolute: 'absolute',
|
||||
@@ -10,15 +11,17 @@ const GradeFormats = StrictDict({
|
||||
});
|
||||
|
||||
const Headings = StrictDict({
|
||||
email: 'Email',
|
||||
totalGrade: 'Total Grade (%)',
|
||||
username: 'Username',
|
||||
email: EMAIL_HEADING,
|
||||
totalGrade: TOTAL_COURSE_GRADE_HEADING,
|
||||
username: USERNAME_HEADING,
|
||||
fullName: FULL_NAME_HEADING,
|
||||
});
|
||||
|
||||
export {
|
||||
EMAIL_HEADING,
|
||||
TOTAL_COURSE_GRADE_HEADING,
|
||||
USERNAME_HEADING,
|
||||
FULL_NAME_HEADING,
|
||||
GradeFormats,
|
||||
Headings,
|
||||
};
|
||||
|
||||
@@ -92,7 +92,11 @@ export const formatMinAssignmentGrade = (percentGrade, options) => (
|
||||
* @param {string} label - assignment filter label
|
||||
* @return {string[]} - list of table headers
|
||||
*/
|
||||
export const headingMapper = (category, label = 'All') => {
|
||||
export const headingMapper = (
|
||||
category,
|
||||
label = 'All',
|
||||
hasMastersTrack = false,
|
||||
) => {
|
||||
const filters = {
|
||||
all: section => section.label,
|
||||
byCategory: section => section.label && section.category === category,
|
||||
@@ -105,12 +109,25 @@ export const headingMapper = (category, label = 'All') => {
|
||||
} else {
|
||||
filter = filters.byLabel;
|
||||
}
|
||||
const { username, email, totalGrade } = Headings;
|
||||
|
||||
const {
|
||||
username,
|
||||
fullName,
|
||||
email,
|
||||
totalGrade,
|
||||
} = Headings;
|
||||
let userIdentificationHeadings;
|
||||
if (hasMastersTrack) {
|
||||
userIdentificationHeadings = [username, fullName, email];
|
||||
} else {
|
||||
userIdentificationHeadings = [username];
|
||||
}
|
||||
|
||||
const filteredLabels = (entry) => entry.filter(filter).map(s => s.label);
|
||||
|
||||
return (entry) => (
|
||||
entry
|
||||
? [username, email, ...filteredLabels(entry), totalGrade]
|
||||
? [...userIdentificationHeadings, ...filteredLabels(entry), totalGrade]
|
||||
: []
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { EMAIL_HEADING, TOTAL_COURSE_GRADE_HEADING, USERNAME_HEADING } from '../constants/grades';
|
||||
import {
|
||||
EMAIL_HEADING,
|
||||
FULL_NAME_HEADING,
|
||||
TOTAL_COURSE_GRADE_HEADING,
|
||||
USERNAME_HEADING,
|
||||
} from '../constants/grades';
|
||||
import { formatDateForDisplay } from '../actions/utils';
|
||||
import * as selectors from './grades';
|
||||
import exportedSelectors from './grades';
|
||||
@@ -177,34 +182,45 @@ describe('grades selectors', () => {
|
||||
});
|
||||
|
||||
describe('headingMapper', () => {
|
||||
const expectedHeaders = (subsectionLabels) => ([
|
||||
const expectedMastersHeaders = (subsectionLabels) => ([
|
||||
USERNAME_HEADING,
|
||||
FULL_NAME_HEADING,
|
||||
EMAIL_HEADING,
|
||||
...subsectionLabels,
|
||||
TOTAL_COURSE_GRADE_HEADING,
|
||||
]);
|
||||
|
||||
const expectedNonMastersHeaders = (subsectionLabels) => ([
|
||||
USERNAME_HEADING,
|
||||
...subsectionLabels,
|
||||
TOTAL_COURSE_GRADE_HEADING,
|
||||
]);
|
||||
const rows = genericResultsRows;
|
||||
const selector = selectors.headingMapper;
|
||||
it('creates headers for all assignments when no filtering is applied', () => {
|
||||
expect(selector('All')(genericResultsRows)).toEqual(
|
||||
expectedHeaders([rows[0].label, rows[1].label, rows[2].label]),
|
||||
);
|
||||
});
|
||||
it('creates headers for only matching assignment types when type filter is applied', () => {
|
||||
expect(
|
||||
selector('Homework')(genericResultsRows),
|
||||
).toEqual(
|
||||
expectedHeaders([rows[0].label, rows[1].label]),
|
||||
);
|
||||
});
|
||||
it('creates headers for only matching assignment when label filter is applied', () => {
|
||||
expect(selector('Homework', rows[1].label)(rows)).toEqual(
|
||||
expectedHeaders([rows[1].label]),
|
||||
);
|
||||
});
|
||||
it('returns an empty array when no entries are passed', () => {
|
||||
expect(selector('all')(undefined)).toEqual([]);
|
||||
[true, false].forEach((isMasters) => {
|
||||
const expectedHeaders = isMasters ? expectedMastersHeaders : expectedNonMastersHeaders;
|
||||
describe(isMasters ? 'Masters' : 'Not Masters', () => {
|
||||
it('creates headers for all assignments when no filtering is applied', () => {
|
||||
expect(selector('All', 'All', isMasters)(genericResultsRows)).toEqual(
|
||||
expectedHeaders([rows[0].label, rows[1].label, rows[2].label]),
|
||||
);
|
||||
});
|
||||
it('creates headers for only matching assignment types when type filter is applied', () => {
|
||||
expect(
|
||||
selector('Homework', 'All', isMasters)(genericResultsRows),
|
||||
).toEqual(
|
||||
expectedHeaders([rows[0].label, rows[1].label]),
|
||||
);
|
||||
});
|
||||
it('creates headers for only matching assignment when label filter is applied', () => {
|
||||
expect(selector('Homework', rows[1].label, isMasters)(rows)).toEqual(
|
||||
expectedHeaders([rows[1].label]),
|
||||
);
|
||||
});
|
||||
it('returns an empty array when no entries are passed', () => {
|
||||
expect(selector('all')(undefined)).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@ export const formattedGradeLimits = (state) => {
|
||||
export const getHeadings = (state) => grades.headingMapper(
|
||||
filters.assignmentType(state) || 'All',
|
||||
filters.selectedAssignmentLabel(state) || 'All',
|
||||
tracks.stateHasMastersTrack(state),
|
||||
)(grades.getExampleSectionBreakdown(state));
|
||||
|
||||
/**
|
||||
|
||||
@@ -295,20 +295,27 @@ describe('root selectors', () => {
|
||||
const selector = moduleSelectors.getHeadings;
|
||||
beforeEach(() => {
|
||||
selectors.grades.headingMapper = jest.fn(
|
||||
(type, label) => (breakdown) => ({ headingMapper: { type, label, breakdown } }),
|
||||
(type, label, hasMastersTrack) => (breakdown) => ({
|
||||
headingMapper: {
|
||||
type, label, hasMastersTrack, breakdown,
|
||||
},
|
||||
}),
|
||||
);
|
||||
selectors.filters.assignmentType = jest.fn();
|
||||
selectors.filters.selectedAssignmentLabel = jest.fn();
|
||||
selectors.tracks.stateHasMastersTrack = jest.fn();
|
||||
selectors.grades.getExampleSectionBreakdown = mockFn('getExampleSectionBreakdown');
|
||||
});
|
||||
describe('no assignmentType or label selected', () => {
|
||||
it('maps selected filters into getExampleSectionBreakdown', () => {
|
||||
selectors.filters.assignmentType.mockReturnValue(undefined);
|
||||
selectors.filters.selectedAssignmentLabel.mockReturnValue(undefined);
|
||||
selectors.tracks.stateHasMastersTrack.mockReturnValue(false);
|
||||
expect(selector(testState)).toEqual({
|
||||
headingMapper: {
|
||||
type: 'All',
|
||||
label: 'All',
|
||||
hasMastersTrack: false,
|
||||
breakdown: { getExampleSectionBreakdown: testState },
|
||||
},
|
||||
});
|
||||
@@ -318,10 +325,27 @@ describe('root selectors', () => {
|
||||
it('maps selected filters into getExampleSectionBreakdown', () => {
|
||||
selectors.filters.assignmentType.mockReturnValue(mockAssignmentType);
|
||||
selectors.filters.selectedAssignmentLabel.mockReturnValue(mockAssignmentLabel);
|
||||
selectors.tracks.stateHasMastersTrack.mockReturnValue(false);
|
||||
expect(selector(testState)).toEqual({
|
||||
headingMapper: {
|
||||
type: mockAssignmentType,
|
||||
label: mockAssignmentLabel,
|
||||
hasMastersTrack: false,
|
||||
breakdown: { getExampleSectionBreakdown: testState },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('has masters track', () => {
|
||||
it('maps selected filters into getExampleSectionBreakdown', () => {
|
||||
selectors.filters.assignmentType.mockReturnValue(undefined);
|
||||
selectors.filters.selectedAssignmentLabel.mockReturnValue(undefined);
|
||||
selectors.tracks.stateHasMastersTrack.mockReturnValue(true);
|
||||
expect(selector(testState)).toEqual({
|
||||
headingMapper: {
|
||||
type: 'All',
|
||||
label: 'All',
|
||||
hasMastersTrack: true,
|
||||
breakdown: { getExampleSectionBreakdown: testState },
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user