mumuki-laboratory 7.7.6 → 7.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -3
  3. data/Rakefile +7 -1
  4. data/app/assets/javascripts/mumuki_laboratory/application/alias-modes.js +1 -1
  5. data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +66 -57
  6. data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +28 -25
  7. data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +8 -10
  8. data/app/assets/javascripts/mumuki_laboratory/application/confirmation.js +2 -2
  9. data/app/assets/javascripts/mumuki_laboratory/application/console.js +41 -43
  10. data/app/assets/javascripts/mumuki_laboratory/application/csrf-token.js +9 -12
  11. data/app/assets/javascripts/mumuki_laboratory/application/custom-editor.js +11 -15
  12. data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +1 -3
  13. data/app/assets/javascripts/mumuki_laboratory/application/editors.js +104 -0
  14. data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +5 -4
  15. data/app/assets/javascripts/mumuki_laboratory/application/exercise.js +32 -0
  16. data/app/assets/javascripts/mumuki_laboratory/application/inputs.js +4 -2
  17. data/app/assets/javascripts/mumuki_laboratory/application/interval.js +2 -4
  18. data/app/assets/javascripts/mumuki_laboratory/application/kids.js +1 -1
  19. data/app/assets/javascripts/mumuki_laboratory/application/load-analytics.js +1 -1
  20. data/app/assets/javascripts/mumuki_laboratory/application/load-error-svg.js +1 -1
  21. data/app/assets/javascripts/mumuki_laboratory/application/messages.js +2 -2
  22. data/app/assets/javascripts/mumuki_laboratory/application/multiple-choice.js +1 -1
  23. data/app/assets/javascripts/mumuki_laboratory/application/multiple-scenarios.js +3 -6
  24. data/app/assets/javascripts/mumuki_laboratory/application/pin.js +3 -5
  25. data/app/assets/javascripts/mumuki_laboratory/application/progress.js +24 -6
  26. data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +20 -11
  27. data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +12 -5
  28. data/app/assets/javascripts/mumuki_laboratory/application/submission.js +19 -101
  29. data/app/assets/javascripts/mumuki_laboratory/application/submissions-store.js +93 -0
  30. data/app/assets/javascripts/mumuki_laboratory/application/sync-mode.js +75 -0
  31. data/app/assets/javascripts/mumuki_laboratory/application/timer.js +5 -6
  32. data/app/assets/javascripts/mumuki_laboratory/application/tooltip.js +1 -1
  33. data/app/assets/javascripts/mumuki_laboratory/application/upload.js +1 -1
  34. data/app/assets/javascripts/mumuki_laboratory/application/user.js +1 -1
  35. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_gs-board.scss +3 -0
  36. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids.scss +0 -1
  37. data/app/controllers/application_controller.rb +1 -0
  38. data/app/helpers/{locale_helper.rb → globals_helper.rb} +6 -2
  39. data/app/mailers/user_mailer.rb +24 -11
  40. data/app/views/book/show.html.erb +1 -1
  41. data/app/views/exercises/show.html.erb +2 -0
  42. data/app/views/layouts/_main.html.erb +1 -2
  43. data/app/views/layouts/_progress.html.erb +1 -1
  44. data/app/views/layouts/_progress_bar.html.erb +7 -1
  45. data/app/views/layouts/application.html.erb +1 -1
  46. data/lib/mumuki/laboratory/controllers.rb +1 -0
  47. data/lib/mumuki/laboratory/controllers/incognito_mode.rb +28 -0
  48. data/lib/mumuki/laboratory/locales/en.yml +6 -4
  49. data/lib/mumuki/laboratory/locales/es.yml +6 -4
  50. data/lib/mumuki/laboratory/locales/pt.yml +4 -2
  51. data/lib/mumuki/laboratory/version.rb +1 -1
  52. data/spec/dummy/db/schema.rb +2 -1
  53. data/spec/features/chapter_spec.rb +17 -0
  54. data/spec/features/exercise_flow_spec.rb +47 -2
  55. data/spec/features/home_public_flow_spec.rb +16 -0
  56. data/spec/javascripts/editors-spec.js +54 -0
  57. data/spec/javascripts/exercise-spec.js +22 -0
  58. data/spec/javascripts/global-spec.js +6 -0
  59. data/spec/javascripts/spec-helper.js +4 -0
  60. data/spec/javascripts/submissions-store-spec.js +44 -0
  61. data/spec/javascripts/sync-mode-spec.js +15 -0
  62. data/spec/mailers/user_mailer_spec.rb +18 -3
  63. data/spec/teaspoon_env.rb +8 -2
  64. data/vendor/assets/javascripts/codemirror-modes/gobstones.js +2 -3
  65. metadata +19 -5
  66. data/app/helpers/version_helper.rb +0 -5
