mumuki-laboratory 5.7.0 → 5.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/application/codemirror-builder.js +16 -8
  3. data/app/assets/javascripts/application/codemirror.js +7 -9
  4. data/app/assets/javascripts/application/discussions.js +20 -12
  5. data/app/assets/javascripts/application/multiple-files.js +222 -0
  6. data/app/assets/javascripts/application/submission.js +1 -0
  7. data/app/assets/stylesheets/application/modules/_discussion.scss +12 -0
  8. data/app/assets/stylesheets/application/modules/_editor.scss +13 -0
  9. data/app/controllers/discussions_controller.rb +10 -0
  10. data/app/controllers/discussions_messages_controller.rb +15 -3
  11. data/app/helpers/application_helper.rb +1 -1
  12. data/app/helpers/discussions_helper.rb +13 -5
  13. data/app/helpers/multiple_file_editor_helper.rb +9 -0
  14. data/app/models/application_record.rb +5 -0
  15. data/app/models/concerns/with_assignments.rb +3 -21
  16. data/app/models/discussion.rb +1 -1
  17. data/app/models/exam.rb +12 -11
  18. data/app/models/exercise.rb +1 -1
  19. data/app/models/guide.rb +1 -1
  20. data/app/models/message.rb +5 -1
  21. data/app/models/stats.rb +4 -29
  22. data/app/models/user.rb +6 -0
  23. data/app/views/discussions/_message.html.erb +3 -0
  24. data/app/views/errors/forbidden.html.erb +1 -1
  25. data/app/views/layouts/_authoring.html.erb +5 -0
  26. data/app/views/layouts/_copyright.html.erb +2 -0
  27. data/app/views/layouts/_social_media.html.erb +4 -0
  28. data/app/views/layouts/application.html.erb +4 -6
  29. data/app/views/layouts/embedded.html.erb +27 -0
  30. data/app/views/layouts/exercise_inputs/editors/_multiple_files.html.erb +8 -3
  31. data/config/routes.rb +3 -1
  32. data/db/migrate/20180802190437_add_approved_to_messages.rb +5 -0
  33. data/lib/mumuki/laboratory/controllers/dynamic_errors.rb +6 -1
  34. data/lib/mumuki/laboratory/controllers/notifications.rb +3 -2
  35. data/lib/mumuki/laboratory/exceptions.rb +1 -0
  36. data/lib/mumuki/laboratory/exceptions/blocked_forum_error.rb +2 -0
  37. data/lib/mumuki/laboratory/locales/en.yml +3 -1
  38. data/lib/mumuki/laboratory/locales/es.yml +3 -2
  39. data/lib/mumuki/laboratory/locales/pt.yml +3 -2
  40. data/lib/mumuki/laboratory/mumukit/directives.rb +6 -5
  41. data/lib/mumuki/laboratory/status/submission/pending.rb +1 -5
  42. data/lib/mumuki/laboratory/status/submission/running.rb +1 -1
  43. data/lib/mumuki/laboratory/status/submission/submission.rb +0 -1
  44. data/lib/mumuki/laboratory/version.rb +1 -1
  45. data/spec/controllers/discussions_controller_spec.rb +1 -0
  46. data/spec/controllers/exercise_solutions_controller_spec.rb +1 -1
  47. data/spec/controllers/organizations_api_controller_spec.rb +1 -1
  48. data/spec/dummy/db/schema.rb +2 -1
  49. data/spec/factories/api_client_factory.rb +3 -3
  50. data/spec/factories/assignments_factory.rb +1 -1
  51. data/spec/factories/chapter_factory.rb +1 -1
  52. data/spec/factories/course_factory.rb +5 -5
  53. data/spec/factories/discussion_factory.rb +2 -2
  54. data/spec/factories/exercise_factory.rb +24 -26
  55. data/spec/factories/guide_factory.rb +3 -3
  56. data/spec/factories/login_settings_factory.rb +1 -1
  57. data/spec/factories/message_factory.rb +1 -1
  58. data/spec/factories/organization_factory.rb +9 -9
  59. data/spec/factories/topic_factory.rb +1 -1
  60. data/spec/features/choose_organization_spec.rb +49 -42
  61. data/spec/models/exercise_spec.rb +3 -27
  62. data/spec/models/query_spec.rb +1 -1
  63. data/spec/models/question_spec.rb +2 -2
  64. data/spec/models/stats_spec.rb +2 -9
  65. data/spec/models/user_spec.rb +13 -0
  66. metadata +8 -3
  67. data/lib/mumuki/laboratory/status/submission/unknown.rb +0 -11
