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.
Files changed (98) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/javascripts/application.js +1 -0
  3. data/app/assets/javascripts/application/codemirror-builder.js +11 -1
  4. data/app/assets/javascripts/application/codemirror.js +0 -1
  5. data/app/assets/javascripts/application/discussions.js +15 -2
  6. data/app/assets/javascripts/application/free-form.js +1 -1
  7. data/app/assets/javascripts/application/kids.js +3 -3
  8. data/app/assets/javascripts/application/load-error-svg.js +1 -1
  9. data/app/controllers/invitations_controller.rb +1 -1
  10. data/app/helpers/application_helper.rb +0 -22
  11. data/app/helpers/assets_helper.rb +12 -0
  12. data/app/helpers/assignment_result_helper.rb +1 -1
  13. data/app/helpers/assistance_box_helper.rb +9 -0
  14. data/app/helpers/editor_helper.rb +13 -0
  15. data/app/helpers/locale_helper.rb +11 -0
  16. data/app/helpers/menu_bar_helper.rb +13 -0
  17. data/app/helpers/multiple_file_editor_helper.rb +5 -0
  18. data/app/helpers/open_graph_helper.rb +12 -0
  19. data/app/helpers/page_title_helper.rb +11 -0
  20. data/app/views/exercise_solutions/_kids_results.html.erb +1 -1
  21. data/app/views/exercises/_read_only.html.erb +3 -1
  22. data/app/views/invitations/show.html.erb +1 -1
  23. data/app/views/layouts/_kids.html.erb +1 -1
  24. data/app/views/layouts/_main.html.erb +5 -20
  25. data/app/views/layouts/application.html.erb +2 -7
  26. data/app/views/layouts/exercise_inputs/editors/_multiple_files.html.erb +11 -12
  27. data/app/views/layouts/exercise_inputs/layouts/_input_kids.html.erb +1 -1
  28. data/app/views/layouts/exercise_inputs/read_only_editors/_code.html.erb +1 -1
  29. data/app/views/layouts/exercise_inputs/read_only_editors/_free_form.html.erb +1 -1
  30. data/app/views/layouts/exercise_inputs/read_only_editors/_multiple_files.html.erb +29 -0
  31. data/app/views/layouts/mailer.html.erb +1 -1
  32. data/app/views/layouts/modals/_kids_context.html.erb +1 -1
  33. data/config/initializers/form_builder.rb +4 -5
  34. data/lib/events.rb +1 -4
  35. data/lib/mumuki/laboratory/locales/en.yml +0 -1
  36. data/lib/mumuki/laboratory/locales/es.yml +0 -1
  37. data/lib/mumuki/laboratory/locales/pt.yml +0 -1
  38. data/lib/mumuki/laboratory/version.rb +1 -1
  39. data/public/character/kids/{yellow_context.svg → kibi_context.svg} +2 -2
  40. data/public/{amarillo.svg → kibi.svg} +2 -2
  41. data/public/{anim_amarillo.svg → kibi_animated.svg} +2 -2
  42. data/public/{amarillo_fracaso.svg → kibi_failure.svg} +2 -2
  43. data/public/{amarillo_exito.svg → kibi_success.svg} +2 -2
  44. data/public/{amarillo_exito_bailarin.svg → kibi_success_dancing.svg} +2 -2
  45. data/spec/capybara_helper.rb +4 -4
  46. data/spec/helpers/application_helper_spec.rb +0 -16
  47. data/spec/helpers/page_title_helper_spec.rb +19 -0
  48. data/spec/spec_helper.rb +2 -1
  49. data/vendor/assets/javascripts/codemirror-autorefresh.js +46 -0
  50. metadata +76 -163
  51. data/spec/factories/api_client_factory.rb +0 -18
  52. data/spec/factories/assignments_factory.rb +0 -7
  53. data/spec/factories/book_factory.rb +0 -7
  54. data/spec/factories/chapter_factory.rb +0 -16
  55. data/spec/factories/complement_factory.rb +0 -6
  56. data/spec/factories/course_factory.rb +0 -9
  57. data/spec/factories/discussion_factory.rb +0 -8
  58. data/spec/factories/exam_factory.rb +0 -9
  59. data/spec/factories/exercise_factory.rb +0 -73
  60. data/spec/factories/guide_factory.rb +0 -30
  61. data/spec/factories/invitation_factory.rb +0 -7
  62. data/spec/factories/lesson_factory.rb +0 -7
  63. data/spec/factories/login_settings_factory.rb +0 -5
  64. data/spec/factories/message_factory.rb +0 -11
  65. data/spec/factories/organization_factory.rb +0 -26
  66. data/spec/factories/topic_factory.rb +0 -9
  67. data/spec/factories/user_factory.rb +0 -8
  68. data/spec/models/api_client_spec.rb +0 -6
  69. data/spec/models/assignment_spec.rb +0 -191
  70. data/spec/models/book_import_spec.rb +0 -49
  71. data/spec/models/book_spec.rb +0 -114
  72. data/spec/models/course_spec.rb +0 -22
  73. data/spec/models/discussion_spec.rb +0 -174
  74. data/spec/models/event_generation_spec.rb +0 -189
  75. data/spec/models/event_publishing_spec.rb +0 -36
  76. data/spec/models/exam_spec.rb +0 -151
  77. data/spec/models/exercise_spec.rb +0 -494
  78. data/spec/models/guide_import_spec.rb +0 -300
  79. data/spec/models/guide_spec.rb +0 -83
  80. data/spec/models/interactive_spec.rb +0 -143
  81. data/spec/models/language_spec.rb +0 -56
  82. data/spec/models/lesson_spec.rb +0 -90
  83. data/spec/models/message_spec.rb +0 -87
  84. data/spec/models/navigation_spec.rb +0 -70
  85. data/spec/models/organization_spec.rb +0 -124
  86. data/spec/models/playground_spec.rb +0 -23
  87. data/spec/models/problem_spec.rb +0 -80
  88. data/spec/models/query_spec.rb +0 -21
  89. data/spec/models/question_spec.rb +0 -37
  90. data/spec/models/reading_spec.rb +0 -10
  91. data/spec/models/solution_spec.rb +0 -66
  92. data/spec/models/stats_spec.rb +0 -15
  93. data/spec/models/string_spec.rb +0 -9
  94. data/spec/models/topic_import_spec.rb +0 -42
  95. data/spec/models/usage_spec.rb +0 -77
  96. data/spec/models/user_changed_spec.rb +0 -35
  97. data/spec/models/user_spec.rb +0 -276
  98. data/spec/models/with_expectations_spec.rb +0 -56
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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