@@ -0,0 +1,54 @@
1
+ describe('editors', () => {
2
+
3
+ beforeEach(() => {
4
+ mumuki.CustomEditor.clearSources()
5
+ })
6
+
7
+ it('has initially no sources', () => {
8
+ expect(mumuki.CustomEditor.hasSources).toBe(false)
9
+ });
10
+
11
+ it('can add a custom source', () => {
12
+ mumuki.editors.addCustomSource({
13
+ getContent() {
14
+ return { name: "solution[content]", value: 'the value' } ;
15
+ }
16
+ });
17
+
18
+ expect(mumuki.CustomEditor.hasSources).toBe(true);
19
+ expect(mumuki.CustomEditor.getContents()[0].value).toEqual('the value');
20
+ expect(mumuki.CustomEditor.getContents()[0].name).toEqual('solution[content]');
21
+ });
22
+
23
+ it('reads the custom sources if present, ignoring the form', () => {
24
+ $('body').html(`
25
+ <form role="form" class="new_solution">
26
+ <div class="field form-group editor-code">
27
+ <textarea class="form-control editor" name="solution[content]" id="solution_content">the standard solution</textarea>
28
+ </div>
29
+ </form>`)
30
+
31
+ mumuki.editors.addCustomSource({
32
+ getContent() {
33
+ return { name: "solution[content]", value: 'the custom solution' } ;
34
+ }
35
+ });
36
+
37
+ expect(mumuki.editors.getSubmission()).toEqual({"solution[content]":"the custom solution"});
38
+ });
39
+
40
+ it('reads the form if no sources', () => {
41
+ $('body').html(`
42
+ <form role="form" class="new_solution">
43
+ <div class="field form-group editor-code">
44
+ <textarea class="form-control editor" name="solution[content]" id="solution_content">the solution</textarea>
45
+ </div>
46
+ </form>`)
47
+ expect(mumuki.editors.getSubmission()).toEqual({"solution[content]":"the solution"});
48
+ });
49
+
50
+ it('produces empty submission if no form nor sources', () => {
51
+ $('body').html(``);
52
+ expect(mumuki.editors.getSubmission()).toEqual({});
53
+ });
54
+ })
@@ -0,0 +1,22 @@
1
+ describe('exercise', () => {
2
+ it('current exercise information is available when present', () => {
3
+ $('body').html(`
4
+ <input type="hidden" name="mu-exercise-id" id="mu-exercise-id" value="3361" />
5
+ <input type="hidden" name="mu-exercise-layout" id="mu-exercise-layout" value="input_right" />`)
6
+
7
+ mumuki.exercise.load()
8
+
9
+ expect(mumuki.exercise.id).toBe(3361);
10
+ expect(mumuki.exercise.layout).toBe('input_right');
11
+ })
12
+
13
+ it('current exercise information is available when not present', () => {
14
+ $('body').html(``)
15
+
16
+ mumuki.exercise.load()
17
+
18
+ expect(mumuki.exercise.id).toBe(null);
19
+ expect(mumuki.exercise.layout).toBe(null);
20
+ })
21
+
22
+ })
@@ -0,0 +1,6 @@
1
+ describe("global loading", () => {
2
+ it("produces no global loading errors", () => {
3
+ const error = window['__globalLoadingError__'];
4
+ expect(!error).toBe(true, `Expected no global loading errors but got ${error && error.message}`)
5
+ })
6
+ })
@@ -28,3 +28,7 @@
28
28
  // the configuration and use this file as a manifest.
29
29
  //
30
30
  // For more information: http://github.com/modeset/teaspoon
