Add variable substitution capabilities to TCP

Fixes PLAT-2235

Test Plan:
- Get the Canvas TCP and verify it contains all
  capabilities listed in lib/lti/capabilities_helper.rb:3
  in its capability_offered section.
- Install an LTI2 tool, launch it, and verify
  none of the following parameters are sent in
  the launch:
  * launch_presentation_document_target
  * launch_presentation_locale
  * tool_consumer_instance_guid
  * lis_course_section_sourcedid
  * roles
  * lis_person_sourcedid
 - Each of the above params now have an associated
   capability offered by Canvas. If a TP wants
   one of the above parameters sent in their
   tool launch they must include the associated
   capability in their enabled_capability section
   of the tool proxy.

   Verify adding the associated capability in the
   tool profile causes the paramter to be sent
   in the tool launch. See variable_expander.rb
   docs for a mapping of capabilities to
   variable names

Change-Id: I027d079d9d3cf53715fcf8ca4d9d8759af02cb88
Reviewed-on: https://gerrit.instructure.com/101336
Reviewed-by: Nathan Mills <nathanm@instructure.com>
Tested-by: Jenkins
QA-Review: August Thornton <august@instructure.com>
Product-Review: Weston Dransfield <wdransfield@instructure.com>
This commit is contained in:
wdransfield 2017-02-07 13:51:01 -07:00 committed by Weston Dransfield
parent fb3966a62d
commit adff709f9d
11 changed files with 385 additions and 125 deletions

View File

@ -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)

View File

@ -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

View File

@ -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 <a href="https://www.imsglobal.org/specs/ltiv1p1p1/implementation-guide#toc-9" target="_blank">IMS LTI specification.</a>
# 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 <a href="https://www.imsglobal.org/specs/ltimemv1p0/specification-3">IMS LTI membership service</a> 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.

View File

@ -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

View File

@ -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 <a href="https://www.imsglobal.org/specs/ltimemv1p0/specification-3">IMS LTI membership service</a> 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 <a href="https://www.imsglobal.org/specs/ltiv1p0/implementation-guide#toc-16" target ="_blank">LIS role full URNs</a>.
# 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.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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'}

View File

@ -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

View File

@ -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