export current gradebook view
flag=enhanced_gradebook_filters closes EVAL-2288 Test Plan: - Course w/ teacher, students, and graded assignments - Fill gradebook with recognizable data - Create Sections, Modules, and Student Groups to filter down the gradebook - Repeat all of the following steps with enhanced_gradebook_filters ON and OFF - Navigate to the gradebook and put any combination of filters On the gradebook - Navigate to the Export (ON) or Actions (OFF) menu and select 'Export Current Gradebook View' - Ensure only the assignments and students currently shown in the filtered gradebook are exported along with all of the totals columns displayed - Navigate to the Export (ON) or Actions (OFF) menu and select 'Export Entire Gradebook' - Ensure all assignments and students are exported regardless of filters applied to the gradebook WITH the totals columns - Create grading periods and associate it with the course - Navigate to the Export (ON) or Actions (OFF) menu and select 'Export Entire Gradebook' - Ensure all assignments and students are exported regardless of filters applied to the gradebook WITHOUT the totals columns - Ensure the 'Export Current Gradebook View' option works the same with grading periods and also respects that filter option Change-Id: Iad3f030c1c26fd770885550a0912d42b975bb648 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/288884 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> QA-Review: Aaron Shafovaloff <ashafovaloff@instructure.com> Product-Review: Jody Sailor Reviewed-by: Syed Hussain <shussain@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com>
This commit is contained in:
parent
9b3455f072
commit
d3058972f9
|
@ -30,7 +30,9 @@ class GradebookCsvsController < ApplicationController
|
|||
|
||||
csv_options = {
|
||||
include_sis_id: @context.grants_any_right?(@current_user, session, :read_sis, :manage_sis),
|
||||
grading_period_id: params[:grading_period_id]
|
||||
grading_period_id: params[:grading_period_id],
|
||||
student_order: params[:student_order],
|
||||
current_view: params[:current_view]
|
||||
}
|
||||
|
||||
if params[:assignment_order]
|
||||
|
|
|
@ -90,7 +90,11 @@ class GradebookExporter
|
|||
end
|
||||
|
||||
# remove duplicate enrollments for students enrolled in multiple sections
|
||||
student_enrollments = student_enrollments.uniq(&:user_id)
|
||||
student_enrollments = if @options[:current_view]
|
||||
student_enrollments.select { |s| @options[:student_order].include?(s[:user_id]) }.uniq(&:user_id)
|
||||
else
|
||||
student_enrollments.uniq(&:user_id)
|
||||
end
|
||||
|
||||
# TODO: Stop using the grade calculator and instead use the scores table entirely.
|
||||
# This cannot be done until we are storing points values in the scores table, which
|
||||
|
@ -105,8 +109,12 @@ class GradebookExporter
|
|||
|
||||
submissions = {}
|
||||
calc.submissions.each { |s| submissions[[s.user_id, s.assignment_id]] = s }
|
||||
assignments = if @options[:current_view]
|
||||
calc.gradable_assignments.select { |a| @options[:assignment_order].include?(a[:id]) }
|
||||
else
|
||||
calc.gradable_assignments
|
||||
end
|
||||
|
||||
assignments = select_in_grading_period(calc.gradable_assignments).to_a
|
||||
Assignment.preload_unposted_anonymous_submissions(assignments)
|
||||
|
||||
ActiveRecord::Associations.preload(assignments, :assignment_group)
|
||||
|
@ -390,6 +398,7 @@ class GradebookExporter
|
|||
end
|
||||
|
||||
def show_totals?
|
||||
return false if !@options[:current_view] && @course.grading_periods?
|
||||
return true unless @course.grading_periods?
|
||||
return true if @options[:grading_period_id].try(:to_i) != 0
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import ActionMenu from 'ui/features/gradebook/react/default_gradebook/components
|
|||
|
||||
const workingMenuProps = () => ({
|
||||
getAssignmentOrder() {},
|
||||
getStudentOrder() {},
|
||||
gradebookIsEditable: true,
|
||||
contextAllowsGradebookUploads: true,
|
||||
gradebookImportUrl: 'http://gradebookImportUrl',
|
||||
|
@ -86,10 +87,17 @@ test('renders the Import menu item', () => {
|
|||
equal(specificMenuItem.textContent, 'Import')
|
||||
})
|
||||
|
||||
test('renders the Export menu item', () => {
|
||||
test('renders the Export Current Gradebook View menu item', () => {
|
||||
const specificMenuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]')
|
||||
|
||||
equal(specificMenuItem.textContent, 'Export')
|
||||
equal(specificMenuItem.textContent, 'Export Current Gradebook View')
|
||||
equal(specificMenuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
})
|
||||
|
||||
test('renders the Export Entire Gradebook menu item', () => {
|
||||
const specificMenuItem = document.querySelector('[role="menuitem"] [data-menu-id="export-all"]')
|
||||
|
||||
equal(specificMenuItem.textContent, 'Export Entire Gradebook')
|
||||
equal(specificMenuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
})
|
||||
|
||||
|
@ -117,7 +125,7 @@ test('renders no Post Grades feature menu item when disabled', () => {
|
|||
strictEqual(specificMenuItem, null)
|
||||
})
|
||||
|
||||
test('renders the Post Grades feature menu item when enabled', function() {
|
||||
test('renders the Post Grades feature menu item when enabled', function () {
|
||||
this.wrapper.unmount()
|
||||
const props = workingMenuProps()
|
||||
props.postGradesFeature.enabled = true
|
||||
|
@ -131,7 +139,7 @@ test('renders the Post Grades feature menu item when enabled', function() {
|
|||
equal(specificMenuItem.textContent, 'Sync to SIS')
|
||||
})
|
||||
|
||||
test('renders the Post Grades feature menu item with label when sis handle is set', function() {
|
||||
test('renders the Post Grades feature menu item with label when sis handle is set', function () {
|
||||
this.wrapper.unmount()
|
||||
const props = workingMenuProps()
|
||||
props.postGradesFeature.enabled = true
|
||||
|
@ -156,7 +164,7 @@ QUnit.module('ActionMenu - getExistingExport', {
|
|||
}
|
||||
})
|
||||
|
||||
test('returns an export hash with workflowState when progressId and attachment.id are present', function() {
|
||||
test('returns an export hash with workflowState when progressId and attachment.id are present', function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -172,11 +180,11 @@ test('returns an export hash with workflowState when progressId and attachment.i
|
|||
deepEqual(this.wrapper.instance().getExistingExport(), expectedExport)
|
||||
})
|
||||
|
||||
test('returns undefined when lastExport is undefined', function() {
|
||||
test('returns undefined when lastExport is undefined', function () {
|
||||
equal(this.wrapper.instance().getExistingExport(), undefined)
|
||||
})
|
||||
|
||||
test("returns undefined when lastExport's attachment is undefined", function() {
|
||||
test("returns undefined when lastExport's attachment is undefined", function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -188,7 +196,7 @@ test("returns undefined when lastExport's attachment is undefined", function() {
|
|||
equal(this.wrapper.instance().getExistingExport(), undefined)
|
||||
})
|
||||
|
||||
test('returns undefined when lastExport is missing progressId', function() {
|
||||
test('returns undefined when lastExport is missing progressId', function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -200,7 +208,7 @@ test('returns undefined when lastExport is missing progressId', function() {
|
|||
equal(this.wrapper.instance().getExistingExport(), undefined)
|
||||
})
|
||||
|
||||
test("returns undefined when lastExport's attachment is missing its id", function() {
|
||||
test("returns undefined when lastExport's attachment is missing its id", function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -221,7 +229,7 @@ QUnit.module('ActionMenu - handleExport', {
|
|||
})
|
||||
}
|
||||
|
||||
return Promise.reject('Export failure reason')
|
||||
return Promise.reject(new Error('Export failure reason'))
|
||||
},
|
||||
|
||||
setup() {
|
||||
|
@ -256,7 +264,7 @@ QUnit.module('ActionMenu - handleExport', {
|
|||
}
|
||||
})
|
||||
|
||||
test('clicking on the export menu option calls the handleExport function', function() {
|
||||
test('clicking on the export menu option calls the handleExport function', function () {
|
||||
this.spies.handleExport = sandbox.stub(ActionMenu.prototype, 'handleExport')
|
||||
|
||||
this.menuItem.click()
|
||||
|
@ -264,7 +272,7 @@ test('clicking on the export menu option calls the handleExport function', funct
|
|||
equal(this.spies.handleExport.callCount, 1)
|
||||
})
|
||||
|
||||
test('shows a message to the user indicating the export is in progress', function() {
|
||||
test('shows a message to the user indicating the export is in progress', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
this.spies.flashMessage = sandbox.stub(window.$, 'flashMessage')
|
||||
|
@ -277,7 +285,7 @@ test('shows a message to the user indicating the export is in progress', functio
|
|||
return exportResult
|
||||
})
|
||||
|
||||
test('changes the "Export" menu item to indicate the export is in progress', function() {
|
||||
test('changes the "Export" menu item to indicate the export is in progress', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -298,7 +306,7 @@ test('changes the "Export" menu item to indicate the export is in progress', fun
|
|||
return exportResult
|
||||
})
|
||||
|
||||
test('starts the export using the GradebookExportManager instance', function() {
|
||||
test('starts the export using the GradebookExportManager instance', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -309,7 +317,7 @@ test('starts the export using the GradebookExportManager instance', function() {
|
|||
return exportResult
|
||||
})
|
||||
|
||||
test('passes the grading period to the GradebookExportManager', function() {
|
||||
test('passes the grading period to the GradebookExportManager', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
@ -321,7 +329,7 @@ test('passes the grading period to the GradebookExportManager', function() {
|
|||
return exportResult
|
||||
})
|
||||
|
||||
test('on success, takes the user to the newly completed export', function() {
|
||||
test('on success, takes the user to the newly completed export', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -336,7 +344,7 @@ test('on success, takes the user to the newly completed export', function() {
|
|||
})
|
||||
})
|
||||
|
||||
test('on success, re-enables the "Export" menu item', function() {
|
||||
test('on success, re-enables the "Export Current Gradebook View" and "Export Entire Gradbook" menu items', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -350,12 +358,17 @@ test('on success, re-enables the "Export" menu item', function() {
|
|||
|
||||
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]')
|
||||
|
||||
equal(this.menuItem.textContent, 'Export')
|
||||
equal(this.menuItem.textContent, 'Export Current Gradebook View')
|
||||
equal(this.menuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
|
||||
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export-all"]')
|
||||
|
||||
equal(this.menuItem.textContent, 'Export Entire Gradebook')
|
||||
equal(this.menuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
})
|
||||
})
|
||||
|
||||
test('on success, shows the "New Export" menu item', function() {
|
||||
test('on success, shows the "New Export" menu item', function () {
|
||||
const exportResult = this.getPromise('resolved')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -375,7 +388,7 @@ test('on success, shows the "New Export" menu item', function() {
|
|||
})
|
||||
})
|
||||
|
||||
test('on failure, shows a message to the user indicating the export failed', function() {
|
||||
test('on failure, shows a message to the user indicating the export failed', function () {
|
||||
const exportResult = this.getPromise('rejected')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
this.spies.flashError = sandbox.stub(window.$, 'flashError')
|
||||
|
@ -387,12 +400,12 @@ test('on failure, shows a message to the user indicating the export failed', fun
|
|||
equal(this.spies.flashError.callCount, 1)
|
||||
equal(
|
||||
this.spies.flashError.getCall(0).args[0],
|
||||
'Gradebook Export Failed: Export failure reason'
|
||||
'Gradebook Export Failed: Error: Export failure reason'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
test('on failure, renables the "Export" menu item', function() {
|
||||
test('on failure, renables the "Export Current Gradebook View" and "Export Entire Gradbook" menu items', function () {
|
||||
const exportResult = this.getPromise('rejected')
|
||||
this.spies.startExport.returns(exportResult)
|
||||
|
||||
|
@ -406,7 +419,12 @@ test('on failure, renables the "Export" menu item', function() {
|
|||
|
||||
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]')
|
||||
|
||||
equal(this.menuItem.textContent, 'Export')
|
||||
equal(this.menuItem.textContent, 'Export Current Gradebook View')
|
||||
equal(this.menuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
|
||||
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export-all"]')
|
||||
|
||||
equal(this.menuItem.textContent, 'Export Entire Gradebook')
|
||||
equal(this.menuItem.parentElement.getAttribute('aria-disabled'), null)
|
||||
})
|
||||
})
|
||||
|
@ -428,7 +446,7 @@ QUnit.module('ActionMenu - handleImport', {
|
|||
}
|
||||
})
|
||||
|
||||
test('clicking on the import menu option calls the handleImport function', function() {
|
||||
test('clicking on the import menu option calls the handleImport function', function () {
|
||||
const handleImportSpy = sandbox.spy(ActionMenu.prototype, 'handleImport')
|
||||
|
||||
this.menuItem.click()
|
||||
|
@ -436,7 +454,7 @@ test('clicking on the import menu option calls the handleImport function', funct
|
|||
equal(handleImportSpy.callCount, 1)
|
||||
})
|
||||
|
||||
test('it takes you to the new imports page', function() {
|
||||
test('it takes you to the new imports page', function () {
|
||||
this.menuItem.click()
|
||||
|
||||
equal(this.spies.gotoUrl.callCount, 1)
|
||||
|
@ -448,7 +466,7 @@ QUnit.module('ActionMenu - disableImports', {
|
|||
}
|
||||
})
|
||||
|
||||
test('is called once when the component renders', function() {
|
||||
test('is called once when the component renders', function () {
|
||||
const disableImportsSpy = sandbox.spy(ActionMenu.prototype, 'disableImports')
|
||||
this.wrapper = mount(<ActionMenu {...workingMenuProps()} />)
|
||||
|
||||
|
@ -457,12 +475,12 @@ test('is called once when the component renders', function() {
|
|||
equal(disableImportsSpy.callCount, 1)
|
||||
})
|
||||
|
||||
test('returns false when gradebook is editable and context allows gradebook uploads', function() {
|
||||
test('returns false when gradebook is editable and context allows gradebook uploads', function () {
|
||||
this.wrapper = mount(<ActionMenu {...workingMenuProps()} />)
|
||||
strictEqual(this.wrapper.instance().disableImports(), false)
|
||||
})
|
||||
|
||||
test('returns true when gradebook is not editable and context allows gradebook uploads', function() {
|
||||
test('returns true when gradebook is not editable and context allows gradebook uploads', function () {
|
||||
const newImportProps = {
|
||||
...workingMenuProps(),
|
||||
gradebookIsEditable: false
|
||||
|
@ -472,7 +490,7 @@ test('returns true when gradebook is not editable and context allows gradebook u
|
|||
strictEqual(this.wrapper.instance().disableImports(), true)
|
||||
})
|
||||
|
||||
test('returns true when gradebook is editable but context does not allow gradebook uploads', function() {
|
||||
test('returns true when gradebook is editable but context does not allow gradebook uploads', function () {
|
||||
const newImportProps = {
|
||||
...workingMenuProps(),
|
||||
contextAllowsGradebookUploads: false
|
||||
|
@ -492,7 +510,7 @@ QUnit.module('ActionMenu - lastExportFromProps', {
|
|||
}
|
||||
})
|
||||
|
||||
test('returns the lastExport hash if props have a completed last export', function() {
|
||||
test('returns the lastExport hash if props have a completed last export', function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -503,11 +521,11 @@ test('returns the lastExport hash if props have a completed last export', functi
|
|||
deepEqual(this.wrapper.instance().lastExportFromProps(), propsWithPreviousExport.lastExport)
|
||||
})
|
||||
|
||||
test('returns undefined if props have no lastExport', function() {
|
||||
test('returns undefined if props have no lastExport', function () {
|
||||
equal(this.wrapper.instance().lastExportFromProps(), undefined)
|
||||
})
|
||||
|
||||
test('returns undefined if props have a lastExport but it is not completed', function() {
|
||||
test('returns undefined if props have a lastExport but it is not completed', function () {
|
||||
const propsWithPreviousExport = {
|
||||
...workingMenuProps(),
|
||||
...previousExportProps()
|
||||
|
@ -529,7 +547,7 @@ QUnit.module('ActionMenu - lastExportFromState', {
|
|||
}
|
||||
})
|
||||
|
||||
test('returns the previous export if state has a previousExport defined', function() {
|
||||
test('returns the previous export if state has a previousExport defined', function () {
|
||||
const expectedPreviousExport = {
|
||||
label: 'previous export label',
|
||||
attachmentUrl: 'http://attachmentUrl'
|
||||
|
@ -540,13 +558,13 @@ test('returns the previous export if state has a previousExport defined', functi
|
|||
deepEqual(this.wrapper.instance().lastExportFromState(), expectedPreviousExport)
|
||||
})
|
||||
|
||||
test('returns undefined if an export is already in progress', function() {
|
||||
test('returns undefined if an export is already in progress', function () {
|
||||
this.wrapper.instance().setExportInProgress(true)
|
||||
|
||||
equal(this.wrapper.instance().lastExportFromState(), undefined)
|
||||
})
|
||||
|
||||
test('returns undefined if no previous export is set in the state', function() {
|
||||
test('returns undefined if no previous export is set in the state', function () {
|
||||
this.wrapper.instance().setExportInProgress(false)
|
||||
|
||||
equal(this.wrapper.instance().lastExportFromState(), undefined)
|
||||
|
@ -567,7 +585,7 @@ QUnit.module('ActionMenu - previousExport', {
|
|||
}
|
||||
})
|
||||
|
||||
test('returns the previous export stored in the state if it is available', function() {
|
||||
test('returns the previous export stored in the state if it is available', function () {
|
||||
const stateExport = {
|
||||
label: 'previous export label',
|
||||
attachmentUrl: 'http://attachmentUrl'
|
||||
|
@ -580,7 +598,7 @@ test('returns the previous export stored in the state if it is available', funct
|
|||
equal(lastExportFromState.callCount, 1)
|
||||
})
|
||||
|
||||
test('returns the previous export stored in the props if nothing is available in state', function() {
|
||||
test('returns the previous export stored in the props if nothing is available in state', function () {
|
||||
const expectedPreviousExport = {
|
||||
attachmentUrl: 'http://downloadUrl',
|
||||
label: 'Previous Export (Jan 20, 2009 at 5pm)'
|
||||
|
@ -598,7 +616,7 @@ test('returns the previous export stored in the props if nothing is available in
|
|||
equal(lastExportFromProps.callCount, 1)
|
||||
})
|
||||
|
||||
test('returns undefined if state has nothing and props have nothing', function() {
|
||||
test('returns undefined if state has nothing and props have nothing', function () {
|
||||
const lastExportFromState = sandbox
|
||||
.stub(ActionMenu.prototype, 'lastExportFromState')
|
||||
.returns(undefined)
|
||||
|
@ -621,13 +639,13 @@ QUnit.module('ActionMenu - exportInProgress', {
|
|||
}
|
||||
})
|
||||
|
||||
test('returns true if exportInProgress is set', function() {
|
||||
test('returns true if exportInProgress is set', function () {
|
||||
this.wrapper.instance().setExportInProgress(true)
|
||||
|
||||
strictEqual(this.wrapper.instance().exportInProgress(), true)
|
||||
})
|
||||
|
||||
test('returns false if exportInProgress is set to false', function() {
|
||||
test('returns false if exportInProgress is set to false', function () {
|
||||
this.wrapper.instance().setExportInProgress(false)
|
||||
|
||||
strictEqual(this.wrapper.instance().exportInProgress(), false)
|
||||
|
@ -647,7 +665,7 @@ QUnit.module('ActionMenu - Post Grade Ltis', {
|
|||
}
|
||||
})
|
||||
|
||||
test('Invokes the onSelect prop when selected', function() {
|
||||
test('Invokes the onSelect prop when selected', function () {
|
||||
document.querySelector('[data-menu-id="post_grades_lti_1"]').click()
|
||||
|
||||
strictEqual(this.props.postGradesLtis[0].onSelect.called, true)
|
||||
|
@ -703,7 +721,7 @@ test('Does not render menu item when isEnabled is false and publishToSisUrl is u
|
|||
equal(menuItem, null)
|
||||
})
|
||||
|
||||
test('Does not render menu item when isEnabled is true and publishToSisUrl is undefined', function() {
|
||||
test('Does not render menu item when isEnabled is true and publishToSisUrl is undefined', function () {
|
||||
this.wrapper.setProps({
|
||||
publishGradesToSis: {
|
||||
isEnabled: true
|
||||
|
@ -716,7 +734,7 @@ test('Does not render menu item when isEnabled is true and publishToSisUrl is un
|
|||
equal(menuItem, null)
|
||||
})
|
||||
|
||||
test('Renders menu item when isEnabled is true and publishToSisUrl is defined', function() {
|
||||
test('Renders menu item when isEnabled is true and publishToSisUrl is defined', function () {
|
||||
this.wrapper.setProps({
|
||||
publishGradesToSis: {
|
||||
isEnabled: true,
|
||||
|
@ -730,7 +748,7 @@ test('Renders menu item when isEnabled is true and publishToSisUrl is defined',
|
|||
ok(menuItem)
|
||||
})
|
||||
|
||||
test('Calls gotoUrl with publishToSisUrl when clicked', function() {
|
||||
test('Calls gotoUrl with publishToSisUrl when clicked', function () {
|
||||
this.wrapper.setProps({
|
||||
publishGradesToSis: {
|
||||
isEnabled: true,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import moxios from 'moxios'
|
||||
|
||||
import GradebookExportManager from 'ui/features/gradebook/react/shared/GradebookExportManager.js'
|
||||
import GradebookExportManager from 'ui/features/gradebook/react/shared/GradebookExportManager'
|
||||
|
||||
const currentUserId = 42
|
||||
const exportingUrl = 'http://exportingUrl'
|
||||
|
@ -165,7 +165,8 @@ test('sets show_student_first_last_name setting if requested', function () {
|
|||
}
|
||||
|
||||
const getAssignmentOrder = () => []
|
||||
return this.subject.startExport(undefined, getAssignmentOrder, true).then(() => {
|
||||
const getStudentOrder = () => []
|
||||
return this.subject.startExport(undefined, getAssignmentOrder, true, getStudentOrder).then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
propEqual(postData.show_student_first_last_name, true)
|
||||
})
|
||||
|
@ -178,10 +179,13 @@ test('does not set show_student_first_last_name setting by default', function ()
|
|||
}
|
||||
|
||||
const getAssignmentOrder = () => []
|
||||
return this.subject.startExport(undefined, getAssignmentOrder).then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
propEqual(postData.show_student_first_last_name, false)
|
||||
})
|
||||
const getStudentOrder = () => []
|
||||
return this.subject
|
||||
.startExport(undefined, getAssignmentOrder, false, getStudentOrder)
|
||||
.then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
propEqual(postData.show_student_first_last_name, false)
|
||||
})
|
||||
})
|
||||
|
||||
test('includes assignment_order if getAssignmentOrder returns some assignments', function () {
|
||||
|
@ -191,10 +195,13 @@ test('includes assignment_order if getAssignmentOrder returns some assignments',
|
|||
}
|
||||
|
||||
const getAssignmentOrder = () => ['1', '2', '3']
|
||||
return this.subject.startExport(undefined, getAssignmentOrder).then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
propEqual(postData.assignment_order, ['1', '2', '3'])
|
||||
})
|
||||
const getStudentOrder = () => []
|
||||
return this.subject
|
||||
.startExport(undefined, getAssignmentOrder, false, getStudentOrder)
|
||||
.then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
propEqual(postData.assignment_order, ['1', '2', '3'])
|
||||
})
|
||||
})
|
||||
|
||||
test('does not include assignment_order if getAssignmentOrder returns no assignments', function () {
|
||||
|
@ -204,10 +211,13 @@ test('does not include assignment_order if getAssignmentOrder returns no assignm
|
|||
}
|
||||
|
||||
const getAssignmentOrder = () => []
|
||||
return this.subject.startExport(undefined, getAssignmentOrder).then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
equal(postData.assignment_order, undefined)
|
||||
})
|
||||
const getStudentOrder = () => []
|
||||
return this.subject
|
||||
.startExport(undefined, getAssignmentOrder, false, getStudentOrder)
|
||||
.then(() => {
|
||||
const postData = JSON.parse(moxios.requests.mostRecent().config.data)
|
||||
equal(postData.assignment_order, undefined)
|
||||
})
|
||||
})
|
||||
|
||||
test('returns a rejected promise if the manager has no exportingUrl set', function () {
|
||||
|
@ -215,7 +225,12 @@ test('returns a rejected promise if the manager has no exportingUrl set', functi
|
|||
this.subject.exportingUrl = undefined
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.catch(reason => {
|
||||
equal(reason, 'No way to export gradebooks provided!')
|
||||
})
|
||||
|
@ -225,7 +240,12 @@ test('returns a rejected promise if the manager already has an export going', fu
|
|||
this.subject = new GradebookExportManager(exportingUrl, currentUserId, workingExport)
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.catch(reason => {
|
||||
equal(reason, 'An export is already in progress.')
|
||||
})
|
||||
|
@ -243,7 +263,12 @@ test('sets a new existing export and returns a fulfilled promise', function () {
|
|||
}
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.then(() => {
|
||||
deepEqual(this.subject.export, expectedExport)
|
||||
})
|
||||
|
@ -254,7 +279,12 @@ test('clears any new export and returns a rejected promise if no monitoring is p
|
|||
this.subject = new GradebookExportManager(exportingUrl, currentUserId)
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.catch(reason => {
|
||||
equal(reason, 'No way to monitor gradebook exports provided!')
|
||||
equal(this.subject.export, undefined)
|
||||
|
@ -275,7 +305,12 @@ test('starts polling for progress and returns a rejected promise on progress fai
|
|||
})
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.catch(reason => {
|
||||
equal(reason, 'Error exporting gradebook: Arbitrary failure')
|
||||
})
|
||||
|
@ -295,7 +330,12 @@ test('starts polling for progress and returns a rejected promise on unknown prog
|
|||
})
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => []
|
||||
)
|
||||
.catch(reason => {
|
||||
equal(reason, 'Error exporting gradebook: Pattern buffer degradation')
|
||||
})
|
||||
|
@ -323,7 +363,12 @@ test('starts polling for progress and returns a fulfilled promise on progress co
|
|||
})
|
||||
|
||||
return this.subject
|
||||
.startExport(undefined, () => [])
|
||||
.startExport(
|
||||
undefined,
|
||||
() => [],
|
||||
false,
|
||||
() => {}
|
||||
)
|
||||
.then(resolution => {
|
||||
equal(this.subject.export, undefined)
|
||||
|
||||
|
|
|
@ -558,55 +558,62 @@ describe GradebookExporter do
|
|||
|
||||
describe "with grading periods" do
|
||||
describe "assignments in the selected grading period are exported" do
|
||||
before do
|
||||
@csv = exporter(grading_period_id: @last_period.id).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
describe "export entire gradebook" do
|
||||
before do
|
||||
@csv = exporter(grading_period_id: @last_period.id).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
end
|
||||
|
||||
it "exports assignments from all grading periods" do
|
||||
expect(@headers).to include @no_due_date_assignment.title_with_id,
|
||||
@current_assignment.title_with_id,
|
||||
@past_assignment.title_with_id,
|
||||
@future_assignment.title_with_id
|
||||
end
|
||||
|
||||
it "does not export totals columns" do
|
||||
expect(@headers).to_not include "Final Score (#{@last_period.title})"
|
||||
end
|
||||
end
|
||||
|
||||
it "exports selected grading period's assignments" do
|
||||
expect(@headers).to include @no_due_date_assignment.title_with_id,
|
||||
@current_assignment.title_with_id
|
||||
final_grade = @rows[1]["Final Score (#{@last_period.title})"].try(:to_f)
|
||||
expect(final_grade).to eq 20
|
||||
end
|
||||
describe "export current gradebook view" do
|
||||
before do
|
||||
exporter_options = {
|
||||
grading_period_id: @last_period.id,
|
||||
current_view: true,
|
||||
assignment_order: @course.assignments.pluck(:id),
|
||||
student_order: @course.student_enrollments.pluck(:user_id)
|
||||
}
|
||||
@csv = exporter(exporter_options).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
end
|
||||
|
||||
it "exports assignments without due dates if exporting last grading period" do
|
||||
expect(@headers).to include @current_assignment.title_with_id,
|
||||
@no_due_date_assignment.title_with_id
|
||||
final_grade = @rows[1]["Final Score (#{@last_period.title})"].try(:to_f)
|
||||
expect(final_grade).to eq 20
|
||||
end
|
||||
it "exports filtered grading period's assignments with totals columns" do
|
||||
expect(@headers).to include @no_due_date_assignment.title_with_id,
|
||||
@current_assignment.title_with_id
|
||||
final_grade = @rows[1]["Final Score (#{@last_period.title})"].try(:to_f)
|
||||
expect(final_grade).to eq 20
|
||||
end
|
||||
|
||||
it "does not export assignments without due date" do
|
||||
@grading_period_id = @first_period.id
|
||||
@csv = exporter(grading_period_id: @grading_period_id).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
it "exports all visible assignments in the gradebook" do
|
||||
exporter_options = {
|
||||
grading_period_id: @first_period.id,
|
||||
current_view: true,
|
||||
assignment_order: [@no_due_date_assignment.id, @future_assignment.id],
|
||||
student_order: @course.student_enrollments.pluck(:user_id).map(&:to_s)
|
||||
}
|
||||
@csv = exporter(exporter_options).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
|
||||
expect(@headers).to_not include @no_due_date_assignment.title_with_id
|
||||
end
|
||||
expect(@headers).to include @no_due_date_assignment.title_with_id,
|
||||
@future_assignment.title_with_id
|
||||
|
||||
it "does not export assignments in other grading periods" do
|
||||
expect(@headers).to_not include @past_assignment.title_with_id,
|
||||
@future_assignment.title_with_id
|
||||
end
|
||||
|
||||
it "does not export future assignments" do
|
||||
expect(@headers).to_not include @future_assignment.title_with_id
|
||||
end
|
||||
|
||||
it "exports the entire gradebook when grading_period_id is 0" do
|
||||
@grading_period_id = 0
|
||||
@csv = exporter(grading_period_id: @grading_period_id).to_csv
|
||||
@rows = CSV.parse(@csv, headers: true)
|
||||
@headers = @rows.headers
|
||||
|
||||
expect(@headers).to include @past_assignment.title_with_id,
|
||||
@current_assignment.title_with_id,
|
||||
@future_assignment.title_with_id,
|
||||
@no_due_date_assignment.title_with_id
|
||||
expect(@headers).not_to include "Final Score"
|
||||
expect(@headers).to_not include @current_assignment.title_with_id,
|
||||
@past_assignment.title_with_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -694,7 +701,13 @@ describe GradebookExporter do
|
|||
end
|
||||
|
||||
let(:exporter) do
|
||||
GradebookExporter.new(@course, @teacher, { grading_period_id: @last_grading_period.id })
|
||||
exporter_options = {
|
||||
grading_period_id: @last_grading_period.id,
|
||||
current_view: true,
|
||||
assignment_order: @course.assignments.pluck(:id),
|
||||
student_order: @course.student_enrollments.pluck(:user_id).map(&:to_s)
|
||||
}
|
||||
GradebookExporter.new(@course, @teacher, exporter_options)
|
||||
end
|
||||
let(:exported_headers) { CSV.parse(exporter.to_csv, headers: true).headers }
|
||||
|
||||
|
@ -863,7 +876,15 @@ describe GradebookExporter do
|
|||
start_date: 1.week.ago, end_date: 1.week.from_now, title: "test period"
|
||||
)
|
||||
end
|
||||
let(:exporter) { GradebookExporter.new(@course, @teacher, { grading_period_id: grading_period.id }) }
|
||||
let(:exporter) do
|
||||
exporter_options = {
|
||||
grading_period_id: grading_period.id,
|
||||
current_view: true,
|
||||
assignment_order: @course.assignments.pluck(:id),
|
||||
student_order: @course.student_enrollments.pluck(:user_id)
|
||||
}
|
||||
GradebookExporter.new(@course, @teacher, exporter_options)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(exporter).to receive(:enrollments_for_csv).and_return([enrollment])
|
||||
|
|
|
@ -2021,6 +2021,7 @@ class Gradebook extends React.Component<GradebookProps, GradebookState> {
|
|||
publishToSisUrl: this.options.publish_to_sis_url
|
||||
},
|
||||
gradingPeriodId: this.state.gradingPeriodId,
|
||||
getStudentOrder: this.getStudentOrder,
|
||||
getAssignmentOrder: this.getAssignmentOrder
|
||||
}
|
||||
const progressData = this.options.gradebook_csv_progress
|
||||
|
|
|
@ -38,6 +38,7 @@ export type ActionMenuProps = {
|
|||
gradebookIsEditable: boolean
|
||||
contextAllowsGradebookUploads: boolean
|
||||
getAssignmentOrder: any
|
||||
getStudentOrder: any
|
||||
gradebookImportUrl: string
|
||||
showStudentFirstLastName: boolean
|
||||
lastExport?: {
|
||||
|
@ -128,7 +129,7 @@ class ActionMenu extends React.Component<ActionMenuProps, ActionMenuState> {
|
|||
this.setState({exportInProgress: !!status})
|
||||
}
|
||||
|
||||
handleExport() {
|
||||
handleExport(currentView) {
|
||||
this.setExportInProgress(true)
|
||||
$.flashMessage(I18n.t('Gradebook export started'))
|
||||
|
||||
|
@ -136,7 +137,9 @@ class ActionMenu extends React.Component<ActionMenuProps, ActionMenuState> {
|
|||
?.startExport(
|
||||
this.props.gradingPeriodId,
|
||||
this.props.getAssignmentOrder,
|
||||
this.props.showStudentFirstLastName
|
||||
this.props.showStudentFirstLastName,
|
||||
this.props.getStudentOrder,
|
||||
currentView
|
||||
)
|
||||
.then(resolution => {
|
||||
this.setExportInProgress(false)
|
||||
|
@ -324,11 +327,26 @@ class ActionMenu extends React.Component<ActionMenuProps, ActionMenuState> {
|
|||
<MenuItem
|
||||
disabled={this.exportInProgress()}
|
||||
onSelect={() => {
|
||||
this.handleExport()
|
||||
this.handleExport(true)
|
||||
}}
|
||||
>
|
||||
<span data-menu-id="export">
|
||||
{this.exportInProgress() ? I18n.t('Export in progress') : I18n.t('Export')}
|
||||
{this.exportInProgress()
|
||||
? I18n.t('Export in progress')
|
||||
: I18n.t('Export Current Gradebook View')}
|
||||
</span>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
disabled={this.exportInProgress()}
|
||||
onSelect={() => {
|
||||
this.handleExport(false)
|
||||
}}
|
||||
>
|
||||
<span data-menu-id="export-all">
|
||||
{this.exportInProgress()
|
||||
? I18n.t('Export in progress')
|
||||
: I18n.t('Export Entire Gradebook')}
|
||||
</span>
|
||||
</MenuItem>
|
||||
|
||||
|
|
|
@ -71,12 +71,18 @@ export default function EnhancedActionMenu(props) {
|
|||
}
|
||||
}
|
||||
|
||||
const handleExport = () => {
|
||||
const handleExport = currentView => {
|
||||
setExportInProgress(true)
|
||||
$.flashMessage(I18n.t('Gradebook export started'))
|
||||
|
||||
return exportManager.current
|
||||
.startExport(props.gradingPeriodId, props.getAssignmentOrder, props.showStudentFirstLastName)
|
||||
.startExport(
|
||||
props.gradingPeriodId,
|
||||
props.getAssignmentOrder,
|
||||
props.showStudentFirstLastName,
|
||||
props.getStudentOrder,
|
||||
currentView
|
||||
)
|
||||
.then(resolution => {
|
||||
setExportInProgress(false)
|
||||
|
||||
|
@ -84,7 +90,7 @@ export default function EnhancedActionMenu(props) {
|
|||
const updatedAt = new Date(resolution.updatedAt)
|
||||
|
||||
const previousExportValue = {
|
||||
label: `${I18n.t('New Export')} (${DateHelper.formatDatetimeForDisplay(updatedAt)})`,
|
||||
label: `${I18n.t('Previous Export')} (${DateHelper.formatDatetimeForDisplay(updatedAt)})`,
|
||||
attachmentUrl
|
||||
}
|
||||
|
||||
|
@ -288,11 +294,24 @@ export default function EnhancedActionMenu(props) {
|
|||
<Menu.Item
|
||||
disabled={exportInProgress}
|
||||
onSelect={() => {
|
||||
handleExport()
|
||||
handleExport(true)
|
||||
}}
|
||||
>
|
||||
<span data-menu-id="export">
|
||||
{exportInProgress ? I18n.t('Export in progress') : I18n.t('New Export')}
|
||||
{exportInProgress
|
||||
? I18n.t('Export in progress')
|
||||
: I18n.t('Export Current Gradebook View')}
|
||||
</span>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
disabled={exportInProgress}
|
||||
onSelect={() => {
|
||||
handleExport(false)
|
||||
}}
|
||||
>
|
||||
<span data-menu-id="export-all">
|
||||
{exportInProgress ? I18n.t('Export in progress') : I18n.t('Export Entire Gradebook')}
|
||||
</span>
|
||||
</Menu.Item>
|
||||
|
||||
|
@ -306,6 +325,7 @@ EnhancedActionMenu.propTypes = {
|
|||
gradebookIsEditable: bool.isRequired,
|
||||
contextAllowsGradebookUploads: bool.isRequired,
|
||||
getAssignmentOrder: func.isRequired,
|
||||
getStudentOrder: func.isRequired,
|
||||
gradebookImportUrl: string.isRequired,
|
||||
|
||||
currentUserId: string.isRequired,
|
||||
|
|
|
@ -36,6 +36,7 @@ const getPromise = (type, object = defaultResult) => {
|
|||
|
||||
const workingMenuProps = () => ({
|
||||
getAssignmentOrder() {},
|
||||
getStudentOrder() {},
|
||||
gradebookIsEditable: true,
|
||||
contextAllowsGradebookUploads: true,
|
||||
gradebookImportUrl: 'http://gradebookImportUrl',
|
||||
|
@ -130,11 +131,20 @@ describe('EnhancedActionMenu', () => {
|
|||
expect(specificMenuItem).toHaveTextContent('Import')
|
||||
})
|
||||
|
||||
it('renders the New Export menu item', async () => {
|
||||
it('renders the Export Current Gradebook View menu item', async () => {
|
||||
component = renderComponent(props)
|
||||
clickOnDropdown('Export')
|
||||
const specificMenuItem = component.getByRole('menuitem', {
|
||||
name: 'New Export'
|
||||
name: 'Export Current Gradebook View'
|
||||
})
|
||||
expect(specificMenuItem).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders the Export Entire Gradebook menu item', async () => {
|
||||
component = renderComponent(props)
|
||||
clickOnDropdown('Export')
|
||||
const specificMenuItem = component.getByRole('menuitem', {
|
||||
name: 'Export Entire Gradebook'
|
||||
})
|
||||
expect(specificMenuItem).toBeInTheDocument()
|
||||
})
|
||||
|
@ -148,7 +158,7 @@ describe('EnhancedActionMenu', () => {
|
|||
expect(specificMenuItem).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('updates the New Export date when export success', async () => {
|
||||
it('updates the Previous Export date when export success', async () => {
|
||||
const exportResult = getPromise('resolved', {
|
||||
...defaultResult,
|
||||
updatedAt: '2021-05-12T13:00:00Z'
|
||||
|
@ -157,12 +167,12 @@ describe('EnhancedActionMenu', () => {
|
|||
startExport.mockReturnValue(exportResult)
|
||||
component = renderComponent(props)
|
||||
clickOnDropdown('Export')
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Entire Gradebook')
|
||||
await waitFor(() => {
|
||||
clickOnDropdown('Export')
|
||||
})
|
||||
const specificMenuItem = component.getByRole('menuitem', {
|
||||
name: 'New Export (May 12, 2021 at 1pm)'
|
||||
name: 'Previous Export (May 12, 2021 at 1pm)'
|
||||
})
|
||||
expect(specificMenuItem).toBeInTheDocument()
|
||||
})
|
||||
|
@ -219,7 +229,7 @@ describe('EnhancedActionMenu', () => {
|
|||
startExport.mockReturnValue(exportResult)
|
||||
const spy = jest.spyOn(window.$, 'flashMessage').mockReturnValue(true)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalled()
|
||||
|
@ -227,17 +237,19 @@ describe('EnhancedActionMenu', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('changes the "Export" menu item to indicate the export is in progress', async () => {
|
||||
it('changes the "Export Current Gradebook View" and "Export Entire Gradebook" menu items to indicate the export is in progress', async () => {
|
||||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
clickOnDropdown('Export')
|
||||
const specificMenuItem = component.getByRole('menuitem', {name: /Export in progress/})
|
||||
const specificMenuItems = component.getAllByRole('menuitem', {name: /Export in progress/})
|
||||
await waitFor(() => {
|
||||
expect(specificMenuItem).toBeInTheDocument()
|
||||
expect(specificMenuItem).toHaveAttribute('aria-disabled', 'true')
|
||||
expect(specificMenuItems[0]).toBeInTheDocument()
|
||||
expect(specificMenuItems[1]).toBeInTheDocument()
|
||||
expect(specificMenuItems[0]).toHaveAttribute('aria-disabled', 'true')
|
||||
expect(specificMenuItems[1]).toHaveAttribute('aria-disabled', 'true')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -245,7 +257,7 @@ describe('EnhancedActionMenu', () => {
|
|||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(startExport).toHaveBeenCalled()
|
||||
|
@ -256,7 +268,7 @@ describe('EnhancedActionMenu', () => {
|
|||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(startExport.mock.calls[0][0]).toEqual('1234')
|
||||
|
@ -267,7 +279,7 @@ describe('EnhancedActionMenu', () => {
|
|||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(startExport.mock.calls[0][2]).toEqual(true)
|
||||
|
@ -278,25 +290,43 @@ describe('EnhancedActionMenu', () => {
|
|||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => expect(window.location.href).toEqual(defaultResult.attachmentUrl))
|
||||
})
|
||||
|
||||
it('on success, re-enables the "New Export" menu item', async () => {
|
||||
it('on success, re-enables the "Export Entire Gradebook" menu item', async () => {
|
||||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Entire Gradebook')
|
||||
})
|
||||
await waitFor(() => {
|
||||
clickOnDropdown('Export')
|
||||
})
|
||||
const specificMenuItem = document
|
||||
.querySelector('[data-menu-id="previous-export"]')
|
||||
.querySelector('[data-menu-id="export-all"]')
|
||||
.closest('[role="menuitem"]')
|
||||
await waitFor(() => {
|
||||
expect(specificMenuItem).toHaveTextContent('New Export')
|
||||
expect(specificMenuItem).toHaveTextContent('Export Entire Gradebook')
|
||||
expect(specificMenuItem).not.toHaveAttribute('aria-disabled', 'true')
|
||||
})
|
||||
})
|
||||
|
||||
it('on success, re-enables the "Export Current Gradebook View" menu item', async () => {
|
||||
const exportResult = getPromise('resolved')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
clickOnDropdown('Export')
|
||||
})
|
||||
const specificMenuItem = document
|
||||
.querySelector('[data-menu-id="export"]')
|
||||
.closest('[role="menuitem"]')
|
||||
await waitFor(() => {
|
||||
expect(specificMenuItem).toHaveTextContent('Export Current Gradebook View')
|
||||
expect(specificMenuItem).not.toHaveAttribute('aria-disabled', 'true')
|
||||
})
|
||||
})
|
||||
|
@ -306,7 +336,7 @@ describe('EnhancedActionMenu', () => {
|
|||
const exportResult = getPromise('rejected')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
expect(spy).toHaveBeenCalled()
|
||||
|
@ -316,21 +346,26 @@ describe('EnhancedActionMenu', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('on failure, renables the "New Export" menu item', async () => {
|
||||
it('on failure, renables the "Export Current Gradebook View" and "Export Entire Gradebook" menu items', async () => {
|
||||
const exportResult = getPromise('rejected')
|
||||
startExport.mockReturnValue(exportResult)
|
||||
act(() => {
|
||||
selectDropdownOption('New Export')
|
||||
selectDropdownOption('Export Current Gradebook View')
|
||||
})
|
||||
await waitFor(() => {
|
||||
clickOnDropdown('Export')
|
||||
})
|
||||
const specificMenuItem = document
|
||||
const exportMenuItem = document
|
||||
.querySelector('[data-menu-id="export"]')
|
||||
.closest('[role="menuitem"]')
|
||||
const exportAllMenuItem = document
|
||||
.querySelector('[data-menu-id="export-all"]')
|
||||
.closest('[role="menuitem"]')
|
||||
await waitFor(() => {
|
||||
expect(specificMenuItem).toHaveTextContent('New Export')
|
||||
expect(specificMenuItem).not.toHaveAttribute('aria-disabled', 'true')
|
||||
expect(exportMenuItem).toHaveTextContent('Export Current Gradebook View')
|
||||
expect(exportMenuItem).not.toHaveAttribute('aria-disabled', 'true')
|
||||
expect(exportAllMenuItem).toHaveTextContent('Export Entire Gradebook')
|
||||
expect(exportAllMenuItem).not.toHaveAttribute('aria-disabled', 'true')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -119,7 +119,13 @@ class GradebookExportManager {
|
|||
}, this.pollingInterval)
|
||||
}
|
||||
|
||||
startExport(gradingPeriodId, getAssignmentOrder, showStudentFirstLastName = false) {
|
||||
startExport(
|
||||
gradingPeriodId,
|
||||
getAssignmentOrder,
|
||||
showStudentFirstLastName = false,
|
||||
getStudentOrder,
|
||||
currentView = false
|
||||
) {
|
||||
if (!this.exportingUrl) {
|
||||
return Promise.reject(I18n.t('No way to export gradebooks provided!'))
|
||||
}
|
||||
|
@ -130,7 +136,9 @@ class GradebookExportManager {
|
|||
}
|
||||
|
||||
const params = {
|
||||
grading_period_id: gradingPeriodId
|
||||
grading_period_id: gradingPeriodId,
|
||||
show_student_first_last_name: showStudentFirstLastName,
|
||||
current_view: currentView
|
||||
}
|
||||
|
||||
const assignmentOrder = getAssignmentOrder()
|
||||
|
@ -138,7 +146,10 @@ class GradebookExportManager {
|
|||
params.assignment_order = assignmentOrder
|
||||
}
|
||||
|
||||
params.show_student_first_last_name = showStudentFirstLastName
|
||||
const studentOrder = getStudentOrder()
|
||||
if (studentOrder && studentOrder.length > 0) {
|
||||
params.student_order = studentOrder.map(Number)
|
||||
}
|
||||
|
||||
return axios.post(this.exportingUrl, params).then(response => {
|
||||
this.export = {
|
||||
|
|
Loading…
Reference in New Issue