diff --git a/app/controllers/lti/message_controller.rb b/app/controllers/lti/message_controller.rb
index eb408b1dd72..4ef7ff725d4 100644
--- a/app/controllers/lti/message_controller.rb
+++ b/app/controllers/lti/message_controller.rb
@@ -88,27 +88,32 @@ module Lti
oauth_consumer_key: tool_proxy.guid,
lti_version: IMS::LTI::Models::LTIModel::LTI_VERSION_2P0,
resource_link_id: build_resource_link_id(message_handler),
- context_id: Lti::Asset.opaque_identifier_for(@context),
- roles: Lti::SubstitutionsHelper.new(@context, @domain_root_account, @current_user).all_roles('lis2'),
+ context_id: Lti::Asset.opaque_identifier_for(@context)
}
- launch_params.merge! enabled_parameters(tool_proxy)
+
if params[:secure_params].present?
secure_params = Canvas::Security.decode_jwt(params[:secure_params])
launch_params.merge!({ext_lti_assignment_id: secure_params[:lti_assignment_id]}) if secure_params[:lti_assignment_id].present?
end
+
+ @lti_launch = Launch.new
+ tag = find_tag
+ custom_param_opts = prep_tool_settings(message_handler.parameters, tool_proxy, launch_params[:resource_link_id])
+ custom_param_opts[:content_tag] = tag if tag
+
+ variable_expander = create_variable_expander(custom_param_opts.merge(tool: tool_proxy))
+ launch_params.merge! enabled_parameters(tool_proxy, message_handler, variable_expander)
+
message = IMS::LTI::Models::Messages::BasicLTILaunchRequest.new(launch_params)
message.user_id = Lti::Asset.opaque_identifier_for(@current_user) if @current_user
@active_tab = message_handler.asset_string
- @lti_launch = Launch.new
@lti_launch.resource_url = message.launch_url
@lti_launch.link_text = resource_handler.name
@lti_launch.launch_type = message.launch_presentation_document_target
- tag = find_tag
module_sequence(tag) if tag
- custom_param_opts = prep_tool_settings(message_handler.parameters, tool_proxy, message.resource_link_id)
- custom_param_opts[:content_tag] = tag if tag
- message.add_custom_params(custom_params(message_handler.parameters, custom_param_opts.merge(tool: tool_proxy)))
+
+ message.add_custom_params(custom_params(message_handler.parameters, variable_expander))
message.add_custom_params(ToolSetting.custom_settings(tool_proxy.id, @context, message.resource_link_id))
@lti_launch.params = message.signed_post_params(tool_proxy.shared_secret)
@@ -133,10 +138,11 @@ module Lti
private
- def enabled_parameters(tp)
- param_capabilities_hash = CapabilitiesHelper.new(@context).parameter_capabilities_hash
- enabled_capabilities = IMS::LTI::Models::ToolProxy.from_json(tp.raw_data).enabled_capabilities
- param_capabilities_hash.each_with_object({}) { |(k, v), hash| hash[k] = v if enabled_capabilities.include? k }
+ def enabled_parameters(tp, mh, variable_expander)
+ tool_proxy = IMS::LTI::Models::ToolProxy.from_json(tp.raw_data)
+ enabled_capability = tool_proxy.enabled_capabilities
+ enabled_capability = enabled_capability.concat(mh.capabilities).uniq if mh.capabilities.present?
+ CapabilitiesHelper.capability_params_hash(enabled_capability, variable_expander)
end
def module_sequence(tag)
@@ -155,9 +161,9 @@ module Lti
end
end
- def custom_params(parameters, opts = {})
+ def custom_params(parameters, variable_expander)
params = IMS::LTI::Models::Parameter.from_json(parameters || [])
- IMS::LTI::Models::Parameter.process_params(params, create_variable_expander(opts))
+ IMS::LTI::Models::Parameter.process_params(params, variable_expander)
end
def find_binding(tool_proxy)
diff --git a/app/models/lti/tool_consumer_profile_creator.rb b/app/models/lti/tool_consumer_profile_creator.rb
index 4129b25888a..9e4de703f69 100644
--- a/app/models/lti/tool_consumer_profile_creator.rb
+++ b/app/models/lti/tool_consumer_profile_creator.rb
@@ -9,7 +9,6 @@ module Lti
CAPABILITIES = %w(
basic-lti-launch-request
- User.id
Canvas.api.domain
LtiLink.custom.url
ToolProxyBinding.custom.url
@@ -21,18 +20,11 @@ module Lti
Canvas.placements.postGrades
Canvas.placements.similarityDetection
User.username
- Person.email.primary
vnd.Canvas.Person.email.sis
- Person.name.given
- Person.name.family
- Person.name.full
- CourseSection.sourcedId
- Person.sourcedId
- Membership.role
ToolConsumerProfile.url
Security.splitSecret
Context.id
- ).concat(CapabilitiesHelper.new(@context).parameter_capabilities).freeze
+ ).concat(CapabilitiesHelper.supported_capabilities).freeze
RESTRICTED_CAPABILITIES = %W(
#{ORIGINALITY_REPORT_SERVICE}.url
diff --git a/doc/api/tools_variable_substitutions.md b/doc/api/tools_variable_substitutions.md
index 2e9f33692ec..c4f9c1b1495 100644
--- a/doc/api/tools_variable_substitutions.md
+++ b/doc/api/tools_variable_substitutions.md
@@ -26,6 +26,9 @@ masquerading users. Additionally, when we don't provide enough information or c
directly through LTI, tools can request everything they need to use the Canvas API for an even
richer experience.
+Some substitutions may be used as 'enabled_capabilities' for LTI2 tools. These substitutions have a
+'Launch Parameter' label indicating the parameter name that will be sent in the tool launch if enabled.
+
For more information on variable substitution, see the IMS LTI specification.
# Usage/Configuration
@@ -96,6 +99,33 @@ particular placement:
```
# Supported Substitutions
+## ToolConsumerInstance.guid
+returns a unique identifier for the Tool Consumer (Canvas)
+
+Launch Parameter: *tool_consumer_instance_guid*
+
+```
+0dWtgJjjFWRNT41WdQMvrleejGgv7AynCVm3lmZ2:canvas-lms
+```
+
+## Message.locale
+returns the current locale
+
+Launch Parameter: *launch_presentation_locale*
+
+```
+de
+```
+
+## Message.documentTarget
+communicates the kind of browser window/frame where the Canvas has launched a tool
+
+Launch Parameter: *launch_presentation_document_target*
+
+```
+iframe
+```
+
## Canvas.api.domain
returns the canvas domain for the current context. Should always be available.
@@ -104,7 +134,7 @@ canvas.instructure.com
```
## Canvas.api.collaborationMembers.url
-returns the api url for the members of the collaboration.
+returns the api url for the members of the collaboration.
```
https://canvas.instructure.com/api/v1/collaborations/1/members
@@ -118,7 +148,7 @@ https://canvas.instructure.com
```
## ToolProxyBinding.memberships.url
-returns the URL for the membership service associated with the current context.
+returns the URL for the membership service associated with the current context.
```
https://canvas.instructure.com/api/lti/courses/1/membership_service
@@ -238,6 +268,8 @@ YYY-MM-DD HH:MM:SS -0700
returns the current course sis source id. Only available when launched in a course.
to return the section source id use Canvas.course.sectionIds
+Launch Parameter: *lis_course_section_sourcedid*
+
```
1234
```
@@ -280,23 +312,35 @@ Only available when launched in a course that was copied (excludes cartridge imp
## Person.name.full
Returns the full name of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *lis_person_name_full*
+
```
John Doe
```
## Person.name.family
Returns the last name of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *lis_person_name_family*
+
```
Doe
```
## Person.name.given
Returns the last name of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *lis_person_name_given*
+
```
John
```
## Person.email.primary
Returns the primary email of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *lis_person_contact_email_primary*
+
```
john.doe@example.com
```
@@ -316,12 +360,18 @@ America/Denver
## User.image
Returns the profile picture URL of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *user_image*
+
```
https://example.com/picture.jpg
```
## User.id [duplicates Canvas.user.id and Canvas.user.loginId]
Returns the Canvas user_id of the launching user. Only available when launched by a logged in user.
+
+Launch Parameter: *user_id*
+
```
420000000000042
```
@@ -339,7 +389,7 @@ false
```
## Canvas.group.contextIds
-returns the context ids for the groups the user belongs to in the course.
+returns the context ids for the groups the user belongs to in the course.
```
1c16f0de65a080803785ecb3097da99872616f0d,d4d8d6ae1611e2c7581ce1b2f5c58019d928b79d,...
@@ -347,6 +397,9 @@ returns the context ids for the groups the user belongs to in the course.
## Membership.role
Returns the IMS LTI membership service roles for filtering via query parameters. Only available when launched by a logged in user.
+
+Launch Parameter: *roles*
+
```
http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator
```
@@ -579,4 +632,3 @@ Only available when an attachment is present and has usage rights defined.
## Canvas.file.usageRights.copyrightText
Only available when an attachment is present and has usage rights defined.
-
diff --git a/lib/lti/capabilities_helper.rb b/lib/lti/capabilities_helper.rb
index b466efcb5e5..6ac0d6d79af 100644
--- a/lib/lti/capabilities_helper.rb
+++ b/lib/lti/capabilities_helper.rb
@@ -1,40 +1,29 @@
module Lti
class CapabilitiesHelper
- attr_accessor :context
- def initialize(context)
- @context = context
+ SUPPORTED_CAPABILITIES = %w(ToolConsumerInstance.guid
+ CourseSection.sourcedId
+ Membership.role
+ Person.email.primary
+ Person.name.given
+ Person.name.family
+ Person.name.full
+ Person.sourcedId
+ User.id
+ User.image
+ Message.documentTarget
+ Message.locale
+ Membership.role).freeze
+
+ def self.supported_capabilities
+ SUPPORTED_CAPABILITIES
end
- def parameter_capabilities_hash
- @_param_capabilities_hash ||= begin
- recommended_params.merge optional_params
- end
+ def self.filter_capabilities(enabled_capability)
+ enabled_capability & SUPPORTED_CAPABILITIES
end
- def parameter_capabilities
- parameter_capabilities_hash.keys
+ def self.capability_params_hash(enabled_capability, variable_expander)
+ variable_expander.enabled_capability_params(filter_capabilities(enabled_capability))
end
-
- def recommended_params
- {
- 'launch_presentation_document_target' => IMS::LTI::Models::Messages::Message::LAUNCH_TARGET_IFRAME,
- 'tool_consumer_instance_guid' => tc_instance_guid
- }
- end
-
- def optional_params
- {
- 'launch_presentation_locale' => I18n.locale || I18n.default_locale.to_s
- }
- end
-
- private
-
- def tc_instance_guid
- if context.respond_to?(:root_account) && context.root_account.present?
- context.root_account.lti_guid
- end
- end
-
end
end
diff --git a/lib/lti/variable_expander.rb b/lib/lti/variable_expander.rb
index b1a59c7377b..10ba5bcd654 100644
--- a/lib/lti/variable_expander.rb
+++ b/lib/lti/variable_expander.rb
@@ -93,6 +93,44 @@ module Lti
end
end
+ def enabled_capability_params(enabled_capabilities)
+ enabled_capabilities.each_with_object({}) do |capability, hash|
+ if (expansion = capability.respond_to?(:to_sym) && self.class.expansions["$#{capability}".to_sym])
+ hash[expansion.default_name] = expansion.expand(self) if expansion.default_name.present?
+ end
+ end
+ end
+
+ # communicates the kind of browser window/frame where the Canvas has launched a tool
+ # associated launch param name: launch_presentation_document_target
+ # @example
+ # ```
+ # ifame
+ # ```
+ register_expansion 'Message.documentTarget', [],
+ -> { IMS::LTI::Models::Messages::Message::LAUNCH_TARGET_IFRAME },
+ default_name: 'launch_presentation_document_target'
+
+ # returns the current locale
+ # associated launch param name: launch_presentation_locale
+ # @example
+ # ```
+ # de
+ # ```
+ register_expansion 'Message.locale', [],
+ -> { I18n.locale || I18n.default_locale },
+ default_name: 'launch_presentation_locale'
+
+ # returns a unique identifier for the Tool Consumer (Canvas)
+ # associated launch param name: 'tool_consumer_instance_guid'
+ # @example
+ # ```
+ # 0dWtgJjjFWRNT41WdQMvrleejGgv7AynCVm3lmZ2:canvas-lms
+ # ```
+ register_expansion 'ToolConsumerInstance.guid', [],
+ -> { @root_account.lti_guid },
+ default_name: 'tool_consumer_instance_guid'
+
# returns the canvas domain for the current context.
# @example
# ```
@@ -282,13 +320,15 @@ module Lti
# returns the current course sis source id
# to return the section source id use Canvas.course.sectionIds
+ # associated launch param name: 'lis_course_section_sourcedid'
# @example
# ```
# 1234
# ```
register_expansion 'CourseSection.sourcedId', [],
-> { @context.sis_source_id },
- COURSE_GUARD
+ COURSE_GUARD,
+ default_name: 'lis_course_section_sourcedid'
# returns the current course enrollment state
# @example
@@ -338,40 +378,48 @@ module Lti
COURSE_GUARD
# Returns the full name of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: lis_person_name_full
# @example
# ```
# John Doe
# ```
register_expansion 'Person.name.full', [],
-> { @current_user.name },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'lis_person_name_full'
# Returns the last name of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: 'lis_person_name_family'
# @example
# ```
# Doe
# ```
register_expansion 'Person.name.family', [],
-> { @current_user.last_name },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'lis_person_name_family'
# Returns the first name of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: 'lis_person_name_given'
# @example
# ```
# John
# ```
register_expansion 'Person.name.given', [],
-> { @current_user.first_name },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'lis_person_name_given'
# Returns the primary email of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: 'lis_person_contact_email_primary'
# @example
# ```
# john.doe@example.com
# ```
register_expansion 'Person.email.primary', [],
-> { @current_user.email },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'lis_person_contact_email_primary'
# Returns the institution assigned email of the launching user. Only available when launched by a logged in user that was added via SIS.
@@ -395,22 +443,26 @@ module Lti
USER_GUARD
# Returns the profile picture URL of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: 'user_image'
# @example
# ```
# https://example.com/picture.jpg
# ```
register_expansion 'User.image', [],
-> { @current_user.avatar_url },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'user_image'
# Returns the Canvas user_id of the launching user. Only available when launched by a logged in user.
+ # associated launch param name: 'user_id'
# @example
# ```
# 420000000000042
# ```
register_expansion 'User.id', [],
-> { @current_user.id },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'user_id'
# Returns the Canvas user_id of the launching user. Only available when launched by a logged in user.
# @example
@@ -443,13 +495,15 @@ module Lti
# Returns the IMS LTI membership service roles for filtering via query parameters.
# Only available when launched by a logged in user.
+ # associated launch param name: 'roles'
# @example
# ```
# http://purl.imsglobal.org/vocab/lis/v2/institution/person#Administrator
# ```
register_expansion 'Membership.role', [],
-> { lti_helper.all_roles('lis2') },
- USER_GUARD
+ USER_GUARD,
+ default_name: 'roles'
# Returns list of LIS role full URNs.
# Should always be available.
@@ -521,7 +575,8 @@ module Lti
# ```
register_expansion 'Person.sourcedId', [],
-> { sis_pseudonym.sis_user_id },
- PSEUDONYM_GUARD
+ PSEUDONYM_GUARD,
+ default_name: 'lis_person_sourcedid'
# Returns the logout service url for the user.
# This is the pseudonym the user is actually logged in as.
diff --git a/lib/lti/variable_expansion.rb b/lib/lti/variable_expansion.rb
index cfee019ed2b..d9f384e6e78 100644
--- a/lib/lti/variable_expansion.rb
+++ b/lib/lti/variable_expansion.rb
@@ -22,14 +22,15 @@
module Lti
class VariableExpansion
- attr_reader :name, :permission_groups
+ attr_reader :name, :permission_groups, :default_name
- def initialize(name, permission_groups, expansion_proc, *guards)
+ def initialize(name, permission_groups, expansion_proc, *guards, default_name: nil)
@name = name
@permission_groups = permission_groups
@expansion_proc = expansion_proc
@guards = guards
@guards << -> { true } if @guards.empty?
+ @default_name = default_name
end
def expand(expander)
diff --git a/spec/controllers/lti/message_controller_spec.rb b/spec/controllers/lti/message_controller_spec.rb
index eef53ab9af0..b403f688c41 100644
--- a/spec/controllers/lti/message_controller_spec.rb
+++ b/spec/controllers/lti/message_controller_spec.rb
@@ -37,9 +37,10 @@ module Lti
)
end
let(:enabled_capability) {
- %w(tool_consumer_instance_guid
- launch_presentation_document_target
- launch_presentation_locale)
+ %w(ToolConsumerInstance.guid
+ Message.documentTarget
+ Message.locale
+ Membership.role)
}
let(:tool_proxy) do
ToolProxy.create(
@@ -267,10 +268,12 @@ module Lti
end
it 'returns the roles' do
+ course_with_student(account: account, active_all: true)
+ user_session(@student)
get 'basic_lti_launch_request', account_id: account.id, message_handler_id: message_handler.id,
params: {tool_launch_context: 'my_custom_context'}
params = assigns[:lti_launch].params.with_indifferent_access
- expect(params['roles']).to eq ["http://purl.imsglobal.org/vocab/lis/v2/person#None"]
+ expect(params['roles']).to eq "http://purl.imsglobal.org/vocab/lis/v2/system/person#User"
end
it 'adds module item substitutions' do
diff --git a/spec/lib/lti/capabilities_helper_spec.rb b/spec/lib/lti/capabilities_helper_spec.rb
index 7013aeb9ce0..ef6d47da2f4 100644
--- a/spec/lib/lti/capabilities_helper_spec.rb
+++ b/spec/lib/lti/capabilities_helper_spec.rb
@@ -1,64 +1,109 @@
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require_dependency "lti/capabilities_helper"
+# Get a list of valid capabilities
+# Validate capabilities array
+# return capability params hash
+
module Lti
describe CapabilitiesHelper do
- let(:test_lti_guid){ 'test-lti-guid-1234' }
- let(:root_account){ Account.new }
- let(:account){ Account.new(root_account: root_account) }
- let(:capabilities_helper){ CapabilitiesHelper.new(account) }
- let(:recommended_params){ %w(launch_presentation_document_target tool_consumer_instance_guid) }
- let(:optional_params){ %w(launch_presentation_locale) }
+ let(:root_account) { Account.new(lti_guid: 'test-lti-guid') }
+ let(:account) { Account.new(root_account: root_account) }
+ let(:course) { Course.new(account: account) }
+ let(:group_category) { course.group_categories.new(name: 'Category') }
+ let(:group) { course.groups.new(name: 'Group', group_category: group_category) }
+ let(:user) { User.new }
+ let(:assignment) { Assignment.new }
+ let(:collaboration) do
+ ExternalToolCollaboration.new(
+ title: "my collab",
+ user: user,
+ url: 'http://www.example.com'
+ )
+ end
+ let(:substitution_helper) { stub_everything }
+ let(:right_now) { DateTime.now }
+ let(:tool) do
+ m = mock('tool')
+ m.stubs(:id).returns(1)
+ m.stubs(:context).returns(root_account)
+ shard_mock = mock('shard')
+ shard_mock.stubs(:settings).returns({encription_key: 'abc'})
+ m.stubs(:shard).returns(shard_mock)
+ m.stubs(:opaque_identifier_for).returns("6cd2e0d65bd5aef3b5ee56a64bdcd595e447bc8f")
+ m
+ end
+ let(:controller) do
+ request_mock = mock('request')
+ request_mock.stubs(:url).returns('https://localhost')
+ request_mock.stubs(:host).returns('/my/url')
+ request_mock.stubs(:scheme).returns('https')
+ m = mock('controller')
+ m.stubs(:css_url_for).with(:common).returns('/path/to/common.scss')
+ m.stubs(:request).returns(request_mock)
+ m.stubs(:logged_in_user).returns(user)
+ m.stubs(:named_context_url).returns('url')
+ m.stubs(:polymorphic_url).returns('url')
+ view_context_mock = mock('view_context')
+ view_context_mock.stubs(:stylesheet_path)
+ .returns(URI.parse(request_mock.url).merge(m.css_url_for(:common)).to_s)
+ m.stubs(:view_context).returns(view_context_mock)
+ m
+ end
- describe "#recommended_params" do
- it "contains all supported recommended params" do
- expect(capabilities_helper.recommended_params.keys).to match_array(recommended_params)
- end
+ let(:variable_expander) { Lti::VariableExpander.new(root_account, account, controller, current_user: user, tool: tool) }
- it "gives correct value for launch_presentation_document_target"
-
- it "gives correct value for tool_consumer_instance_guid" do
- root_account.update_attributes(lti_guid: test_lti_guid)
- instance_guid = capabilities_helper.recommended_params['tool_consumer_instance_guid']
- expect(instance_guid).to eq root_account.lti_guid
- end
-
- it "gives nil for tool_consumer_instance_guid if context does not have root_account" do
- a = Account.new
- c_helper = CapabilitiesHelper.new(a)
- instance_guid = c_helper.recommended_params[:tool_consumer_instance_guid]
- expect(instance_guid).to be_nil
+ let(:invalid_enabled_caps){ %w(InvalidCap.Foo AnotherInvalid.Bar) }
+ let(:valid_enabled_caps){ %w(ToolConsumerInstance.guid Membership.role CourseSection.sourcedId) }
+ let(:supported_capabilities){
+ %w(ToolConsumerInstance.guid
+ CourseSection.sourcedId
+ Membership.role
+ Person.email.primary
+ Person.name.given
+ Person.name.family
+ Person.name.full
+ Person.sourcedId
+ User.id
+ User.image
+ Message.documentTarget
+ Message.locale
+ Membership.role)
+ }
+ describe '#supported_capabilities' do
+ it 'returns all supported capabilities asociated with launch params' do
+ expect(CapabilitiesHelper.supported_capabilities).to match_array(supported_capabilities)
end
end
- describe "#optional_params" do
- it "contains all supported optional params" do
- expect(capabilities_helper.optional_params.keys).to match_array(optional_params)
+ describe '#filter_capabilities' do
+ it 'removes invalid capabilities' do
+ valid_capabilities = CapabilitiesHelper.filter_capabilities(valid_enabled_caps + invalid_enabled_caps)
+ expect(valid_capabilities).not_to include(*invalid_enabled_caps)
end
- it "gives correct value for launch_presentation_locale with locale set" do
- allow_any_instance_of(I18n).to receive(:locale) { :en }
- launch_locale = capabilities_helper.optional_params['launch_presentation_locale']
- expect(launch_locale).to eq I18n.locale
- end
-
- it "gives correct value for launch_presentation_locale with locale not set" do
- allow_any_instance_of(I18n).to receive(:locale) { nil }
- allow_any_instance_of(I18n).to receive(:default_locale) { :da }
- launch_locale = capabilities_helper.optional_params['launch_presentation_locale']
- expect(launch_locale).to eq I18n.default_locale
+ it 'does not remove valid capabilities' do
+ valid_capabilities = CapabilitiesHelper.filter_capabilities(valid_enabled_caps + invalid_enabled_caps)
+ expect(valid_capabilities).to match_array valid_enabled_caps
end
end
- describe "#parameter_capabilities" do
- it "returns keys of all optional and recommended params" do
- expect(capabilities_helper.parameter_capabilities).to match_array(recommended_params + optional_params)
- end
- end
+ describe '#capability_params_hash' do
+ let(:valid_keys) { %w(tool_consumer_instance_guid roles lis_course_section_sourcedid) }
- describe "#paramter_capabilities_hash" do
- it "returns all recommended and optional params" do
- expect(capabilities_helper.parameter_capabilities_hash.keys).to match_array(recommended_params + optional_params)
+ it 'does not include a name (key) for invalid capabilities' do
+ params_hash = CapabilitiesHelper.capability_params_hash(invalid_enabled_caps + valid_enabled_caps, variable_expander)
+ expect(params_hash.keys).not_to include(*invalid_enabled_caps)
+ end
+
+ it 'does include a valid name (key) for valid capabilities' do
+ params_hash = CapabilitiesHelper.capability_params_hash(invalid_enabled_caps + valid_enabled_caps, variable_expander)
+ expect(params_hash.keys).to include(*valid_keys)
+ end
+
+ it 'does include a value for each valid capability' do
+ params_hash = CapabilitiesHelper.capability_params_hash(invalid_enabled_caps + valid_enabled_caps, variable_expander)
+ expect(params_hash.values.length).to eq valid_keys.length
end
end
end
diff --git a/spec/lib/lti/variable_expander_spec.rb b/spec/lib/lti/variable_expander_spec.rb
index 421d73b7bca..26932b644da 100644
--- a/spec/lib/lti/variable_expander_spec.rb
+++ b/spec/lib/lti/variable_expander_spec.rb
@@ -20,7 +20,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require_dependency "lti/variable_expander"
module Lti
describe VariableExpander do
- let(:root_account) { Account.new }
+ let(:root_account) { Account.new(lti_guid: 'test-lti-guid') }
let(:account) { Account.new(root_account: root_account) }
let(:course) { Course.new(account: account) }
let(:group_category) { course.group_categories.new(name: 'Category') }
@@ -116,6 +116,102 @@ module Lti
expect(expanded[:some_name]).to eq "my variable is buried in here ${tests_expan} can you find it?"
end
+ describe '#enabled_capability_params' do
+ let(:enabled_capability) {
+ %w(TestCapability.Foo
+ ToolConsumerInstance.guid
+ CourseSection.sourcedId
+ Membership.role
+ Person.email.primary
+ Person.name.given
+ Person.name.family
+ Person.name.full
+ Person.sourcedId
+ User.id
+ User.image
+ Message.documentTarget
+ Message.locale)
+ }
+
+ it 'does not use expansions that do not have default names' do
+ described_class.register_expansion('TestCapability.Foo', ['a'], -> {'test'})
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).not_to include 'TestCapability.Foo'
+ end
+
+ it 'does use expansion that have default names' do
+ described_class.register_expansion('TestCapability.Foo', ['a'], -> { 'test' }, default_name: 'test_capability_foo')
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.values).to include('test')
+ end
+
+ it 'does use the default name as the key' do
+ described_class.register_expansion('TestCapability.Foo', ['a'], -> { 'test' }, default_name: 'test_capability_foo')
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded['test_capability_foo']).to eq 'test'
+ end
+
+ it 'includes ToolConsumerInstance.guid when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded['tool_consumer_instance_guid']).to eq 'test-lti-guid'
+ end
+
+ it 'includes CourseSection.sourcedId when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_course_section_sourcedid'
+ end
+
+ it 'includes Membership.role when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'roles'
+ end
+
+ it 'includes Person.email.primary when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_person_contact_email_primary'
+ end
+
+ it 'includes Person.name.given when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_person_name_given'
+ end
+
+ it 'includes Person.name.family when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_person_name_family'
+ end
+
+ it 'includes Person.name.full when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_person_name_full'
+ end
+
+ it 'includes Person.sourcedId when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'lis_person_sourcedid'
+ end
+
+ it 'includes User.id when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'user_id'
+ end
+
+ it 'includes User.image when in enabled capability' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'user_image'
+ end
+
+ it 'includes Message.documentTarget' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'launch_presentation_document_target'
+ end
+
+ it 'includes Message.locale' do
+ expanded = subject.enabled_capability_params(enabled_capability)
+ expect(expanded.keys).to include 'launch_presentation_locale'
+ end
+ end
+
context 'lti1' do
it 'handles expansion' do
described_class.register_expansion('test_expan', ['a'], -> { @context })
@@ -132,7 +228,19 @@ module Lti
expect(expanded['some_name']).to eq "my variable is buried in here 42 can you find it?"
end
end
+
describe "#variable expansions" do
+ it 'has substitution for Message.documentTarget' do
+ exp_hash = {test: '$Message.documentTarget'}
+ subject.expand_variables!(exp_hash)
+ expect(exp_hash[:test]).to eq IMS::LTI::Models::Messages::Message::LAUNCH_TARGET_IFRAME
+ end
+
+ it 'has substitution for Message.locale' do
+ exp_hash = {test: '$Message.locale'}
+ subject.expand_variables!(exp_hash)
+ expect(exp_hash[:test]).to eq I18n.locale
+ end
it 'has substitution for $Canvas.api.domain' do
exp_hash = {test: '$Canvas.api.domain'}
diff --git a/spec/lib/lti/variable_expansion_spec.rb b/spec/lib/lti/variable_expansion_spec.rb
index b91d5877d2a..7cccd2f19c4 100644
--- a/spec/lib/lti/variable_expansion_spec.rb
+++ b/spec/lib/lti/variable_expansion_spec.rb
@@ -40,6 +40,11 @@ module Lti
expect(var_exp.expand(TestExpander.new)).to eq '$test'
end
+ it 'accepts and sets default_name' do
+ var_exp = described_class.new('test', [], -> { 'test' }, -> { true }, default_name: 'test_name' )
+ expect(var_exp.default_name).to eq 'test_name'
+ end
+
it 'expands variables' do
var_exp = described_class.new('test', [], -> { @one + @two + @three } )
expect(var_exp.expand(TestExpander.new)).to eq 6
diff --git a/spec/models/lti/tool_consumer_profile_creator_spec.rb b/spec/models/lti/tool_consumer_profile_creator_spec.rb
index 0c82adf907e..60c1e80eb2d 100644
--- a/spec/models/lti/tool_consumer_profile_creator_spec.rb
+++ b/spec/models/lti/tool_consumer_profile_creator_spec.rb
@@ -149,16 +149,20 @@ module Lti
expect(subject.create(true).capability_offered).to include 'vnd.Canvas.OriginalityReport.url'
end
- it 'adds the launch_presentation_document_target paramter capability' do
- expect(subject.create(true).capability_offered).to include 'launch_presentation_document_target'
+ it 'adds the Message.documentTarget capability' do
+ expect(subject.create(true).capability_offered).to include 'Message.documentTarget'
end
- it 'adds the tool_consumer_instance_guid paramter capability' do
- expect(subject.create(true).capability_offered).to include 'tool_consumer_instance_guid'
+ it 'adds the ToolConsumerInstance.guid capability' do
+ expect(subject.create(true).capability_offered).to include 'ToolConsumerInstance.guid'
end
- it 'adds the launch_presentation_locale paramter capability' do
- expect(subject.create(true).capability_offered).to include 'launch_presentation_locale'
+ it 'adds the Message.locale capability' do
+ expect(subject.create(true).capability_offered).to include 'Message.locale'
+ end
+
+ it 'adds the Membership.role capability' do
+ expect(subject.create(true).capability_offered).to include 'Membership.role'
end
it 'does not add the OriginalityReport capability if developer_key is false' do