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
data/spec/models/problem_spec.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Problem, organization_workspace: :test do
|
4
|
-
|
5
|
-
context 'when no manual evaluation and' do
|
6
|
-
before { problem.manual_evaluation = false }
|
7
|
-
|
8
|
-
context 'when no test nor expectations' do
|
9
|
-
let(:problem) { build(:problem, test: nil, expectations: []) }
|
10
|
-
it { expect(problem.evaluation_criteria?).to be false }
|
11
|
-
end
|
12
|
-
|
13
|
-
context 'when no test but expectations' do
|
14
|
-
let(:problem) { build(:problem, test: nil, expectations: [{inspection: 'HasBinding', binding: 'foo'}]) }
|
15
|
-
it { expect(problem.evaluation_criteria?).to be true }
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'when no expectations but test' do
|
19
|
-
let(:problem) { build(:problem, test: 'describe ...', expectations: []) }
|
20
|
-
it { expect(problem.evaluation_criteria?).to be true }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when is manual evaluation and' do
|
25
|
-
before { problem.manual_evaluation = true }
|
26
|
-
|
27
|
-
context 'when no test nor expectations' do
|
28
|
-
let(:problem) { build(:problem, test: nil, expectations: []) }
|
29
|
-
it { expect(problem.evaluation_criteria?).to be true }
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when solving then failing' do
|
35
|
-
let!(:problem) { create(:problem) }
|
36
|
-
let!(:user) { create(:user) }
|
37
|
-
|
38
|
-
before do
|
39
|
-
assignment = problem.submit_solution!(user, content: 'foo')
|
40
|
-
|
41
|
-
assignment.test_results = [{title: 'foo', result: '', status: :passed}]
|
42
|
-
assignment.expectation_results = [{result: :passed, binding: 'foo', inspection: 'HasBinding'}]
|
43
|
-
assignment.status = :passed
|
44
|
-
assignment.save!
|
45
|
-
|
46
|
-
@assignment = problem.submit_solution!(user, content: 'bar')
|
47
|
-
end
|
48
|
-
|
49
|
-
it { expect(@assignment.expectation_results).to eq [] }
|
50
|
-
it { expect(@assignment.test_results).to eq nil }
|
51
|
-
it { expect(@assignment.result).to eq 'noop result' }
|
52
|
-
it { expect(@assignment.status).to eq :failed }
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'when submit exercise with blank utf8 chars' do
|
56
|
-
let!(:problem) { create(:problem) }
|
57
|
-
let!(:user) { create(:user) }
|
58
|
-
|
59
|
-
before do
|
60
|
-
@assignment = problem.submit_solution!(user, content: "program {\n Poner(Norte)\n}")
|
61
|
-
end # ▲
|
62
|
-
# ╰ Blank unsupported UTF-8 char
|
63
|
-
it { expect(@assignment.solution).to eq "program {\n Poner(Norte)\n}" }
|
64
|
-
# ▲
|
65
|
-
# ╰ Normalized text / No blank UTF-8 char
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'when submit exercise with non blank utf8 chars' do
|
69
|
-
let!(:problem) { create(:problem) }
|
70
|
-
let!(:user) { create(:user) }
|
71
|
-
|
72
|
-
before do
|
73
|
-
@assignment = problem.submit_solution!(user, content: "semáforo")
|
74
|
-
end
|
75
|
-
|
76
|
-
it { expect(@assignment.solution).to eq "semáforo" }
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
data/spec/models/query_spec.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mumuki::Domain::Submission::Query do
|
4
|
-
let!(:exercise) { create(:exercise) }
|
5
|
-
let(:user) { create(:user) }
|
6
|
-
|
7
|
-
before do
|
8
|
-
expect_any_instance_of(Challenge).to receive(:automated_evaluation_class).and_return(Mumuki::Domain::Evaluation::Automated)
|
9
|
-
allow_any_instance_of(Language).to receive(:run_query!).and_return(status: :passed, result: '5')
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#submit_query!' do
|
13
|
-
let!(:results) { exercise.submit_query!(user, query: 'foo', content: 'bar', cookie: ['foo', 'bar']) }
|
14
|
-
let(:assignment) { exercise.find_assignment_for user }
|
15
|
-
|
16
|
-
it { expect(results[:status]).to eq :passed }
|
17
|
-
it { expect(results[:result]).to eq '5' }
|
18
|
-
it { expect(assignment.solution).to eq 'bar' }
|
19
|
-
it { expect(assignment.status).to eq :pending }
|
20
|
-
end
|
21
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mumuki::Domain::Submission::Query, organization_workspace: :test do
|
4
|
-
let!(:exercise) { create(:problem) }
|
5
|
-
let(:student) { create(:user) }
|
6
|
-
|
7
|
-
describe '#submit_question!' do
|
8
|
-
let(:assignment) { exercise.find_assignment_for student }
|
9
|
-
|
10
|
-
context 'when just a question on an empty assignment is sent' do
|
11
|
-
before { exercise.submit_question!(student, content: 'Please help!') }
|
12
|
-
|
13
|
-
it { expect(assignment.status).to eq :pending }
|
14
|
-
it { expect(assignment.result).to be nil }
|
15
|
-
|
16
|
-
it { expect(assignment.solution).to be nil }
|
17
|
-
it { expect(assignment.messages.count).to eq 1 }
|
18
|
-
it { expect(assignment.submission_id).to_not be nil }
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'when a question on a previous submission is sent' do
|
22
|
-
before do
|
23
|
-
assignment = exercise.submit_solution!(student, content: 'x = 1')
|
24
|
-
assignment.failed!
|
25
|
-
@original_submission_id = assignment.submission_id
|
26
|
-
end
|
27
|
-
|
28
|
-
before { exercise.submit_question!(student, content: 'Please help!') }
|
29
|
-
|
30
|
-
it { expect(assignment.status).to eq :failed }
|
31
|
-
it { expect(assignment.result).to eq 'noop result' }
|
32
|
-
it { expect(assignment.solution).to eq 'x = 1' }
|
33
|
-
it { expect(assignment.messages.count).to eq 1 }
|
34
|
-
it { expect(assignment.submission_id).to eq @original_submission_id }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/spec/models/reading_spec.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Reading, organization_workspace: :test do
|
4
|
-
let!(:reading) { create(:reading) }
|
5
|
-
let!(:user) { create(:user) }
|
6
|
-
|
7
|
-
let!(:result) { reading.submit_confirmation!(user) }
|
8
|
-
|
9
|
-
it { expect(result).to eq status: :passed, result: '' }
|
10
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mumuki::Domain::Submission::Solution, organization_workspace: :test do
|
4
|
-
|
5
|
-
let(:user) { create(:user) }
|
6
|
-
|
7
|
-
describe '#try_submit_solution!' do
|
8
|
-
|
9
|
-
context 'when on chapter' do
|
10
|
-
let(:problem) { create(:problem) }
|
11
|
-
let!(:chapter) {
|
12
|
-
create(:chapter, name: 'Functional Programming', lessons: [
|
13
|
-
create(:lesson, exercises: [problem])
|
14
|
-
]) }
|
15
|
-
|
16
|
-
before { reindex_current_organization! }
|
17
|
-
let!(:result) { problem.try_submit_solution! user }
|
18
|
-
|
19
|
-
it { expect(result).to eq problem.find_assignment_for(user) }
|
20
|
-
it { expect(result.attempts_left).to eq nil }
|
21
|
-
it { expect(result.attempts_left?).to be true }
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when on exam' do
|
25
|
-
let(:problem) { create(:problem) }
|
26
|
-
let!(:exam) { create(:exam, max_problem_submissions: 10, exercises: [problem]) }
|
27
|
-
|
28
|
-
before { reindex_current_organization! }
|
29
|
-
let(:result) { problem.try_submit_solution! user }
|
30
|
-
|
31
|
-
it { expect(result).to eq problem.find_assignment_for(user) }
|
32
|
-
it { expect(result.attempts_left).to eq 9 }
|
33
|
-
it { expect(result.attempts_left?).to be true }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '#submit_solution!' do
|
38
|
-
|
39
|
-
before { expect_any_instance_of(Challenge).to receive(:automated_evaluation_class).and_return(Mumuki::Domain::Evaluation::Automated) }
|
40
|
-
before { expect_any_instance_of(Language).to receive(:run_tests!).and_return(bridge_response) }
|
41
|
-
|
42
|
-
context 'when results have no expectation' do
|
43
|
-
let(:exercise) { create(:x_equal_5_exercise) }
|
44
|
-
let(:assignment) { exercise.submit_solution! user }
|
45
|
-
let(:bridge_response) { {result: '0 failures', status: :passed} }
|
46
|
-
|
47
|
-
it { expect(assignment.status).to eq(:passed) }
|
48
|
-
it { expect(assignment.result).to include('0 failures') }
|
49
|
-
end
|
50
|
-
|
51
|
-
context 'when results have expectations' do
|
52
|
-
let(:exercise_with_expectations) {
|
53
|
-
create(:x_equal_5_exercise, expectations: [{binding: :foo, inspection: :HasComposition}]) }
|
54
|
-
let(:assignment) { exercise_with_expectations.submit_solution! user }
|
55
|
-
let(:bridge_response) { {
|
56
|
-
result: '0 failures',
|
57
|
-
status: :passed,
|
58
|
-
expectation_results: [binding: 'foo', inspection: 'HasBinding', result: :passed]} }
|
59
|
-
|
60
|
-
it { expect(assignment.status).to eq(:passed) }
|
61
|
-
it { expect(assignment.result).to include('0 failures') }
|
62
|
-
it { expect(assignment.expectation_results).to eq([{binding: 'foo', inspection: 'HasBinding', result: :passed}]) }
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
data/spec/models/stats_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Stats do
|
4
|
-
|
5
|
-
context 'with good stats' do
|
6
|
-
let(:stats) { Stats.new(passed: 6, passed_with_warnings: 3, failed: 1, pending: 0) }
|
7
|
-
it { expect(stats.done?).to be false }
|
8
|
-
end
|
9
|
-
|
10
|
-
|
11
|
-
context 'with bad stats' do
|
12
|
-
let(:stats) { Stats.new(passed: 1, passed_with_warnings: 0, failed: 4, pending: 5) }
|
13
|
-
it { expect(stats.done?).to be false }
|
14
|
-
end
|
15
|
-
end
|
data/spec/models/string_spec.rb
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe String do
|
4
|
-
describe 'markdown_paragraphs' do
|
5
|
-
it { expect("hello\nworld !\n\nbye bye".markdown_paragraphs).to eq ["hello\nworld !", 'bye bye'] }
|
6
|
-
it { expect("hello\nworld !\n \nbye bye".markdown_paragraphs).to eq ["hello\nworld !", 'bye bye'] }
|
7
|
-
it { expect("hello\nworld !\n \n\nbye bye".markdown_paragraphs).to eq ["hello\nworld !", 'bye bye'] }
|
8
|
-
end
|
9
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Guide do
|
4
|
-
let!(:haskell) { create(:haskell) }
|
5
|
-
let!(:gobstones) { create(:gobstones) }
|
6
|
-
|
7
|
-
let!(:lesson_1) { create(:lesson, name: 'l1') }
|
8
|
-
let(:guide_1) { lesson_1.guide }
|
9
|
-
|
10
|
-
let!(:lesson_2) { create(:lesson, name: 'l2') }
|
11
|
-
|
12
|
-
let!(:guide_2) { create(:guide, name: 'g2') }
|
13
|
-
let!(:guide_3) { create(:guide, name: 'g3') }
|
14
|
-
|
15
|
-
let(:topic_json) do
|
16
|
-
{name: 'sample topic',
|
17
|
-
description: 'topic description',
|
18
|
-
slug: 'mumuki/mumuki-sample-topic',
|
19
|
-
locale: 'en',
|
20
|
-
lessons: [guide_2, guide_1, guide_3].map(&:slug)}
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#import_from_resource_h!' do
|
24
|
-
context 'when guide is empty' do
|
25
|
-
let(:topic) { create(:topic, lessons: [lesson_1, lesson_2]) }
|
26
|
-
|
27
|
-
before do
|
28
|
-
topic.import_from_resource_h!(topic_json)
|
29
|
-
end
|
30
|
-
|
31
|
-
it { expect(topic.name).to eq 'sample topic' }
|
32
|
-
it { expect(topic.description).to eq 'topic description' }
|
33
|
-
it { expect(topic.locale).to eq 'en' }
|
34
|
-
it { expect(topic.lessons.count).to eq 3 }
|
35
|
-
it { expect(topic.lessons.first.guide).to eq guide_2 }
|
36
|
-
it { expect(topic.lessons.second).to eq lesson_1 }
|
37
|
-
it { expect(topic.lessons.third.guide).to eq guide_3 }
|
38
|
-
it { expect(Guide.count).to eq 4 }
|
39
|
-
it { expect(Lesson.count).to eq 3 }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/spec/models/usage_spec.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Usage do
|
4
|
-
|
5
|
-
let!(:fundamentals) { create(:topic) }
|
6
|
-
let!(:functional_programming) { create(:topic) }
|
7
|
-
let!(:oop) { create(:topic) }
|
8
|
-
let!(:logic_programming) { create(:topic) }
|
9
|
-
|
10
|
-
let!(:programming) { create(:book, chapters: [
|
11
|
-
build(:chapter, topic: fundamentals),
|
12
|
-
build(:chapter, topic: functional_programming),
|
13
|
-
build(:chapter, topic: oop),
|
14
|
-
build(:chapter, topic: logic_programming),
|
15
|
-
]) }
|
16
|
-
|
17
|
-
let!(:paradigms) { create(:book, chapters: [
|
18
|
-
build(:chapter, topic: functional_programming),
|
19
|
-
build(:chapter, topic: logic_programming),
|
20
|
-
build(:chapter, topic: oop),
|
21
|
-
]) }
|
22
|
-
|
23
|
-
let!(:central) { create(:organization, name: 'central', book: programming) }
|
24
|
-
let!(:pdep) { create(:organization, name: 'pdep', book: paradigms) }
|
25
|
-
|
26
|
-
context 'on central' do
|
27
|
-
before { central.switch! }
|
28
|
-
|
29
|
-
it { expect(Topic.all.count).to eq 4 }
|
30
|
-
it { expect(Chapter.all.count).to eq 7 }
|
31
|
-
it { expect(Book.all.count).to eq 2 }
|
32
|
-
it { expect(Organization.all.count).to eq 2 }
|
33
|
-
|
34
|
-
it { expect(Organization.current).to eq central }
|
35
|
-
it { expect(central.book).to eq programming }
|
36
|
-
|
37
|
-
it { expect(programming.chapters.count).to eq 4 }
|
38
|
-
it { expect(programming.chapters.map(&:topic)).to eq [fundamentals, functional_programming, oop, logic_programming] }
|
39
|
-
|
40
|
-
it { expect(fundamentals.usage_in_organization).to_not be_nil }
|
41
|
-
it { expect(fundamentals.usage_in_organization.number).to eq 1 }
|
42
|
-
|
43
|
-
it { expect(functional_programming.usage_in_organization).to_not be_nil }
|
44
|
-
it { expect(functional_programming.usage_in_organization).to be_a(Chapter) }
|
45
|
-
it { expect(functional_programming.usage_in_organization.number).to eq 2 }
|
46
|
-
it { expect(oop.usage_in_organization.number).to eq 3 }
|
47
|
-
it { expect(logic_programming.usage_in_organization.number).to eq 4 }
|
48
|
-
|
49
|
-
it { expect(Usage.in_organization.count).to eq 4 }
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'on pdep' do
|
54
|
-
before { pdep.switch! }
|
55
|
-
|
56
|
-
it { expect(Topic.all.count).to eq 4 }
|
57
|
-
it { expect(Chapter.all.count).to eq 7 }
|
58
|
-
it { expect(Book.all.count).to eq 2 }
|
59
|
-
it { expect(Organization.all.count).to eq 2 }
|
60
|
-
|
61
|
-
it { expect(Organization.current).to eq pdep }
|
62
|
-
it { expect(pdep.book).to eq paradigms }
|
63
|
-
|
64
|
-
it { expect(paradigms.chapters.count).to eq 3 }
|
65
|
-
it { expect(paradigms.chapters.map(&:topic)).to eq [functional_programming, logic_programming, oop] }
|
66
|
-
|
67
|
-
it { expect(fundamentals.usage_in_organization).to be_nil }
|
68
|
-
|
69
|
-
it { expect(functional_programming.usage_in_organization).to_not be_nil }
|
70
|
-
it { expect(functional_programming.usage_in_organization).to be_a(Chapter) }
|
71
|
-
it { expect(functional_programming.usage_in_organization.number).to eq 1 }
|
72
|
-
it { expect(logic_programming.usage_in_organization.number).to eq 2 }
|
73
|
-
it { expect(oop.usage_in_organization.number).to eq 3 }
|
74
|
-
|
75
|
-
it { expect(Usage.in_organization.count).to eq 3 }
|
76
|
-
end
|
77
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe User, organization_workspace: :test do
|
4
|
-
let(:user) { User.find_by(uid: 'foo@bar.com') }
|
5
|
-
let(:user_json) { {
|
6
|
-
uid: 'foo@bar.com',
|
7
|
-
first_name: 'Foo',
|
8
|
-
last_name: 'Bar',
|
9
|
-
permissions: {student: 'test/example'},
|
10
|
-
id: 1
|
11
|
-
} }
|
12
|
-
|
13
|
-
context 'when new user' do
|
14
|
-
before { User.import_from_resource_h! user_json }
|
15
|
-
it { expect(user.uid).to eq 'foo@bar.com' }
|
16
|
-
it { expect(user.name).to eq 'Foo Bar' }
|
17
|
-
it { expect(user.student_here?).to be true }
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'when user exists' do
|
21
|
-
let(:new_json) { {
|
22
|
-
uid: 'foo@bar.com',
|
23
|
-
first_name: 'Foo',
|
24
|
-
last_name: 'Baz',
|
25
|
-
permissions: {student: 'test/example2'},
|
26
|
-
id: 1
|
27
|
-
} }
|
28
|
-
before { User.import_from_resource_h! user_json }
|
29
|
-
before { User.import_from_resource_h! new_json }
|
30
|
-
it { expect(user.name).to eq 'Foo Baz' }
|
31
|
-
it { expect(user.student_here?).to be true }
|
32
|
-
it { expect(user.student? 'test/example2').to be true }
|
33
|
-
it { expect(user.student? 'test/example').to be false }
|
34
|
-
end
|
35
|
-
end
|
data/spec/models/user_spec.rb
DELETED
@@ -1,276 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe User, organization_workspace: :test do
|
4
|
-
describe '#clear_progress!' do
|
5
|
-
let(:student) { create :user }
|
6
|
-
let(:more_clauses) { create(:exercise, name: 'More Clauses') }
|
7
|
-
|
8
|
-
before { more_clauses.submit_solution! student, content: 'foo(X) :- not(bar(X))' }
|
9
|
-
|
10
|
-
before { student.reload.clear_progress! }
|
11
|
-
|
12
|
-
it { expect(student.reload.assignments).to be_empty }
|
13
|
-
it { expect(student.never_submitted?).to be true }
|
14
|
-
end
|
15
|
-
describe '#transfer_progress_to!' do
|
16
|
-
|
17
|
-
let(:codeorga) { create :organization, name: 'code.orga' }
|
18
|
-
let(:prologschool) { create :organization, name: 'prologschool' }
|
19
|
-
|
20
|
-
let(:your_first_program) { create(:exercise, name: 'Your First Program') }
|
21
|
-
let(:more_clauses) { create(:exercise, name: 'More Clauses') }
|
22
|
-
|
23
|
-
let(:two_hours_ago) { 2.hours.ago }
|
24
|
-
|
25
|
-
context 'when final user has less information than original' do
|
26
|
-
let!(:submission) { your_first_program.submit_solution! original, content: 'adasdsadas' }
|
27
|
-
|
28
|
-
before { original.reload.copy_progress_to! final }
|
29
|
-
|
30
|
-
let(:original) { create :user,
|
31
|
-
permissions: {student: 'codeorga/*'},
|
32
|
-
first_name: 'johnny',
|
33
|
-
last_name: 'doe',
|
34
|
-
social_id: 'auth0|123456',
|
35
|
-
last_organization: codeorga }
|
36
|
-
|
37
|
-
let(:final) { create :user,
|
38
|
-
permissions: Mumukit::Auth::Permissions.new,
|
39
|
-
first_name: 'John',
|
40
|
-
last_name: 'Doe',
|
41
|
-
social_id: 'auth0|345678' }
|
42
|
-
|
43
|
-
it { expect(final.name).to eq 'John Doe' }
|
44
|
-
it { expect(final.social_id).to eq 'auth0|345678' }
|
45
|
-
|
46
|
-
it { expect(final.last_submission_date).to eq original.last_submission_date }
|
47
|
-
it { expect(final.last_organization).to eq codeorga }
|
48
|
-
it { expect(final.last_exercise).to eq your_first_program }
|
49
|
-
|
50
|
-
it { expect(final.permissions.as_json).to json_like({}) }
|
51
|
-
|
52
|
-
it { expect(submission.reload.submitter).to eq final }
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'when final user has more information than original' do
|
56
|
-
before { more_clauses.submit_solution! final, content: 'adasdsadas' }
|
57
|
-
before { original.copy_progress_to! final.reload }
|
58
|
-
|
59
|
-
let(:original) { create :user,
|
60
|
-
permissions: Mumukit::Auth::Permissions.new,
|
61
|
-
first_name: 'johnny',
|
62
|
-
last_name: 'doe',
|
63
|
-
social_id: 'auth0|123456' }
|
64
|
-
let(:final) { create :user,
|
65
|
-
permissions: {student: 'prologschool/*'},
|
66
|
-
first_name: 'John',
|
67
|
-
last_name: 'Doe',
|
68
|
-
social_id: 'auth0|345678',
|
69
|
-
last_organization: prologschool }
|
70
|
-
|
71
|
-
it { expect(final.name).to eq 'John Doe' }
|
72
|
-
it { expect(final.social_id).to eq 'auth0|345678' }
|
73
|
-
|
74
|
-
it { expect(final.last_submission_date).to_not be nil }
|
75
|
-
it { expect(final.last_organization).to eq prologschool }
|
76
|
-
it { expect(final.last_exercise).to eq more_clauses }
|
77
|
-
|
78
|
-
it { expect(final.permissions.as_json).to json_like student: 'prologschool/*' }
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when both have information, but final is newer' do
|
82
|
-
before { original.copy_progress_to! final }
|
83
|
-
|
84
|
-
let(:original) { create :user,
|
85
|
-
permissions: {student: 'codeorga/*'},
|
86
|
-
first_name: 'johnny',
|
87
|
-
last_name: 'doe',
|
88
|
-
social_id: 'auth0|123456',
|
89
|
-
last_submission_date: 6.hours.ago,
|
90
|
-
last_organization: codeorga,
|
91
|
-
last_exercise: your_first_program }
|
92
|
-
let(:final) { create :user,
|
93
|
-
permissions: {student: 'prologschool/*'},
|
94
|
-
first_name: 'John',
|
95
|
-
last_name: 'Doe',
|
96
|
-
social_id: 'auth0|345678',
|
97
|
-
last_submission_date: two_hours_ago,
|
98
|
-
last_organization: prologschool,
|
99
|
-
last_exercise: more_clauses }
|
100
|
-
|
101
|
-
it { expect(final.name).to eq 'John Doe' }
|
102
|
-
it { expect(final.social_id).to eq 'auth0|345678' }
|
103
|
-
|
104
|
-
it { expect(final.last_submission_date).to eq two_hours_ago }
|
105
|
-
it { expect(final.last_organization).to eq prologschool }
|
106
|
-
it { expect(final.last_exercise).to eq more_clauses }
|
107
|
-
|
108
|
-
it { expect(final.permissions.as_json).to json_like student: 'prologschool/*' }
|
109
|
-
end
|
110
|
-
|
111
|
-
context 'when both have information, but original is newer' do
|
112
|
-
before { original.copy_progress_to! final }
|
113
|
-
|
114
|
-
let(:original) { create :user,
|
115
|
-
permissions: {student: 'codeorga/*'},
|
116
|
-
first_name: 'johnny',
|
117
|
-
last_name: 'doe',
|
118
|
-
social_id: 'auth0|123456',
|
119
|
-
last_submission_date: two_hours_ago,
|
120
|
-
last_organization: codeorga,
|
121
|
-
last_exercise: your_first_program }
|
122
|
-
let(:final) { create :user,
|
123
|
-
permissions: {student: 'prologschool/*'},
|
124
|
-
first_name: 'John',
|
125
|
-
last_name: 'Doe',
|
126
|
-
social_id: 'auth0|345678',
|
127
|
-
last_submission_date: 5.hours.ago,
|
128
|
-
last_organization: prologschool,
|
129
|
-
last_exercise: more_clauses }
|
130
|
-
|
131
|
-
it { expect(final.name).to eq 'John Doe' }
|
132
|
-
it { expect(final.social_id).to eq 'auth0|345678' }
|
133
|
-
|
134
|
-
it { expect(final.last_submission_date).to eq two_hours_ago }
|
135
|
-
it { expect(final.last_organization).to eq codeorga }
|
136
|
-
it { expect(final.last_exercise).to eq your_first_program }
|
137
|
-
|
138
|
-
it { expect(final.permissions.as_json).to json_like student: 'prologschool/*' }
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
describe '#visit!' do
|
143
|
-
let(:user) { create(:user) }
|
144
|
-
|
145
|
-
before { user.visit! Organization.current }
|
146
|
-
|
147
|
-
it { expect(user.last_organization).to eq Organization.current }
|
148
|
-
end
|
149
|
-
|
150
|
-
describe 'roles' do
|
151
|
-
let(:other) { create(:organization, name: 'pdep') }
|
152
|
-
let(:user) { create :user, permissions: {student: 'pdep/k2001', teacher: 'test/all'} }
|
153
|
-
|
154
|
-
it { expect(user.student? 'test/all').to be true }
|
155
|
-
it { expect(user.student? 'pdep/k2001').to be true }
|
156
|
-
|
157
|
-
it { expect(user.teacher? 'test/all').to be true }
|
158
|
-
it { expect(user.teacher? 'pdep/k2001').to be false }
|
159
|
-
end
|
160
|
-
|
161
|
-
describe '#submissions_count' do
|
162
|
-
let!(:exercise_1) { create(:exercise) }
|
163
|
-
let!(:exercise_2) { create(:exercise) }
|
164
|
-
let!(:exercise_3) { create(:exercise) }
|
165
|
-
|
166
|
-
let(:user) { create(:user) }
|
167
|
-
context 'when there are no submissions' do
|
168
|
-
it { expect(user.reload.last_submission_date).to be nil }
|
169
|
-
it { expect(user.submitted_exercises_count).to eq 0 }
|
170
|
-
it { expect(user.solved_exercises_count).to eq 0 }
|
171
|
-
it { expect(user.submissions_count).to eq 0 }
|
172
|
-
it { expect(user.passed_submissions_count).to eq 0 }
|
173
|
-
it { expect(user.reload.last_exercise).to be_nil }
|
174
|
-
it { expect(user.reload.last_guide).to be_nil }
|
175
|
-
end
|
176
|
-
|
177
|
-
context 'when there are passed submissions' do
|
178
|
-
let!(:assignment_for) do
|
179
|
-
exercise_1.submit_solution!(user, content: '')
|
180
|
-
exercise_1.submit_solution!(user, content: '').passed!
|
181
|
-
|
182
|
-
exercise_2.submit_solution!(user, content: '').passed!
|
183
|
-
|
184
|
-
exercise_3.submit_solution!(user, content: '')
|
185
|
-
exercise_3.submit_solution!(user, content: '')
|
186
|
-
end
|
187
|
-
|
188
|
-
it { expect(user.reload.last_submission_date).to be > Assignment.last.created_at }
|
189
|
-
it { expect(user.submitted_exercises_count).to eq 3 }
|
190
|
-
it { expect(user.solved_exercises_count).to eq 2 }
|
191
|
-
it { expect(user.submissions_count).to eq 5 }
|
192
|
-
it { expect(user.passed_submissions_count).to eq 2 }
|
193
|
-
it { expect(user.reload.last_exercise).to eq exercise_3 }
|
194
|
-
it { expect(user.reload.last_guide).to eq exercise_3.guide }
|
195
|
-
|
196
|
-
end
|
197
|
-
|
198
|
-
|
199
|
-
context 'when there are only failed submissions' do
|
200
|
-
let!(:exercise_4) { create(:exercise) }
|
201
|
-
|
202
|
-
let!(:assignment_for) do
|
203
|
-
exercise_4.submit_solution!(user, content: '').failed!
|
204
|
-
end
|
205
|
-
|
206
|
-
it { expect(user.reload.last_exercise).to eq exercise_4 }
|
207
|
-
it { expect(user.reload.last_guide).to eq exercise_4.guide }
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
|
212
|
-
describe '.for_profile' do
|
213
|
-
let(:user) { create(:user, first_name: 'some name', last_name: 'some last name') }
|
214
|
-
let(:profile) { struct(uid: user.uid, first_name: nil, last_name: 'some other last name') }
|
215
|
-
|
216
|
-
before { User.for_profile profile }
|
217
|
-
|
218
|
-
it{ expect(User.find(user.id).first_name).to eq 'some name' }
|
219
|
-
it{ expect(User.find(user.id).last_name).to eq 'some other last name' }
|
220
|
-
|
221
|
-
describe 'notification' do
|
222
|
-
let(:user) { create(:user) }
|
223
|
-
|
224
|
-
context 'no changes' do
|
225
|
-
before { expect_any_instance_of(Mumukit::Nuntius::NotificationMode::Deaf).to_not receive(:notify_event!) }
|
226
|
-
it { User.for_profile profile }
|
227
|
-
end
|
228
|
-
|
229
|
-
context 'with changes' do
|
230
|
-
before { expect_any_instance_of(Mumukit::Nuntius::NotificationMode::Deaf).to receive(:notify_event!).exactly(1).times }
|
231
|
-
it { User.for_profile profile.to_h.merge(first_name: 'Mary').to_struct }
|
232
|
-
it { User.for_profile profile.to_h.merge(last_name: 'Doe').to_struct }
|
233
|
-
end
|
234
|
-
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
describe '#resubmit!' do
|
239
|
-
let(:student) { create :user }
|
240
|
-
let(:exercises) { FactoryBot.create_list(:exercise, 5) }
|
241
|
-
|
242
|
-
let!(:chapter) {
|
243
|
-
create(:chapter, lessons: [
|
244
|
-
create(:lesson, exercises: exercises)]) }
|
245
|
-
|
246
|
-
before { reindex_current_organization! }
|
247
|
-
|
248
|
-
before { exercises.each { |it| it.submit_solution! student, content: '' } }
|
249
|
-
|
250
|
-
it do
|
251
|
-
student.assignments.each { |it| expect(it).to receive(:notify!).once }
|
252
|
-
student.resubmit! Organization.current.name
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
describe '#accept_invitation!' do
|
257
|
-
let(:student) { create :user }
|
258
|
-
let(:invitation) { create :invitation, course: 'some_orga/some_course' }
|
259
|
-
before { student.accept_invitation! invitation }
|
260
|
-
it { expect(student.student? invitation.course).to be true }
|
261
|
-
it { expect(student.student? 'foo/bar').to be false }
|
262
|
-
end
|
263
|
-
|
264
|
-
describe '#currently_in_exam?' do
|
265
|
-
let(:student_not_in_exam) { create :user }
|
266
|
-
let(:student_in_exam) { create :user }
|
267
|
-
let(:exam) { create :exam }
|
268
|
-
|
269
|
-
before { exam.authorize! student_in_exam }
|
270
|
-
before { exam.authorize! student_not_in_exam }
|
271
|
-
before { exam.start! student_in_exam }
|
272
|
-
|
273
|
-
it { expect(student_not_in_exam.currently_in_exam?).to be false }
|
274
|
-
it { expect(student_in_exam.currently_in_exam?).to be true }
|
275
|
-
end
|
276
|
-
end
|