qti 2.16.0 → 2.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c06cc4e78f29ecb23354e39dc3e93ac5da9600f0b09284a59b1202c553eb0c93
4
- data.tar.gz: b91ded981174a7822c7b6756f69e4a30daf5c6845f004a9a05da4a3f23a6af28
3
+ metadata.gz: 336700103b4d3c146a3a14e388d0cc03b568aa7561401ffabede5cab0881559d
4
+ data.tar.gz: 29a3213732a5377ba14d133c06a5e545c3f16c25e1e19200d9f4dd98e1b98792
5
5
  SHA512:
6
- metadata.gz: afcb1b453f47cec30c61b8d56d0a80109b6660a9f71b1e863db23cf8a3f6f79095dffd1512dad87554ba316d512574391dfe1f87da8c4bfa4efbbe74f95fcd2f
7
- data.tar.gz: a5acbfc53c6508b9d50e795435476b9aa72e32390f739697fd319dc4e4777037db4f7af5b70acbdc698fadcc5e0251af22e2ea7907cbf5b5ee8a3bed298a0b4b
6
+ metadata.gz: e31d581b78da6e468e3a8c5d188310585981b42c2a581f66d9938861c2fcdc701f86d8cbc99c13f3eaf6977e191237deb9904d50bd83159e6b780ffd89005846
7
+ data.tar.gz: 3ad4b4496777d9df2ef092ae2a9c9cbd7d19808c4939bbfdd63fdc1710faa85aeee2296c2209c8642fd15d9bf9ae417f5618f4858e13e4296075aaac65631c35
@@ -84,6 +84,27 @@ module Qti
84
84
  end
85
85
  end
86
86
 
87
+ def calculator_type
88
+ @calculator_type ||= begin
89
+ if calculator_type_metadata?
90
+ calculator_type_metadata_label = qti_metadata_children.children.find do |node|
91
+ node.text == 'calculator_type'
92
+ end
93
+ calculator_type_metadata_label.next.text
94
+ end
95
+ end
96
+ end
97
+
98
+ def calculator_type_metadata?
99
+ if @doc.at_xpath('.//xmlns:qtimetadata').present?
100
+ qti_metadata_children.children.find do |node|
101
+ node.text == 'calculator_type'
102
+ end.present?
103
+ else
104
+ false
105
+ end
106
+ end
107
+
87
108
  def decvar_maxvalue
88
109
  @doc.at_xpath('.//xmlns:decvar/@maxvalue')&.value&.to_i ||
89
110
  @doc.at_xpath('.//xmlns:decvar/@defaultval')&.value&.to_i || 0
@@ -40,6 +40,16 @@ module Qti
40
40
  @node.at_xpath('.//xmlns:render_choice/@shuffle')&.value.try(:downcase) == 'yes'
41
41
  end
42
42
 
43
+ def locked_choices
44
+ return [] unless shuffled?
45
+
46
+ @node.xpath('.//xmlns:response_label').filter_map.with_index do |answer_node, index|
47
+ is_locked = answer_node.attributes['lock']&.value&.downcase == 'yes'
48
+
49
+ is_locked ? index : nil
50
+ end
51
+ end
52
+
43
53
  def scoring_data_structs
44
54
  raise NotImplementedError
45
55
  end
