moodle2cc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +4 -0
  3. data/Guardfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +38 -0
  6. data/Rakefile +12 -0
  7. data/bin/moodle2cc +6 -0
  8. data/lib/moodle2cc.rb +60 -0
  9. data/lib/moodle2cc/canvas/.converter.rb.swo +0 -0
  10. data/lib/moodle2cc/canvas/.wiki.rb.swo +0 -0
  11. data/lib/moodle2cc/canvas/assessment.rb +109 -0
  12. data/lib/moodle2cc/canvas/assignment.rb +108 -0
  13. data/lib/moodle2cc/canvas/converter.rb +28 -0
  14. data/lib/moodle2cc/canvas/course.rb +145 -0
  15. data/lib/moodle2cc/canvas/discussion_topic.rb +64 -0
  16. data/lib/moodle2cc/canvas/label.rb +8 -0
  17. data/lib/moodle2cc/canvas/question.rb +468 -0
  18. data/lib/moodle2cc/canvas/question_bank.rb +54 -0
  19. data/lib/moodle2cc/canvas/resource.rb +16 -0
  20. data/lib/moodle2cc/canvas/templates/assignment.html.erb +9 -0
  21. data/lib/moodle2cc/canvas/templates/syllabus.html.erb +9 -0
  22. data/lib/moodle2cc/canvas/templates/wiki_content.html.erb +10 -0
  23. data/lib/moodle2cc/canvas/web_content.rb +10 -0
  24. data/lib/moodle2cc/canvas/web_link.rb +17 -0
  25. data/lib/moodle2cc/canvas/wiki.rb +25 -0
  26. data/lib/moodle2cc/cc/assessment.rb +25 -0
  27. data/lib/moodle2cc/cc/assignment.rb +66 -0
  28. data/lib/moodle2cc/cc/cc_helper.rb +282 -0
  29. data/lib/moodle2cc/cc/converter.rb +136 -0
  30. data/lib/moodle2cc/cc/course.rb +16 -0
  31. data/lib/moodle2cc/cc/discussion_topic.rb +53 -0
  32. data/lib/moodle2cc/cc/label.rb +6 -0
  33. data/lib/moodle2cc/cc/question.rb +23 -0
  34. data/lib/moodle2cc/cc/resource.rb +30 -0
  35. data/lib/moodle2cc/cc/templates/assignment.html.erb +9 -0
  36. data/lib/moodle2cc/cc/templates/syllabus.html.erb +9 -0
  37. data/lib/moodle2cc/cc/templates/wiki_content.html.erb +10 -0
  38. data/lib/moodle2cc/cc/web_content.rb +40 -0
  39. data/lib/moodle2cc/cc/web_link.rb +53 -0
  40. data/lib/moodle2cc/cc/wiki.rb +72 -0
  41. data/lib/moodle2cc/cli.rb +14 -0
  42. data/lib/moodle2cc/error.rb +3 -0
  43. data/lib/moodle2cc/migrator.rb +23 -0
  44. data/lib/moodle2cc/moodle/backup.rb +38 -0
  45. data/lib/moodle2cc/moodle/course.rb +24 -0
  46. data/lib/moodle2cc/moodle/grade_item.rb +24 -0
  47. data/lib/moodle2cc/moodle/info.rb +8 -0
  48. data/lib/moodle2cc/moodle/mod.rb +127 -0
  49. data/lib/moodle2cc/moodle/question.rb +98 -0
  50. data/lib/moodle2cc/moodle/question_category.rb +17 -0
  51. data/lib/moodle2cc/moodle/section.rb +37 -0
  52. data/lib/moodle2cc/resource_factory.rb +32 -0
  53. data/lib/moodle2cc/version.rb +3 -0
  54. data/moodle2cc.gemspec +29 -0
  55. data/test/acceptance/migrator_test.rb +23 -0
  56. data/test/fixtures/cc.imscc +0 -0
  57. data/test/fixtures/moodle_backup/course_files/folder/test.txt +1 -0
  58. data/test/fixtures/moodle_backup/course_files/test.txt +1 -0
  59. data/test/fixtures/moodle_backup/moodle.xml +916 -0
  60. data/test/test_helper.rb +43 -0
  61. data/test/test_question_helper.rb +107 -0
  62. data/test/test_wiki_helper.rb +21 -0
  63. data/test/unit/canvas/assessment_test.rb +218 -0
  64. data/test/unit/canvas/assignment_test.rb +220 -0
  65. data/test/unit/canvas/converter_test.rb +159 -0
  66. data/test/unit/canvas/course_test.rb +176 -0
  67. data/test/unit/canvas/discussion_topic_test.rb +129 -0
  68. data/test/unit/canvas/label_test.rb +32 -0
  69. data/test/unit/canvas/question_bank_test.rb +73 -0
  70. data/test/unit/canvas/question_test.rb +824 -0
  71. data/test/unit/canvas/web_content_test.rb +37 -0
  72. data/test/unit/canvas/web_link_test.rb +48 -0
  73. data/test/unit/canvas/wiki_test.rb +74 -0
  74. data/test/unit/cc/assessment_test.rb +48 -0
  75. data/test/unit/cc/assignment_test.rb +67 -0
  76. data/test/unit/cc/cc_helper_test.rb +19 -0
  77. data/test/unit/cc/converter_test.rb +159 -0
  78. data/test/unit/cc/course_test.rb +36 -0
  79. data/test/unit/cc/discussion_topic_test.rb +83 -0
  80. data/test/unit/cc/label_test.rb +29 -0
  81. data/test/unit/cc/question_test.rb +49 -0
  82. data/test/unit/cc/web_content_test.rb +76 -0
  83. data/test/unit/cc/web_link_test.rb +79 -0
  84. data/test/unit/cc/wiki_test.rb +139 -0
  85. data/test/unit/migrator_test.rb +56 -0
  86. data/test/unit/moodle/backup_test.rb +30 -0
  87. data/test/unit/moodle/course_test.rb +57 -0
  88. data/test/unit/moodle/grade_item_test.rb +72 -0
  89. data/test/unit/moodle/info_test.rb +21 -0
  90. data/test/unit/moodle/mod_test.rb +301 -0
  91. data/test/unit/moodle/question_category_test.rb +34 -0
  92. data/test/unit/moodle/question_test.rb +185 -0
  93. data/test/unit/moodle/section_test.rb +75 -0
  94. data/test/unit/resource_factory_test.rb +119 -0
  95. metadata +342 -0
