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,18 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
factory :api_client do |t|
|
3
|
-
transient do
|
4
|
-
role { :janitor }
|
5
|
-
grant { 'test/*' }
|
6
|
-
end
|
7
|
-
|
8
|
-
description { "foo" }
|
9
|
-
user {
|
10
|
-
create :user,
|
11
|
-
first_name: 'foo',
|
12
|
-
last_name: 'bar',
|
13
|
-
email: 'foo+1@bar.com',
|
14
|
-
uid: 'foo+1@bar.com',
|
15
|
-
permissions: { role => grant }
|
16
|
-
}
|
17
|
-
end
|
18
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
|
3
|
-
factory :chapter do
|
4
|
-
number { Faker::Number.between(1, 40) }
|
5
|
-
book { Organization.current.book rescue nil }
|
6
|
-
|
7
|
-
transient do
|
8
|
-
lessons { [] }
|
9
|
-
name { Faker::Lorem.sentence(3) }
|
10
|
-
end
|
11
|
-
|
12
|
-
after(:build) do |chapter, evaluator|
|
13
|
-
chapter.topic = build(:topic, name: evaluator.name, lessons: evaluator.lessons) unless evaluator.topic
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
|
3
|
-
factory :language do
|
4
|
-
sequence(:name) { |n| "lang#{n}" }
|
5
|
-
|
6
|
-
runner_url { Faker::Internet.url }
|
7
|
-
queriable { true }
|
8
|
-
end
|
9
|
-
|
10
|
-
factory :haskell, parent: :language do
|
11
|
-
name { 'haskell' }
|
12
|
-
end
|
13
|
-
|
14
|
-
factory :bash, parent: :language do
|
15
|
-
name { 'bash' }
|
16
|
-
triable { true }
|
17
|
-
stateful_console { true }
|
18
|
-
end
|
19
|
-
|
20
|
-
factory :text_language, parent: :language do
|
21
|
-
name { 'text' }
|
22
|
-
end
|
23
|
-
|
24
|
-
factory :gobstones, parent: :language do
|
25
|
-
name { 'gobstones' }
|
26
|
-
extension { 'gbs' }
|
27
|
-
queriable { false }
|
28
|
-
end
|
29
|
-
|
30
|
-
factory :exercise_base do
|
31
|
-
language { guide ? guide.language : create(:language) }
|
32
|
-
sequence(:bibliotheca_id) { |n| n }
|
33
|
-
sequence(:number) { |n| n }
|
34
|
-
|
35
|
-
locale { :en }
|
36
|
-
guide
|
37
|
-
end
|
38
|
-
|
39
|
-
factory :challenge, parent: :exercise_base do
|
40
|
-
layout { 'input_right' }
|
41
|
-
end
|
42
|
-
|
43
|
-
factory :reading, class: Reading, parent: :exercise_base do
|
44
|
-
name { 'A reading' }
|
45
|
-
description { 'Simple reading' }
|
46
|
-
end
|
47
|
-
|
48
|
-
factory :problem, class: Problem, parent: :challenge do
|
49
|
-
name { 'A problem' }
|
50
|
-
description { 'Simple problem' }
|
51
|
-
test { 'dont care' }
|
52
|
-
end
|
53
|
-
|
54
|
-
factory :interactive, class: Interactive, parent: :challenge do
|
55
|
-
name { 'An interactive problem' }
|
56
|
-
description { 'Simple interactive problem' }
|
57
|
-
goal { :query_passes }
|
58
|
-
language { create(:bash) }
|
59
|
-
end
|
60
|
-
|
61
|
-
factory :playground, class: Playground, parent: :challenge do
|
62
|
-
name { 'A Playground' }
|
63
|
-
description { 'Simple playground' }
|
64
|
-
end
|
65
|
-
|
66
|
-
factory :exercise, parent: :problem
|
67
|
-
|
68
|
-
factory :x_equal_5_exercise, parent: :exercise do
|
69
|
-
test { 'describe "x" $ do
|
70
|
-
it "should be equal 5" $ do
|
71
|
-
x `shouldBe` 5' }
|
72
|
-
end
|
73
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
|
3
|
-
factory :guide do
|
4
|
-
sequence(:name) { |n| "guide#{n}" }
|
5
|
-
locale { 'en' }
|
6
|
-
description { 'A Guide' }
|
7
|
-
slug { "flbulgarelli/mumuki-sample-guide-#{SecureRandom.uuid}" }
|
8
|
-
language
|
9
|
-
end
|
10
|
-
|
11
|
-
trait :guide_container do
|
12
|
-
transient do
|
13
|
-
exercises { [] }
|
14
|
-
name { Faker::Lorem.sentence(3) }
|
15
|
-
description { Faker::Lorem.sentence(10) }
|
16
|
-
language { create(:language) }
|
17
|
-
slug { "mumuki/mumuki-test-lesson-#{SecureRandom.uuid}" }
|
18
|
-
end
|
19
|
-
|
20
|
-
after(:build) do |lesson, evaluator|
|
21
|
-
lesson.guide = build(:guide,
|
22
|
-
name: evaluator.name,
|
23
|
-
slug: evaluator.slug,
|
24
|
-
exercises: evaluator.exercises,
|
25
|
-
description: evaluator.description,
|
26
|
-
language: evaluator.language) unless evaluator.guide
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
FactoryBot.define do
|
2
|
-
|
3
|
-
factory :organization do
|
4
|
-
contact_email { Faker::Internet.email }
|
5
|
-
description { 'a great org' }
|
6
|
-
locale { 'en' }
|
7
|
-
settings {}
|
8
|
-
book
|
9
|
-
end
|
10
|
-
|
11
|
-
factory :base, parent: :organization do
|
12
|
-
public { true }
|
13
|
-
name { 'base' }
|
14
|
-
login_methods { Mumukit::Login::Settings.login_methods }
|
15
|
-
end
|
16
|
-
|
17
|
-
factory :public_organization, parent: :organization do
|
18
|
-
public { true }
|
19
|
-
name { 'the-public-org' }
|
20
|
-
login_methods { Mumukit::Login::Settings.login_methods }
|
21
|
-
end
|
22
|
-
|
23
|
-
factory :private_organization, parent: :organization do
|
24
|
-
name { 'the-private-org' }
|
25
|
-
end
|
26
|
-
end
|
@@ -1,191 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Assignment, organization_workspace: :test do
|
4
|
-
|
5
|
-
describe 'messages' do
|
6
|
-
let(:student) { create(:user) }
|
7
|
-
let(:problem) { create(:problem, manual_evaluation: true) }
|
8
|
-
let(:assignment) { problem.assignment_for(student) }
|
9
|
-
let(:message) { assignment.messages.first }
|
10
|
-
|
11
|
-
before { problem.submit_solution! student, content: '...' }
|
12
|
-
|
13
|
-
describe '.send_question!' do
|
14
|
-
before { problem.submit_question! student, content: 'How can i solve this?' }
|
15
|
-
|
16
|
-
it { expect(assignment.new_record?).to be false }
|
17
|
-
it { expect(assignment.has_messages?).to be true }
|
18
|
-
it { expect(message.sender).to eq student.uid }
|
19
|
-
it { expect(message.content).to eq 'How can i solve this?' }
|
20
|
-
it { expect(message.read).to be true }
|
21
|
-
it { expect(message.assignment).to eq assignment }
|
22
|
-
it { expect(message.submission_id).to eq assignment.submission_id }
|
23
|
-
it { expect(message.date).to_not be nil }
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '.receive_answer!' do
|
27
|
-
before { problem.submit_question! student, content: 'How can i solve this?' }
|
28
|
-
before { assignment.receive_answer! sender: 'bot@mumuki.org', content: 'Check this link' }
|
29
|
-
|
30
|
-
it { expect(assignment.has_messages?).to be true }
|
31
|
-
it { expect(assignment.messages.count).to eq 2 }
|
32
|
-
it { expect(message.sender).to eq 'bot@mumuki.org' }
|
33
|
-
it { expect(message.content).to eq 'Check this link' }
|
34
|
-
it { expect(message.read).to be false }
|
35
|
-
it { expect(message.assignment).to eq assignment }
|
36
|
-
it { expect(message.submission_id).to eq assignment.submission_id }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe 'manual evaluation' do
|
41
|
-
let(:user) { create(:user) }
|
42
|
-
let(:exercise) { create(:exercise, manual_evaluation: true, test: nil, expectations: []) }
|
43
|
-
let(:assignment) { exercise.submit_solution!(user, content: '') }
|
44
|
-
|
45
|
-
it { expect(assignment.status).to eq :manual_evaluation_pending }
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '#results_visible?' do
|
49
|
-
let(:gobstones) { create(:language, visible_success_output: true) }
|
50
|
-
let(:gobstones_exercise) { create(:exercise, language: gobstones) }
|
51
|
-
|
52
|
-
let(:failed_submission) { create(:assignment, status: :failed) }
|
53
|
-
let(:passed_submission) { create(:assignment, status: :passed, expectation_results: []) }
|
54
|
-
let(:passed_submission_with_visible_output_language) { create(:assignment, status: :passed, exercise: gobstones_exercise) }
|
55
|
-
let(:manual_evaluation_pending_submission) { create(:assignment, status: :manual_evaluation_pending) }
|
56
|
-
|
57
|
-
it { expect(passed_submission.results_visible?).to be false }
|
58
|
-
it { expect(failed_submission.should_retry?).to be true }
|
59
|
-
it { expect(failed_submission.results_visible?).to be true }
|
60
|
-
it { expect(passed_submission_with_visible_output_language.results_visible?).to be true }
|
61
|
-
it { expect(manual_evaluation_pending_submission.results_visible?).to be false }
|
62
|
-
end
|
63
|
-
describe '#expectation_results_visible?' do
|
64
|
-
let(:haskell) { create(:language, visible_success_output: true) }
|
65
|
-
let(:exercise) { create(:exercise) }
|
66
|
-
context 'should show expectation with failed submissions' do
|
67
|
-
let(:failed_submission) { create(:assignment, status: :failed, expectation_results: [{binding: "foo", inspection: "HasBinding", result: :failed}]) }
|
68
|
-
it { expect(failed_submission.expectation_results_visible?).to be true }
|
69
|
-
it { expect(failed_submission.failed_expectation_results.size).to eq 1 }
|
70
|
-
end
|
71
|
-
context 'should show expectation with errored submissions' do
|
72
|
-
let(:errored_submission) { create(:assignment, status: :errored, expectation_results: [{binding: "foo", inspection: "HasBinding", result: :failed}]) }
|
73
|
-
it { expect(errored_submission.expectation_results_visible?).to be true }
|
74
|
-
end
|
75
|
-
end
|
76
|
-
describe '#showable_results_visible?' do
|
77
|
-
let(:failed_submission) { create(:assignment, exercise: problem, status: :failed, expectation_results: [{binding: "foo", inspection: "HasBinding", result: :failed},
|
78
|
-
{binding: "bar", inspection: "HasBinding", result: :failed}]) }
|
79
|
-
|
80
|
-
context 'should show all failed expectation results for regular problems' do
|
81
|
-
let(:problem) { create(:problem) }
|
82
|
-
it { expect(failed_submission.visible_expectation_results.size).to eq 2 }
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'should show only the first failed expectation result for kids problems' do
|
86
|
-
let(:problem) { create(:problem, layout: 'input_kids') }
|
87
|
-
it { expect(failed_submission.visible_expectation_results.size).to eq 1 }
|
88
|
-
end
|
89
|
-
end
|
90
|
-
describe '#run_update!' do
|
91
|
-
let(:assignment) { create(:assignment) }
|
92
|
-
context 'when run passes unstructured' do
|
93
|
-
before { assignment.run_update! { {result: 'ok', status: :passed} } }
|
94
|
-
it { expect(assignment.status).to eq(:passed) }
|
95
|
-
it { expect(assignment.result).to eq('ok') }
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'when run fails unstructured' do
|
99
|
-
before { assignment.run_update! { {result: 'ups', status: :failed} } }
|
100
|
-
it { expect(assignment.status).to eq(:failed) }
|
101
|
-
it { expect(assignment.result).to eq('ups') }
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'when run aborts unstructured' do
|
105
|
-
before { assignment.run_update! { {result: 'took more thn 4 seconds', status: :aborted} } }
|
106
|
-
it { expect(assignment.status).to eq(:aborted) }
|
107
|
-
it { expect(assignment.result).to eq('took more thn 4 seconds') }
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'when run passes with warnings unstructured' do
|
111
|
-
let(:runner_response) do
|
112
|
-
{status: :passed_with_warnings,
|
113
|
-
test_results: [{title: 'true is true', status: :passed, result: ''},
|
114
|
-
{title: 'false is false', status: :passed, result: ''}],
|
115
|
-
expectation_results: [{binding: 'bar', inspection: 'HasBinding', result: :passed},
|
116
|
-
{binding: 'foo', inspection: 'HasBinding', result: :failed}],
|
117
|
-
feedback: 'foo'}
|
118
|
-
end
|
119
|
-
before { assignment.run_update! { runner_response } }
|
120
|
-
|
121
|
-
it { expect(assignment.status).to eq(:passed_with_warnings) }
|
122
|
-
it { expect(assignment.result).to be_blank }
|
123
|
-
it { expect(assignment.test_results).to eq(runner_response[:test_results]) }
|
124
|
-
it { expect(assignment.expectation_results).to eq(runner_response[:expectation_results]) }
|
125
|
-
it { expect(assignment.feedback).to eq('foo') }
|
126
|
-
end
|
127
|
-
context 'when run raises exception' do
|
128
|
-
before do
|
129
|
-
begin
|
130
|
-
assignment.run_update! { raise 'ouch' }
|
131
|
-
rescue
|
132
|
-
end
|
133
|
-
end
|
134
|
-
it { expect(assignment.status).to eq(:errored) }
|
135
|
-
it { expect(assignment.result).to eq('ouch') }
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe '#update_submissions_count!' do
|
140
|
-
let(:exercise) { create(:exercise) }
|
141
|
-
let(:user) { create(:user) }
|
142
|
-
|
143
|
-
before do
|
144
|
-
exercise.submit_solution!(user)
|
145
|
-
exercise.submit_solution!(user)
|
146
|
-
exercise.submit_solution!(user)
|
147
|
-
end
|
148
|
-
|
149
|
-
it { expect(exercise.reload.submissions_count).to eq(3) }
|
150
|
-
end
|
151
|
-
|
152
|
-
describe '#submission_id' do
|
153
|
-
let(:exercise) { create(:exercise) }
|
154
|
-
let(:user) { create(:user) }
|
155
|
-
|
156
|
-
before { exercise.submit_solution!(user, content: 'foo') }
|
157
|
-
|
158
|
-
it do
|
159
|
-
submission_id = exercise.assignment_for(user).submission_id
|
160
|
-
expect(submission_id).to be_present
|
161
|
-
|
162
|
-
exercise.submit_solution!(user, content: 'bar')
|
163
|
-
|
164
|
-
new_submission_id = exercise.assignment_for(user).submission_id
|
165
|
-
expect(new_submission_id).to be_present
|
166
|
-
expect(new_submission_id).to_not eq submission_id
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
describe '#evaluate_manually!' do
|
171
|
-
|
172
|
-
let(:user) { create(:user) }
|
173
|
-
let(:exercise) { create(:exercise, manual_evaluation: true, test: nil, expectations: []) }
|
174
|
-
let(:assignment) { exercise.submit_solution!(user, content: '') }
|
175
|
-
let(:evaluated_assignment) { Assignment.find assignment.id }
|
176
|
-
|
177
|
-
before { Assignment.evaluate_manually! submission_id: assignment.submission_id, manual_evaluation: '**Good**', status: 'passed_with_warnings' }
|
178
|
-
|
179
|
-
it { expect(evaluated_assignment.status).to eq :passed_with_warnings }
|
180
|
-
it { expect(evaluated_assignment.manual_evaluation_comment).to eq '**Good**' }
|
181
|
-
end
|
182
|
-
|
183
|
-
describe '#extra' do
|
184
|
-
let(:user) { create(:user, email: 'some_email', first_name: 'some_first_name', last_name: 'some_last_name') }
|
185
|
-
let(:exercise) { create(:exercise, extra: "/*...user_email...*/\n/*...user_first_name...*/\n/*...user_last_name...*/") }
|
186
|
-
let(:assignment) { exercise.submit_solution!(user, content: '') }
|
187
|
-
|
188
|
-
it { expect(assignment.extra).to eq "some_email\nsome_first_name\nsome_last_name\n" }
|
189
|
-
end
|
190
|
-
|
191
|
-
end
|