qti 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/qti.rb +1 -0
- data/lib/qti/v1/models/assessment.rb +17 -4
- data/lib/qti/v1/models/assessment_item.rb +4 -0
- data/lib/qti/v1/models/base.rb +2 -1
- data/lib/qti/v1/models/interactions/base_interaction.rb +36 -0
- data/lib/qti/v1/models/interactions/choice_interaction.rb +9 -0
- data/lib/qti/v1/models/interactions/fill_blank_interaction.rb +1 -1
- data/lib/qti/v1/models/interactions/match_interaction.rb +3 -1
- data/lib/qti/v1/models/interactions/numeric_interaction.rb +1 -1
- data/lib/qti/v1/models/interactions/string_interaction.rb +3 -2
- data/lib/qti/v1/models/stimulus_item.rb +33 -0
- data/lib/qti/v2/models/assessment_item.rb +4 -0
- data/lib/qti/v2/models/interactions/base_interaction.rb +2 -0
- data/lib/qti/version.rb +1 -1
- data/spec/fixtures/all_canvas_simple_1.2.xml +1676 -0
- data/spec/fixtures/feedback_quiz_1.2.xml +246 -0
- data/spec/fixtures/items_1.2/matching_feedback.xml +370 -0
- data/spec/fixtures/items_1.2/text.no.question.xml +36 -0
- data/spec/lib/qti/v1/models/assessment_item_spec.rb +11 -0
- data/spec/lib/qti/v1/models/assessment_spec.rb +187 -13
- data/spec/lib/qti/v1/models/interactions/base_interaction_spec.rb +56 -0
- data/spec/lib/qti/v1/models/interactions/choice_interaction_spec.rb +12 -0
- data/spec/lib/qti/v1/models/interactions/match_interaction_spec.rb +67 -23
- data/spec/lib/qti/v1/models/stimulus_item_spec.rb +55 -0
- metadata +14 -7
- data/spec/gemfiles/nokogiri-1.6.gemfile.lock +0 -149
- data/spec/gemfiles/nokogiri-1.8.gemfile.lock +0 -149
@@ -0,0 +1,36 @@
|
|
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="i1e5e0d6fba7342e63ae43afe9863070d" title="Quiz.text">
|
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="i5dae6b32741a0962b55c06c35e49ffb8" title="Question1">
|
12
|
+
<itemmetadata>
|
13
|
+
<qtimetadata>
|
14
|
+
<qtimetadatafield>
|
15
|
+
<fieldlabel>question_type</fieldlabel>
|
16
|
+
<fieldentry>text_only_question</fieldentry>
|
17
|
+
</qtimetadatafield>
|
18
|
+
<qtimetadatafield>
|
19
|
+
<fieldlabel>points_possible</fieldlabel>
|
20
|
+
<fieldentry>0</fieldentry>
|
21
|
+
</qtimetadatafield>
|
22
|
+
<qtimetadatafield>
|
23
|
+
<fieldlabel>assessment_question_identifierref</fieldlabel>
|
24
|
+
<fieldentry>if47b767d37e06559ff801f2d253307ba</fieldentry>
|
25
|
+
</qtimetadatafield>
|
26
|
+
</qtimetadata>
|
27
|
+
</itemmetadata>
|
28
|
+
<presentation>
|
29
|
+
<material>
|
30
|
+
<mattext texttype="text/html"><div><p>asfdfas asdvadsfsdav a . aasvdafa</p></div></mattext>
|
31
|
+
</material>
|
32
|
+
</presentation>
|
33
|
+
</item>
|
34
|
+
</section>
|
35
|
+
</assessment>
|
36
|
+
</questestinterop>
|
@@ -1,6 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Qti::V1::Models::AssessmentItem do
|
4
|
+
context 'multiple_fib' do
|
5
|
+
let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'single_fib.xml') }
|
6
|
+
let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
|
7
|
+
let(:assessment_item_refs) { test_object.assessment_items }
|
8
|
+
let(:loaded_class) { described_class.new(assessment_item_refs) }
|
9
|
+
|
10
|
+
it 'has sanitized item_body' do
|
11
|
+
expect(loaded_class.item_body).to include '<div'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
context 'quiz.xml' do
|
5
16
|
let(:file_path) { File.join('spec', 'fixtures', 'items_1.2', 'true_false.xml') }
|
6
17
|
let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
|
@@ -1,22 +1,174 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
fixtures_path = File.join('spec', 'fixtures')
|
4
|
-
|
5
3
|
describe Qti::V1::Models::Assessment do
|
6
|
-
|
7
|
-
|
4
|
+
describe 'interaction item' do
|
5
|
+
let(:fixtures_path) { File.join('spec', 'fixtures') }
|
6
|
+
shared_examples_for 'basic quiz fields' do
|
7
|
+
it 'loads an AssessmentXML file' do
|
8
|
+
expect do
|
9
|
+
described_class.from_path!(path)
|
10
|
+
end.to_not raise_error
|
11
|
+
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
describe '#title' do
|
14
|
+
context '<assessmentTest> has a title property' do
|
15
|
+
it 'has the title' do
|
16
|
+
expect(loaded_class.title).to eq(expected_title)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'it has the correct number of items' do
|
21
|
+
expect(loaded_class.assessment_items.count).to eq(expected_item_count)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
shared_examples_for 'verify quiz items' do
|
27
|
+
it 'has the correct item data' do
|
28
|
+
loaded_class.assessment_items.zip(expected_item_data).each do |node, cmp|
|
29
|
+
item = Qti::V1::Models::AssessmentItem.new(node)
|
30
|
+
expect(item.interaction_model.class).to eq(cmp[:interaction_class])
|
31
|
+
expect(item.title).to eq(cmp[:title])
|
32
|
+
expect(item.feedback).to eq(cmp[:feedback])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'reference qti 1.2 quiz' do
|
38
|
+
let(:path) { File.join(fixtures_path, 'test_qti_1.2', 'quiz.xml') }
|
39
|
+
let(:loaded_class) { described_class.from_path!(path) }
|
40
|
+
let(:expected_title) { '1.2 Import Quiz' }
|
41
|
+
let(:expected_item_count) { 5 }
|
42
|
+
|
43
|
+
include_examples('basic quiz fields')
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'quiz with feedback samples' do
|
47
|
+
let(:path) { File.join(fixtures_path, 'feedback_quiz_1.2.xml') }
|
48
|
+
let(:loaded_class) { described_class.from_path!(path) }
|
49
|
+
let(:expected_title) { 'I Can Haz Feedback' }
|
50
|
+
let(:expected_item_count) { 3 }
|
51
|
+
let(:expected_item_data) do
|
52
|
+
[
|
53
|
+
{
|
54
|
+
interaction_class: Qti::V1::Models::Interactions::StringInteraction,
|
55
|
+
title: 'Question',
|
56
|
+
feedback: { neutral: '<p>General Feedback</p>' }
|
57
|
+
},
|
58
|
+
{
|
59
|
+
interaction_class: Qti::V1::Models::Interactions::ChoiceInteraction,
|
60
|
+
title: 'Question',
|
61
|
+
feedback: { neutral: '<p>Neutral</p>', correct: '<p>Correct</p>', incorrect: '<p>Incorrect</p>' }
|
62
|
+
},
|
63
|
+
{
|
64
|
+
interaction_class: Qti::V1::Models::Interactions::ChoiceInteraction,
|
65
|
+
title: 'Question',
|
66
|
+
feedback: {}
|
67
|
+
}
|
68
|
+
]
|
69
|
+
end
|
14
70
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
71
|
+
include_examples('basic quiz fields')
|
72
|
+
include_examples('verify quiz items')
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'reference qti 1.2 quiz' do
|
76
|
+
let(:path) { File.join(fixtures_path, 'all_canvas_simple_1.2.xml') }
|
77
|
+
let(:loaded_class) { described_class.from_path!(path) }
|
78
|
+
let(:expected_title) { 'Every Canvas Interaction' }
|
79
|
+
let(:expected_item_count) { 10 }
|
80
|
+
let(:expected_item_data) do
|
81
|
+
[
|
82
|
+
{
|
83
|
+
interaction_class: Qti::V1::Models::Interactions::ChoiceInteraction,
|
84
|
+
title: 'Question 1',
|
85
|
+
feedback: {
|
86
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
87
|
+
correct: '<p>Item Feedback, Correct</p>',
|
88
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
89
|
+
}
|
90
|
+
},
|
91
|
+
{
|
92
|
+
interaction_class: Qti::V1::Models::Interactions::ChoiceInteraction,
|
93
|
+
title: 'Question 2',
|
94
|
+
feedback: {
|
95
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
96
|
+
correct: '<p>Item Feedback, Correct</p>',
|
97
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
98
|
+
}
|
99
|
+
},
|
100
|
+
{
|
101
|
+
interaction_class: Qti::V1::Models::Interactions::FillBlankInteraction,
|
102
|
+
title: 'Question 3',
|
103
|
+
feedback: {
|
104
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
105
|
+
correct: '<p>Item Feedback, Correct</p>',
|
106
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
107
|
+
}
|
108
|
+
},
|
109
|
+
{
|
110
|
+
interaction_class: Qti::V1::Models::Interactions::FillBlankInteraction,
|
111
|
+
title: 'Question 4',
|
112
|
+
feedback: {
|
113
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
114
|
+
correct: '<p>Item Feedback, Correct</p>',
|
115
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
116
|
+
}
|
117
|
+
},
|
118
|
+
{
|
119
|
+
interaction_class: Qti::V1::Models::Interactions::ChoiceInteraction,
|
120
|
+
title: 'Question 5',
|
121
|
+
feedback: {
|
122
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
123
|
+
correct: '<p>Item Feedback, Correct</p>',
|
124
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
125
|
+
}
|
126
|
+
},
|
127
|
+
{
|
128
|
+
interaction_class: Qti::V1::Models::Interactions::CanvasMultipleDropdownInteraction,
|
129
|
+
title: 'Question 6',
|
130
|
+
feedback: {
|
131
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
132
|
+
correct: '<p>Item Feedback, Correct</p>',
|
133
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
134
|
+
}
|
135
|
+
},
|
136
|
+
{
|
137
|
+
interaction_class: Qti::V1::Models::Interactions::MatchInteraction,
|
138
|
+
title: 'Question 7',
|
139
|
+
feedback: {
|
140
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
141
|
+
correct: '<p>Item Feedback, Correct</p>',
|
142
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
143
|
+
}
|
144
|
+
},
|
145
|
+
{
|
146
|
+
interaction_class: Qti::V1::Models::Interactions::NumericInteraction,
|
147
|
+
title: 'Question 8',
|
148
|
+
feedback: {
|
149
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
150
|
+
correct: '<p>Item Feedback, Correct</p>',
|
151
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
152
|
+
}
|
153
|
+
},
|
154
|
+
{
|
155
|
+
interaction_class: Qti::V1::Models::Interactions::FormulaInteraction,
|
156
|
+
title: 'Question 9',
|
157
|
+
feedback: {
|
158
|
+
neutral: '<p>Item Feedback, Neutral</p>',
|
159
|
+
correct: '<p>Item Feedback, Correct</p>',
|
160
|
+
incorrect: '<p>Item Feedback, Incorrect</p>'
|
161
|
+
}
|
162
|
+
},
|
163
|
+
{
|
164
|
+
interaction_class: Qti::V1::Models::Interactions::StringInteraction,
|
165
|
+
title: 'Question 10',
|
166
|
+
feedback: { neutral: '<p>Item Feedback, Neutral</p>' }
|
167
|
+
}
|
168
|
+
]
|
19
169
|
end
|
170
|
+
include_examples('basic quiz fields')
|
171
|
+
include_examples('verify quiz items')
|
20
172
|
end
|
21
173
|
|
22
174
|
context '<assessmentTest> has no title property' do
|
@@ -34,4 +186,26 @@ describe Qti::V1::Models::Assessment do
|
|
34
186
|
end
|
35
187
|
end
|
36
188
|
end
|
189
|
+
|
190
|
+
describe 'stimulus (text-no-question) item' do
|
191
|
+
let(:fixtures_path) { File.join('spec', 'fixtures', 'items_1.2') }
|
192
|
+
let(:test_object) { described_class.from_path!(file_path) }
|
193
|
+
let(:assessment_item_refs) { test_object.assessment_items }
|
194
|
+
let(:assessment_item_ref) { assessment_item_refs.first }
|
195
|
+
let(:file_path) { File.join(fixtures_path, 'text.no.question.xml') }
|
196
|
+
|
197
|
+
it 'methods behave as expected' do
|
198
|
+
expect(
|
199
|
+
test_object.create_assessment_item(assessment_item_ref)
|
200
|
+
).to eq(nil)
|
201
|
+
|
202
|
+
expect(
|
203
|
+
test_object.stimulus_ref(assessment_item_ref)
|
204
|
+
).to eq(assessment_item_ref)
|
205
|
+
|
206
|
+
expect(
|
207
|
+
test_object.create_stimulus(assessment_item_ref).class
|
208
|
+
).to be(Qti::V1::Models::StimulusItem)
|
209
|
+
end
|
210
|
+
end
|
37
211
|
end
|
@@ -18,4 +18,60 @@ describe Qti::V1::Models::Interactions::BaseInteraction do
|
|
18
18
|
interaction = described_class.new(node, assessment)
|
19
19
|
expect(interaction.rcardinality).to eq 'Single'
|
20
20
|
end
|
21
|
+
|
22
|
+
let(:fixtures_path) { File.join('spec', 'fixtures', 'items_1.2') }
|
23
|
+
let(:test_object) { Qti::V1::Models::Assessment.from_path!(file_path) }
|
24
|
+
let(:assessment_item_refs) { test_object.assessment_items }
|
25
|
+
let(:loaded_class) { described_class.new(assessment_item_refs.first, test_object) }
|
26
|
+
|
27
|
+
shared_examples_for 'item_level_feedback' do
|
28
|
+
it 'returns the correct item-level feedback' do
|
29
|
+
expect(loaded_class.canvas_item_feedback[:neutral]).to eq(general_fb)
|
30
|
+
expect(loaded_class.canvas_item_feedback[:correct]).to eq(correct_fb)
|
31
|
+
expect(loaded_class.canvas_item_feedback[:incorrect]).to eq(incorrect_fb)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
shared_examples_for 'answer_feedback' do
|
36
|
+
it 'returns the correct answer feedback' do
|
37
|
+
expect(loaded_class.answer_feedback).to eq(answer_fb)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'canvas_multiple_dropdown.xml' do
|
42
|
+
let(:file_path) { File.join(fixtures_path, 'canvas_multiple_dropdown.xml') }
|
43
|
+
let(:general_fb) do
|
44
|
+
"<p>Roses come in many colors, violets probably do too.</p>\n<p>Never the less, " \
|
45
|
+
'the correct answers were <strong>red</strong> and <strong>blue</strong>.</p>'
|
46
|
+
end
|
47
|
+
let(:correct_fb) { '<p>Completing the poem, is left to you.</p>' }
|
48
|
+
let(:incorrect_fb) { '<p>Those aren\'t colors, you meant <strong>red</strong> and <strong>blue</strong>.</p>' }
|
49
|
+
|
50
|
+
let(:answer_fb) do
|
51
|
+
[
|
52
|
+
{ response_id: 'response_color1', response_value: '6548',
|
53
|
+
texttype: 'text/html', feedback: '<p>Yes! <strong>Red</strong>.</p>' },
|
54
|
+
{ response_id: 'response_color1', response_value: '5550',
|
55
|
+
texttype: 'text/html', feedback: "<p>I'm pretty sure you meant <strong>red.</strong></p>" },
|
56
|
+
{ response_id: 'response_color2', response_value: '6951',
|
57
|
+
texttype: 'text/html', feedback: '<p>Yes, <strong>blue</strong>!</p>' },
|
58
|
+
{ response_id: 'response_color2', response_value: '4500',
|
59
|
+
texttype: 'text/html', feedback: '<p>Did you also chose plaid? You wanted to <strong>blue</strong>.</p>' }
|
60
|
+
]
|
61
|
+
end
|
62
|
+
|
63
|
+
include_examples('item_level_feedback')
|
64
|
+
include_examples('answer_feedback')
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'canvas_multiple_fib.xml' do
|
68
|
+
let(:file_path) { File.join(fixtures_path, 'canvas_multiple_fib.xml') }
|
69
|
+
let(:general_fb) { nil }
|
70
|
+
let(:correct_fb) { nil }
|
71
|
+
let(:incorrect_fb) { nil }
|
72
|
+
let(:answer_fb) { nil }
|
73
|
+
|
74
|
+
include_examples('item_level_feedback')
|
75
|
+
include_examples('answer_feedback')
|
76
|
+
end
|
21
77
|
end
|
@@ -20,22 +20,32 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
shared_examples_for 'meta_type' do
|
24
|
+
it 'returns interaction type from canvas meta data' do
|
25
|
+
expect(loaded_class.meta_type).to eq meta_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
23
29
|
context 'multiple_choice.xml' do
|
24
30
|
let(:file_path) { File.join(fixtures_path, 'multiple_choice.xml') }
|
25
31
|
let(:shuffle_value) { false }
|
26
32
|
let(:answer_choices_count) { 5 }
|
33
|
+
let(:meta_type) { nil }
|
27
34
|
|
28
35
|
include_examples 'shuffled?'
|
29
36
|
include_examples 'answers'
|
37
|
+
include_examples 'meta_type'
|
30
38
|
end
|
31
39
|
|
32
40
|
context 'true_false.xml' do
|
33
41
|
let(:file_path) { File.join(fixtures_path, 'true_false.xml') }
|
34
42
|
let(:shuffle_value) { true }
|
35
43
|
let(:answer_choices_count) { 2 }
|
44
|
+
let(:meta_type) { nil }
|
36
45
|
|
37
46
|
include_examples 'shuffled?'
|
38
47
|
include_examples 'answers'
|
48
|
+
include_examples 'meta_type'
|
39
49
|
end
|
40
50
|
|
41
51
|
context 'multiple_answer.xml' do
|
@@ -49,8 +59,10 @@ describe Qti::V1::Models::Interactions::ChoiceInteraction do
|
|
49
59
|
let(:file_path) { File.join(fixtures_path, 'multiple_answer_canvas.xml') }
|
50
60
|
let(:shuffle_value) { false }
|
51
61
|
let(:answer_choices_count) { 4 }
|
62
|
+
let(:meta_type) { 'multiple_answers_question' }
|
52
63
|
|
53
64
|
include_examples 'shuffled?'
|
65
|
+
include_examples 'meta_type'
|
54
66
|
end
|
55
67
|
|
56
68
|
context 'multiple respconditions with empty setvars' do
|
@@ -1,44 +1,88 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Qti::V1::Models::Interactions::MatchInteraction do
|
4
|
-
let(:
|
4
|
+
let(:path) { File.join('spec', 'fixtures', 'items_1.2') }
|
5
5
|
let(:assessment) { Qti::V1::Models::Assessment.from_path!(file) }
|
6
6
|
let(:item) { assessment.assessment_items.first }
|
7
|
-
subject { described_class.new(item, assessment) }
|
7
|
+
let(:subject) { described_class.new(item, assessment) }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
shared_examples_for 'common features' do
|
10
|
+
describe '.matches' do
|
11
|
+
it 'matches the item in file' do
|
12
|
+
expect(described_class.matches(item, assessment)).to be_truthy
|
13
|
+
end
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
"Uses a beam of electrons. Can provide details of cells' internal structure.",
|
17
|
-
'A distractor answer.']
|
18
|
-
)
|
16
|
+
it 'returns shuffle setting' do
|
17
|
+
expect(subject.shuffled?).to eq false
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
it '
|
23
|
-
expect(
|
21
|
+
shared_examples_for 'questions and answers' do
|
22
|
+
it 'returns the answers' do
|
23
|
+
expect(subject.answers.map(&:item_body)).to eq(expected_answers)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns the questions' do
|
27
|
+
expect(subject.questions).to eq(expected_questions)
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
|
31
|
+
shared_examples_for '#scoring_data_structs' do
|
28
32
|
it 'grabs scoring data value for matching questions' do
|
29
|
-
expect(subject.scoring_data_structs.first.values).to eq(
|
33
|
+
expect(subject.scoring_data_structs.first.values).to eq(expected_scoring_data)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'matching.xml' do
|
38
|
+
let(:file) { File.join(path, 'matching.xml') }
|
39
|
+
let(:expected_answers) do
|
40
|
+
[
|
41
|
+
'Magnify up to about 400 times. Sometimes requires colored staining of cells.',
|
42
|
+
"Uses a beam of electrons. Can provide details of cells' internal structure.",
|
43
|
+
'A distractor answer.'
|
44
|
+
]
|
45
|
+
end
|
46
|
+
let(:expected_questions) do
|
47
|
+
[
|
48
|
+
{ id: 'question_1', itemBody: 'Light Microscope' },
|
49
|
+
{ id: 'question_2', itemBody: 'Electron Microscopes' }
|
50
|
+
]
|
51
|
+
end
|
52
|
+
let(:expected_scoring_data) do
|
53
|
+
{
|
30
54
|
'question_1' => 'Magnify up to about 400 times. Sometimes requires colored staining of cells.',
|
31
55
|
'question_2' => "Uses a beam of electrons. Can provide details of cells' internal structure."
|
32
|
-
|
56
|
+
}
|
33
57
|
end
|
58
|
+
|
59
|
+
include_examples('common features')
|
60
|
+
include_examples('questions and answers')
|
61
|
+
include_examples('#scoring_data_structs')
|
34
62
|
end
|
35
63
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
64
|
+
context 'matching_feedback.xml' do
|
65
|
+
let(:file) { File.join(path, 'matching_feedback.xml') }
|
66
|
+
let(:expected_answers) { '1,2,,C,D,E,F,3,4,5,6'.split(',') }
|
67
|
+
let(:expected_questions) do
|
68
|
+
[
|
69
|
+
{ id: 'response_6831', itemBody: 'A' },
|
70
|
+
{ id: 'response_6259', itemBody: 'B' },
|
71
|
+
{ id: 'response_743', itemBody: '' },
|
72
|
+
{ id: 'response_1943', itemBody: '' }
|
73
|
+
]
|
74
|
+
end
|
75
|
+
let(:expected_scoring_data) do
|
76
|
+
{
|
77
|
+
'response_6831' => '1',
|
78
|
+
'response_6259' => '2',
|
79
|
+
'response_743' => '',
|
80
|
+
'response_1943' => ''
|
81
|
+
}
|
42
82
|
end
|
83
|
+
|
84
|
+
include_examples('common features')
|
85
|
+
include_examples('questions and answers')
|
86
|
+
include_examples('#scoring_data_structs')
|
43
87
|
end
|
44
88
|
end
|