@@ -0,0 +1,32 @@
1
+ require 'nokogiri'
2
+ require 'minitest/autorun'
3
+ require 'test/test_helper'
4
+ require 'moodle2cc'
5
+
6
+ class TestUnitCanvasLabel < MiniTest::Unit::TestCase
7
+ include TestHelper
8
+
9
+ def setup
10
+ convert_moodle_backup 'canvas'
11
+ @mod = @backup.course.mods.find { |m| m.mod_type == "label" }
12
+ end
13
+
14
+ def teardown
15
+ clean_tmp_folder
16
+ end
17
+
18
+ def test_it_creates_item_in_module_meta
19
+ label = Moodle2CC::Canvas::Label.new @mod
20
+ node = Builder::XmlMarkup.new
21
+ xml = Nokogiri::XML(label.create_module_meta_item_node(node, 5))
22
+
23
+ assert_equal 'item', xml.root.name
24
+ assert_equal 'ifcf0624ce811c812c749c53f3c914f20', xml.root.attributes['identifier'].value
25
+ assert_equal "label123", xml.root.xpath('title').text
26
+ assert_equal '5', xml.root.xpath('position').text
27
+ assert_equal '', xml.root.xpath('new_tab').text
28
+ assert_equal '1', xml.root.xpath('indent').text
29
+ assert_equal 'ContextModuleSubHeader', xml.root.xpath('content_type').text
30
+ refute xml.root.xpath('identifierref').first, 'label should not have identifierref'
31
+ end
32
+ end
@@ -0,0 +1,73 @@
1
+ require 'nokogiri'
2
+ require 'minitest/autorun'
3
+ require 'test/test_helper'
4
+ require 'moodle2cc'
5
+
6
+ class TestUnitCanvasQuestionBank < MiniTest::Unit::TestCase
7
+ include TestHelper
8
+
9
+ def setup
10
+ convert_moodle_backup 'canvas'
11
+ @course = @backup.course
12
+ @question_category = @course.question_categories.first
13
+ end
14
+
15
+ def teardown
16
+ clean_tmp_folder
17
+ end
18
+
19
+ def test_it_converts_id
20
+ @question_category.id = 121
21
+ question_bank = Moodle2CC::Canvas::QuestionBank.new @question_category
22
+ assert_equal 121, question_bank.id
23
+ end
24
+
25
+ def test_it_converts_title
26
+ @question_category.name = 'Default for Beginning Ruby on Rails'
27
+ question_bank = Moodle2CC::Canvas::QuestionBank.new @question_category
28
+ assert_equal 'Default for Beginning Ruby on Rails', question_bank.title
29
+ end
30
+
31
+ def test_it_has_an_identifier
32
+ @question_category.id = 121
33
+ question_bank = Moodle2CC::Canvas::QuestionBank.new @question_category
34
+ # objectbank_{id}
35
+ assert_equal 'i02849cd800255cc6c762cdafd8d8db67', question_bank.identifier
36
+ end
37
+
38
+ def test_it_creates_resource_in_imsmanifest
39
+ question_bank = Moodle2CC::Canvas::QuestionBank.new @question_category
40
+ node = Builder::XmlMarkup.new
41
+ xml = Nokogiri::XML(question_bank.create_resource_node(node))
42
+
43
+ resource = xml.xpath('resource').first
44
+ assert resource
45
+ assert_equal 'associatedcontent/imscc_xmlv1p1/learning-application-resource', resource.attributes['type'].value
46
+ assert_equal 'non_cc_assessments/i02849cd800255cc6c762cdafd8d8db67.xml.qti', resource.attributes['href'].value
47
+ assert_equal 'i02849cd800255cc6c762cdafd8d8db67', resource.attributes['identifier'].value
48
+
49
+ file = resource.xpath('file[@href="non_cc_assessments/i02849cd800255cc6c762cdafd8d8db67.xml.qti"]').first
50
+ assert file
51
+ end
52
+
53
+ def test_it_creates_qti_xml
54
+ question_bank = Moodle2CC::Canvas::QuestionBank.new @question_category
55
+ tmp_dir = File.expand_path('../../../tmp', __FILE__)
56
+ question_bank.create_qti_xml(tmp_dir)
57
+ xml = Nokogiri::XML(File.read(File.join(tmp_dir, 'non_cc_assessments', "i02849cd800255cc6c762cdafd8d8db67.xml.qti")))
58
+
59
+ assert xml
60
+ assert_equal "http://www.imsglobal.org/xsd/ims_qtiasiv1p2 http://www.imsglobal.org/xsd/ims_qtiasiv1p2p1.xsd", xml.root.attributes['schemaLocation'].value
61
+ assert_equal "http://www.w3.org/2001/XMLSchema-instance", xml.namespaces['xmlns:xsi']
62
+ assert_equal "http://www.imsglobal.org/xsd/ims_qtiasiv1p2", xml.namespaces['xmlns']
63
+ assert_equal 'questestinterop', xml.root.name
64
+
65
+ assert_equal 'i02849cd800255cc6c762cdafd8d8db67', xml.root.xpath('xmlns:objectbank').first.attributes['ident'].value
66
+
67
+ time_data = xml.root.xpath('xmlns:objectbank/xmlns:qtimetadata/xmlns:qtimetadatafield[xmlns:fieldlabel="bank_title" and xmlns:fieldentry="Default for Beginning Ruby on Rails"]').first
68
+ assert time_data, 'qtimetadata does not exist for time limit'
69
+
70
+ items = xml.root.xpath('xmlns:objectbank/xmlns:item')
71
+ assert_equal 5, items.length
72
+ end
73
+ end
@@ -0,0 +1,824 @@
1
+ require 'nokogiri'
2
+ require 'minitest/autorun'
3
+ require 'test/test_helper'
4
+ require 'test/test_question_helper'
5
+ require 'moodle2cc'
6
+
7
+ class TestUnitCanvasQuestion < MiniTest::Unit::TestCase
8
+ include TestHelper
9
+ include TestQuestionHelper
10
+
11
+ def setup
12
+ convert_moodle_backup 'canvas'
13
+ @mod = @backup.course.mods.find { |mod| mod.mod_type == 'quiz' }
14
+ @question = @mod.questions.first
15
+ end
16
+
17
+ def teardown
18
+ clean_tmp_folder
19
+ end
20
+
21
+ def test_it_converts_id
22
+ @question.id = 989
23
+ question = Moodle2CC::Canvas::Question.new @question
24
+ assert_equal 989, question.id
25
+ end
26
+
27
+ def test_it_converts_title
28
+ @question.name = "Basic Arithmetic"
29
+ question = Moodle2CC::Canvas::Question.new @question
30
+ assert_equal "Basic Arithmetic", question.title
31
+ end
32
+
33
+ def test_it_converts_length
34
+ @question.length = 5
35
+ question = Moodle2CC::Canvas::Question.new @question
36
+ assert_equal 5, question.length
37
+ end
38
+
39
+ def test_it_converts_question_type
40
+ @question.type = 'calculated'
41
+ question = Moodle2CC::Canvas::Question.new @question
42
+ assert_equal 'calculated_question', question.question_type
43
+
44
+ @question.type = 'description'
45
+ question = Moodle2CC::Canvas::Question.new @question
46
+ assert_equal 'text_only_question', question.question_type
47
+
48
+ @question.type = 'essay'
49
+ question = Moodle2CC::Canvas::Question.new @question
50
+ assert_equal 'essay_question', question.question_type
51
+
52
+ @question.type = 'match'
53
+ question = Moodle2CC::Canvas::Question.new @question
54
+ assert_equal 'matching_question', question.question_type
55
+
56
+ @question.type = 'multianswer'
57
+ question = Moodle2CC::Canvas::Question.new @question
58
+ assert_equal 'embedded_answers_question', question.question_type
59
+
60
+ @question.type = 'multichoice'
61
+ question = Moodle2CC::Canvas::Question.new @question
62
+ assert_equal 'multiple_choice_question', question.question_type
63
+
64
+ @question.type = 'shortanswer'
65
+ question = Moodle2CC::Canvas::Question.new @question
66
+ assert_equal 'short_answer_question', question.question_type
67
+
68
+ @question.type = 'numerical'
69
+ question = Moodle2CC::Canvas::Question.new @question
70
+ assert_equal 'numerical_question', question.question_type
71
+
72
+ @question.type = 'truefalse'
73
+ question = Moodle2CC::Canvas::Question.new @question
74
+ assert_equal 'true_false_question', question.question_type
75
+
76
+ @question.type = nil
77
+
78
+ @question.type_id = 1
79
+ question = Moodle2CC::Canvas::Question.new @question
80
+ assert_equal 'true_false_question', question.question_type
81
+
82
+ @question.type_id = 2
83
+ question = Moodle2CC::Canvas::Question.new @question
84
+ assert_equal 'essay_question', question.question_type
85
+
86
+ @question.type_id = 3
87
+ question = Moodle2CC::Canvas::Question.new @question
88
+ assert_equal 'essay_question', question.question_type
89
+
90
+ @question.type_id = 4
91
+ question = Moodle2CC::Canvas::Question.new @question
92
+ assert_equal 'multiple_choice_question', question.question_type
93
+
94
+ @question.type_id = 5
95
+ question = Moodle2CC::Canvas::Question.new @question
96
+ assert_equal 'multiple_answers_question', question.question_type
97
+
98
+ @question.type_id = 6
99
+ question = Moodle2CC::Canvas::Question.new @question
100
+ assert_equal 'multiple_choice_question', question.question_type
101
+
102
+ @question.type_id = 8
103
+ question = Moodle2CC::Canvas::Question.new @question
104
+ assert_equal 'multiple_dropdowns_question', question.question_type
105
+
106
+ @question.type_id = 9
107
+ question = Moodle2CC::Canvas::Question.new @question
108
+ assert_equal 'essay_question', question.question_type
109
+
110
+ @question.type_id = 10
111
+ question = Moodle2CC::Canvas::Question.new @question
112
+ assert_equal 'numerical_question', question.question_type
113
+
114
+ @question.type_id = 100
115
+ question = Moodle2CC::Canvas::Question.new @question
116
+ assert_equal 'text_only_question', question.question_type
117
+ end
118
+
119
+ def test_it_converts_points_possible
120
+ @question.grade = 5
121
+ question = Moodle2CC::Canvas::Question.new @question
122
+ assert_equal 5, question.points_possible
123
+ end
124
+
125
+ def test_it_converts_material
126
+ @question.text = "How much is {a} + {b} ?"
127
+ question = Moodle2CC::Canvas::Question.new @question
128
+ assert_equal "How much is [a] + [b] ?", question.material
129
+ end
130
+
131
+ def test_it_converts_material_for_multiple_dropdowns_question
132
+ multiple_dropdowns_question!
133
+ @question.content = "This is a rating question"
134
+ question = Moodle2CC::Canvas::Question.new @question
135
+ assert_equal "This is a rating question\nI test my code [response1]\nI am happy [response2]", question.material
136
+ end
137
+
138
+ def test_it_converts_general_feedback
139
+ @question.general_feedback = "This should be easy"
140
+ question = Moodle2CC::Canvas::Question.new @question
141
+ assert_equal "This should be easy", question.general_feedback
142
+ end
143
+
144
+ def test_it_converts_answer_tolerance
145
+ @question.calculations.first.tolerance = 0.01
146
+ question = Moodle2CC::Canvas::Question.new @question
147
+ assert_equal 0.01, question.answer_tolerance
148
+ end
149
+
150
+ def test_it_converts_formula_decimal_places
151
+ calculation = @question.calculations.first
152
+ calculation.correct_answer_format = 1 # decimal
153
+ calculation.correct_answer_length = 2
154
+
155
+ question = Moodle2CC::Canvas::Question.new @question
156
+ assert_equal 2, question.formula_decimal_places
157
+
158
+ calculation.correct_answer_format = 2 # significant figures
159
+
160
+ question = Moodle2CC::Canvas::Question.new @question
161
+ assert_equal 0, question.formula_decimal_places
162
+ end
163
+
164
+ def test_it_converts_formulas
165
+ answer1 = @question.answers.first
166
+ answer2 = answer1.dup
167
+ @question.answers << answer2
168
+
169
+ answer1.text = '{a} + {b}'
170
+ answer2.text = '{a} * {b}'
171
+
172
+ question = Moodle2CC::Canvas::Question.new @question
173
+ assert_equal 2, question.formulas.length
174
+ assert_equal 'a+b', question.formulas.first
175
+ assert_equal 'a*b', question.formulas.last
176
+ end
177
+
178
+ def test_it_converts_vars
179
+ calculation = @question.calculations.first
180
+ ds_def1 = calculation.dataset_definitions.first
181
+ ds_def2 = calculation.dataset_definitions.last
182
+
183
+ ds_def1.name = 'a'
184
+ ds_def1.options = 'uniform:3.0:9.0:3'
185
+
186
+ ds_def2.name = 'b'
187
+ ds_def2.options = 'uniform:1.0:10.0:1'
188
+
189
+ question = Moodle2CC::Canvas::Question.new @question
190
+ assert_equal 2, question.vars.length
191
+ assert_equal({:name => 'a', :scale => '3', :min => '3.0', :max => '9.0'}, question.vars.first)
192
+ assert_equal({:name => 'b', :scale => '1', :min => '1.0', :max => '10.0'}, question.vars.last)
193
+ end
194
+
195
+ def test_it_converts_var_sets
196
+ calculation = @question.calculations.first
197
+ ds_def1 = calculation.dataset_definitions.first
198
+ ds_def2 = calculation.dataset_definitions.last
199
+
200
+ ds_def1.name = 'a'
201
+ ds_item1 = ds_def1.dataset_items.first
202
+ ds_item2 = ds_item1.dup
203
+ ds_def1.dataset_items[1] = ds_item2
204
+
205
+ ds_item1.number = 1
206
+ ds_item1.value = 3.0
207
+ ds_item2.number = 2
208
+ ds_item2.value = 5.5
209
+
210
+ ds_def2.name = 'b'
211
+ ds_item1 = ds_def2.dataset_items.first
212
+ ds_item2 = ds_item1.dup
213
+ ds_def2.dataset_items[1] = ds_item2
214
+
215
+ ds_item1.number = 1
216
+ ds_item1.value = 6.0
217
+ ds_item2.number = 2
218
+ ds_item2.value = 1.0
219
+
220
+ question = Moodle2CC::Canvas::Question.new @question
221
+ assert_equal 2, question.var_sets.length
222
+ assert_equal({:vars => {'a' => 3.0, 'b' => 6.0}, :answer => 9.0}, question.var_sets.first)
223
+ assert_equal({:vars => {'a' => 5.5, 'b' => 1.0}, :answer => 6.5}, question.var_sets.last)
224
+ end
225
+
226
+ def test_it_converts_matches
227
+ match_question!
228
+
229
+ question = Moodle2CC::Canvas::Question.new @question
230
+ assert_equal 2, question.matches.length
231
+ assert_equal(Moodle2CC::OpenStruct.new(
232
+ :question => 'Ruby on Rails is written in this language',
233
+ :answers => {123 => 'Ruby', 234 => 'Python', 345 => 'CoffeeScript'},
234
+ :answer => 123
235
+ ), question.matches.first)
236
+ assert_equal(Moodle2CC::OpenStruct.new(
237
+ :question => 'Files with .coffee extension use which language?',
238
+ :answers => {123 => 'Ruby', 234 => 'Python', 345 => 'CoffeeScript'},
239
+ :answer => 345
240
+ ), question.matches.last)
241
+ end
242
+
243
+ def test_it_converts_numericals
244
+ answer = Moodle2CC::Moodle::Question::Answer.new
245
+ answer.id = 43
246
+ answer.text = "Blah"
247
+ numerical = Moodle2CC::Moodle::Question::Numerical.new
248
+ numerical.answer_id = 43
249
+ numerical.tolerance = 3
250
+ @question.numericals = [numerical]
251
+ @question.answers = [answer]
252
+ question = Moodle2CC::Canvas::Question.new @question
253
+
254
+ assert_equal 1, question.numericals.length
255
+
256
+ assert_equal(Moodle2CC::OpenStruct.new(
257
+ :answer => question.answers.first,
258
+ :tolerance => 3
259
+ ), question.numericals.first)
260
+ end
261
+
262
+ def test_it_converts_answers
263
+ multiple_choice_question!
264
+
265
+ question = Moodle2CC::Canvas::Question.new @question
266
+ assert_equal 4, question.answers.length
267
+
268
+ assert_equal(Moodle2CC::OpenStruct.new(
269
+ :id => 123,
270
+ :text => 'Ruby',
271
+ :fraction => 1,
272
+ :feedback => 'Yippee!'
273
+ ), question.answers[0])
274
+ assert_equal(Moodle2CC::OpenStruct.new(
275
+ :id => 234,
276
+ :text => 'CoffeeScript',
277
+ :fraction => 0.75,
278
+ :feedback => 'Nope'
279
+ ), question.answers[1])
280
+ assert_equal(Moodle2CC::OpenStruct.new(
281
+ :id => 345,
282
+ :text => 'Java',
283
+ :fraction => 0.25,
284
+ :feedback => 'No way'
285
+ ), question.answers[2])
286
+ assert_equal(Moodle2CC::OpenStruct.new(
287
+ :id => 456,
288
+ :text => 'Clojure',
289
+ :fraction => 0,
290
+ :feedback => 'Not even close'
291
+ ), question.answers[3])
292
+ end
293
+
294
+ def test_it_converts_answers_from_questionnaire_choices
295
+ @question.type = nil
296
+ @question.type_id = 4
297
+
298
+ choice1 = Moodle2CC::Moodle::Question::Choice.new
299
+ choice1.id = 123
300
+ choice1.content = 'Ruby'
301
+
302
+ choice2 = Moodle2CC::Moodle::Question::Choice.new
303
+ choice2.id = 234
304
+ choice2.content = 'CoffeeScript'
305
+
306
+ choice3 = Moodle2CC::Moodle::Question::Choice.new
307
+ choice3.id = 345
308
+ choice3.content = 'Java'
309
+
310
+ choice4 = Moodle2CC::Moodle::Question::Choice.new
311
+ choice4.id = 456
312
+ choice4.content = 'Clojure'
313
+
314
+ @question.choices = [choice1, choice2, choice3, choice4]
315
+ @question.answers = []
316
+
317
+ question = Moodle2CC::Canvas::Question.new @question
318
+ assert_equal 4, question.answers.length
319
+
320
+ assert_equal(Moodle2CC::OpenStruct.new(
321
+ :id => 123,
322
+ :text => 'Ruby'
323
+ ), question.answers[0])
324
+ assert_equal(Moodle2CC::OpenStruct.new(
325
+ :id => 234,
326
+ :text => 'CoffeeScript'
327
+ ), question.answers[1])
328
+ assert_equal(Moodle2CC::OpenStruct.new(
329
+ :id => 345,
330
+ :text => 'Java'
331
+ ), question.answers[2])
332
+ assert_equal(Moodle2CC::OpenStruct.new(
333
+ :id => 456,
334
+ :text => 'Clojure'
335
+ ), question.answers[3])
336
+ end
337
+
338
+ def test_it_has_an_identifier_based_on_id
339
+ @question.id = 989
340
+ @question.instance_id = nil
341
+ question = Moodle2CC::Canvas::Question.new @question
342
+ assert_equal 'i04823ed56ffd4fd5f9c21db0cf25be6c', question.identifier
343
+ # question_989
344
+ end
345
+
346
+ def test_it_has_an_identifier_based_on_instance_id
347
+ @question.instance_id = 787
348
+ question = Moodle2CC::Canvas::Question.new @question
349
+ assert_equal 'i2edcb021d100c968ba3f570253a6aa1c', question.identifier
350
+ # question_instance_787
351
+ end
352
+
353
+ def test_it_has_an_assessment_question_identifierref_if_instance_id_exists
354
+ @question.id = 989
355
+ @question.instance_id = 787
356
+ question = Moodle2CC::Canvas::Question.new @question
357
+ assert_equal 'i04823ed56ffd4fd5f9c21db0cf25be6c', question.assessment_question_identifierref
358
+ # question_989
359
+ end
360
+
361
+ def test_it_does_not_have_an_assessment_question_identifierref_if_instance_id_does_not_exist
362
+ @question.id = 989
363
+ @question.instance_id = nil
364
+ question = Moodle2CC::Canvas::Question.new @question
365
+ refute question.assessment_question_identifierref
366
+ # question_989
367
+ end
368
+
369
+ def test_it_creates_fractions
370
+ question = Moodle2CC::Canvas::Question.new @question
371
+ assert_equal 100, question.get_score(1)
372
+ assert_equal 50, question.get_score(0.5)
373
+ assert_equal 0, question.get_score(0)
374
+ assert_equal 100, question.get_score(nil)
375
+ end
376
+
377
+ def test_it_create_multple_question_from_choice_mod
378
+ @choice_mod = @backup.course.mods.find { |m| m.mod_type == 'choice' }
379
+ question = Moodle2CC::Canvas::Question.new @choice_mod.questions.first
380
+
381
+ assert_equal 'multiple_choice_question', question.question_type
382
+ end
383
+
384
+ def test_it_creates_item_xml
385
+ question = Moodle2CC::Canvas::Question.new @question
386
+ node = Builder::XmlMarkup.new
387
+ xml = Nokogiri::XML(question.create_item_xml(node))
388
+
389
+ assert xml.root
390
+ assert_equal 'item', xml.root.name
391
+ assert_equal 'Basic Arithmetic', xml.root.attributes['title'].value
392
+ assert_equal 'i7cf4483ef2da120de20ff6cfc9dd3e58', xml.root.attributes['ident'].value
393
+
394
+ assert xml.root.xpath('itemmetadata/qtimetadata/qtimetadatafield[fieldlabel="question_type" and fieldentry="calculated_question"]').first, 'does not have meta data for question type'
395
+ assert xml.root.xpath('itemmetadata/qtimetadata/qtimetadatafield[fieldlabel="points_possible" and fieldentry="1"]').first, 'does not have meta data for points possible'
396
+ assert xml.root.xpath('itemmetadata/qtimetadata/qtimetadatafield[fieldlabel="assessment_question_identifierref" and fieldentry="i04823ed56ffd4fd5f9c21db0cf25be6c"]').first, 'does not have meta data for assessment_question_identifierref'
397
+
398
+ assert_equal 'How much is [a] + [b] ?', xml.root.xpath('presentation/material/mattext[@texttype="text/html"]').text
399
+
400
+ # Score
401
+ outcome = xml.root.xpath('resprocessing/outcomes/decvar').first
402
+ assert_equal '100', outcome.attributes['maxvalue'].value
403
+ assert_equal '0', outcome.attributes['minvalue'].value
404
+ assert_equal 'SCORE', outcome.attributes['varname'].value
405
+ assert_equal 'Decimal', outcome.attributes['vartype'].value
406
+
407
+ # General Feedback
408
+ general_feedback = xml.root.xpath('resprocessing/respcondition[1]').first
409
+ assert_equal 'Yes', general_feedback.attributes['continue'].value
410
+ assert general_feedback.xpath('conditionvar/other').first, 'does not contain conditionvar'
411
+ assert_equal 'Response', general_feedback.xpath('displayfeedback').first.attributes['feedbacktype'].value
412
+ assert_equal 'general_fb', general_feedback.xpath('displayfeedback').first.attributes['linkrefid'].value
413
+
414
+ general_feedback = xml.root.xpath('itemfeedback[@ident="general_fb"]').first
415
+ assert general_feedback, 'no feeback node'
416
+ material = general_feedback.xpath('flow_mat/material/mattext[@texttype="text/plain"]').first
417
+ assert material, 'no feedback text'
418
+ assert_equal 'This should be easy', material.text
419
+ end
420
+
421
+ def test_it_creates_item_xml_for_calculated_question
422
+ @question.type = 'calculated'
423
+ question = Moodle2CC::Canvas::Question.new @question
424
+ node = Builder::XmlMarkup.new
425
+ xml = Nokogiri::XML(question.create_item_xml(node))
426
+
427
+ response = xml.root.xpath('presentation/response_str').first
428
+ assert_equal 'Single', response.attributes['rcardinality'].value
429
+ assert_equal 'response1', response.attributes['ident'].value
430
+ assert_equal 'Decimal', response.xpath('render_fib').first.attributes['fibtype'].value
431
+ assert_equal 'answer1', response.xpath('render_fib/response_label').first.attributes['ident'].value
432
+
433
+ # Correct Condition
434
+ condition = xml.root.xpath('resprocessing/respcondition[@title="correct"]').first
435
+ assert condition, 'correct condition node does not exist'
436
+ assert condition.xpath('conditionvar/other').first, 'conditionvar does not exist for correct condition node'
437
+ setvar = condition.xpath('setvar').first
438
+ assert setvar, 'setvar does not exist for correct condition node'
439
+ assert_equal 'SCORE', setvar.attributes['varname'].value
440
+ assert_equal 'Set', setvar.attributes['action'].value
441
+ assert_equal '100', setvar.text
442
+
443
+ # Incorrect Condition
444
+ condition = xml.root.xpath('resprocessing/respcondition[@title="incorrect"]').first
445
+ assert condition, 'incorrect condition node does not exist'
446
+ assert condition.xpath('conditionvar/other').first, 'conditionvar does not exist for incorrect condition node'
447
+ setvar = condition.xpath('setvar').first
448
+ assert setvar, 'setvar does not exist for incorrect condition node'
449
+ assert_equal 'SCORE', setvar.attributes['varname'].value
450
+ assert_equal 'Set', setvar.attributes['action'].value
451
+ assert_equal '0', setvar.text
452
+
453
+ # Calculations
454
+ calculated = xml.root.xpath('itemproc_extension/calculated').first
455
+ assert calculated, 'calculated node does not exist'
456
+ assert_equal '0.01', calculated.xpath('answer_tolerance').text
457
+
458
+ # Formulas
459
+ assert calculated.xpath('formulas[@decimal_places="2"]').first, 'calculated node does not contain formulas with decimal_places'
460
+ assert calculated.xpath('formulas/formula["a+b"]').first, 'calculated node does not contain the formula a+b'
461
+
462
+ # Var
463
+ a_var = calculated.xpath('vars/var[@scale="1"][@name="a"]').first
464
+ assert a_var, 'calculated node does not have variable for a'
465
+ assert_equal '1.0', a_var.xpath('min').text
466
+ assert_equal '10.0', a_var.xpath('max').text
467
+ b_var = calculated.xpath('vars/var[@scale="1"][@name="b"]').first
468
+ assert b_var, 'calculated node does not have variable for b'
469
+ assert_equal '1.0', b_var.xpath('min').text
470
+ assert_equal '10.0', b_var.xpath('max').text
471
+
472
+ # Var Sets
473
+ var_set1 = calculated.xpath('var_sets/var_set[1]').first
474
+ assert var_set1, 'first var_set does not exist'
475
+ assert_equal '3060', var_set1.attributes['ident'].value
476
+ assert var_set1.xpath('var[@name="a"][3.0]'), 'first var_set does not have a value for a'
477
+ assert var_set1.xpath('var[@name="b"][6.0]'), 'first var_set does not have a value for b'
478
+ assert var_set1.xpath('answer[9.0]'), 'first var_set does not have an answer'
479
+
480
+ var_set2 = calculated.xpath('var_sets/var_set[2]').first
481
+ assert var_set2, 'second var_set does not exist'
482
+ assert_equal '5510', var_set2.attributes['ident'].value
483
+ assert var_set2.xpath('var[@name="a"][5.5]'), 'second var_set does not have a value for a'
484
+ assert var_set2.xpath('var[@name="b"][1.0]'), 'second var_set does not have a value for b'
485
+ assert var_set2.xpath('answer[6.5]'), 'second var_set does not have an answer'
486
+ end
487
+
488
+ def test_it_creates_item_xml_for_essay_question
489
+ @question.type = 'essay'
490
+ question = Moodle2CC::Canvas::Question.new @question
491
+ node = Builder::XmlMarkup.new
492
+ xml = Nokogiri::XML(question.create_item_xml(node))
493
+
494
+ response = xml.root.xpath('presentation/response_str').first
495
+ assert_equal 'Single', response.attributes['rcardinality'].value
496
+ assert_equal 'response1', response.attributes['ident'].value
497
+ assert_equal 'No', response.xpath('render_fib/response_label').first.attributes['rshuffle'].value
498
+ assert_equal 'answer1', response.xpath('render_fib/response_label').first.attributes['ident'].value
499
+
500
+ # No Continue Condition
501
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]').first
502
+ assert condition, 'no continue condition node does not exist'
503
+ assert condition.xpath('conditionvar/other').first, 'conditionvar does not exist for no continue condition node'
504
+ end
505
+
506
+ def test_it_creates_item_xml_for_matching_question
507
+ match_question!
508
+
509
+ question = Moodle2CC::Canvas::Question.new @question
510
+ node = Builder::XmlMarkup.new
511
+ xml = Nokogiri::XML(question.create_item_xml(node))
512
+
513
+ response = xml.root.xpath('presentation/response_lid[@ident="response_123"]').first
514
+ assert response, 'response for first matching question does not exist'
515
+ assert_equal 'Ruby on Rails is written in this language', response.xpath('material/mattext[@texttype="text/plain"]').text
516
+ assert_equal 'Ruby', response.xpath('render_choice/response_label[@ident="123"]/material/mattext').text
517
+ assert_equal 'Python', response.xpath('render_choice/response_label[@ident="234"]/material/mattext').text
518
+ assert_equal 'CoffeeScript', response.xpath('render_choice/response_label[@ident="345"]/material/mattext').text
519
+
520
+ response = xml.root.xpath('presentation/response_lid[@ident="response_345"]').first
521
+ assert response, 'response for second matching question does not exist'
522
+ assert_equal 'Files with .coffee extension use which language?', response.xpath('material/mattext[@texttype="text/plain"]').text
523
+ assert_equal 'Ruby', response.xpath('render_choice/response_label[@ident="123"]/material/mattext').text
524
+ assert_equal 'Python', response.xpath('render_choice/response_label[@ident="234"]/material/mattext').text
525
+ assert_equal 'CoffeeScript', response.xpath('render_choice/response_label[@ident="345"]/material/mattext').text
526
+
527
+ condition = xml.root.xpath('resprocessing/respcondition/conditionvar[varequal=123]/..').first
528
+ assert condition, 'first matching condition does not exist'
529
+ assert condition.xpath('conditionvar/varequal[@respident="response_123"]').first, 'condition does not reference correct response'
530
+ set_var = condition.xpath('setvar').first
531
+ assert_equal 'SCORE', set_var.attributes['varname'].value
532
+ assert_equal 'Add', set_var.attributes['action'].value
533
+ assert_equal '50.00', set_var.text
534
+
535
+ condition = xml.root.xpath('resprocessing/respcondition/conditionvar[varequal=345]/..').first
536
+ assert condition, 'second matching condition does not exist'
537
+ assert condition.xpath('conditionvar/varequal[@respident="response_345"]').first, 'condition does not reference correct response'
538
+ set_var = condition.xpath('setvar').first
539
+ assert_equal 'SCORE', set_var.attributes['varname'].value
540
+ assert_equal 'Add', set_var.attributes['action'].value
541
+ assert_equal '50.00', set_var.text
542
+ end
543
+
544
+ def test_it_creates_item_xml_for_multiple_choice_question
545
+ multiple_choice_question!
546
+
547
+ question = Moodle2CC::Canvas::Question.new @question
548
+ node = Builder::XmlMarkup.new
549
+ xml = Nokogiri::XML(question.create_item_xml(node))
550
+
551
+ # Responses
552
+ response = xml.root.xpath('presentation/response_lid[@ident="response1"]').first
553
+ assert response, 'response for multiple choice question does not exist'
554
+ assert_equal 'Single', response.attributes['rcardinality'].value
555
+ assert_equal 'Ruby', response.xpath('render_choice/response_label[@ident="123"]/material/mattext[@texttype="text/plain"]').text
556
+ assert_equal 'CoffeeScript', response.xpath('render_choice/response_label[@ident="234"]/material/mattext[@texttype="text/plain"]').text
557
+ assert_equal 'Java', response.xpath('render_choice/response_label[@ident="345"]/material/mattext[@texttype="text/plain"]').text
558
+ assert_equal 'Clojure', response.xpath('render_choice/response_label[@ident="456"]/material/mattext[@texttype="text/plain"]').text
559
+
560
+ # Feedback
561
+ feedback = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="123"]/../..').first
562
+ assert feedback, 'feedback does not exist for first answer'
563
+ display = feedback.xpath('displayfeedback[@feedbacktype="Response"][@linkrefid="123_fb"]').first
564
+ assert display, 'display feedback does not exist for first answer'
565
+
566
+ feedback = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="234"]/../..').first
567
+ assert feedback, 'feedback does not exist for second answer'
568
+ display = feedback.xpath('displayfeedback[@feedbacktype="Response"][@linkrefid="234_fb"]').first
569
+ assert display, 'display feedback does not exist for second answer'
570
+
571
+ feedback = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="345"]/../..').first
572
+ assert feedback, 'feedback does not exist for third answer'
573
+ display = feedback.xpath('displayfeedback[@feedbacktype="Response"][@linkrefid="345_fb"]').first
574
+ assert display, 'display feedback does not exist for third answer'
575
+
576
+ feedback = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="456"]/../..').first
577
+ assert feedback, 'feedback does not exist for fourth answer'
578
+ display = feedback.xpath('displayfeedback[@feedbacktype="Response"][@linkrefid="456_fb"]').first
579
+ assert display, 'display feedback does not exist for fourth answer'
580
+
581
+ feedback = xml.root.xpath('itemfeedback[@ident="123_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
582
+ assert feedback, 'feedback text does not exist for first answer'
583
+ assert_equal 'Yippee!', feedback.text
584
+
585
+ feedback = xml.root.xpath('itemfeedback[@ident="234_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
586
+ assert feedback, 'feedback text does not exist for second answer'
587
+ assert_equal 'Nope', feedback.text
588
+
589
+ feedback = xml.root.xpath('itemfeedback[@ident="345_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
590
+ assert feedback, 'feedback text does not exist for third answer'
591
+ assert_equal 'No way', feedback.text
592
+
593
+ feedback = xml.root.xpath('itemfeedback[@ident="456_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
594
+ assert feedback, 'feedback text does not exist for fourth answer'
595
+ assert_equal 'Not even close', feedback.text
596
+
597
+ # Conditions
598
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="123"]/../..').first
599
+ assert condition, 'condition does not exist for first answer'
600
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="100"]').first
601
+ assert var, 'score does not exist for first answer'
602
+
603
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="234"]/../..').first
604
+ assert condition, 'condition does not exist for first answer'
605
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="75"]').first
606
+ assert var, 'score does not exist for second answer'
607
+
608
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="345"]/../..').first
609
+ assert condition, 'condition does not exist for first answer'
610
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="25"]').first
611
+ assert var, 'score does not exist for third answer'
612
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="456"]/../..').first
613
+
614
+ assert condition, 'condition does not exist for first answer'
615
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="0"]').first
616
+ assert var, 'score does not exist for fourth answer'
617
+ end
618
+
619
+ def test_it_creates_item_xml_for_multiple_dropdowns_question
620
+ multiple_dropdowns_question!
621
+
622
+ question = Moodle2CC::Canvas::Question.new @question
623
+ node = Builder::XmlMarkup.new
624
+ xml = Nokogiri::XML(question.create_item_xml(node))
625
+
626
+ # Responses
627
+ response = xml.root.xpath('presentation/response_lid[@ident="response_response1"]').first
628
+ assert response, 'first response for multiple dropdowns question does not exist'
629
+ assert response.xpath('material/mattext["response1"]').first, 'material text does not exist for multiple dropdowns question first response'
630
+ assert_equal '1=Almost Never', response.xpath('render_choice/response_label[@ident="11"]/material/mattext[@texttype="text/plain"]').text
631
+ assert_equal '2=Sometimes', response.xpath('render_choice/response_label[@ident="12"]/material/mattext[@texttype="text/plain"]').text
632
+ assert_equal '3=Always', response.xpath('render_choice/response_label[@ident="13"]/material/mattext[@texttype="text/plain"]').text
633
+ refute response.xpath('render_choice/response_label[4]').first, 'there should not be a response for answer text'
634
+ refute response.xpath('render_choice/response_label[5]').first, 'there should not be a response for answer text'
635
+
636
+ response = xml.root.xpath('presentation/response_lid[@ident="response_response2"]').first
637
+ assert response, 'second response for multiple dropdowns question does not exist'
638
+ assert response.xpath('material/mattext["response2"]').first, 'material text does not exist for multiple dropdowns question second response'
639
+ assert_equal '1=Almost Never', response.xpath('render_choice/response_label[@ident="21"]/material/mattext[@texttype="text/plain"]').text
640
+ assert_equal '2=Sometimes', response.xpath('render_choice/response_label[@ident="22"]/material/mattext[@texttype="text/plain"]').text
641
+ assert_equal '3=Always', response.xpath('render_choice/response_label[@ident="23"]/material/mattext[@texttype="text/plain"]').text
642
+ refute response.xpath('render_choice/response_label[4]').first, 'there should not be a response for answer text'
643
+ refute response.xpath('render_choice/response_label[5]').first, 'there should not be a response for answer text'
644
+
645
+ # Conditions
646
+ condition = xml.root.xpath('resprocessing/respcondition/conditionvar/varequal[@respident="response_response1" and text()="11"]/../..').first
647
+ assert condition, 'condition does not exist for first answer'
648
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Add" and text()="50.00"]').first
649
+ assert var, 'score does not exist for first answer'
650
+
651
+ condition = xml.root.xpath('resprocessing/respcondition/conditionvar/varequal[@respident="response_response2" and text()="21"]/../..').first
652
+ assert condition, 'condition does not exist for first answer'
653
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Add" and text()="50.00"]').first
654
+ assert var, 'score does not exist for second answer'
655
+ end
656
+
657
+ def test_it_create_item_xml_for_multiple_answers_question
658
+ multiple_answers_question!
659
+
660
+ question = Moodle2CC::Canvas::Question.new @question
661
+ node = Builder::XmlMarkup.new
662
+ xml = Nokogiri::XML(question.create_item_xml(node))
663
+
664
+ # Responses
665
+ response = xml.root.xpath('presentation/response_lid[@ident="response1" and @rcardinality="Multiple"]').first
666
+ assert response, 'response for multiple answers question does not exist'
667
+ assert_equal 'Ruby', response.xpath('render_choice/response_label[@ident="1"]/material/mattext[@texttype="text/plain"]').text
668
+ assert_equal 'Javascript', response.xpath('render_choice/response_label[@ident="2"]/material/mattext[@texttype="text/plain"]').text
669
+ assert_equal 'Python', response.xpath('render_choice/response_label[@ident="3"]/material/mattext[@texttype="text/plain"]').text
670
+
671
+ # Conditions
672
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]').first
673
+ assert condition, 'condition does not exist for multiple answer question'
674
+ var = condition.xpath('conditionvar/and/varequal[@respident="response1" and text()="1"]').first
675
+ assert var, 'varequal does not exist for first answer'
676
+ var = condition.xpath('conditionvar/and/not/varequal[@respident="response1" and text()="2"]').first
677
+ assert var, 'varequal does not exist for second answer'
678
+ var = condition.xpath('conditionvar/and/not/varequal[@respident="response1" and text()="3"]').first
679
+ assert var, 'varequal does not exist for third answer'
680
+ var = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="100"]').first
681
+ assert var, 'score does not exist for first answer'
682
+ end
683
+
684
+ def test_it_creates_item_xml_for_numerical_question
685
+ numerical_question!
686
+
687
+ question = Moodle2CC::Canvas::Question.new @question
688
+ node = Builder::XmlMarkup.new
689
+ xml = Nokogiri::XML(question.create_item_xml(node))
690
+
691
+ response = xml.root.xpath('presentation/response_str').first
692
+ assert_equal 'Single', response.attributes['rcardinality'].value
693
+ assert_equal 'response1', response.attributes['ident'].value
694
+ assert_equal 'Decimal', response.xpath('render_fib').first.attributes['fibtype'].value
695
+ assert_equal 'answer1', response.xpath('render_fib/response_label').first.attributes['ident'].value
696
+
697
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"][1]').first
698
+ assert condition, 'condition does not exist for first answer'
699
+ var = condition.xpath('conditionvar/or/varequal[@respident="response1" and text()="28"]').first
700
+ assert var, 'conditionvar varequal does not exist for first answer'
701
+ var = condition.xpath('conditionvar/or/and/vargte[@respident="response1" and text()="26.0"]').first
702
+ assert var, 'conditionvar vargte does not exist for first answer'
703
+ var = condition.xpath('conditionvar/or/and/varlte[@respident="response1" and text()="30.0"]').first
704
+ assert var, 'conditionvar varlte does not exist for first answer'
705
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="100"]').first
706
+ assert setvar, 'setvar does not exist for first answer'
707
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="43_fb"]').first
708
+ assert feedback, 'displayfeedback does not exist for first answer'
709
+
710
+ feedback = xml.root.xpath('itemfeedback[@ident="43_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
711
+ assert feedback, 'feedback text does not exist for first answer'
712
+ assert_equal 'Great age!', feedback.text
713
+ end
714
+
715
+
716
+ def test_it_creates_item_xml_for_short_answer_question
717
+ short_answer_question!
718
+
719
+ question = Moodle2CC::Canvas::Question.new @question
720
+ node = Builder::XmlMarkup.new
721
+ xml = Nokogiri::XML(question.create_item_xml(node))
722
+
723
+ response = xml.root.xpath('presentation/response_str').first
724
+ assert_equal 'Single', response.attributes['rcardinality'].value
725
+ assert_equal 'response1', response.attributes['ident'].value
726
+ assert_equal 'No', response.xpath('render_fib/response_label').first.attributes['rshuffle'].value
727
+ assert_equal 'answer1', response.xpath('render_fib/response_label').first.attributes['ident'].value
728
+
729
+ # Conditions
730
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="Ruby"]/../..').first
731
+ assert condition, 'condition does not exist for first answer'
732
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="100"]').first
733
+ assert setvar, 'setvar does not exist for first answer'
734
+
735
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="JavaScript"]/../..').first
736
+ assert condition, 'condition does not exist for second answer'
737
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="50"]').first
738
+ assert setvar, 'setvar does not exist for second answer'
739
+
740
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="Java"]/../..').first
741
+ assert condition, 'condition does not exist for third answer'
742
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="10"]').first
743
+ assert setvar, 'setvar does not exist for third answer'
744
+
745
+ # Feedback
746
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="Ruby"]/../..').first
747
+ assert condition, 'feedback condition does not exist for first answer'
748
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="40_fb"]').first
749
+ assert feedback, 'displayfeedback does not exist for first answer'
750
+
751
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="JavaScript"]/../..').first
752
+ assert condition, 'feedback condition does not exist for second answer'
753
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="41_fb"]').first
754
+ assert feedback, 'displayfeedback does not exist for second answer'
755
+
756
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="Yes"]/conditionvar/varequal[@respident="response1" and text()="Java"]/../..').first
757
+ assert condition, 'feedback condition does not exist for third answer'
758
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="42_fb"]').first
759
+ assert feedback, 'displayfeedback does not exist for third answer'
760
+
761
+ feedback = xml.root.xpath('itemfeedback[@ident="40_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
762
+ assert feedback, 'feedback text does not exist for first answer'
763
+ assert_equal 'Good choice!', feedback.text
764
+ feedback = xml.root.xpath('itemfeedback[@ident="41_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
765
+ assert feedback, 'feedback text does not exist for second answer'
766
+ assert_equal 'Not what I would have chosen...', feedback.text
767
+ feedback = xml.root.xpath('itemfeedback[@ident="42_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
768
+ assert feedback, 'feedback text does not exist for third answer'
769
+ assert_equal "You're kidding, right?", feedback.text
770
+ end
771
+
772
+ def test_it_creates_item_xml_for_true_false_question
773
+ true_false_question!
774
+
775
+ question = Moodle2CC::Canvas::Question.new @question
776
+ node = Builder::XmlMarkup.new
777
+ xml = Nokogiri::XML(question.create_item_xml(node))
778
+
779
+ response = xml.root.xpath('presentation/response_lid').first
780
+ assert_equal 'Single', response.attributes['rcardinality'].value
781
+ assert_equal 'response1', response.attributes['ident'].value
782
+ assert response.xpath('render_choice/response_label[@ident="44"]/material/mattext[@texttype="text/plain" and text()="True"]').first, 'true response choice does not exist'
783
+ assert response.xpath('render_choice/response_label[@ident="45"]/material/mattext[@texttype="text/plain" and text()="False"]').first, 'false response choice does not exist'
784
+
785
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="44"]/../..').first
786
+ assert condition, 'condition does not exist for first answer'
787
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="44_fb"]').first
788
+ assert feedback, 'displayfeedback does not exist for first answer'
789
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="100"]').first
790
+ assert setvar, 'setvar does not exist for first answer'
791
+
792
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]/conditionvar/varequal[@respident="response1" and text()="45"]/../..').first
793
+ assert condition, 'condition does not exist for second answer'
794
+ feedback = condition.xpath('displayfeedback[@feedbacktype="Response" and @linkrefid="45_fb"]').first
795
+ assert feedback, 'displayfeedback does not exist for second answer'
796
+ setvar = condition.xpath('setvar[@varname="SCORE" and @action="Set" and text()="0"]').first
797
+ assert setvar, 'setvar does not exist for second answer'
798
+
799
+ feedback = xml.root.xpath('itemfeedback[@ident="44_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
800
+ assert feedback, 'feedback text does not exist for first answer'
801
+ assert_equal 'Smarty pants!', feedback.text
802
+ feedback = xml.root.xpath('itemfeedback[@ident="45_fb"]/flow_mat/material/mattext[@texttype="text/plain"]').first
803
+ assert feedback, 'feedback text does not exist for second answer'
804
+ assert_equal 'What exactly are you doing?', feedback.text
805
+ end
806
+
807
+ def test_it_creates_item_xml_for_embedded_answers_question
808
+ @question.type = 'multianswer'
809
+ question = Moodle2CC::Canvas::Question.new @question
810
+ node = Builder::XmlMarkup.new
811
+ xml = Nokogiri::XML(question.create_item_xml(node))
812
+
813
+ response = xml.root.xpath('presentation/response_str').first
814
+ assert_equal 'Single', response.attributes['rcardinality'].value
815
+ assert_equal 'response1', response.attributes['ident'].value
816
+ assert_equal 'No', response.xpath('render_fib/response_label').first.attributes['rshuffle'].value
817
+ assert_equal 'answer1', response.xpath('render_fib/response_label').first.attributes['ident'].value
818
+
819
+ # No Continue Condition
820
+ condition = xml.root.xpath('resprocessing/respcondition[@continue="No"]').first
821
+ assert condition, 'no continue condition node does not exist'
822
+ assert condition.xpath('conditionvar/other').first, 'conditionvar does not exist for no continue condition node'
823
+ end
824
+ end