@@ -0,0 +1,81 @@
1
+ module Qti
2
+ module V1
3
+ module Models
4
+ module Interactions
5
+ class CategorizationInteraction < BaseInteraction
6
+ def self.matches(node, parent)
7
+ return false if canvas_multiple_fib?(node)
8
+ matches = node.xpath('.//xmlns:response_lid')
9
+ return false if matches.count <= 1
10
+ rcardinality = matches.first.attributes['rcardinality']&.value || 'Single'
11
+ return false if rcardinality != 'Multiple'
12
+ new(node, parent)
13
+ end
14
+
15
+ def item_body
16
+ @item_body ||= begin
17
+ node = @node.dup
18
+ presentation = node.at_xpath('.//xmlns:presentation')
19
+ mattext = presentation.at_xpath('.//xmlns:mattext')
20
+ inner_content = return_inner_content!(mattext)
21
+ sanitize_content!(inner_content)
22
+ end
23
+ end
24
+
25
+ def categories
26
+ node.xpath('.//xmlns:response_lid').map do |lid_node|
27
+ mattext = lid_node.at_xpath('.//xmlns:mattext')
28
+ inner_content = return_inner_content!(mattext)
29
+ item_body = sanitize_content!(inner_content)
30
+ category_id = lid_node.attributes['ident'].value
31
+ [category_id, { id: category_id, item_body: item_body }]
32
+ end.to_h
33
+ end
34
+
35
+ def distractors
36
+ @distractors ||= choices.reduce({}) do |acc, answer|
37
+ acc.update answer.identifier => answer.item_body
38
+ end
39
+ end
40
+
41
+ def scoring_data_structs
42
+ @scoring_data_structs ||= parse_scoring_data
43
+ end
44
+
45
+ private
46
+
47
+ def parse_scoring_data
48
+ # This preserves the original behavior while not breaking on item feedback
49
+ path = './/xmlns:respcondition/xmlns:setvar/../xmlns:conditionvar/xmlns:varequal'
50
+ raw_scoring_data = node.xpath(path).reduce({}) do |acc, node|
51
+ category_id = node.attributes['respident'].value
52
+ values = (acc[category_id] || []) + [node.text]
53
+ acc.update category_id => values
54
+ end
55
+
56
+ raw_scoring_data.map do |id, values|
57
+ Models::ScoringData.new(values, rcardinality, id: id)
58
+ end
59
+ end
60
+
61
+ def choices
62
+ @choices ||= answer_nodes.map do |node|
63
+ V1::Models::Choices::LogicalIdentifierChoice.new(node, self)
64
+ end
65
+ end
66
+
67
+ def answer_nodes
68
+ responses = []
69
+ response_ids = Set.new
70
+ node.xpath('.//xmlns:response_label').each do |answer_node|
71
+ ident = answer_node.attributes['ident'].value
72
+ responses << answer_node unless response_ids.include? ident
73
+ response_ids << ident
74
+ end
75
+ responses
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -17,7 +17,8 @@ module Qti
17
17
  'calculated_question' => FormulaInteraction,
18
18
  'essay_question ' => StringInteraction,
19
19
  'file_upload_question' => UploadInteraction,
20
- 'hot_spot_question' => HotSpotInteraction
20
+ 'hot_spot_question' => HotSpotInteraction,
21
+ 'categorization_question' => CategorizationInteraction
21
22
  # "text_only_question" => StimulusNoQuestion
22
23
  }.freeze
23
24
 
data/lib/qti/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qti
2
- VERSION = '2.16.0'.freeze
2
+ VERSION = '2.18.1'.freeze
3
3
  end
data/lib/qti.rb CHANGED
@@ -123,6 +123,7 @@ require 'qti/v1/models/interactions/choice_interaction'
123
123
 
124
124
  require 'qti/v1/models/interactions/base_fill_blank_interaction'
125
125
  require 'qti/v1/models/interactions/canvas_multiple_dropdown'
126
+ require 'qti/v1/models/interactions/categorization_interaction'
126
127
  require 'qti/v1/models/interactions/fill_blank_interaction'
127
128
  require 'qti/v1/models/interactions/formula_interaction'
128
129
  require 'qti/v1/models/interactions/hot_spot_interaction'