@@ -2,15 +2,15 @@ FactoryBot.define do
2
2
 
3
3
  factory :guide do
4
4
  sequence(:name) { |n| "guide#{n}" }
5
- locale 'en'
6
- description 'A Guide'
5
+ locale { 'en' }
6
+ description { 'A Guide' }
7
7
  slug { "flbulgarelli/mumuki-sample-guide-#{SecureRandom.uuid}" }
8
8
  language
9
9
  end
10
10
 
11
11
  trait :guide_container do
12
12
  transient do
13
- exercises []
13
+ exercises { [] }
14
14
  name { Faker::Lorem.sentence(3) }
15
15
  description { Faker::Lorem.sentence(10) }
16
16
  language { create(:language) }
@@ -1,5 +1,5 @@
1
1
  FactoryBot.define do
2
2
  factory :all_login_settings, class: Mumukit::Login::Settings do
3
- login_methods Mumukit::Login::Settings.login_methods
3
+ login_methods { Mumukit::Login::Settings.login_methods }
4
4
  end
5
5
  end
@@ -5,7 +5,7 @@ FactoryBot.define do
5
5
  assignment
6
6
  submission_id { assignment.id }
7
7
  sender { Faker::Internet.email }
8
- type 'success'
8
+ type { 'success' }
9
9
  content { Faker::Lorem.sentence(3) }
10
10
  end
11
11
  end
@@ -2,25 +2,25 @@ FactoryBot.define do
2
2
 
3
3
  factory :organization do
4
4
  contact_email { Faker::Internet.email }
5
- description 'a great org'
6
- locale 'en'
5
+ description { 'a great org' }
6
+ locale { 'en' }
7
7
  settings {}
8
8
  book
9
9
  end
10
10
 
11
11
  factory :base, parent: :organization do
12
- public true
13
- name 'base'
14
- login_methods Mumukit::Login::Settings.login_methods
12
+ public { true }
13
+ name { 'base' }
14
+ login_methods { Mumukit::Login::Settings.login_methods }
15
15
  end
16
16
 
17
17
  factory :public_organization, parent: :organization do
18
- public true
19
- name 'the-public-org'
20
- login_methods Mumukit::Login::Settings.login_methods
18
+ public { true }
19
+ name { 'the-public-org' }
20
+ login_methods { Mumukit::Login::Settings.login_methods }
21
21
  end
22
22
 
23
23
  factory :private_organization, parent: :organization do
24
- name 'the-private-org'
24
+ name { 'the-private-org' }
25
25
  end
26
26
  end
@@ -4,6 +4,6 @@ FactoryBot.define do
4
4
  name { Faker::Lorem::sentence(3) }
5
5
  description { Faker::Lorem.paragraph(2) }
6
6
  slug { "mumuki/mumuki-sample-topic-#{SecureRandom.uuid}" }
7
- locale :en
7
+ locale { :en }
8
8
  end
9
9
  end
@@ -19,67 +19,74 @@ feature 'Choose organization Flow' do
19
19
  end
20
20
 
21
21
  before { Organization.find_by_name('immersive-orga').tap { |it| it.immersive = true }.save! }
22
-
23
- before { Organization.central.switch! }
24
22
  before { set_current_user! user }
25
23
 
26
- scenario 'when visiting with implicit subdomain and no permissions' do
27
- set_implicit_central!
24
+ context 'when organization exists' do
25
+ before { Organization.central.switch! }
28
26
 
29
- visit '/'
27
+ scenario 'when visiting with implicit subdomain and no permissions' do
28
+ set_implicit_central!
30
29
 