31
+
32
+ window.addEventListener("error", (e) => {
33
+ window['__globalLoadingError__'] = e;
34
+ });
@@ -0,0 +1,44 @@
1
+ describe("SubmissionsStore", () => {
2
+ const emptyProgramSubmission = {"solution[content]": "program {}"};
3
+ /** @type {SubmissionResult} */
4
+ const passedSubmissionResult = {status: 'passed'};
5
+ /** @type {SubmissionAndResult} */
6
+ const passedEmptyProgramSubmissionAndResult = { submission: emptyProgramSubmission, result: passedSubmissionResult };
7
+
8
+ beforeEach(() => {
9
+ window.localStorage.clear()
10
+ });
11
+
12
+ describe('getLastSubmission', () => {
13
+ it("answers null if submission not present", () => {
14
+ expect(mumuki.SubmissionsStore.getLastSubmissionAndResult(1)).toBe(null)
15
+ })
16
+
17
+ it("answers the last submission result if already sent", () => {
18
+ mumuki.SubmissionsStore.setSubmissionResultFor(1, passedEmptyProgramSubmissionAndResult)
19
+ expect(mumuki.SubmissionsStore.getLastSubmissionAndResult(1)).toEqual(passedEmptyProgramSubmissionAndResult)
20
+ })
21
+ })
22
+
23
+ describe('getLastSubmissionStatus', () => {
24
+ it("answers pending if submission not present", () => {
25
+ expect(mumuki.SubmissionsStore.getLastSubmissionStatus(1)).toBe('pending')
26
+ })
27
+
28
+ it("answers the last submission status if previously sent", () => {
29
+ mumuki.SubmissionsStore.setSubmissionResultFor(1, passedEmptyProgramSubmissionAndResult)
30
+ expect(mumuki.SubmissionsStore.getLastSubmissionStatus(1)).toBe('passed')
31
+ })
32
+ });
33
+
34
+ describe('getCachedResultFor', () => {
35
+ it("answers null if submission not present", () => {
36
+ expect(mumuki.SubmissionsStore.getSubmissionResultFor(1, emptyProgramSubmission)).toBe(null)
37
+ })
38
+
39
+ it("answers the last submission if previously sent", () => {
40
+ mumuki.SubmissionsStore.setSubmissionResultFor(1, passedEmptyProgramSubmissionAndResult)
41
+ expect(mumuki.SubmissionsStore.getSubmissionResultFor(1, emptyProgramSubmission)).toEqual(passedSubmissionResult)
42
+ })
43
+ });
44
+ })
@@ -0,0 +1,15 @@
1
+ describe('sync mode', () => {
2
+ it('can choose server mode', () => {
3
+ mumuki.incognitoUser = false;
4
+ mumuki.syncMode._selectSyncMode();
5
+
6
+ expect(mumuki.syncMode._current instanceof mumuki.syncMode.ServerSyncMode).toBe(true);
7
+ })
8
+
9
+ it('can choose local mode', () => {
10
+ mumuki.incognitoUser = true;
11
+ mumuki.syncMode._selectSyncMode();
12
+
13
+ expect(mumuki.syncMode._current instanceof mumuki.syncMode.ClientSyncMode).toBe(true);
14
+ })
15
+ })
@@ -148,21 +148,21 @@ RSpec.describe UserMailer, type: :mailer do
148
148
 
149
149
  context "registered 1 week ago" do
150
150
  it { expect(user.should_remind?).to be true }
151
- it { expect(reminder.body.encoded).to include("you've never submitted solutions") }
151
+ it { expect(reminder.body.encoded).to include('you&#39;ve never submitted solutions') }
152
152
  end
153
153
 
154
154
  context "last submission 2 weeks ago" do
155
155
  let(:days_since_user_creation) { 16 }
156
156
 
157
157
  it { expect(user.should_remind?).to be true }
158
- it { expect(reminder.body.encoded).to include("you've never submitted solutions") }
158
+ it { expect(reminder.body.encoded).to include('you&#39;ve never submitted solutions') }
159
159
  end
160
160
 
161
161
  context "last submission 3 weeks ago" do
162
162
  let(:days_since_user_creation) { 26 }
163
163
 
164
164
  it { expect(user.should_remind?).to be true }
165
- it { expect(reminder.body.encoded).to include("you've never submitted solutions") }
165
+ it { expect(reminder.body.encoded).to include('you&#39;ve never submitted solutions') }
166
166
  end
167
167
 
168
168
  context "last submission 4 weeks ago" do