@@ -0,0 +1,133 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
3
+ <assessment ident="id2b817165c302c0c57416146dc94ce47" title="Quiz with hot-spot question">
4
+ <qtimetadata>
5
+ <qtimetadatafield>
6
+ <fieldlabel>cc_maxattempts</fieldlabel>
7
+ <fieldentry>1</fieldentry>
8
+ </qtimetadatafield>
9
+ </qtimetadata>
10
+ <section ident="root_section">
11
+ <item ident="d74b47a4abeeed159e030bfecbcecea2" title="quiz with categorization question">
12
+ <itemmetadata>
13
+ <qtimetadata>
14
+ <qtimetadatafield>
15
+ <fieldlabel>question_type</fieldlabel>
16
+ <fieldentry>categorization_question</fieldentry>
17
+ </qtimetadatafield>
18
+ <qtimetadatafield>
19
+ <fieldlabel>points_possible</fieldlabel>
20
+ <fieldentry>1.0</fieldentry>
21
+ </qtimetadatafield>
22
+ <qtimetadatafield>
23
+ <fieldlabel>original_answer_ids</fieldlabel>
24
+ <fieldentry/>
25
+ </qtimetadatafield>
26
+ <qtimetadatafield>
27
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
28
+ <fieldentry>9f47365e112840d80a79a960b1b0b6a7</fieldentry>
29
+ </qtimetadatafield>
30
+ </qtimetadata>
31
+ </itemmetadata>
32
+ <presentation>
33
+ <material>
34
+ <mattext texttype="text/html">&lt;p&gt;Hello there&lt;/p&gt;</mattext>
35
+ </material>
36
+ <response_lid ident="df4fb8d7-8033-445a-b8be-171dd9b973ba" rcardinality="Multiple">
37
+ <material>
38
+ <mattext texttype="text/plain">Category_A</mattext>
39
+ </material>
40
+ <render_choice>
41
+ <response_label ident="19e37ce3-3a8b-4e26-ab61-9770e58af00e">
42
+ <material>
43
+ <mattext texttype="text/plain">Distractor2</mattext>
44
+ </material>
45
+ </response_label>
46
+ <response_label ident="3b8dcef8-c8c1-4827-85b0-6e381739adbf">
47
+ <material>
48
+ <mattext texttype="text/plain">B1</mattext>
49
+ </material>
50
+ </response_label>
51
+ <response_label ident="53a97aa7-d55c-402c-a061-f85d837c7c77">
52
+ <material>
53
+ <mattext texttype="text/plain">A2</mattext>
54
+ </material>
55
+ </response_label>
56
+ <response_label ident="5a67c627-cf85-4b70-922a-c7d1b7c720b8">
57
+ <material>
58
+ <mattext texttype="text/plain">B2</mattext>
59
+ </material>
60
+ </response_label>
61
+ <response_label ident="5d78f3f5-28c2-4e71-9c33-70c6b301e017">
62
+ <material>
63
+ <mattext texttype="text/plain">Distractor1</mattext>
64
+ </material>
65
+ </response_label>
66
+ <response_label ident="9432e8cb-1d3e-4d04-89b5-95185b7e557d">
67
+ <material>
68
+ <mattext texttype="text/plain">A1</mattext>
69
+ </material>
70
+ </response_label>
71
+ </render_choice>
72
+ </response_lid>
73
+ <response_lid ident="eb2f823d-b857-4c06-9d5f-998d14ee8d58" rcardinality="Multiple">
74
+ <material>
75
+ <mattext texttype="text/plain">Category_B</mattext>
76
+ </material>
77
+ <render_choice>
78
+ <response_label ident="19e37ce3-3a8b-4e26-ab61-9770e58af00e">
79
+ <material>
80
+ <mattext texttype="text/plain">Distractor2</mattext>
81
+ </material>
82
+ </response_label>
83
+ <response_label ident="3b8dcef8-c8c1-4827-85b0-6e381739adbf">
84
+ <material>
85
+ <mattext texttype="text/plain">B1</mattext>
86
+ </material>
87
+ </response_label>
88
+ <response_label ident="53a97aa7-d55c-402c-a061-f85d837c7c77">
89
+ <material>
90
+ <mattext texttype="text/plain">A2</mattext>
91
+ </material>
92
+ </response_label>
93
+ <response_label ident="5a67c627-cf85-4b70-922a-c7d1b7c720b8">
94
+ <material>
95
+ <mattext texttype="text/plain">B2</mattext>
96
+ </material>
97
+ </response_label>
98
+ <response_label ident="5d78f3f5-28c2-4e71-9c33-70c6b301e017">
99
+ <material>
100
+ <mattext texttype="text/plain">Distractor1</mattext>
101
+ </material>
102
+ </response_label>
103
+ <response_label ident="9432e8cb-1d3e-4d04-89b5-95185b7e557d">
104
+ <material>
105
+ <mattext texttype="text/plain">A1</mattext>
106
+ </material>
107
+ </response_label>
108
+ </render_choice>
109
+ </response_lid>
110
+ </presentation>
111
+ <resprocessing>
112
+ <outcomes>
113
+ <decvar maxvalue="100" minvalue="0" varname="SCORE" vartype="Decimal"/>
114
+ </outcomes>
115
+ <respcondition>
116
+ <conditionvar>
117
+ <varequal respident="df4fb8d7-8033-445a-b8be-171dd9b973ba">9432e8cb-1d3e-4d04-89b5-95185b7e557d</varequal>
118
+ <varequal respident="df4fb8d7-8033-445a-b8be-171dd9b973ba">53a97aa7-d55c-402c-a061-f85d837c7c77</varequal>
119
+ </conditionvar>
120
+ <setvar action="Add" varname="SCORE">50.00</setvar>
121
+ </respcondition>
122
+ <respcondition>
123
+ <conditionvar>
124
+ <varequal respident="eb2f823d-b857-4c06-9d5f-998d14ee8d58">3b8dcef8-c8c1-4827-85b0-6e381739adbf</varequal>
125
+ <varequal respident="eb2f823d-b857-4c06-9d5f-998d14ee8d58">5a67c627-cf85-4b70-922a-c7d1b7c720b8</varequal>
126
+ </conditionvar>
127
+ <setvar action="Add" varname="SCORE">50.00</setvar>
128
+ </respcondition>
129
+ </resprocessing>
130
+ </item>
131
+ </section>
132
+ </assessment>
133
+ </questestinterop>
@@ -21,7 +21,7 @@
21
21
  </material>