31
- expect(page).to have_text('Sign Out')
32
- expect(page).not_to have_text('Do you want to go there?')
33
- end
30
+ visit '/'
34
31
 
35
- scenario 'when visiting with implicit subdomain and permissions to only one non-immersive organization' do
36
- set_current_user! user2
37
- set_implicit_central!
32
+ expect(page).to have_text('Sign Out')
33
+ expect(page).not_to have_text('Do you want to go there?')
34
+ end
38
35
 
39
- visit '/'
36
+ scenario 'when visiting with implicit subdomain and permissions to only one non-immersive organization' do
37
+ set_current_user! user2
38
+ set_implicit_central!
40
39
 
41
- expect(page).to have_text('Sign Out')
42
- expect(page).to have_text('Do you want to go there?')
43
- end
40
+ visit '/'
44
41
 
45
- scenario 'when visiting with implicit subdomain and permissions to only one immersive organization' do
46
- set_current_user! user4
47
- set_implicit_central!
42
+ expect(page).to have_text('Sign Out')
43
+ expect(page).to have_text('Do you want to go there?')
44
+ end
48
45
 
49
- visit '/'
46
+ scenario 'when visiting with implicit subdomain and permissions to only one immersive organization' do
47
+ set_current_user! user4
48
+ set_implicit_central!
50
49
 
51
- expect(page).to have_text('Sign Out')
52
- expect(page).not_to have_text('Do you want to go there?')
53
- expect(page).to have_text('immersive-orga')
54
- end
50
+ visit '/'
55
51
 
56
- scenario 'when visiting with implicit subdomain and permissions to two or more organizations' do
57
- set_current_user! user3
58
- set_implicit_central!
52
+ expect(page).to have_text('Sign Out')
53
+ expect(page).not_to have_text('Do you want to go there?')
54
+ expect(page).to have_text('immersive-orga')
55
+ end
59
56
 
60
- visit '/'
57
+ scenario 'when visiting with implicit subdomain and permissions to two or more organizations' do
58
+ set_current_user! user3
59
+ set_implicit_central!
61
60
 
62
- expect(page).to have_text('Sign Out')
63
- expect(page).to have_text('Do you want to go there?')
64
- end
61
+ visit '/'
65
62
 
66
- scenario 'when visiting central explicitly' do
67
- set_subdomain_host!('central')
63
+ expect(page).to have_text('Sign Out')
64
+ expect(page).to have_text('Do you want to go there?')
65
+ end
68
66
 
69
- visit '/'
67
+ scenario 'when visiting central explicitly' do
68
+ set_subdomain_host!('central')
70
69
 
71
- expect(page).not_to have_text('Do you want to go there?')
72
- expect(page).not_to have_text('pdep')
73
- end
70
+ visit '/'
74
71
 
75
- scenario 'when visit foo subdomain' do
76
- set_current_user! user3
77
- set_subdomain_host!('foo')
72
+ expect(page).not_to have_text('Do you want to go there?')
73
+ expect(page).not_to have_text('pdep')
74
+ end
78
75
 
79
- visit '/'
76
+ scenario 'when visit foo subdomain' do
77
+ set_current_user! user3
78
+ set_subdomain_host!('foo')
80
79
 
81
- expect(page).not_to have_text('Do you want to go there?')
82
- expect(page).to have_text('foo')
80
+ visit '/'
81
+
82
+ expect(page).not_to have_text('Do you want to go there?')
83
+ expect(page).to have_text('foo')
84
+ end
83
85
  end
84
86
 
87
+ scenario 'when organization does not exist' do
88
+ visit '/'
89
+
90
+ expect(page).to have_http_status(404)
91
+ end
85
92
  end
@@ -123,37 +123,13 @@ describe Exercise, organization_workspace: :test do
123
123
  it { expect(exercise.extra_preview(user)).to eq "```haskell\nf x = 1\ng y = y + 3\n```" }
124
124
  end
125
125
 
126
- describe '#submitted_by?' do
126
+ describe '#submit_solution!' do
127
127
  context 'when user did a submission' do
