include “Term” column in course search results
Closes: CNVS-39755 CNVS-39647 Test plan: * enable user/course search feature flag * go to /accounts/x * on the “Courses” tab, there should be a “Term” Column on the results table * clicking it should sort the results by term name properly Change-Id: Idb27356f6eeb66380f739b8d4550cf2fdd908dc2 Reviewed-on: https://gerrit.instructure.com/128347 Tested-by: Jenkins Reviewed-by: Clay Diffrient <cdiffrient@instructure.com> Product-Review: Ryan Shaw <ryan@instructure.com> QA-Review: Ryan Shaw <ryan@instructure.com>
This commit is contained in:
parent
ce29dd4fe0
commit
aac714911f
|
@ -378,6 +378,10 @@ class AccountsController < ApplicationController
|
|||
"(SELECT #{name_col} FROM #{Account.quoted_table_name}
|
||||
WHERE #{Account.quoted_table_name}.id
|
||||
= #{Course.quoted_table_name}.account_id)"
|
||||
elsif params[:sort] == 'term'
|
||||
"(SELECT #{EnrollmentTerm.quoted_table_name}.name FROM #{EnrollmentTerm.quoted_table_name}
|
||||
WHERE #{EnrollmentTerm.quoted_table_name}.id
|
||||
= #{Course.quoted_table_name}.enrollment_term_id)"
|
||||
else
|
||||
"id"
|
||||
end
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
*/
|
||||
|
||||
import preventDefault from 'compiled/fn/preventDefault'
|
||||
import IconArrowUpSolid from 'instructure-icons/lib/Solid/IconArrowUpSolid'
|
||||
import IconArrowDownSolid from 'instructure-icons/lib/Solid/IconArrowDownSolid'
|
||||
import Typography from 'instructure-ui/lib/components/Typography'
|
||||
import IconMiniArrowUpSolid from 'instructure-icons/lib/Solid/IconMiniArrowUpSolid'
|
||||
import IconMiniArrowDownSolid from 'instructure-icons/lib/Solid/IconMiniArrowDownSolid'
|
||||
import Link from 'instructure-ui/lib/components/Link'
|
||||
import Tooltip from 'instructure-ui/lib/components/Tooltip'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
@ -68,91 +68,24 @@ class CoursesList extends React.Component {
|
|||
})
|
||||
}
|
||||
|
||||
renderHeader ({id, label, tipDesc, tipAsc}) {
|
||||
return (
|
||||
|
||||
<Tooltip
|
||||
as={Link}
|
||||
tip={(this.props.sort === id && this.props.order === 'asc') ? tipAsc : tipDesc}
|
||||
onClick={preventDefault(() => this.props.onChangeSort(id))}
|
||||
>
|
||||
{label}
|
||||
{this.props.sort === id ?
|
||||
(this.props.order === 'asc' ? <IconMiniArrowDownSolid /> : <IconMiniArrowUpSolid />) :
|
||||
''
|
||||
}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const sort = this.props.sort
|
||||
const order = this.props.order
|
||||
|
||||
const courseLabel = I18n.t('Course')
|
||||
const idLabel = I18n.t('SIS ID')
|
||||
const teacherLabel = I18n.t('Teacher')
|
||||
const enrollmentsLabel = I18n.t('Enrollments')
|
||||
const subaccountLabel = I18n.t('Sub-Account')
|
||||
|
||||
let courseTip
|
||||
let idTip
|
||||
let teacherTip
|
||||
let enrollmentsTip
|
||||
let subaccountTip
|
||||
|
||||
let courseArrow = ''
|
||||
let idArrow = ''
|
||||
let teacherArrow = ''
|
||||
let enrollmentsArrow = ''
|
||||
let subaccountArrow = ''
|
||||
|
||||
if (sort === 'course_name') {
|
||||
idTip = I18n.t('Click to sort by SIS ID ascending')
|
||||
teacherTip = I18n.t('Click to sort by teacher ascending')
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments ascending')
|
||||
subaccountTip = I18n.t('Click to sort by subaccount ascending')
|
||||
if (order === 'asc') {
|
||||
courseTip = I18n.t('Click to sort by name descending')
|
||||
courseArrow = <IconArrowDownSolid />
|
||||
} else {
|
||||
courseTip = I18n.t('Click to sort by name ascending')
|
||||
courseArrow = <IconArrowUpSolid />
|
||||
}
|
||||
} else if (sort === 'sis_course_id') {
|
||||
courseTip = I18n.t('Click to sort by name ascending')
|
||||
teacherTip = I18n.t('Click to sort by teacher ascending')
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments ascending')
|
||||
subaccountTip = I18n.t('Click to sort by subaccount ascending')
|
||||
if (order === 'asc') {
|
||||
idTip = I18n.t('Click to sort by SIS ID descending')
|
||||
idArrow = <IconArrowDownSolid />
|
||||
} else {
|
||||
idTip = I18n.t('Click to sort by SIS ID ascending')
|
||||
idArrow = <IconArrowUpSolid />
|
||||
}
|
||||
} else if (sort === 'teacher') {
|
||||
courseTip = I18n.t('Click to sort by name ascending')
|
||||
idTip = I18n.t('Click to sort by SIS ID ascending')
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments ascending')
|
||||
subaccountTip = I18n.t('Click to sort by subaccount ascending')
|
||||
if (order === 'asc') {
|
||||
teacherTip = I18n.t('Click to sort by teacher descending')
|
||||
teacherArrow = <IconArrowDownSolid />
|
||||
} else {
|
||||
teacherTip = I18n.t('Click to sort by teacher ascending')
|
||||
teacherArrow = <IconArrowUpSolid />
|
||||
}
|
||||
} else if (sort === 'enrollments') {
|
||||
courseTip = I18n.t('Click to sort by name ascending')
|
||||
idTip = I18n.t('Click to sort by SIS ID ascending')
|
||||
teacherTip = I18n.t('Click to sort by teacher ascending')
|
||||
subaccountTip = I18n.t('Click to sort by subaccount ascending')
|
||||
if (order === 'asc') {
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments descending')
|
||||
enrollmentsArrow = <IconArrowDownSolid />
|
||||
} else {
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments ascending')
|
||||
enrollmentsArrow = <IconArrowUpSolid />
|
||||
}
|
||||
} else if (sort === 'subaccount') {
|
||||
courseTip = I18n.t('Click to sort by name ascending')
|
||||
idTip = I18n.t('Click to sort by SIS ID ascending')
|
||||
teacherTip = I18n.t('Click to sort by teacher ascending')
|
||||
enrollmentsTip = I18n.t('Click to sort by enrollments ascending')
|
||||
if (order === 'asc') {
|
||||
subaccountTip = I18n.t('Click to sort by subaccount descending')
|
||||
subaccountArrow = <IconArrowDownSolid />
|
||||
} else {
|
||||
subaccountTip = I18n.t('Click to sort by subaccount ascending')
|
||||
subaccountArrow = <IconArrowUpSolid />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const courses = this.props.courses
|
||||
|
||||
return (
|
||||
|
@ -162,71 +95,54 @@ class CoursesList extends React.Component {
|
|||
<div className="grid-row">
|
||||
<div className="col-xs-2" />
|
||||
<div className="col-xs-10" role="columnheader">
|
||||
<a
|
||||
role="button"
|
||||
href=""
|
||||
className="courses-user-list-header"
|
||||
onClick={preventDefault(() => this.props.onChangeSort('course_name'))}
|
||||
>
|
||||
<Tooltip as={Typography} tip={courseTip}>
|
||||
{courseLabel}
|
||||
{courseArrow}
|
||||
</Tooltip>
|
||||
</a>
|
||||
{this.renderHeader({
|
||||
id: 'course_name',
|
||||
label: I18n.t('Course'),
|
||||
tipDesc: I18n.t('Click to sort by name ascending'),
|
||||
tipAsc: I18n.t('Click to sort by name descending')
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-1">
|
||||
<a
|
||||
role="button"
|
||||
href=""
|
||||
className="courses-user-list-header"
|
||||
onClick={preventDefault(() => this.props.onChangeSort('sis_course_id'))}
|
||||
>
|
||||
<Tooltip as={Typography} tip={idTip}>
|
||||
{idLabel}
|
||||
{idArrow}
|
||||
</Tooltip>
|
||||
</a>
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-2">
|
||||
<a
|
||||
role="button"
|
||||
href=""
|
||||
className="courses-user-list-header"
|
||||
onClick={preventDefault(() => this.props.onChangeSort('teacher'))}
|
||||
>
|
||||
<Tooltip as={Typography} tip={teacherTip}>
|
||||
{teacherLabel}
|
||||
{teacherArrow}
|
||||
</Tooltip>
|
||||
</a>
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-2">
|
||||
<a
|
||||
role="button"
|
||||
href=""
|
||||
className="courses-user-list-header"
|
||||
onClick={preventDefault(() => this.props.onChangeSort('subaccount'))}
|
||||
>
|
||||
<Tooltip as={Typography} tip={subaccountTip}>
|
||||
{subaccountLabel}
|
||||
{subaccountArrow}
|
||||
</Tooltip>
|
||||
</a>
|
||||
{this.renderHeader({
|
||||
id: 'sis_course_id',
|
||||
label: I18n.t('SIS ID'),
|
||||
tipDesc: I18n.t('Click to sort by SIS ID ascending'),
|
||||
tipAsc: I18n.t('Click to sort by SIS ID descending')
|
||||
})}
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-1">
|
||||
<a
|
||||
role="button"
|
||||
href=""
|
||||
className="courses-user-list-header"
|
||||
onClick={preventDefault(() => this.props.onChangeSort('enrollments'))}
|
||||
>
|
||||
<Tooltip as={Typography} tip={enrollmentsTip}>
|
||||
{enrollmentsLabel}
|
||||
{enrollmentsArrow}
|
||||
</Tooltip>
|
||||
</a>
|
||||
{this.renderHeader({
|
||||
id: 'term',
|
||||
label: I18n.t('Term'),
|
||||
tipDesc: I18n.t('Click to sort by term ascending'),
|
||||
tipAsc: I18n.t('Click to sort by term descending')
|
||||
})}
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-2">
|
||||
{this.renderHeader({
|
||||
id: 'teacher',
|
||||
label: I18n.t('Teacher'),
|
||||
tipDesc: I18n.t('Click to sort by teacher ascending'),
|
||||
tipAsc: I18n.t('Click to sort by teacher descending')
|
||||
})}
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-2">
|
||||
{this.renderHeader({
|
||||
id: 'subaccount',
|
||||
label: I18n.t('Sub-Account'),
|
||||
tipDesc: I18n.t('Click to sort by sub-account ascending'),
|
||||
tipAsc: I18n.t('Click to sort by sub-account descending')
|
||||
})}
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-1">
|
||||
{this.renderHeader({
|
||||
id: 'enrollments',
|
||||
label: I18n.t('Enrollments'),
|
||||
tipDesc: I18n.t('Click to sort by enrollments ascending'),
|
||||
tipAsc: I18n.t('Click to sort by enrollments descending')
|
||||
})}
|
||||
</div>
|
||||
<div role="columnheader" className="col-xs-2">
|
||||
<span className="screenreader-only">{I18n.t('Course option links')}</span>
|
||||
|
|
|
@ -41,6 +41,7 @@ class CoursesListRow extends React.Component {
|
|||
teachers: arrayOf(shape(UserLink.propTypes)).isRequired,
|
||||
sis_course_id: string.isRequired,
|
||||
subaccount_name: string.isRequired,
|
||||
term: shape({name: string.isRequired}).isRequired,
|
||||
urls: shape({ ENROLL_USERS_URL: string.isRequired, USER_LISTS_URL: string.isRequired }),
|
||||
roles: arrayOf(shape({ id: string.isRequired })),
|
||||
sections: arrayOf(shape(UserLink.propTypes)),
|
||||
|
@ -145,6 +146,10 @@ class CoursesListRow extends React.Component {
|
|||
<div className="courseSIS">{sis_course_id}</div>
|
||||
</div>
|
||||
|
||||
<div className="col-xs-1" role="gridcell">
|
||||
<div className="courseSIS">{this.props.term.name}</div>
|
||||
</div>
|
||||
|
||||
<div className="col-xs-2" role="gridcell">
|
||||
{this.state.teachersToShow && this.state.teachersToShow.map(teacher => <UserLink key={teacher.id} {...teacher} />)}
|
||||
{ this.showMoreLink() }
|
||||
|
|
|
@ -31,7 +31,7 @@ const CoursesStore = createStore({
|
|||
if (params.sort) payload.sort = params.sort
|
||||
if (params.order) payload.order = params.order
|
||||
if (params.search_by) payload.search_by = params.search_by
|
||||
payload.include = ['total_students', 'teachers', 'subaccount']
|
||||
payload.include = ['total_students', 'teachers', 'subaccount', 'term']
|
||||
|
||||
return payload
|
||||
}
|
||||
|
|
|
@ -921,6 +921,33 @@ describe AccountsController do
|
|||
expect(response.body).to match(/\"sis_course_id\":\"30\".+\"sis_course_id\":\"31\".+\"sis_course_id\":\"42\".+\"sis_course_id\":\"52\"/)
|
||||
end
|
||||
|
||||
context "sorting by term" do
|
||||
let(:letters_in_random_order) { 'daqwds'.split('') }
|
||||
before do
|
||||
@account = Account.create!
|
||||
create_courses(letters_in_random_order.map { |i|
|
||||
{enrollment_term_id: @account.enrollment_terms.create!(name: i).id}
|
||||
}, account: @account)
|
||||
admin_logged_in(@account)
|
||||
end
|
||||
|
||||
it "should be able to sort courses by term ascending" do
|
||||
get 'courses_api', params: {account_id: @account.id, sort: "term", order: "asc", include: ['term']}
|
||||
|
||||
expect(response).to be_success
|
||||
term_names = json_parse(response.body).map{|c| c['term']['name']}
|
||||
expect(term_names).to eq(letters_in_random_order.sort)
|
||||
end
|
||||
|
||||
it "should be able to sort courses by term descending" do
|
||||
get 'courses_api', params: {account_id: @account.id, sort: "term", order: "desc", include: ['term']}
|
||||
|
||||
expect(response).to be_success
|
||||
term_names = json_parse(response.body).map{|c| c['term']['name']}
|
||||
expect(term_names).to eq(letters_in_random_order.sort.reverse)
|
||||
end
|
||||
end
|
||||
|
||||
it "should be able to sort courses by enrollments ascending" do
|
||||
@c3 = course_factory(account: @account, course_name: "apple", sis_source_id: 30)
|
||||
|
||||
|
|
|
@ -32,7 +32,10 @@ const props = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
term:{
|
||||
name: "Testing Term"
|
||||
}
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
|
@ -45,7 +48,7 @@ const props = {
|
|||
base_role_type: 'StudentEnrollment'
|
||||
}]
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
test('renders with the proper urls and roles', () => {
|
||||
const wrapper = shallow(<CoursesList {...props} />)
|
||||
|
@ -69,9 +72,11 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
},
|
||||
{
|
||||
}],
|
||||
term: {
|
||||
name: "A Term"
|
||||
}
|
||||
}, {
|
||||
id: '2',
|
||||
name: 'Ba',
|
||||
workflow_state: 'alive',
|
||||
|
@ -79,9 +84,11 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
},
|
||||
{
|
||||
}],
|
||||
term: {
|
||||
name: "Ba Term"
|
||||
}
|
||||
}, {
|
||||
id: '3',
|
||||
name: 'Bb',
|
||||
workflow_state: 'alive',
|
||||
|
@ -89,9 +96,11 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
},
|
||||
{
|
||||
}],
|
||||
term: {
|
||||
name: "Bb Term"
|
||||
}
|
||||
}, {
|
||||
id: '4',
|
||||
name: 'C',
|
||||
workflow_state: 'alive',
|
||||
|
@ -99,9 +108,11 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
},
|
||||
{
|
||||
}],
|
||||
term: {
|
||||
name: "C Term"
|
||||
}
|
||||
}, {
|
||||
id: '5',
|
||||
name: 'De',
|
||||
workflow_state: 'alive',
|
||||
|
@ -109,9 +120,11 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
},
|
||||
{
|
||||
}],
|
||||
term: {
|
||||
name: "De Term"
|
||||
}
|
||||
}, {
|
||||
id: '6',
|
||||
name: 'Dz',
|
||||
workflow_state: 'alive',
|
||||
|
@ -119,7 +132,10 @@ const coursesProps = {
|
|||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
term: {
|
||||
name: "Dz Term"
|
||||
}
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
|
@ -136,10 +152,66 @@ const coursesProps = {
|
|||
order: 'asc'
|
||||
};
|
||||
|
||||
test('displays courses that are passed in as props', () => {
|
||||
Object.entries({
|
||||
course_name: 'Course',
|
||||
sis_course_id: 'SIS ID',
|
||||
term: 'Term',
|
||||
teacher: 'Teacher',
|
||||
subaccount: 'Sub-Account',
|
||||
enrollments: 'Enrollments'
|
||||
}).forEach(([columnID, label]) => {
|
||||
|
||||
test(`sorting by ${columnID} asc puts down-arrow on ${label} only`, () => {
|
||||
const wrapper = shallow(<CoursesList {...{
|
||||
...coursesProps,
|
||||
sort: columnID,
|
||||
order: 'asc'
|
||||
}} />)
|
||||
equal(wrapper.find('IconMiniArrowUpSolid').length, 0, 'no columns have an up arrow')
|
||||
const icons = wrapper.find('IconMiniArrowDownSolid')
|
||||
equal(icons.length, 1, 'only one down arrow')
|
||||
const header = icons.first().parents('Tooltip')
|
||||
let expectedTip = `Click to sort by ${label} descending`
|
||||
if (columnID === 'course_name') {
|
||||
expectedTip = 'Click to sort by name descending'
|
||||
}
|
||||
ok(header.prop('tip').match(RegExp(expectedTip, 'i')), 'has right tooltip')
|
||||
ok(header.contains(label), `${label} is the one that has the down arrow`)
|
||||
})
|
||||
|
||||
test(`sorting by ${columnID} desc puts up-arrow on ${label} only`, () => {
|
||||
const wrapper = shallow(<CoursesList {...{
|
||||
...coursesProps,
|
||||
sort: columnID,
|
||||
order: 'desc'
|
||||
}} />)
|
||||
equal(wrapper.find('IconMiniArrowDownSolid').length, 0)
|
||||
const icons = wrapper.find('IconMiniArrowUpSolid', 'no columns have a down arrow')
|
||||
equal(icons.length, 1, 'only one up arrow')
|
||||
const header = icons.first().parents('Tooltip')
|
||||
let expectedTip = `Click to sort by ${label} ascending`
|
||||
if (columnID === 'course_name') {
|
||||
expectedTip = 'Click to sort by name ascending'
|
||||
}
|
||||
ok(header.prop('tip').match(RegExp(expectedTip, 'i')), 'has right tooltip')
|
||||
ok(header.contains(label), `${label} is the one that has the up arrow`)
|
||||
})
|
||||
|
||||
test(`clicking the ${label} column header calls onChangeSort with ${columnID}`, function() {
|
||||
const sortSpy = this.spy()
|
||||
const wrapper = shallow(<CoursesList {...{
|
||||
...coursesProps,
|
||||
onChangeSort: sortSpy
|
||||
}} />)
|
||||
const header = wrapper.findWhere(n => n.text() === label).first().parents('Tooltip')
|
||||
header.simulate('click')
|
||||
ok(sortSpy.calledOnce)
|
||||
ok(sortSpy.calledWith(columnID))
|
||||
})
|
||||
})
|
||||
|
||||
test('displays courses in the right order', () => {
|
||||
const wrapper = shallow(<CoursesList {...coursesProps} />)
|
||||
|
||||
const renderedList = wrapper.find(CoursesListRow)
|
||||
|
||||
equal(renderedList.nodes[0].props.name, 'A')
|
||||
|
@ -157,186 +229,13 @@ test('displays courses that are passed in as props', () => {
|
|||
equal(renderedList.nodes[5].props.id, '6')
|
||||
});
|
||||
|
||||
test('sorting by course name ascending puts down-arrow on Name', () => {
|
||||
const wrapper = shallow(<CoursesList {...coursesProps} />)
|
||||
const header = wrapper.find('a')
|
||||
equal(header.nodes[0].props.children.props.children[1].type.name, 'IconArrowDownSolid')
|
||||
});
|
||||
test('displays Terms in right order', () => {
|
||||
const renderedList = shallow(<CoursesList {...coursesProps} />).find(CoursesListRow)
|
||||
|
||||
|
||||
const descIdSinonProps = {
|
||||
courses: [{
|
||||
id: '1',
|
||||
name: 'A',
|
||||
workflow_state: 'alive',
|
||||
total_students: 6,
|
||||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
ENROLL_USERS_URL: 'http://courses/{{id}}/users/enroll'
|
||||
},
|
||||
sort: 'sis_course_id',
|
||||
order: 'desc',
|
||||
onChangeSort: sinon.spy(),
|
||||
};
|
||||
|
||||
test('sorting by id descending puts up-arrow on SIS ID', () => {
|
||||
const wrapper = shallow(<CoursesList {...descIdSinonProps} />)
|
||||
const header = wrapper.find('a')
|
||||
equal(header.nodes[1].props.children.props.children[1].type.name, 'IconArrowUpSolid')
|
||||
});
|
||||
|
||||
test('clicking the Courses column header calls onChangeSort with course_name', () => {
|
||||
const wrapper = shallow(<CoursesList {...descIdSinonProps} />)
|
||||
const header = wrapper.find('a').first()
|
||||
header.simulate('click')
|
||||
|
||||
const sinonCallback = wrapper.unrendered.props.onChangeSort
|
||||
ok(sinonCallback.calledOnce)
|
||||
ok(sinonCallback.calledWith('course_name'))
|
||||
});
|
||||
|
||||
|
||||
const moreSinonProps = {
|
||||
courses: [{
|
||||
id: '1',
|
||||
name: 'A',
|
||||
workflow_state: 'alive',
|
||||
total_students: 6,
|
||||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
ENROLL_USERS_URL: 'http://courses/{{id}}/users/enroll'
|
||||
},
|
||||
sort: 'sis_course_id',
|
||||
order: 'desc',
|
||||
onChangeSort: sinon.spy(),
|
||||
};
|
||||
|
||||
test('clicking the SIS ID column header calls onChangeSort with sis_source_id', () => {
|
||||
const wrapper = shallow(<CoursesList {...moreSinonProps} />)
|
||||
const header = wrapper.find('a').slice(1, 2)
|
||||
header.simulate('click')
|
||||
header.simulate('click')
|
||||
header.simulate('click')
|
||||
|
||||
const sinonCallback = wrapper.unrendered.props.onChangeSort
|
||||
ok(sinonCallback.callCount === 3)
|
||||
ok(sinonCallback.calledWith('sis_course_id'))
|
||||
});
|
||||
|
||||
const teacherSinonProps = {
|
||||
courses: [{
|
||||
id: '1',
|
||||
name: 'A',
|
||||
workflow_state: 'alive',
|
||||
total_students: 6,
|
||||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
ENROLL_USERS_URL: 'http://courses/{{id}}/users/enroll'
|
||||
},
|
||||
sort: 'teacher',
|
||||
order: 'asc',
|
||||
onChangeSort: sinon.spy(),
|
||||
};
|
||||
|
||||
test('sorting by teacher ascending puts down-arrow on Teacher', () => {
|
||||
const wrapper = shallow(<CoursesList {...teacherSinonProps} />)
|
||||
const header = wrapper.find('a')
|
||||
equal(header.nodes[2].props.children.props.children[1].type.name, 'IconArrowDownSolid')
|
||||
});
|
||||
|
||||
test('clicking the Teacher column header calls onChangeSort with teacher', () => {
|
||||
const wrapper = shallow(<CoursesList {...teacherSinonProps} />)
|
||||
const header = wrapper.find('a').slice(2, 3)
|
||||
header.simulate('click')
|
||||
|
||||
const sinonCallback = wrapper.unrendered.props.onChangeSort
|
||||
ok(sinonCallback.calledOnce)
|
||||
ok(sinonCallback.calledWith('teacher'))
|
||||
});
|
||||
|
||||
const subaccountSinonProps = {
|
||||
courses: [{
|
||||
id: '1',
|
||||
name: 'A',
|
||||
workflow_state: 'alive',
|
||||
total_students: 6,
|
||||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
ENROLL_USERS_URL: 'http://courses/{{id}}/users/enroll'
|
||||
},
|
||||
sort: 'subaccount',
|
||||
order: 'asc',
|
||||
onChangeSort: sinon.spy(),
|
||||
};
|
||||
|
||||
test('sorting by subaccount ascending puts down-arrow on Enrollments', () => {
|
||||
const wrapper = shallow(<CoursesList {...subaccountSinonProps} />)
|
||||
const header = wrapper.find('a')
|
||||
equal(header.nodes[3].props.children.props.children[1].type.name, 'IconArrowDownSolid')
|
||||
});
|
||||
|
||||
test('clicking the Enrollments column header calls onChangeSort with enrollments', () => {
|
||||
const wrapper = shallow(<CoursesList {...subaccountSinonProps} />)
|
||||
const header = wrapper.find('a').slice(3, 4)
|
||||
header.simulate('click')
|
||||
|
||||
const sinonCallback = wrapper.unrendered.props.onChangeSort
|
||||
ok(sinonCallback.calledOnce)
|
||||
ok(sinonCallback.calledWith('subaccount'))
|
||||
});
|
||||
|
||||
const enrollmentsSinonProps = {
|
||||
courses: [{
|
||||
id: '1',
|
||||
name: 'A',
|
||||
workflow_state: 'alive',
|
||||
total_students: 6,
|
||||
teachers: [{
|
||||
id: '1',
|
||||
display_name: 'Testing Teacher'
|
||||
}]
|
||||
}],
|
||||
addUserUrls: {
|
||||
USER_LISTS_URL: 'http://courses/{{id}}/users',
|
||||
ENROLL_USERS_URL: 'http://courses/{{id}}/users/enroll'
|
||||
},
|
||||
sort: 'enrollments',
|
||||
order: 'asc',
|
||||
onChangeSort: sinon.spy(),
|
||||
};
|
||||
|
||||
test('sorting by enrollments ascending puts down-arrow on Enrollments', () => {
|
||||
const wrapper = shallow(<CoursesList {...enrollmentsSinonProps} />)
|
||||
const header = wrapper.find('a')
|
||||
equal(header.nodes[4].props.children.props.children[1].type.name, 'IconArrowDownSolid')
|
||||
});
|
||||
|
||||
test('clicking the Enrollments column header calls onChangeSort with enrollments', () => {
|
||||
const wrapper = shallow(<CoursesList {...enrollmentsSinonProps} />)
|
||||
const header = wrapper.find('a').slice(4, 5)
|
||||
header.simulate('click')
|
||||
|
||||
const sinonCallback = wrapper.unrendered.props.onChangeSort
|
||||
ok(sinonCallback.calledOnce)
|
||||
ok(sinonCallback.calledWith('enrollments'))
|
||||
});
|
||||
equal(renderedList.nodes[0].props.term.name, 'A Term')
|
||||
equal(renderedList.nodes[1].props.term.name, 'Ba Term')
|
||||
equal(renderedList.nodes[2].props.term.name, 'Bb Term')
|
||||
equal(renderedList.nodes[3].props.term.name, 'C Term')
|
||||
equal(renderedList.nodes[4].props.term.name, 'De Term')
|
||||
equal(renderedList.nodes[5].props.term.name, 'Dz Term')
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue