Skip to content

Commit

Permalink
fix viewing with archived grading schemes
Browse files Browse the repository at this point in the history
fix issues with using the wrong endpoint when requesting schemes and
summaries for archived grading schemes. added query parameter to the
endpoints to allow for course scheme management page to include
archived schemes.

closes EVAL-4101

flag=archived_grading_schemes

test plan:
- make a grading scheme
- change an assignment to letter grade and choose that grading scheme
- save those changes
- go back to the edit assignment page, and click manage all grading
  schemes
- archive the grading scheme that is assigned to that assignment
- close the manage grading schemes modal
- ensure that the grading scheme is still assigned to the assignment
  and still selected
- go back to the manage grading schemes modal
- archive some schemes
- ensure they are not shown in the course settings page nor the
  assignment edit page when choosing a grading scheme (unless they are
  set to that assignment's grading scheme or the course default)
- ensure that when you close out of the manage schemes modal and open
  it again, they show up in the archived schemes table
- go back to the course settings page and select an account scheme from
  the dropdown
- click 'view'
- ensure that the pencil icon to edit the scheme is disabled
- do the same from the assignment edit view

Change-Id: I4c67f9062172997d0ff94dd203ed95af71b96508
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/345365
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Derek Williams <derek.williams@instructure.com>
Reviewed-by: Kai Bjorkman <kbjorkman@instructure.com>
QA-Review: Kai Bjorkman <kbjorkman@instructure.com>
Product-Review: Ravi Koll <ravi.koll@instructure.com>
  • Loading branch information
rohanchugh14 committed Apr 19, 2024
1 parent e276c84 commit 0a8628e
Show file tree
Hide file tree
Showing 21 changed files with 347 additions and 62 deletions.
2 changes: 1 addition & 1 deletion app/controllers/gradebooks_controller.rb
Expand Up @@ -539,7 +539,7 @@ def set_default_gradebook_env
grade_calc_ignore_unposted_anonymous_enabled: root_account.feature_enabled?(:grade_calc_ignore_unposted_anonymous),
graded_late_submissions_exist:,
grading_period_set: grading_period_group_json,
grading_schemes: GradingStandard.for(@context).as_json(include_root: false),
grading_schemes: GradingStandard.for(@context, include_archived: true).as_json(include_root: false),
grading_standard: @context.grading_standard_enabled? && grading_standard.data,
grading_standard_points_based: active_grading_standard_points_based(grading_standard),
grading_standard_scaling_factor: active_grading_standard_scaling_factor(grading_standard),
Expand Down
5 changes: 3 additions & 2 deletions app/controllers/grading_schemes_json_controller.rb
Expand Up @@ -210,11 +210,12 @@ def self.json_serialized_fields
end

def grading_standards_for_context
include_archived = params[:include_archived] == "true"
if params[:assignment_id]
@assignment = @context.assignments.find(params[:assignment_id])
return GradingStandard.for(@assignment)
return GradingStandard.for(@assignment, include_archived:)
end
GradingStandard.for(@context)
GradingStandard.for(@context, include_archived:)
end

def self.default_canvas_grading_standard(context)
Expand Down
14 changes: 7 additions & 7 deletions app/models/grading_standard.rb
Expand Up @@ -97,7 +97,7 @@ class GradingStandard < ActiveRecord::Base
can :manage
end

def self.for(context)
def self.for(context, include_archived: false)
unless Account.site_admin.feature_enabled?(:archived_grading_schemes)
return GradingStandard.active.for_context(context)
end
Expand All @@ -106,14 +106,14 @@ def self.for(context)
when Account
for_account(context)
when Course
for_course(context)
for_course(context, include_archived:)
else
for_assignment(context)
for_assignment(context, include_archived:)
end
end

def self.for_assignment(assignment)
standards = GradingStandard.active.for_context(assignment.context)
def self.for_assignment(assignment, include_archived: false)
standards = include_archived ? GradingStandard.for_context(assignment.context) : GradingStandard.active.for_context(assignment.context)
standards = GradingStandard.where(id: standards)
course_scheme = assignment.context.grading_standard
standards = standards.union(GradingStandard.where(id: course_scheme)) if course_scheme&.archived?
Expand All @@ -123,8 +123,8 @@ def self.for_assignment(assignment)
standards
end

def self.for_course(course)
standards = GradingStandard.active.for_context(course)
def self.for_course(course, include_archived: false)
standards = include_archived ? GradingStandard.for_context(course) : GradingStandard.active.for_context(course)
standards = GradingStandard.where(id: standards)
standards = standards.union(GradingStandard.where(id: course.grading_standard)) if course.grading_standard&.archived?
standards
Expand Down
34 changes: 34 additions & 0 deletions spec/controllers/grading_schemes_json_controller_spec.rb
Expand Up @@ -115,6 +115,8 @@
describe "get grading schemes with archived feature" do
before(:once) do
Account.site_admin.enable_feature!(:archived_grading_schemes)
@root_account = Account.default
course_with_teacher(active_all: true, account: @root_account)
end

it "doesn't return unrelated archived schemes" do
Expand Down Expand Up @@ -148,6 +150,38 @@
response_json = response.parsed_body
expect(response_json.first["title"]).to eq("My Grading Scheme")
end

it "returns archived schemes if the parameter is included" do
data = GradingSchemesJsonController.to_grading_standard_data(test_data)
course_level_grading_standard = @course.grading_standards.build(title: "My Grading Scheme",
data:,
scaling_factor: 1.0,
points_based: false,
workflow_state: "archived")
course_level_grading_standard.save
user_session(@admin)
get "/courses/#{@course.id}/grading_schemes?include_archived=true", as: :json
expect(response).to have_http_status(:ok)

response_json = response.parsed_body
expect(response_json.first["title"]).to eq("My Grading Scheme")
end

it "does not return archived schemes if the parameter is not included" do
data = GradingSchemesJsonController.to_grading_standard_data(test_data)
course_level_grading_standard = @course.grading_standards.build(title: "My Grading Scheme",
data:,
scaling_factor: 1.0,
points_based: false,
workflow_state: "archived")
course_level_grading_standard.save
user_session(@admin)
get "/courses/#{course_level_grading_standard.context_id}/grading_schemes", as: :json
expect(response).to have_http_status(:ok)

response_json = response.parsed_body
expect(response_json.first).to be_nil
end
end

describe "get grouped schemes list by workflow_state" do
Expand Down
16 changes: 16 additions & 0 deletions spec/models/grading_standard_spec.rb
Expand Up @@ -193,6 +193,22 @@ def compare_schemes(subject, expected)
expect(standards.length).to eq 1
expect(standards[0].id).to eq @standard.id
end

it "only includes active schemes when include_archived is false" do
grading_standard_for @course
@standard.archive!
standards = GradingStandard.for(@course)
expect(standards.length).to eq 0
end

it "includes archived when the parameter is true for archived grading schemes" do
Account.site_admin.enable_feature!(:archived_grading_schemes)
grading_standard_for @course
@standard.archive!
standards = GradingStandard.for(@course, include_archived: true)
expect(standards.length).to eq 1
expect(standards[0].id).to eq @standard.id
end
end

context "sorted" do
Expand Down
89 changes: 89 additions & 0 deletions spec/selenium/assignments/assignments_spec.rb
Expand Up @@ -140,6 +140,95 @@ def create_assignment(publish = true, params = { name: "Test Assignment" })
expect(f("#speed-grader-link-container").attribute("class")).to include("hidden")
end

context "archived grading schemes enabled" do
before do
Account.site_admin.enable_feature!(:grading_scheme_updates)
Account.site_admin.enable_feature!(:archived_grading_schemes)
@account = @course.account
@active_grading_standard = @course.grading_standards.create!(title: "Active Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "active")
@archived_grading_standard = @course.grading_standards.create!(title: "Archived Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
@account_grading_standard = @account.grading_standards.create!(title: "Account Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "active")
assignment_name = "first test assignment"
due_date = Time.now.utc + 2.days
group = @course.assignment_groups.create!(name: "default")
@course.assignment_groups.create!(name: "second default")
@assignment = @course.assignments.create!(
name: assignment_name,
due_at: due_date,
assignment_group: group,
unlock_at: due_date - 1.day,
grading_type: "letter_grade"
)
end

it "shows archived grading scheme if it is the course default twice, once to follow course default scheme and once to choose that scheme to use" do
@course.update!(grading_standard_id: @archived_grading_standard.id)
@course.reload
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq(@archived_grading_standard.title + " (course default)")
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-option-#{@course.grading_standard.id}']")).to include_text(@course.grading_standard.title)
end

it "shows archived grading scheme if it is the current assignment grading standard" do
@assignment.update!(grading_standard_id: @archived_grading_standard.id)
@assignment.reload
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq(@archived_grading_standard.title)
end

it "removes grading schemes from dropdown after archiving them but still shows them upon reopening the modal" do
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-option-#{@active_grading_standard.id}']")).to be_present
f("[data-testid='manage-all-grading-schemes-button']").click
wait_for_ajaximations
f("[data-testid='grading-scheme-#{@active_grading_standard.id}-archive-button']").click
wait_for_ajaximations
f("[data-testid='manage-all-grading-schemes-close-button']").click
wait_for_ajaximations
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-dropdown-form']")).not_to contain_css("[data-testid='grading-schemes-selector-option-#{@active_grading_standard.id}']")
f("[data-testid='manage-all-grading-schemes-button']").click
wait_for_ajaximations
expect(f("[data-testid='grading-scheme-row-#{@active_grading_standard.id}']").text).to be_present
end

it "shows all archived schemes in the manage grading schemes modal" do
archived_gs1 = @course.grading_standards.create!(title: "Archived Grading Scheme 1", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
archived_gs2 = @course.grading_standards.create!(title: "Archived Grading Scheme 2", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
archived_gs3 = @course.grading_standards.create!(title: "Archived Grading Scheme 3", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
f("[data-testid='manage-all-grading-schemes-button']").click
wait_for_ajaximations
expect(f("[data-testid='grading-scheme-#{archived_gs1.id}-name']")).to include_text(archived_gs1.title)
expect(f("[data-testid='grading-scheme-#{archived_gs2.id}-name']")).to include_text(archived_gs2.title)
expect(f("[data-testid='grading-scheme-#{archived_gs3.id}-name']")).to include_text(archived_gs3.title)
end

it "will still show the assignment grading scheme if you archive it on the edit page in the management modal and persist on reload" do
@assignment.update!(grading_standard_id: @active_grading_standard.id)
@assignment.reload
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq(@active_grading_standard.title)
f("[data-testid='manage-all-grading-schemes-button']").click
wait_for_ajaximations
f("[data-testid='grading-scheme-#{@active_grading_standard.id}-archive-button']").click
wait_for_ajaximations
f("[data-testid='manage-all-grading-schemes-close-button']").click
wait_for_ajaximations
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq(@active_grading_standard.title)
get "/courses/#{@course.id}/assignments/#{@assignment.id}/edit"
wait_for_ajaximations
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq(@active_grading_standard.title)
end
end

it "edits an assignment", priority: "1" do
assignment_name = "first test assignment"
due_date = Time.now.utc + 2.days
Expand Down
68 changes: 68 additions & 0 deletions spec/selenium/courses/course_settings_spec.rb
Expand Up @@ -175,6 +175,74 @@ def test_select_standard_for(context)
expect(course_status).to have_attribute("title", "You cannot unpublish this course if there are graded student submissions")
end

context "archived grading schemes" do
before do
Account.site_admin.enable_feature!(:grading_scheme_updates)
Account.site_admin.enable_feature!(:archived_grading_schemes)
@active_grading_standard = @course.grading_standards.create!(title: "Active Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "active")
@archived_grading_standard = @course.grading_standards.create!(title: "Archived Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
@account_grading_standard = @account.grading_standards.create!(title: "Account Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "active")
end

it "does not show archived grading schemes" do
get "/courses/#{@course.id}/settings"
f(".grading_standard_checkbox").click unless is_checked(".grading_standard_checkbox")
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-option-#{@active_grading_standard.id}']")).to include_text(@active_grading_standard.title)
expect(f("[data-testid='grading-schemes-selector-dropdown-form']")).not_to contain_css("[data-testid='grading-schemes-selector-option-#{@archived_grading_standard.id}']")
end

it "shows archived grading schemes if it is the course default and is auto-selected on page load" do
@course.update!(grading_standard_id: @archived_grading_standard.id)
get "/courses/#{@course.id}/settings"
f(".grading_standard_checkbox").click unless is_checked(".grading_standard_checkbox")
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("value")).to eq(@archived_grading_standard.title)
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-option-#{@course.grading_standard.id}']")).to include_text(@course.grading_standard.title)
end

it "doesn't let you edit an account level grading scheme" do
get "/courses/#{@course.id}/settings"
f(".grading_standard_checkbox").click unless is_checked(".grading_standard_checkbox")
f("[data-testid='grading-schemes-selector-dropdown']").click
expect(f("[data-testid='grading-schemes-selector-option-#{@account_grading_standard.id}']")).to include_text(@account_grading_standard.title)
f("[data-testid='grading-schemes-selector-option-#{@account_grading_standard.id}']").click
f("[data-testid='grading-schemes-selector-view-button']").click
wait_for_ajaximations
expect(f("[data-testid='grading-scheme-#{@account_grading_standard.id}-edit-button']").attribute("disabled")).to eq("true")
end

it "only lets you edit the name of an in-use grading-scheme" do
@course.update!(grading_standard_id: @active_grading_standard.id)
get "/courses/#{@course.id}/settings"
f(".grading_standard_checkbox").click unless is_checked(".grading_standard_checkbox")
f("[data-testid='grading-schemes-selector-dropdown']").click
f("[data-testid='grading-schemes-selector-option-#{@course.grading_standard.id}']").click
f("[data-testid='grading-schemes-selector-view-button']").click
wait_for_ajaximations
f("[data-testid='grading-scheme-#{@course.grading_standard.id}-edit-button']").click
wait_for_ajaximations
f("[data-testid='grading-scheme-name-input']").send_keys(" Edited")
f("[data-testid='grading-scheme-edit-modal-update-button']").click
wait_for_ajaximations
f("[data-testid='grading-scheme-view-modal-close-button']").click
expect(f("[data-testid='grading-schemes-selector-dropdown']").attribute("title")).to eq("Active Grading Scheme Edited")
end

it "shows all archived grading schemes when on course settings scheme management modal" do
archived_gs1 = @course.grading_standards.create!(title: "Archived Grading Scheme", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
archived_gs2 = @course.grading_standards.create!(title: "Archived Grading Scheme 2", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
archived_gs3 = @course.grading_standards.create!(title: "Archived Grading Scheme 3", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
get "/courses/#{@course.id}/settings"
f(".grading_standard_checkbox").click unless is_checked(".grading_standard_checkbox")
f("[data-testid='manage-all-grading-schemes-button']").click
wait_for_ajaximations
expect(f("[data-testid='grading-scheme-#{archived_gs1.id}-name']")).to include_text(archived_gs1.title)
expect(f("[data-testid='grading-scheme-#{archived_gs2.id}-name']")).to include_text(archived_gs2.title)
expect(f("[data-testid='grading-scheme-#{archived_gs3.id}-name']")).to include_text(archived_gs3.title)
end
end

it "allows selection of existing course grading standard" do
skip "FOO-4220" # TODO: re-enable this test before merging EVAL-3171
test_select_standard_for @course
Expand Down
12 changes: 12 additions & 0 deletions spec/selenium/grades/gradebook/gradebook_grade_edit_spec.rb
Expand Up @@ -96,6 +96,18 @@
expect(sub.score).to eq 0.0
end

it "loads archived schemes properly and uses them for assignments", priority: "1" do
grading_standard = @course.grading_standards.create!(title: "Test Grading Standard", data: { "A" => 0.9, "F" => 0 }, scaling_factor: 1.0, points_based: false, workflow_state: "archived")
assignment_model(course: @course, grading_type: "letter_grade", points_possible: 100, title: "no-points")
@assignment.update!(grading_standard_id: grading_standard.id)
@assignment.grade_student(@student_1, grade: 89, grader: @teacher)
puts(@student_1.name)
Gradebook.visit(@course)
expect(f("#gradebook_grid .container_1 .slick-row:nth-child(1) .b4")).to include_text("F")
edit_grade("#gradebook_grid .container_1 .slick-row:nth-child(1) .b4", "90")
expect(f("#gradebook_grid .container_1 .slick-row:nth-child(1) .b4")).to include_text("A")
end

it "tab sets focus on the options menu trigger when editing a grade", priority: "1" do
Gradebook.visit(@course)

Expand Down
Expand Up @@ -192,6 +192,7 @@ GradingTypeSelector.prototype.renderGradingSchemeSelector = function () {
contextId: ENV.COURSE_ID,
contextType: 'Course',
archivedGradingSchemesEnabled: ENV.ARCHIVED_GRADING_SCHEMES_ENABLED,
assignmentId: ENV.ASSIGNMENT.id ? String(this.parentModel.id) : undefined,
}
const mountPoint = document.querySelector('#grading_scheme_selector-target')
// eslint-disable-next-line react/no-render-return-value
Expand Down

0 comments on commit 0a8628e

Please sign in to comment.