Add ability to set calculation_method and calculation_int when creating

an outcome

When creating an outcome, allow the ability to specify
a calculation_method and/or a calculation_int

Fixes CNVS-17681

Test Plan:
    - Using the outcome groups API link action, create a new outcome with
      a specific calculation_method and calculation_int
      ('decaying_average' and 65 are a good test case)
    - Observe that an outcome was successfully created with the
      specified calculation_method and calculation_int
    - Attempt to create another outcome, this time specifying an invalid
      calculation_method (like 'foo bar baz qux')
    - Observe that the call fails with an explanatory error message
    - Repeat with a valid calculation_method but an invalid
      calculation_int (such as 'decaying_average' and 15000)
    - Observe a failed call with an explanatory error message

Change-Id: I7aacb66fa2b70291d7b09c53214191e1ed770a1a
Reviewed-on: https://gerrit.instructure.com/46326
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Simon Williams <simon@instructure.com>
QA-Review: Adam Stone <astone@instructure.com>
Product-Review: Benjamin Porter <bporter@instructure.com>
This commit is contained in:
Benjamin Porter 2014-12-26 21:53:54 -07:00
parent 1b86f2f51b
commit 2d4e4f5c92
3 changed files with 136 additions and 12 deletions

View File

@ -406,6 +406,12 @@ class OutcomeGroupsApiController < ApplicationController
# @argument ratings[][points] [Integer]
# The points corresponding to a rating level for the embedded rubric criterion.
#
# @argument calculation_method [String, "decaying_average"|"n_mastery"|"latest"|"highest"]
# The new calculation method.
#
# @argument calculation_int [Integer]
# The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"
#
# @returns OutcomeLink
#
# @example_request
@ -422,13 +428,15 @@ class OutcomeGroupsApiController < ApplicationController
# -F 'display_name=Title for reporting' \
# -F 'description=Outcome description' \
# -F 'vendor_guid=customid9000' \
# -F 'mastery_points=3' \
# -F 'ratings[][description]=Exceeds Expectations' \
# -F 'ratings[][points]=5' \
# -F 'ratings[][description]=Meets Expectations' \
# -F 'ratings[][points]=3' \
# -F 'ratings[][description]=Does Not Meet Expectations' \
# -F 'ratings[][points]=0' \
# -F 'mastery_points=3' \
# -F 'calculation_method=decaying_average' \
# -F 'calculation_int=75' \
# -F 'ratings[][description]=Exceeds Expectations' \
# -F 'ratings[][points]=5' \
# -F 'ratings[][description]=Meets Expectations' \
# -F 'ratings[][points]=3' \
# -F 'ratings[][description]=Does Not Meet Expectations' \
# -F 'ratings[][points]=0' \
# -H "Authorization: Bearer <token>"
#
# @example_request
@ -461,7 +469,7 @@ class OutcomeGroupsApiController < ApplicationController
return
end
else
@outcome = context_create_outcome(params.slice(:title, :description, :ratings, :mastery_points, :vendor_guid, :display_name))
@outcome = context_create_outcome(params.slice(:title, :description, :ratings, :mastery_points, :vendor_guid, :display_name, :calculation_method, :calculation_int))
unless @outcome.valid?
render :json => @outcome.errors, :status => :bad_request
return
@ -669,8 +677,10 @@ class OutcomeGroupsApiController < ApplicationController
def context_create_outcome(data)
scope = @context ? @context.created_learning_outcomes : LearningOutcome.global
outcome = scope.build(data.slice(:title, :display_name, :description, :vendor_guid))
if data[:ratings]
outcome.rubric_criterion = data.slice(:ratings, :mastery_points)
outcome.rubric_criterion = data.slice(:ratings, :mastery_points) if data[:ratings]
if data[:calculation_method]
outcome.calculation_method = data[:calculation_method]
outcome.calculation_int = data[:calculation_int]
end
outcome.save
outcome

View File

@ -178,14 +178,14 @@ class OutcomesApiController < ApplicationController
# -F 'description=Outcome description' \
# -F 'vendor_guid=customid9001' \
# -F 'mastery_points=3' \
# -F 'calculation_method=decaying_average' \
# -F 'calculation_int=75' \
# -F 'ratings[][description]=Exceeds Expectations' \
# -F 'ratings[][points]=5' \
# -F 'ratings[][description]=Meets Expectations' \
# -F 'ratings[][points]=3' \
# -F 'ratings[][description]=Does Not Meet Expectations' \
# -F 'ratings[][points]=0' \
# -F 'calculation_method=decaying_average' \
# -F 'calculation_int=75' \
# -F 'ratings[][points]=0' \
# -H "Authorization: Bearer <token>"
#