22
22
  <response_lid ident="QUE_1004_RL" rcardinality="Single" rtiming="No">
23
23
  <render_choice shuffle="Yes">
24
- <response_label ident="QUE_1005_A1">
24
+ <response_label ident="QUE_1005_A1" lock="Yes">
25
25
  <material>
26
26
  <mattext texttype="text/html"><![CDATA[True]]></mattext>
27
27
  </material>
@@ -0,0 +1,90 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <questestinterop xmlns="http://www.imsglobal.org/xsd/ims_qtiasiv1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd">
3
+ <assessment title="1.2 Import Quiz" ident="A1001">
4
+ <section title="Main" ident="S1002">
5
+ <item title="Grading - specific - 3 pt score" ident="QUE_1003">
6
+ <itemmetadata>
7
+ <qtimetadata>
8
+ <qtimetadatafield>
9
+ <fieldlabel>question_type</fieldlabel>
10
+ <fieldentry>true_false_question</fieldentry>
11
+ </qtimetadatafield>
12
+ <qtimetadatafield>
13
+ <fieldlabel>assessment_question_identifierref</fieldlabel>
14
+ <fieldentry>iff205c7405d3b36bdca9b75b51198932</fieldentry>
15
+ </qtimetadatafield>
16
+ <qtimetadatafield>
17
+ <fieldlabel>calculator_type</fieldlabel>
18
+ <fieldentry>basic</fieldentry>
19
+ </qtimetadatafield>
20
+ </qtimetadata>
21
+ </itemmetadata>
22
+ <presentation>
23
+ <material>
24
+ <mattext texttype="text/html"><![CDATA[If I get a 3, I must have done something wrong. <img data-equation-content="sample equation" script="alert('bad')" align="bottom" alt="image.png" src="org0/images/image.png" border="0"/> <img script="alert('bad')" align="bottom" alt="image.png" src="org0/images/image.png" border="0"/>]]></mattext>
25
+ </material>
26
+ <response_lid ident="QUE_1004_RL" rcardinality="Single" rtiming="No">
27
+ <render_choice shuffle="Yes">
28
+ <response_label ident="QUE_1005_A1">
29
+ <material>
30
+ <mattext texttype="text/html"><![CDATA[True]]></mattext>
31
+ </material>
32
+ </response_label>
33
+ <response_label ident="QUE_1006_A2">
34
+ <material>
35
+ <mattext texttype="text/html"><![CDATA[False]]></mattext>
36
+ </material>
37
+ </response_label>
38
+ </render_choice>
39
+ </response_lid>
40
+ </presentation>
41
+ <resprocessing>
42
+ <outcomes>
43
+ <decvar vartype="Decimal" defaultval="0" varname="que_score"/>
44
+ </outcomes>
45
+ <respcondition>
46
+ <conditionvar>
47
+ <varequal respident="QUE_1004_RL">QUE_1005_A1</varequal>
48
+ </conditionvar>
49
+ <setvar varname="que_score" action="Add">0</setvar>
50
+ </respcondition>
51
+ <respcondition>
52
+ <conditionvar>
53
+ <varequal respident="QUE_1004_RL">QUE_1006_A2</varequal>
54
+ </conditionvar>
55
+ <setvar varname="que_score" action="Set">10.00</setvar>
56
+ <displayfeedback feedbacktype="Response" linkrefid="fb_QUE_1006_A2"/>
57
+ </respcondition>
58
+ </resprocessing>
59
+ <itemfeedback ident="general_fb">
60
+ <flow_mat>
61
+ <material>
62
+ <mattext texttype="text/html">&lt;p&gt;Neutral&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
63
+ </material>
64
+ </flow_mat>
65
+ </itemfeedback>
66
+ <itemfeedback ident="correct_fb">
67
+ <flow_mat>
68
+ <material>
69
+ <mattext texttype="text/html">&lt;p&gt;Correct&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
70
+ </material>
71
+ </flow_mat>
72
+ </itemfeedback>
73
+ <itemfeedback ident="general_incorrect_fb">
74
+ <flow_mat>
75
+ <material>
76
+ <mattext texttype="text/html">&lt;p&gt;Incorrect&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
77
+ </material>
78
+ </flow_mat>
79
+ </itemfeedback>
80
+ <itemfeedback ident="fb_QUE_1006_A2">
81
+ <flow_mat>
82
+ <material>
83
+ <mattext texttype="text/html">&lt;p&gt;Answer was Correct&lt;/p&gt;&lt;img script="alert('bad')" alt="image.png" src="org0/images/image.png"/&gt;</mattext>
84
+ </material>
85
+ </flow_mat>
86
+ </itemfeedback>
87
+ </item>
88
+ </section>
89
+ </assessment>
90
+ </questestinterop>
@@ -115,6 +115,26 @@ describe Qti::V1::Models::AssessmentItem do
115
115
  end
