mumuki-laboratory 6.1.5 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/app/assets/javascripts/application.js +1 -0
- data/app/assets/javascripts/application/codemirror-builder.js +11 -1
- data/app/assets/javascripts/application/codemirror.js +0 -1
- data/app/assets/javascripts/application/discussions.js +15 -2
- data/app/assets/javascripts/application/free-form.js +1 -1
- data/app/assets/javascripts/application/kids.js +3 -3
- data/app/assets/javascripts/application/load-error-svg.js +1 -1
- data/app/controllers/invitations_controller.rb +1 -1
- data/app/helpers/application_helper.rb +0 -22
- data/app/helpers/assets_helper.rb +12 -0
- data/app/helpers/assignment_result_helper.rb +1 -1
- data/app/helpers/assistance_box_helper.rb +9 -0
- data/app/helpers/editor_helper.rb +13 -0
- data/app/helpers/locale_helper.rb +11 -0
- data/app/helpers/menu_bar_helper.rb +13 -0
- data/app/helpers/multiple_file_editor_helper.rb +5 -0
- data/app/helpers/open_graph_helper.rb +12 -0
- data/app/helpers/page_title_helper.rb +11 -0
- data/app/views/exercise_solutions/_kids_results.html.erb +1 -1
- data/app/views/exercises/_read_only.html.erb +3 -1
- data/app/views/invitations/show.html.erb +1 -1
- data/app/views/layouts/_kids.html.erb +1 -1
- data/app/views/layouts/_main.html.erb +5 -20
- data/app/views/layouts/application.html.erb +2 -7
- data/app/views/layouts/exercise_inputs/editors/_multiple_files.html.erb +11 -12
- data/app/views/layouts/exercise_inputs/layouts/_input_kids.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/read_only_editors/_code.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/read_only_editors/_free_form.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/read_only_editors/_multiple_files.html.erb +29 -0
- data/app/views/layouts/mailer.html.erb +1 -1
- data/app/views/layouts/modals/_kids_context.html.erb +1 -1
- data/config/initializers/form_builder.rb +4 -5
- data/lib/events.rb +1 -4
- data/lib/mumuki/laboratory/locales/en.yml +0 -1
- data/lib/mumuki/laboratory/locales/es.yml +0 -1
- data/lib/mumuki/laboratory/locales/pt.yml +0 -1
- data/lib/mumuki/laboratory/version.rb +1 -1
- data/public/character/kids/{yellow_context.svg → kibi_context.svg} +2 -2
- data/public/{amarillo.svg → kibi.svg} +2 -2
- data/public/{anim_amarillo.svg → kibi_animated.svg} +2 -2
- data/public/{amarillo_fracaso.svg → kibi_failure.svg} +2 -2
- data/public/{amarillo_exito.svg → kibi_success.svg} +2 -2
- data/public/{amarillo_exito_bailarin.svg → kibi_success_dancing.svg} +2 -2
- data/spec/capybara_helper.rb +4 -4
- data/spec/helpers/application_helper_spec.rb +0 -16
- data/spec/helpers/page_title_helper_spec.rb +19 -0
- data/spec/spec_helper.rb +2 -1
- data/vendor/assets/javascripts/codemirror-autorefresh.js +46 -0
- metadata +76 -163
- data/spec/factories/api_client_factory.rb +0 -18
- data/spec/factories/assignments_factory.rb +0 -7
- data/spec/factories/book_factory.rb +0 -7
- data/spec/factories/chapter_factory.rb +0 -16
- data/spec/factories/complement_factory.rb +0 -6
- data/spec/factories/course_factory.rb +0 -9
- data/spec/factories/discussion_factory.rb +0 -8
- data/spec/factories/exam_factory.rb +0 -9
- data/spec/factories/exercise_factory.rb +0 -73
- data/spec/factories/guide_factory.rb +0 -30
- data/spec/factories/invitation_factory.rb +0 -7
- data/spec/factories/lesson_factory.rb +0 -7
- data/spec/factories/login_settings_factory.rb +0 -5
- data/spec/factories/message_factory.rb +0 -11
- data/spec/factories/organization_factory.rb +0 -26
- data/spec/factories/topic_factory.rb +0 -9
- data/spec/factories/user_factory.rb +0 -8
- data/spec/models/api_client_spec.rb +0 -6
- data/spec/models/assignment_spec.rb +0 -191
- data/spec/models/book_import_spec.rb +0 -49
- data/spec/models/book_spec.rb +0 -114
- data/spec/models/course_spec.rb +0 -22
- data/spec/models/discussion_spec.rb +0 -174
- data/spec/models/event_generation_spec.rb +0 -189
- data/spec/models/event_publishing_spec.rb +0 -36
- data/spec/models/exam_spec.rb +0 -151
- data/spec/models/exercise_spec.rb +0 -494
- data/spec/models/guide_import_spec.rb +0 -300
- data/spec/models/guide_spec.rb +0 -83
- data/spec/models/interactive_spec.rb +0 -143
- data/spec/models/language_spec.rb +0 -56
- data/spec/models/lesson_spec.rb +0 -90
- data/spec/models/message_spec.rb +0 -87
- data/spec/models/navigation_spec.rb +0 -70
- data/spec/models/organization_spec.rb +0 -124
- data/spec/models/playground_spec.rb +0 -23
- data/spec/models/problem_spec.rb +0 -80
- data/spec/models/query_spec.rb +0 -21
- data/spec/models/question_spec.rb +0 -37
- data/spec/models/reading_spec.rb +0 -10
- data/spec/models/solution_spec.rb +0 -66
- data/spec/models/stats_spec.rb +0 -15
- data/spec/models/string_spec.rb +0 -9
- data/spec/models/topic_import_spec.rb +0 -42
- data/spec/models/usage_spec.rb +0 -77
- data/spec/models/user_changed_spec.rb +0 -35
- data/spec/models/user_spec.rb +0 -276
- data/spec/models/with_expectations_spec.rb +0 -56
@@ -1,300 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Guide do
|
4
|
-
let!(:haskell) { create(:haskell) }
|
5
|
-
let!(:text) { create(:text_language) }
|
6
|
-
let!(:gobstones) { create(:gobstones) }
|
7
|
-
let(:reloaded_exercise_1) { Exercise.find(exercise_1.id) }
|
8
|
-
|
9
|
-
let(:guide_resource_h) do
|
10
|
-
{name: 'sample guide',
|
11
|
-
description: 'Baz',
|
12
|
-
slug: 'mumuki/sample-guide',
|
13
|
-
language: { name: 'haskell' },
|
14
|
-
locale: 'en',
|
15
|
-
extra: 'bar',
|
16
|
-
teacher_info: 'an info',
|
17
|
-
authors: 'Foo Bar',
|
18
|
-
exercises: [
|
19
|
-
{type: 'problem',
|
20
|
-
name: 'Bar',
|
21
|
-
description: 'a description',
|
22
|
-
test: 'foo bar',
|
23
|
-
tag_list: %w(baz bar),
|
24
|
-
layout: 'input_bottom',
|
25
|
-
teacher_info: 'an info',
|
26
|
-
language: { name: 'gobstones' },
|
27
|
-
solution: 'foo',
|
28
|
-
assistance_rules: [
|
29
|
-
{when: :content_empty, then: 'remember to copy the code in the editor!'},
|
30
|
-
{when: :submission_errored, then: 'remember to copy code exactly as presented'},
|
31
|
-
],
|
32
|
-
id: 1},
|
33
|
-
|
34
|
-
{type: 'playground',
|
35
|
-
description: 'lorem ipsum',
|
36
|
-
name: 'Foo',
|
37
|
-
tag_list: %w(foo bar),
|
38
|
-
extra: 'an extra code',
|
39
|
-
extra_visible: true,
|
40
|
-
default_content: 'a default content',
|
41
|
-
id: 4},
|
42
|
-
|
43
|
-
{name: 'Baz',
|
44
|
-
description: 'lorem ipsum',
|
45
|
-
tag_list: %w(baz bar),
|
46
|
-
layout: 'input_bottom',
|
47
|
-
type: 'problem',
|
48
|
-
expectations: [{inspection: 'HasBinding', binding: 'foo'}],
|
49
|
-
id: 2},
|
50
|
-
|
51
|
-
{type: 'problem',
|
52
|
-
description: 'lorem ipsum',
|
53
|
-
name: 'Choice',
|
54
|
-
tag_list: %w(bar),
|
55
|
-
extra: '',
|
56
|
-
language: { name: 'text' },
|
57
|
-
test: "---\nequal: '1'\n",
|
58
|
-
choices: [{value: 'foo', checked: false}, {value: 'bar', checked: true}],
|
59
|
-
extra_visible: false,
|
60
|
-
id: 8},
|
61
|
-
{type: 'reading',
|
62
|
-
description: 'lorem ipsum',
|
63
|
-
name: 'Reading',
|
64
|
-
expectations: [],
|
65
|
-
choices: [],
|
66
|
-
tag_list: %w(bar),
|
67
|
-
language: { name: 'text' },
|
68
|
-
layout: 'input_bottom',
|
69
|
-
extra_visible: false,
|
70
|
-
id: 9}]}
|
71
|
-
end
|
72
|
-
|
73
|
-
describe '#import_from_resource_h!' do
|
74
|
-
context 'when an exercise is deleted' do
|
75
|
-
let(:guide) { create(:guide, exercises: [exercise_1, exercise_2, exercise_3, exercise_4, exercise_5, exercise_6]) }
|
76
|
-
|
77
|
-
let(:exercise_1) { build(:problem,
|
78
|
-
language: haskell,
|
79
|
-
name: 'Exercise 1',
|
80
|
-
bibliotheca_id: 1,
|
81
|
-
number: 1) }
|
82
|
-
|
83
|
-
let(:exercise_2) { build(:playground,
|
84
|
-
language: haskell,
|
85
|
-
name: 'Exercise 2',
|
86
|
-
bibliotheca_id: 4,
|
87
|
-
number: 2) }
|
88
|
-
|
89
|
-
let(:exercise_3) { build(:problem,
|
90
|
-
language: haskell,
|
91
|
-
name: 'Exercise 3',
|
92
|
-
bibliotheca_id: 2,
|
93
|
-
number: 3) }
|
94
|
-
|
95
|
-
let(:exercise_4) { create(:problem,
|
96
|
-
language: haskell,
|
97
|
-
name: 'Exercise 4',
|
98
|
-
bibliotheca_id: 8,
|
99
|
-
number: 4) }
|
100
|
-
|
101
|
-
let(:exercise_5) { create(:problem,
|
102
|
-
language: haskell,
|
103
|
-
name: 'Exercise 5',
|
104
|
-
bibliotheca_id: 11,
|
105
|
-
number: 5) }
|
106
|
-
|
107
|
-
let(:exercise_6) { create(:problem,
|
108
|
-
language: haskell,
|
109
|
-
name: 'Exercise 6',
|
110
|
-
bibliotheca_id: 14,
|
111
|
-
number: 6) }
|
112
|
-
|
113
|
-
before do
|
114
|
-
guide.import_from_resource_h!(guide_resource_h)
|
115
|
-
end
|
116
|
-
|
117
|
-
describe 'it is removed from the guide' do
|
118
|
-
it { expect(guide.exercises.count).to eq 5 }
|
119
|
-
it { expect(guide.exercises).not_to include exercise_6 }
|
120
|
-
end
|
121
|
-
|
122
|
-
describe 'it is deleted from the database' do
|
123
|
-
it { expect { Exercise.find(exercise_6.id) }.to raise_error(ActiveRecord::RecordNotFound) }
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context 'when guide is empty' do
|
128
|
-
let(:lesson) { create(:lesson, guide: create(:guide, exercises: [])) }
|
129
|
-
let(:guide) { lesson.guide }
|
130
|
-
|
131
|
-
before do
|
132
|
-
guide.import_from_resource_h!(guide_resource_h)
|
133
|
-
end
|
134
|
-
|
135
|
-
it { expect(guide).to_not be nil }
|
136
|
-
it { expect(guide.name).to eq 'sample guide' }
|
137
|
-
it { expect(guide.language).to eq haskell }
|
138
|
-
it { expect(guide.slug).to eq 'mumuki/sample-guide' }
|
139
|
-
it { expect(guide.extra).to eq 'bar' }
|
140
|
-
it { expect(guide.description).to eq 'Baz' }
|
141
|
-
|
142
|
-
it { expect(guide.exercises.count).to eq 5 }
|
143
|
-
it { expect(guide.exercises.first.language).to eq gobstones }
|
144
|
-
it { expect(guide.exercises.first.extra_visible).to be false }
|
145
|
-
it { expect(guide.exercises.first.assistance_rules).to be_present }
|
146
|
-
it { expect(guide.exercises.first.assistant.rules.count).to eq 2 }
|
147
|
-
|
148
|
-
it { expect(guide.exercises.second.language).to eq haskell }
|
149
|
-
it { expect(guide.exercises.second.default_content).to eq 'a default content' }
|
150
|
-
it { expect(guide.exercises.second.extra_visible).to be true }
|
151
|
-
it { expect(guide.exercises.fourth.choices).to eq [{'value' => 'foo', 'checked' => false}, {'value' => 'bar', 'checked' => true}] }
|
152
|
-
it { expect(guide.exercises.fourth.choice_values).to eq ['foo', 'bar'] }
|
153
|
-
|
154
|
-
it { expect(guide.exercises.third.expectations.first['binding']).to eq 'foo' }
|
155
|
-
|
156
|
-
it { expect(guide.exercises.pluck(:name)).to eq %W(Bar Foo Baz Choice Reading) }
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'when exercise already exists' do
|
160
|
-
let(:guide) { create(:guide, language: haskell, exercises: [exercise_1]) }
|
161
|
-
|
162
|
-
before do
|
163
|
-
guide.import_from_resource_h! guide_resource_h
|
164
|
-
end
|
165
|
-
|
166
|
-
context 'when exercise changes its type' do
|
167
|
-
let(:exercise_1) { build(:playground,
|
168
|
-
bibliotheca_id: 1,
|
169
|
-
language: haskell,
|
170
|
-
name: 'Exercise 1',
|
171
|
-
description: 'description') }
|
172
|
-
|
173
|
-
describe 'exercises are not duplicated' do
|
174
|
-
it { expect(guide.exercises.count).to eq 5 }
|
175
|
-
it { expect(Exercise.count).to eq 5 }
|
176
|
-
end
|
177
|
-
|
178
|
-
it { expect(guide.exercises.first).to be_instance_of(Problem) }
|
179
|
-
it { expect(guide.exercises.first).to eq reloaded_exercise_1 }
|
180
|
-
end
|
181
|
-
|
182
|
-
context 'when exercise doesnt have choices anymore' do
|
183
|
-
let(:exercise_1) { build(:problem,
|
184
|
-
bibliotheca_id: 1,
|
185
|
-
language: haskell,
|
186
|
-
name: 'Choices 1',
|
187
|
-
description: 'description',
|
188
|
-
hint: 'baz',
|
189
|
-
choices: ['option 1', 'option 2'],
|
190
|
-
test: 'pending',
|
191
|
-
extra: 'foo') }
|
192
|
-
|
193
|
-
it { expect(guide.exercises.first.choices?).to be false }
|
194
|
-
end
|
195
|
-
|
196
|
-
context 'exercises are reordered' do
|
197
|
-
let(:exercise_1) { create(:problem,
|
198
|
-
bibliotheca_id: 4,
|
199
|
-
language: haskell,
|
200
|
-
name: 'Exercise 1',
|
201
|
-
description: 'description',
|
202
|
-
hint: 'baz',
|
203
|
-
test: 'pending',
|
204
|
-
extra: 'foo') }
|
205
|
-
|
206
|
-
it 'identity should be preserved' do
|
207
|
-
expect(guide.exercises.first).to_not eq reloaded_exercise_1
|
208
|
-
expect(guide.exercises.second).to eq reloaded_exercise_1
|
209
|
-
end
|
210
|
-
|
211
|
-
it { expect(guide.exercises.pluck(:bibliotheca_id)).to eq [1, 4, 2, 8, 9] }
|
212
|
-
|
213
|
-
describe 'exercises are not duplicated' do
|
214
|
-
it { expect(guide.exercises.count).to eq 5 }
|
215
|
-
it { expect(Exercise.count).to eq 5 }
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
context 'when many exercises already exist' do
|
221
|
-
let(:guide) { create(:guide, language: haskell, exercises: [exercise_1, exercise_2]) }
|
222
|
-
|
223
|
-
let(:exercise_1) { build(:problem,
|
224
|
-
language: haskell,
|
225
|
-
name: 'Exercise 1',
|
226
|
-
bibliotheca_id: 2,
|
227
|
-
number: 1,
|
228
|
-
description: 'description',
|
229
|
-
corollary: 'A corollary',
|
230
|
-
test: 'foo',
|
231
|
-
hint: 'baz',
|
232
|
-
extra: 'foo') }
|
233
|
-
let(:exercise_2) { build(:playground,
|
234
|
-
language: haskell,
|
235
|
-
name: 'Exercise 2',
|
236
|
-
bibliotheca_id: 4,
|
237
|
-
number: 2,
|
238
|
-
description: 'description',
|
239
|
-
corollary: 'A corollary',
|
240
|
-
hint: 'baz',
|
241
|
-
extra: 'foo') }
|
242
|
-
let(:reloaded_exercise_2) { Exercise.find(exercise_2.id) }
|
243
|
-
|
244
|
-
before do
|
245
|
-
guide.import_from_resource_h! guide_resource_h
|
246
|
-
end
|
247
|
-
|
248
|
-
describe 'exercises are not duplicated' do
|
249
|
-
it { expect(guide.exercises.count).to eq 5 }
|
250
|
-
it { expect(Exercise.count).to eq 5 }
|
251
|
-
end
|
252
|
-
|
253
|
-
it { expect(guide.exercises.first).to be_instance_of(Problem) }
|
254
|
-
it { expect(guide.exercises.second).to be_instance_of(Playground) }
|
255
|
-
it { expect(guide.exercises.third).to be_instance_of(Problem) }
|
256
|
-
|
257
|
-
it { expect(guide.exercises.second).to eq reloaded_exercise_2 }
|
258
|
-
it { expect(guide.exercises.third).to eq reloaded_exercise_1 }
|
259
|
-
|
260
|
-
it { expect(guide.exercises.first.number).to eq 1 }
|
261
|
-
it { expect(guide.exercises.second.number).to eq 2 }
|
262
|
-
it { expect(guide.exercises.third.number).to eq 3 }
|
263
|
-
it { expect(guide.exercises.fourth.number).to eq 4 }
|
264
|
-
|
265
|
-
it { expect(guide.exercises.pluck(:bibliotheca_id)).to eq [1, 4, 2, 8, 9] }
|
266
|
-
it { expect(guide.exercises.pluck(:id).drop(1)).to eq [reloaded_exercise_2.id, reloaded_exercise_1.id, guide.exercises.fourth.id, guide.exercises.fifth.id] }
|
267
|
-
end
|
268
|
-
|
269
|
-
context 'when new_expecations' do
|
270
|
-
let(:guide) { create(:guide, language: haskell) }
|
271
|
-
let(:guide_resource_h) do
|
272
|
-
{name: 'sample guide',
|
273
|
-
description: 'Baz',
|
274
|
-
slug: 'mumuki/sample-guide',
|
275
|
-
language: { name: 'haskell' },
|
276
|
-
locale: 'en',
|
277
|
-
extra: 'bar',
|
278
|
-
teacher_info: 'an info',
|
279
|
-
authors: 'Foo Bar',
|
280
|
-
exercises: [
|
281
|
-
{name: 'Baz',
|
282
|
-
description: 'lorem ipsum',
|
283
|
-
tag_list: %w(baz bar),
|
284
|
-
layout: 'input_bottom',
|
285
|
-
test: 'foo bar',
|
286
|
-
type: 'problem',
|
287
|
-
expectations: [{inspection: 'HasBinding', binding: 'foo'}],
|
288
|
-
new_expectations: true,
|
289
|
-
id: 2}]}
|
290
|
-
end
|
291
|
-
|
292
|
-
before do
|
293
|
-
guide.import_from_resource_h! guide_resource_h
|
294
|
-
end
|
295
|
-
|
296
|
-
it { expect(guide.exercises.first.new_expectations).to be_truthy }
|
297
|
-
it { expect(guide.exercises.first.expectations).to eq [] }
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
data/spec/models/guide_spec.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Guide, organization_workspace: :test do
|
4
|
-
let!(:extra_user) { create(:user, first_name: 'Ignatius', last_name: 'Reilly') }
|
5
|
-
let(:guide) { create(:guide) }
|
6
|
-
|
7
|
-
describe '#clear_progress!' do
|
8
|
-
let(:an_exercise) { create(:exercise) }
|
9
|
-
let(:another_exercise) { create(:exercise) }
|
10
|
-
|
11
|
-
before do
|
12
|
-
guide.exercises = [an_exercise]
|
13
|
-
an_exercise.submit_solution! extra_user
|
14
|
-
another_exercise.submit_solution! extra_user
|
15
|
-
guide.clear_progress!(extra_user)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'destroys the guides assignments for the given user' do
|
19
|
-
expect(an_exercise.find_assignment_for(extra_user)).to be_nil
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'does not destroy other guides assignments' do
|
23
|
-
expect(another_exercise.find_assignment_for(extra_user)).to be_truthy
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '#fork!' do
|
28
|
-
let(:syncer) { double(:syncer) }
|
29
|
-
let!(:guide_from) { create :guide, slug: 'foo/bar' }
|
30
|
-
let(:slug_from) { guide_from.slug }
|
31
|
-
let(:slug_to) { 'baz/bar'.to_mumukit_slug }
|
32
|
-
let(:guide_to) { Guide.find_by_slug! slug_to.to_s }
|
33
|
-
let!(:guide) { create(:guide, slug: 'test/bar') }
|
34
|
-
|
35
|
-
context 'fork works' do
|
36
|
-
before { expect(syncer).to receive(:export!).with(instance_of(Guide)) }
|
37
|
-
before { Guide.find_by_slug!(slug_from).fork_to! 'baz', syncer }
|
38
|
-
it { expect(guide_from.to_resource_h).to json_eq guide_to.to_resource_h, except: [:slug] }
|
39
|
-
end
|
40
|
-
|
41
|
-
context 'fork does not work if guide already exists' do
|
42
|
-
before { expect(syncer).to_not receive(:export!) }
|
43
|
-
it { expect { Guide.find_by_slug!(slug_from).fork_to! 'test', syncer }.to raise_error ActiveRecord::RecordInvalid }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '#to_markdownified_resource_h' do
|
48
|
-
subject { guide.to_markdownified_resource_h }
|
49
|
-
context 'description' do
|
50
|
-
let(:guide) { create(:guide, description: '`foo = (+)`') }
|
51
|
-
it { expect(subject[:description]).to eq("<p><code>foo = (+)</code></p>\n") }
|
52
|
-
end
|
53
|
-
context 'corollary' do
|
54
|
-
let(:guide) { create(:guide, corollary: '[Google](https://google.com)') }
|
55
|
-
it { expect(subject[:corollary]).to eq("<p><a title=\"\" href=\"https://google.com\" target=\"_blank\">Google</a></p>\n") }
|
56
|
-
end
|
57
|
-
context 'teacher_info' do
|
58
|
-
let(:guide) { create(:guide, teacher_info: '**foo**') }
|
59
|
-
it { expect(subject[:teacher_info]).to eq("<p><strong>foo</strong></p>\n") }
|
60
|
-
end
|
61
|
-
context 'exercises' do
|
62
|
-
let(:guide) { create(:guide, exercises: [exercise]) }
|
63
|
-
subject { guide.to_markdownified_resource_h[:exercises].first }
|
64
|
-
|
65
|
-
context 'description' do
|
66
|
-
let(:exercise) { build(:exercise, description: '`foo = (+)`') }
|
67
|
-
it { expect(subject[:description]).to eq("<p><code>foo = (+)</code></p>\n") }
|
68
|
-
end
|
69
|
-
context 'corollary' do
|
70
|
-
let(:exercise) { build(:exercise, corollary: '[Google](https://google.com)') }
|
71
|
-
it { expect(subject[:corollary]).to eq("<p><a title=\"\" href=\"https://google.com\" target=\"_blank\">Google</a></p>\n") }
|
72
|
-
end
|
73
|
-
context 'teacher_info' do
|
74
|
-
let(:exercise) { build(:exercise, teacher_info: '**foo**') }
|
75
|
-
it { expect(subject[:teacher_info]).to eq("<p><strong>foo</strong></p>\n") }
|
76
|
-
end
|
77
|
-
context 'hint' do
|
78
|
-
let(:exercise) { build(:exercise, hint: '***foo***') }
|
79
|
-
it { expect(subject[:hint]).to eq("<p><strong><em>foo</em></strong></p>\n") }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
@@ -1,143 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Interactive, organization_workspace: :test do
|
4
|
-
let!(:interactive) { create(:interactive) }
|
5
|
-
let!(:user) { create(:user) }
|
6
|
-
let(:assignment) { interactive.assignment_for(user) }
|
7
|
-
let!(:bridge) { double(:bridge) }
|
8
|
-
before { allow_any_instance_of(Language).to receive(:bridge).and_return bridge }
|
9
|
-
|
10
|
-
context 'before even trying' do
|
11
|
-
it { expect(assignment.queries).to eq [] }
|
12
|
-
it { expect(assignment.query_results).to be_blank }
|
13
|
-
it { expect(assignment.status).to eq :pending }
|
14
|
-
it { expect(assignment.result).to be_blank }
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'on first, failing try' do
|
18
|
-
before do
|
19
|
-
expect(bridge)
|
20
|
-
.to receive(:run_try!).and_return status: :failed,
|
21
|
-
result: '',
|
22
|
-
query_result: {
|
23
|
-
status: :passed,
|
24
|
-
result: 'foo out'
|
25
|
-
}
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
before { interactive.submit_try!(user, query: 'foo') }
|
30
|
-
|
31
|
-
it { expect(assignment.queries).to eq ['foo'] }
|
32
|
-
it { expect(assignment.query_results).to eq [{status: :passed, result: "foo out"}] }
|
33
|
-
it { expect(assignment.queries_with_results).to eq [{query: 'foo', status: :passed, result: "foo out"}] }
|
34
|
-
it { expect(assignment.status).to eq :failed }
|
35
|
-
it { expect(assignment.result).to eq '' }
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'on second, failing try' do
|
39
|
-
before do
|
40
|
-
expect(bridge)
|
41
|
-
.to receive(:run_try!).and_return({status: :failed,
|
42
|
-
result: '',
|
43
|
-
query_result: { status: :passed, result: 'foo out' }},
|
44
|
-
{status: :failed,
|
45
|
-
result: '',
|
46
|
-
query_result: { status: :failed, result: 'bar out' }})
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
before do
|
52
|
-
interactive.submit_try!(user, query: 'foo')
|
53
|
-
interactive.submit_try!(user, query: 'bar', cookie: ['foo'])
|
54
|
-
end
|
55
|
-
|
56
|
-
it { expect(assignment.queries).to eq ['foo', 'bar'] }
|
57
|
-
it { expect(assignment.query_results).to eq [
|
58
|
-
{status: :passed, result: 'foo out'},
|
59
|
-
{status: :failed, result: 'bar out'}] }
|
60
|
-
it { expect(assignment.queries_with_results).to eq [
|
61
|
-
{query: 'foo', status: :passed, result: 'foo out'},
|
62
|
-
{query: 'bar', status: :failed, result: 'bar out'}] }
|
63
|
-
|
64
|
-
it { expect(assignment.status).to eq :failed }
|
65
|
-
it { expect(assignment.result).to be_blank }
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'on third, passing try' do
|
69
|
-
before do
|
70
|
-
expect(bridge)
|
71
|
-
.to receive(:run_try!).and_return({status: :failed,
|
72
|
-
result: '',
|
73
|
-
query_result: { status: :passed, result: 'foo out' }},
|
74
|
-
{status: :failed,
|
75
|
-
result: '',
|
76
|
-
query_result: { status: :failed, result: 'bar out' }},
|
77
|
-
{status: :passed,
|
78
|
-
result: 'foobaz',
|
79
|
-
query_result: { status: :passed, result: 'baz out' }})
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
before do
|
85
|
-
interactive.submit_try!(user, query: 'foo')
|
86
|
-
interactive.submit_try!(user, query: 'bar', cookie: ['foo'])
|
87
|
-
interactive.submit_try!(user, query: 'baz', cookie: ['foo', 'bar'])
|
88
|
-
end
|
89
|
-
|
90
|
-
it { expect(assignment.queries).to eq ['foo', 'bar', 'baz'] }
|
91
|
-
it { expect(assignment.query_results).to eq [
|
92
|
-
{status: :passed, result: 'foo out'},
|
93
|
-
{status: :failed, result: 'bar out'},
|
94
|
-
{status: :passed, result: 'baz out'}] }
|
95
|
-
it { expect(assignment.status).to eq :passed }
|
96
|
-
it { expect(assignment.result).to eq 'foobaz' }
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
context 'on first failing try after reset' do
|
101
|
-
before do
|
102
|
-
expect(bridge)
|
103
|
-
.to receive(:run_try!).and_return({status: :failed,
|
104
|
-
result: '',
|
105
|
-
query_result: { status: :passed, result: 'foo out' }},
|
106
|
-
{status: :failed,
|
107
|
-
result: '',
|
108
|
-
query_result: { status: :failed, result: 'bar out' }},
|
109
|
-
{status: :failed,
|
110
|
-
result: '',
|
111
|
-
query_result: { status: :failed, result: 'goo out' }})
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
before do
|
117
|
-
interactive.submit_try!(user, query: 'foo')
|
118
|
-
interactive.submit_try!(user, query: 'bar', cookie: ['foo'])
|
119
|
-
interactive.submit_try!(user, query: 'goo')
|
120
|
-
end
|
121
|
-
|
122
|
-
it { expect(assignment.queries).to eq ['goo'] }
|
123
|
-
it { expect(assignment.query_results).to eq [{status: :failed, result: 'goo out'}] }
|
124
|
-
it { expect(assignment.status).to eq :failed }
|
125
|
-
it { expect(assignment.result).to be_blank }
|
126
|
-
end
|
127
|
-
|
128
|
-
context 'on aborted try with no query_result' do
|
129
|
-
before do
|
130
|
-
expect(bridge).to receive(:run_try!).and_return({status: :aborted, result: ''})
|
131
|
-
end
|
132
|
-
|
133
|
-
before do
|
134
|
-
interactive.submit_try!(user, query: 'foo')
|
135
|
-
end
|
136
|
-
|
137
|
-
it { expect(assignment.queries).to eq ['foo'] }
|
138
|
-
it { expect(assignment.query_results).to eq [] }
|
139
|
-
it { expect(assignment.status).to eq :aborted }
|
140
|
-
it { expect(assignment.result).to eq 'Oops, something went wrong in Mumuki. Restart the exercise, wait a few seconds and try again.'}
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|