128
128
  before { exercise.submit_solution!(user) }
129
- it { expect(exercise.assigned_to? user).to be true }
129
+ it { expect(exercise.assignment_for(user)).to be_present }
130
130
  end
131
131
  context 'when user did no submission' do
132
- it { expect(exercise.assigned_to? user).to be false }
133
- end
134
- end
135
-
136
- describe '#solved_by?' do
137
- context 'when user did no submission' do
138
- it { expect(exercise.solved_by? user).to be false }
139
- end
140
- context 'when user did a successful submission' do
141
- before { exercise.submit_solution!(user).passed! }
142
-
143
- it { expect(exercise.solved_by? user).to be true }
144
- end
145
- context 'when user did a pending submission' do
146
- before { exercise.submit_solution!(user) }
147
-
148
- it { expect(exercise.solved_by? user).to be false }
149
- end
150
- context 'when user did both successful and failed submissions' do
151
- before do
152
- exercise.submit_solution!(user)
153
- exercise.submit_solution!(user).passed!
154
- end
155
-
156
- it { expect(exercise.solved_by? user).to be true }
132
+ it { expect(exercise.assignment_for(user)).to be_blank }
157
133
  end
158
134
  end
159
135
 
@@ -15,7 +15,7 @@ describe Query do
15
15
 
16
16
  it { expect(results[:status]).to eq :passed }
17
17
  it { expect(results[:result]).to eq '5' }
18
- it { expect(exercise.assigned_to? user).to be true }
18
+ it { expect(exercise.assignment_for(user)).to be_present }
19
19
  it { expect(assignment.solution).to eq 'bar' }
20
20
  it { expect(assignment.status).to eq :pending }
21
21
  end
@@ -14,7 +14,7 @@ describe Query, organization_workspace: :test do
14
14
  it { expect(assignment.result).to be nil }
15
15
 
16
16
  it { expect(assignment.solution).to be nil }
17
- it { expect(exercise.assigned_to? student).to be true }
17
+ it { expect(exercise.assignment_for(student)).to be_present }
18
18
  it { expect(assignment.messages.count).to eq 1 }
19
19
  it { expect(assignment.submission_id).to_not be nil }
20
20
  end
@@ -28,7 +28,7 @@ describe Query, organization_workspace: :test do
28
28
 
29
29
  before { exercise.submit_question!(student, content: 'Please help!') }
30
30
 
31
- it { expect(exercise.assigned_to? student).to be true }
31
+ it { expect(exercise.assignment_for(student)).to be_present }
32
32
  it { expect(assignment.status).to eq :failed }
33
33
  it { expect(assignment.result).to eq 'noop result' }
34
34
  it { expect(assignment.solution).to eq 'x = 1' }
@@ -3,20 +3,13 @@ require 'spec_helper'
3
3
  describe Stats do
4
4
 
5
5
  context 'with good stats' do
6
- let(:stats) { Stats.new(passed: 6, passed_with_warnings: 3, failed: 1, unknown: 0) }
6
+ let(:stats) { Stats.new(passed: 6, passed_with_warnings: 3, failed: 1, pending: 0) }
7
7
  it { expect(stats.done?).to be false }
8
8
  end
9
9
 
10
10
 
11
11
  context 'with bad stats' do
12
- let(:stats) { Stats.new(passed: 1, passed_with_warnings: 0, failed: 4, unknown: 5) }
12
+ let(:stats) { Stats.new(passed: 1, passed_with_warnings: 0, failed: 4, pending: 5) }
13
13
  it { expect(stats.done?).to be false }
14
14
  end
15
-
16
- describe '#to_h' do
17
- let(:hash) { {passed: 4, passed_with_warnings: 3, failed: 2, unknown: 1} }
18
- let(:stats) { Stats.new(hash) }
19
-
20
- it { expect(stats.to_h { |it| it }).to eq(hash) }
21
- end
22
15
  end
@@ -260,4 +260,17 @@ describe User, organization_workspace: :test do
260
260
  it { expect(student.student? invitation.course).to be true }