116
116
  end
117
117
 
118
+ describe '#calculator_type' do
119
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
120
+ let(:assessment_item_refs) { test_object.assessment_items }
121
+ let(:loaded_class) { described_class.new(assessment_item_refs) }
122
+
123
+ context 'when it does not contain calculator_type metadata' do
124
+ let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'true_false.xml') }
125
+ it 'returns nil' do
126
+ expect(loaded_class.calculator_type).to be_nil
127
+ end
128
+ end
129
+
130
+ context 'when it contains calculator_type metadata' do
131
+ let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'true_false_with_calculator.xml') }
132
+ it 'returns the calculator_type value' do
133
+ expect(loaded_class.calculator_type).to eq 'basic'
134
+ end
135
+ end
136
+ end
137
+
118
138
  describe '#scoring_data_structs' do
119
139
  it 'grabs the rcardinality and scoring data value' do
120
140
  struct = loaded_class.send(:scoring_data_structs)
@@ -0,0 +1,62 @@
1
+ describe Qti::V1::Models::Interactions::CategorizationInteraction do
2
+ let(:xml_file_name) { 'categorization.xml' }
3
+ let(:fixtures_path) { File.join('spec', 'fixtures', 'items_1.2') }
4
+ let(:file_path) { File.join(fixtures_path, xml_file_name) }
5
+ let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
6
+ let(:assessment_item_refs) { test_object.assessment_items }
7
+ let(:item) { assessment_item_refs.first }
8
+
9
+ describe '.matches' do
10
+ it 'matches the item in file' do
11
+ expect(described_class.matches(item, test_object)).to be_truthy
12
+ end
13
+ end
14
+
15
+ describe '#item_body' do
16
+ let(:loaded_class) { described_class.new(item, test_object) }
17
+ it 'returns correct item body' do
18
+ expect(loaded_class.item_body).to eq '<p>Hello there</p>'
19
+ end
20
+ end
21
+
22
+ describe '#categories' do
23
+ let(:loaded_class) { described_class.new(item, test_object) }
24
+ it 'returns correct categories' do
25
+ expected_categories =
26
+ {
27
+ 'df4fb8d7-8033-445a-b8be-171dd9b973ba' => { id: 'df4fb8d7-8033-445a-b8be-171dd9b973ba',
28
+ item_body: 'Category_A' },
29
+ 'eb2f823d-b857-4c06-9d5f-998d14ee8d58' => { id: 'eb2f823d-b857-4c06-9d5f-998d14ee8d58',
30
+ item_body: 'Category_B' }
31
+ }
32
+ expect(loaded_class.categories).to eq(expected_categories)
33
+ end
34
+ end
35
+
36
+ describe '#distractors' do
37
+ let(:loaded_class) { described_class.new(item, test_object) }
38
+ it 'returns the correct distractors' do
39
+ expected_distractors =
40
+ { '19e37ce3-3a8b-4e26-ab61-9770e58af00e' => 'Distractor2',
41
+ '3b8dcef8-c8c1-4827-85b0-6e381739adbf' => 'B1',
42
+ '53a97aa7-d55c-402c-a061-f85d837c7c77' => 'A2',
43
+ '5a67c627-cf85-4b70-922a-c7d1b7c720b8' => 'B2',
44
+ '5d78f3f5-28c2-4e71-9c33-70c6b301e017' => 'Distractor1',
45
+ '9432e8cb-1d3e-4d04-89b5-95185b7e557d' => 'A1' }
46
+ expect(loaded_class.distractors).to eq(expected_distractors)
47
+ end
48
+ end
49
+
50
+ describe '#scoring_data_structs' do
51
+ let(:loaded_class) { described_class.new(item, test_object) }
52
+ it 'returns the correct scoring data structs' do
53
+ scoring_data_ids = %w[df4fb8d7-8033-445a-b8be-171dd9b973ba eb2f823d-b857-4c06-9d5f-998d14ee8d58]
54
+ scoring_data_values = [
55
+ %w[9432e8cb-1d3e-4d04-89b5-95185b7e557d 53a97aa7-d55c-402c-a061-f85d837c7c77],
56
+ %w[3b8dcef8-c8c1-4827-85b0-6e381739adbf 5a67c627-cf85-4b70-922a-c7d1b7c720b8]
57
+ ]
58
+ expect(loaded_class.scoring_data_structs.map(&:id)).to eq(scoring_data_ids)
59
+ expect(loaded_class.scoring_data_structs.map(&:values)).to eq(scoring_data_values)
60
+ end
61
+ end
62
+ end
@@ -10,6 +10,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
10
10
  end