View File

@ -916,6 +916,120 @@ describe "Outcome Groups API", type: :request do
expect(@group.child_outcome_links.count).to eq 1
expect(@group.child_outcome_links.first.content).to eq @outcome
end
context "creating with calculation options specified" do
it "should create a new outcome with calculation options specified" do
LearningOutcome.update_all(:workflow_state => 'deleted')
api_call(:post, "/api/v1/accounts/#{@account.id}/outcome_groups/#{@group.id}/outcomes",
{ :controller => 'outcome_groups_api',
:action => 'link',
:account_id => @account.id.to_s,
:id => @group.id.to_s,
:format => 'json' },
{ :title => "My Outcome",
:display_name => "Friendly Name",
:description => "Description of my outcome",
:mastery_points => 5,
:ratings => [
{ :points => 5, :description => "Exceeds Expectations" },
{ :points => 3, :description => "Meets Expectations" },
{ :points => 0, :description => "Does Not Meet Expectations" }
],
:calculation_method => 'n_mastery',
:calculation_int => 4,
})
expect(LearningOutcome.active.count).to eq 1
@outcome = LearningOutcome.active.first
expect(@outcome.title).to eq "My Outcome"
expect(@outcome.display_name).to eq "Friendly Name"
expect(@outcome.description).to eq "Description of my outcome"
expect(@outcome.data[:rubric_criterion]).to eq({
:description => 'My Outcome',
:mastery_points => 5,
:points_possible => 5,
:ratings => [
{ :points => 5, :description => "Exceeds Expectations" },
{ :points => 3, :description => "Meets Expectations" },
{ :points => 0, :description => "Does Not Meet Expectations" }
]
})
expect(@outcome.calculation_method).to eq("n_mastery")
expect(@outcome.calculation_int).to eq(4)
end
it "should fail (400) to create a new outcome with illegal calculation options" do
LearningOutcome.update_all(:workflow_state => 'deleted')
json = api_call(:post, "/api/v1/accounts/#{@account.id}/outcome_groups/#{@group.id}/outcomes",
{ :controller => 'outcome_groups_api',
:action => 'link',
:account_id => @account.id.to_s,
:id => @group.id.to_s,
:format => 'json' },
{ :title => "My Outcome",
:display_name => "Friendly Name",
:description => "Description of my outcome",
:mastery_points => 5,
:ratings => [
{ :points => 5, :description => "Exceeds Expectations" },
{ :points => 3, :description => "Meets Expectations" },
{ :points => 0, :description => "Does Not Meet Expectations" }
],
:calculation_method => 'foo bar baz qux',
:calculation_int => 1500,
},
{},
{ :expected_status => 400 })
expect(LearningOutcome.active.count).to eq 0
expect(json).not_to be_nil
expect(json["errors"]).not_to be_nil
expect(json["errors"]["calculation_method"]).not_to be_nil
expect(json["errors"]["calculation_method"][0]).not_to be_nil
expect(json["errors"]["calculation_method"][0]["message"]).not_to be_nil
expect(json["errors"]["calculation_method"][0]["message"]).to include("not a valid calculation_method")
end
context "should fail (400) to create a new outcome with an illegal calculation_int" do
methods = [
'decaying_average',
'n_mastery',
'highest',
'latest'
]
methods.each do |method|
it "should fail (400) to create a new outcome with an illegal calculation_int" do
LearningOutcome.update_all(:workflow_state => 'deleted')
json = api_call(:post, "/api/v1/accounts/#{@account.id}/outcome_groups/#{@group.id}/outcomes",
{ :controller => 'outcome_groups_api',
:action => 'link',
:account_id => @account.id.to_s,
:id => @group.id.to_s,
:format => 'json' },
{ :title => "My Outcome",
:display_name => "Friendly Name",
:description => "Description of my outcome",
:mastery_points => 5,
:ratings => [
{ :points => 5, :description => "Exceeds Expectations" },
{ :points => 3, :description => "Meets Expectations" },
{ :points => 0, :description => "Does Not Meet Expectations" }
],
:calculation_method => method,
:calculation_int => 1500,
},
{},
{ :expected_status => 400 })
expect(LearningOutcome.active.count).to eq 0
expect(json).not_to be_nil
expect(json["errors"]).not_to be_nil
expect(json["errors"]["calculation_int"]).not_to be_nil
expect(json["errors"]["calculation_int"][0]).not_to be_nil
expect(json["errors"]["calculation_int"][0]["message"]).not_to be_nil
expect(json["errors"]["calculation_int"][0]["message"]).to include("not a valid calculation_int")
end
end
end
end
end
describe "unlink" do