261
261
  it { expect(student.student? 'foo/bar').to be false }
262
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
263
276
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-laboratory
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.0
4
+ version: 5.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-02 00:00:00.000000000 Z
11
+ date: 2018-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -273,6 +273,7 @@ files:
273
273
  - app/assets/javascripts/application/load-error-svg.js
274
274
  - app/assets/javascripts/application/messages.js
275
275
  - app/assets/javascripts/application/multiple-choice.js
276
+ - app/assets/javascripts/application/multiple-files.js
276
277
  - app/assets/javascripts/application/pin.js
277
278
  - app/assets/javascripts/application/progress.js
278
279
  - app/assets/javascripts/application/submission.js
@@ -368,6 +369,7 @@ files:
368
369
  - app/helpers/links_helper.rb
369
370
  - app/helpers/menu_bar_helper.rb
370
371
  - app/helpers/messages_helper.rb
372
+ - app/helpers/multiple_file_editor_helper.rb
371
373
  - app/helpers/organization_list_helper.rb
372
374
  - app/helpers/progress_bar_helper.rb
373
375
  - app/helpers/progress_helper.rb
@@ -485,6 +487,7 @@ files:
485
487
  - app/views/exercises/show.html.erb
486
488
  - app/views/invitations/show.html.erb
487
489
  - app/views/layouts/_authoring.html.erb
490
+ - app/views/layouts/_copyright.html.erb
488
491
  - app/views/layouts/_discussions.html.erb
489
492
  - app/views/layouts/_error.html.erb
490
493
  - app/views/layouts/_guide.html.erb
@@ -497,6 +500,7 @@ files:
497
500
  - app/views/layouts/_progress_listing.html.erb
498
501
  - app/views/layouts/_result.html.erb
499
502
  - app/views/layouts/_runner_assets.html.erb
503
+ - app/views/layouts/_social_media.html.erb
500
504
  - app/views/layouts/_submission_result_error.html.erb
501
505
  - app/views/layouts/_submission_result_error_body.html.erb
502
506
  - app/views/layouts/_test_results.html.erb
@@ -791,6 +795,7 @@ files:
791
795
  - db/migrate/20180702153442_create_upvotes.rb
792
796
  - db/migrate/20180702175220_add_upvotes_count_to_discussions.rb
793
797
  - db/migrate/20180704150839_rename_assignment_status_to_submission_status.rb
798
+ - db/migrate/20180802190437_add_approved_to_messages.rb
794
799
  - db/seeds/users.rb
795
800
  - lib/events.rb
796
801
  - lib/mumuki/laboratory.rb
@@ -809,6 +814,7 @@ files:
809
814
  - lib/mumuki/laboratory/evaluation/automated.rb
810
815
  - lib/mumuki/laboratory/evaluation/manual.rb
811
816
  - lib/mumuki/laboratory/exceptions.rb
817
+ - lib/mumuki/laboratory/exceptions/blocked_forum_error.rb
812
818
  - lib/mumuki/laboratory/exceptions/forbidden_error.rb
813
819
  - lib/mumuki/laboratory/exceptions/gone_error.rb
814
820
  - lib/mumuki/laboratory/exceptions/not_found_error.rb
@@ -849,7 +855,6 @@ files:
849
855
  - lib/mumuki/laboratory/status/submission/pending.rb
850
856
  - lib/mumuki/laboratory/status/submission/running.rb
851
857
  - lib/mumuki/laboratory/status/submission/submission.rb
852
- - lib/mumuki/laboratory/status/submission/unknown.rb
853
858
  - lib/mumuki/laboratory/version.rb
854
859
  - lib/tasks/assignments.rake
855
860
  - lib/tasks/events.rake
@@ -1,11 +0,0 @@
1
- module Mumuki::Laboratory::Status::Submission::Unknown
2
- extend Mumuki::Laboratory::Status::Submission
3
-
4
- def self.to_i
5
- raise 'unknown status'
6
- end
7
-
8
- def self.iconize
9
- {class: :muted, type: :circle}
10
- end
11
- end