@@ -178,4 +178,19 @@ RSpec.describe UserMailer, type: :mailer do
178
178
  it { expect(user.should_remind?).to be false }
179
179
  end
180
180
  end
181
+
182
+ describe 'welcome email' do
183
+ let(:email) { UserMailer.welcome_email(user, organization) }
184
+
185
+ let(:non_custom_welcome_orga) { create :organization }
186
+ let(:custom_welcome_orga) { create :organization, welcome_email_template: 'hello <%= @user.first_name %>!' }
187
+
188
+ let(:user) { create :user, first_name: 'some name' }
189
+
190
+ context 'when organization does have a custom welcome template' do
191
+ let(:organization) { custom_welcome_orga }
192
+
193
+ it { expect(email.body.encoded).to eq 'hello some name!' }
194
+ end
195
+ end
181
196
  end
data/spec/teaspoon_env.rb CHANGED
@@ -3,6 +3,8 @@ unless defined?(Rails)
3
3
  require File.expand_path("../dummy/config/environment", __FILE__)
4
4
  end
5
5
 
6
+ # Enable this line for more verbose debugging
7
+ # Selenium::WebDriver.logger.level = :debug
6
8
 
7
9
  Teaspoon.configure do |config|
8
10
  # Determines where the Teaspoon routes will be mounted. Changing this to "/jasmine" would allow you to browse to
@@ -106,8 +108,12 @@ Teaspoon.configure do |config|
106
108
  # Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit
107
109
  # config.driver = :capybara_webkit
108
110
  config.driver = :selenium
109
- config.driver_options = {client_driver: :firefox}
110
-
111
+ config.driver_options = {
112
+ client_driver: :firefox,
113
+ selenium_options: {
114
+ options: Selenium::WebDriver::Firefox::Options.new(log_level: :warn)
115
+ }
116
+ }
111
117
 
112
118
  # Specify the timeout for the driver. Specs are expected to complete within this time frame or the run will be
113
119
  # considered a failure. This is to avoid issues that can arise where tests stall.
@@ -2,7 +2,6 @@
2
2
 
3
3
  (function() {
4
4
  var locale = document.querySelector("html").lang || 'es';
5
- var languageCode = locale.split("-")[0];
6
5
 
7
6
  var keywords = [
8
7
  "program", "procedure", "function", "interactive", "if",
@@ -23,8 +22,8 @@
23
22
  en: ["Put", "Grab", "Move", "GoToEdge", "EmptyBoardContents", "numStones", "anyStones", "canMove", "next", "prev", "opposite", "minBool", "maxBool", "minDir", "maxDir", "minColor", "maxColor"]
24
23
  };
25
24
 
26
- const localizedKeywordsAndBuiltins = keywords.concat(builtins[languageCode]);
27
- const localizedAtoms = atoms[languageCode];
25
+ const localizedKeywordsAndBuiltins = keywords.concat(builtins[locale]);
26
+ const localizedAtoms = atoms[locale];
28
27
 
29
28
  var buildList = function(values) {
30
29
  return values.join('|');
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-laboratory
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.7.6
4
+ version: 7.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 7.7.3
33
+ version: 7.8.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 7.7.3
40
+ version: 7.8.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mumukit-bridge
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -344,7 +344,9 @@ files:
344
344
  - app/assets/javascripts/mumuki_laboratory/application/csrf-token.js
345
345
  - app/assets/javascripts/mumuki_laboratory/application/custom-editor.js
346
346
  - app/assets/javascripts/mumuki_laboratory/application/discussions.js
347
+ - app/assets/javascripts/mumuki_laboratory/application/editors.js
347
348
  - app/assets/javascripts/mumuki_laboratory/application/elipsis.js
349
+ - app/assets/javascripts/mumuki_laboratory/application/exercise.js
348
350
  - app/assets/javascripts/mumuki_laboratory/application/free-form.js
349
351
  - app/assets/javascripts/mumuki_laboratory/application/inputs.js
350
352
  - app/assets/javascripts/mumuki_laboratory/application/interval.js
@@ -361,6 +363,8 @@ files:
361
363
  - app/assets/javascripts/mumuki_laboratory/application/results-renderer.js
362
364
  - app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js
363
365
  - app/assets/javascripts/mumuki_laboratory/application/submission.js
366
+ - app/assets/javascripts/mumuki_laboratory/application/submissions-store.js
367
+ - app/assets/javascripts/mumuki_laboratory/application/sync-mode.js
364
368
  - app/assets/javascripts/mumuki_laboratory/application/timer.js
365
369
  - app/assets/javascripts/mumuki_laboratory/application/tooltip.js
366
370
  - app/assets/javascripts/mumuki_laboratory/application/upload.js
@@ -461,9 +465,9 @@ files:
461
465
  - app/helpers/editor_tabs_helper.rb
462
466
  - app/helpers/email_helper.rb
463
467
  - app/helpers/exercise_input_helper.rb
468
+ - app/helpers/globals_helper.rb
464
469
  - app/helpers/icons_helper.rb
465
470
  - app/helpers/links_helper.rb
466
- - app/helpers/locale_helper.rb
467
471
  - app/helpers/menu_bar_helper.rb
468
472
  - app/helpers/messages_helper.rb
469
473
  - app/helpers/multiple_file_editor_helper.rb
@@ -475,7 +479,6 @@ files:
475
479
  - app/helpers/progress_bar_helper.rb
476
480
  - app/helpers/progress_helper.rb
477
481
  - app/helpers/runner_assets_helper.rb
478
- - app/helpers/version_helper.rb
479
482
  - app/mailers/application_mailer.rb
480
483
  - app/mailers/user_mailer.rb
481
484
  - app/views/appendixes/show.html.erb
@@ -595,6 +598,7 @@ files:
595
598
  - lib/mumuki/laboratory/controllers/dynamic_errors.rb
596
599
  - lib/mumuki/laboratory/controllers/embedded_mode.rb
597
600
  - lib/mumuki/laboratory/controllers/exercise_seed.rb
601
+ - lib/mumuki/laboratory/controllers/incognito_mode.rb
598
602
  - lib/mumuki/laboratory/controllers/nested_in_exercise.rb
599
603
  - lib/mumuki/laboratory/controllers/notifications.rb
600
604
  - lib/mumuki/laboratory/controllers/results_rendering.rb
@@ -719,10 +723,15 @@ files:
719
723
  - spec/helpers/with_navigation_spec.rb
720
724
  - spec/javascripts/bridge-spec.js
721
725
  - spec/javascripts/csrf-token-spec.js
726
+ - spec/javascripts/editors-spec.js
722
727
  - spec/javascripts/elipsis-spec.js
728
+ - spec/javascripts/exercise-spec.js
729
+ - spec/javascripts/global-spec.js
723
730
  - spec/javascripts/results-renderers-spec.js
724
731
  - spec/javascripts/spec-helper.js
725
732
  - spec/javascripts/speech-bubble-renderer-spec.js
733
+ - spec/javascripts/submissions-store-spec.js
734
+ - spec/javascripts/sync-mode-spec.js
726
735
  - spec/javascripts/timeout-spec.js
727
736
  - spec/javascripts/timer-spec.js
728
737
  - spec/login_helper.rb
@@ -876,13 +885,18 @@ test_files:
876
885
  - spec/capybara_helper.rb
877
886
  - spec/evaluation_helper.rb
878
887
  - spec/javascripts/bridge-spec.js
888
+ - spec/javascripts/exercise-spec.js
889
+ - spec/javascripts/global-spec.js
879
890
  - spec/javascripts/speech-bubble-renderer-spec.js
880
891
  - spec/javascripts/timeout-spec.js
881
892
  - spec/javascripts/results-renderers-spec.js
882
893
  - spec/javascripts/csrf-token-spec.js
883
894
  - spec/javascripts/elipsis-spec.js
884
895
  - spec/javascripts/timer-spec.js
896
+ - spec/javascripts/editors-spec.js
885
897
  - spec/javascripts/spec-helper.js
898
+ - spec/javascripts/submissions-store-spec.js
899
+ - spec/javascripts/sync-mode-spec.js
886
900
  - spec/controllers/discussions_controller_spec.rb
887
901
  - spec/controllers/chapters_controller_spec.rb
888
902
  - spec/controllers/students_api_controller_spec.rb
@@ -1,5 +0,0 @@
1
- module VersionHelper
2
- def version_tags
3
- %Q{<script type="text/javascript">mumuki.version = '#{Mumuki::Laboratory::VERSION}';</script>}.html_safe
4
- end
5
- end