11
11
  end
12
12
 
13
+ shared_examples_for 'locked_choices' do
14
+ it 'returns locked choices setting' do
15
+ expect(loaded_class.locked_choices).to eq locked_choices_value
16
+ end
17
+ end
18
+
13
19
  shared_examples_for 'answers' do
14
20
  it 'returns the answers' do
15
21
  expect(loaded_class.answers.count).to eq answer_choices_count
@@ -27,10 +33,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
27
33
  context 'multiple_choice.xml' do
28
34
  let(:file_path) { File.join(fixtures_path, 'multiple_choice.xml') }
29
35
  let(:shuffle_value) { false }
36
+ let(:locked_choices_value) { [] }
30
37
  let(:answer_choices_count) { 5 }
31
38
  let(:meta_type) { nil }
32
39
 
33
40
  include_examples 'shuffled?'
41
+ include_examples 'locked_choices'
34
42
  include_examples 'answers'
35
43
  include_examples 'meta_type'
36
44
  end
@@ -38,10 +46,12 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
38
46
  context 'true_false.xml' do
39
47
  let(:file_path) { File.join(fixtures_path, 'true_false.xml') }
40
48
  let(:shuffle_value) { true }
49
+ let(:locked_choices_value) { [0] }
41
50
  let(:answer_choices_count) { 2 }
42
51
  let(:meta_type) { 'true_false_question' }
43
52
 
44
53
  include_examples 'shuffled?'
54
+ include_examples 'locked_choices'
45
55
  include_examples 'answers'
46
56
  include_examples 'meta_type'
47
57
  end
@@ -49,17 +59,21 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
49
59
  context 'multiple_answer.xml' do
50
60
  let(:file_path) { File.join(fixtures_path, 'multiple_answer.xml') }
51
61
  let(:shuffle_value) { false }
62
+ let(:locked_choices_value) { [] }
52
63
 
53
64
  include_examples 'shuffled?'
65
+ include_examples 'locked_choices'
54
66
  end
55
67
 
56
68
  context 'multiple_answer_canvas.xml' do
57
69
  let(:file_path) { File.join(fixtures_path, 'multiple_answer_canvas.xml') }
58
70
  let(:shuffle_value) { false }
71
+ let(:locked_choices_value) { [] }
59
72
  let(:answer_choices_count) { 4 }
60
73
  let(:meta_type) { 'multiple_answers_question' }
61
74
 
62
75
  include_examples 'shuffled?'
