Compare commits

..

8 Commits

Author SHA1 Message Date
Simon Chen
dd82054bbc Merge pull request #39 from edx/schen/setup-test
feat(test): Setup unit testing
2018-12-05 14:20:58 -05:00
Jansen Kantor
6a4bc67841 Merge pull request #38 from edx/encoding
fix(UI) specify utf8 to avoid incorrect character rendering
2018-12-05 14:15:51 -05:00
Simon Chen
adfefac85d feat(test): Setup unit testing 2018-12-05 13:52:33 -05:00
jkantor
c92144c436 fix(UI) specify utf8 to avoid incorrect character rendering 2018-12-05 13:35:28 -05:00
Jansen Kantor
ca0156ea4c Merge pull request #36 from edx/rounded-percents
fix(UI) rounded percentages to two decimal places
2018-12-05 13:33:38 -05:00
jkantor
61c4bc11bd fix(UI) rounded percentages to two decimal places 2018-12-05 10:53:55 -05:00
Jansen Kantor
db25a18f9d Merge pull request #35 from edx/updateMessage-filter
fix(UI) box should appear after editing grade
2018-12-04 14:01:05 -05:00
jkantor
0d7fa18acd fix(UI) box should appear after editing grade 2018-12-04 13:38:27 -05:00
9 changed files with 103 additions and 6 deletions

View File

@@ -30,3 +30,6 @@ restart-detached:
validate-no-uncommitted-package-lock-changes:
git diff --exit-code package-lock.json
test:
docker exec -it edx.gradebook jest

9
package-lock.json generated
View File

@@ -4161,6 +4161,15 @@
"is-buffer": "^1.1.5"
}
},
"axios-mock-adapter": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.15.0.tgz",
"integrity": "sha1-+8BoJdgwLJXDM00hAju6mWJV1F0=",
"dev": true,
"requires": {
"deep-equal": "^1.0.1"
}
},
"axobject-query": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-0.1.0.tgz",

View File

@@ -47,6 +47,7 @@
"whatwg-fetch": "^2.0.3"
},
"devDependencies": {
"axios-mock-adapter": "^1.15.0",
"babel-cli": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-jest": "^22.4.0",

View File

@@ -1,6 +1,8 @@
<!doctype html>
<html>
<head></head>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="root"></div>
</body>

View File

@@ -11,6 +11,8 @@ import {
import queryString from 'query-string';
import { configuration } from '../../config';
const DECIMAL_PRECISION = 2;
export default class Gradebook extends React.Component {
constructor(props) {
super(props);
@@ -174,6 +176,8 @@ export default class Gradebook extends React.Component {
return 'Tracks';
};
roundPercentageGrade = percent => parseFloat(percent.toFixed(DECIMAL_PRECISION));
formatter = {
percent: entries => entries.map((entry) => {
const results = { username: entry.username };
@@ -185,11 +189,11 @@ export default class Gradebook extends React.Component {
className="btn btn-header link-style"
onClick={() => this.setNewModalState(entry, subsection)}
>
{subsection.percent * 100}%
{this.roundPercentageGrade(subsection.percent * 100)}%
</button>);
return acc;
}, {});
const totals = { total: `${entry.percent * 100}%` };
const totals = { total: `${this.roundPercentageGrade(entry.percent * 100)}%` };
return Object.assign(results, assignments, totals);
}),

View File

@@ -37,7 +37,7 @@ const mapDispatchToProps = dispatch => (
dispatch(fetchGrades(courseId, cohort, track));
},
searchForUser: (courseId, searchText, cohort, track) => {
dispatch(fetchMatchingUserGrades(courseId, searchText, cohort, track));
dispatch(fetchMatchingUserGrades(courseId, searchText, cohort, track, false));
},
getPrevNextGrades: (endpoint, cohort, track) => {
dispatch(fetchPrevNextGrades(endpoint, cohort, track));

View File

@@ -0,0 +1,73 @@
import configureMockStore from 'redux-mock-store';
import MockAdapter from 'axios-mock-adapter';
import thunk from 'redux-thunk';
import apiClient from '../apiClient';
import { fetchCohorts } from './cohorts';
import {
STARTED_FETCHING_COHORTS,
GOT_COHORTS,
ERROR_FETCHING_COHORTS,
} from '../constants/actionTypes/cohorts';
const mockStore = configureMockStore([thunk]);
const axiosMock = new MockAdapter(apiClient);
describe('actions', () => {
afterEach(() => {
axiosMock.reset();
});
describe('fetchCohorts', () => {
const courseId = 'course-v1:edX+DemoX+Demo_Course';
it('dispatches success action after fetching cohorts', () => {
const responseData = {
cohorts: [
{
assignment_type: 'manual',
group_id: null,
id: 1,
name: 'default_group',
user_count: 2,
user_partition_id: null,
},
{
assignment_type: 'auto',
group_id: null,
id: 2,
name: 'auto_group',
user_count: 5,
user_partition_id: null,
}],
};
const expectedActions = [
{ type: STARTED_FETCHING_COHORTS },
{ type: GOT_COHORTS, cohorts: responseData.cohorts },
];
const store = mockStore();
axiosMock.onGet(`http://localhost:18000/courses/${courseId}/cohorts/`)
.replyOnce(200, JSON.stringify(responseData));
return store.dispatch(fetchCohorts(courseId)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
it('dispatches failure action after fetching cohorts', () => {
const expectedActions = [
{ type: STARTED_FETCHING_COHORTS },
{ type: ERROR_FETCHING_COHORTS },
];
const store = mockStore();
axiosMock.onGet(`http://localhost:18000/courses/${courseId}/cohorts/`)
.replyOnce(500, JSON.stringify({}));
return store.dispatch(fetchCohorts(courseId)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});
});
});

View File

@@ -87,7 +87,7 @@ const fetchGrades = (courseId, cohort, track, showSuccess) => (
}
);
const fetchMatchingUserGrades = (courseId, searchText, cohort, track) => (
const fetchMatchingUserGrades = (courseId, searchText, cohort, track, showSuccess) => (
(dispatch) => {
dispatch(startedFetchingGrades());
return LmsApiService.fetchGradebookData(courseId, searchText, cohort, track)
@@ -102,6 +102,7 @@ const fetchMatchingUserGrades = (courseId, searchText, cohort, track) => (
data.next,
));
dispatch(finishedFetchingGrades());
dispatch(updateBanner(showSuccess));
})
.catch(() => {
dispatch(errorFetchingGrades());
@@ -139,7 +140,7 @@ const updateGrades = (courseId, updateData, searchText, cohort, track) => (
.then(response => response.data)
.then((data) => {
dispatch(gradeUpdateSuccess(data));
dispatch(fetchMatchingUserGrades(courseId, searchText, cohort, track));
dispatch(fetchMatchingUserGrades(courseId, searchText, cohort, track, true));
})
.catch((error) => {
dispatch(gradeUpdateFailure(error));

View File

@@ -4,3 +4,7 @@ import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// These configuration values are usually set in webpack's EnvironmentPlugin however
// Jest does not use webpack so we need to set these so for testing
process.env.LMS_BASE_URL = 'http://localhost:18000';