76
+ include_examples 'locked_choices'
63
77
  include_examples 'meta_type'
64
78
  end
65
79
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qti
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.16.0
4
+ version: 2.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Diaz
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2023-07-06 00:00:00.000000000 Z
15
+ date: 2023-07-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: actionview
@@ -332,6 +332,7 @@ files:
332
332
  - lib/qti/v1/models/interactions/base_fill_blank_interaction.rb
333
333
  - lib/qti/v1/models/interactions/base_interaction.rb
334
334
  - lib/qti/v1/models/interactions/canvas_multiple_dropdown.rb
335
+ - lib/qti/v1/models/interactions/categorization_interaction.rb
335
336
  - lib/qti/v1/models/interactions/choice_interaction.rb
336
337
  - lib/qti/v1/models/interactions/fill_blank_interaction.rb
337
338
  - lib/qti/v1/models/interactions/formula_interaction.rb
@@ -397,6 +398,7 @@ files:
397
398
  - spec/fixtures/items_1.2/canvas_multiple_fib.xml
398
399
  - spec/fixtures/items_1.2/canvas_multiple_fib_as_single.xml
399
400
  - spec/fixtures/items_1.2/canvas_multiple_fib_extra_brackets.xml
401
+ - spec/fixtures/items_1.2/categorization.xml
400
402
  - spec/fixtures/items_1.2/choice.xml
401
403
  - spec/fixtures/items_1.2/essay.xml
402
404
  - spec/fixtures/items_1.2/fib.xml
@@ -426,6 +428,7 @@ files:
426
428
  - spec/fixtures/items_1.2/stimulus_with_child_item.xml
427
429
  - spec/fixtures/items_1.2/text.no.question.xml
428
430
  - spec/fixtures/items_1.2/true_false.xml
431
+ - spec/fixtures/items_1.2/true_false_with_calculator.xml
429
432
  - spec/fixtures/items_1.2/upload.xml
430
433
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
431
434
  - spec/fixtures/items_2.1/categorization.xml
@@ -678,6 +681,7 @@ files:
678
681
  - spec/lib/qti/v1/models/interactions/base_fill_blank_interaction_spec.rb
679
682
  - spec/lib/qti/v1/models/interactions/base_interaction_spec.rb
680
683
  - spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb
684
+ - spec/lib/qti/v1/models/interactions/categorization_interaction_spec.rb
681
685
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
682
686
  - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
683
687
  - spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb
@@ -762,6 +766,7 @@ test_files:
762
766
  - spec/fixtures/items_1.2/canvas_multiple_fib.xml
763
767
  - spec/fixtures/items_1.2/canvas_multiple_fib_as_single.xml
764
768
  - spec/fixtures/items_1.2/canvas_multiple_fib_extra_brackets.xml
769
+ - spec/fixtures/items_1.2/categorization.xml
765
770
  - spec/fixtures/items_1.2/choice.xml
766
771
  - spec/fixtures/items_1.2/essay.xml
767
772
  - spec/fixtures/items_1.2/fib.xml
@@ -791,6 +796,7 @@ test_files:
791
796
  - spec/fixtures/items_1.2/stimulus_with_child_item.xml
792
797
  - spec/fixtures/items_1.2/text.no.question.xml
793
798
  - spec/fixtures/items_1.2/true_false.xml
799
+ - spec/fixtures/items_1.2/true_false_with_calculator.xml
794
800
  - spec/fixtures/items_1.2/upload.xml
795
801
  - spec/fixtures/items_2.1/Example02-feedbackInline.xml
796
802
  - spec/fixtures/items_2.1/categorization.xml
@@ -1043,6 +1049,7 @@ test_files:
1043
1049
  - spec/lib/qti/v1/models/interactions/base_fill_blank_interaction_spec.rb
1044
1050
  - spec/lib/qti/v1/models/interactions/base_interaction_spec.rb
1045
1051
  - spec/lib/qti/v1/models/interactions/canvas_multiple_dropdown_spec.rb
1052
+ - spec/lib/qti/v1/models/interactions/categorization_interaction_spec.rb
1046
1053
  - spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb
1047
1054
  - spec/lib/qti/v1/models/interactions/fill_blank_interaction_spec.rb
1048
1055
  - spec/lib/qti/v1/models/interactions/formula_interaction_spec.rb