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
@@ -1,24 +1,37 @@
1
1
  class UserMailer < ApplicationMailer
2
+ def welcome_email(user, organization)
3
+ with_locale(user, organization) do
4
+ organization_name = organization.display_name || t(:your_new_organization)
5
+ build_email t(:welcome, name: organization_name), { inline: organization.welcome_email_template }
6
+ end
7
+ end
2
8
 
3
9
  def we_miss_you_reminder(user, cycles)
4
- send_reminder! user, :we_miss_you, "#{cycles.ordinalize}_reminder"
10
+ with_locale(user) do
11
+ build_email t(:we_miss_you), "#{cycles.ordinalize}_reminder"
12
+ end
5
13
  end
6
14
 
7
15
  def no_submissions_reminder(user)
8
- send_reminder! user, :start_using_mumuki, "no_submissions_reminder"
16
+ with_locale(user) do
17
+ build_email t(:start_using_mumuki), 'no_submissions_reminder'
18
+ end
9
19
  end
10
20
 
11
- private
12
-
13
- def send_reminder!(user, subject, template_name)
21
+ def with_locale(user, organization = nil, &block)
14
22
  @user = user
15
23
  @unsubscribe_code = User.unsubscription_verifier.generate(user.id)
16
- @organization = user.last_organization
24
+ @organization = organization || user.last_organization
17
25
 
18
- I18n.with_locale(@organization.locale) do
19
- mail to: user.email,
20
- subject: t(subject),
21
- template_name: template_name
22
- end
26
+ I18n.with_locale(@organization.locale, &block)
27
+ end
28
+
29
+ private
30
+
31
+ def build_email(subject, template)
32
+ mail to: @user.email,
33
+ subject: subject,
34
+ content_type: 'text/html',
35
+ body: render(template)
23
36
  end
24
37
  end
@@ -36,7 +36,7 @@
36
36
  <div class="chapter-container">
37
37
  <div class="chapter <%= enabled ? '' : 'mu-locked' %>">
38
38
  <h3><%= it.number %>. <%= link_to_path_element it, mode: :plain %></h3>
39
- <div class="text-box" <%= 'aria-label=""' unless enabled %>%>
39
+ <div class="text-box" <%= 'aria-label=""' unless enabled %>>
40
40
  <%= it.description_teaser_html %>
41
41
  </div>
42
42
  </div>
@@ -45,6 +45,8 @@
45
45
  <%= render_exercise_input_layout(@exercise) %>
46
46
 
47
47
  <%= hidden_field_tag default_content_tag_id(@exercise), @default_content %>
48
+ <%= hidden_field_tag "mu-exercise-id", @exercise.id %>
49
+ <%= hidden_field_tag "mu-exercise-layout", @exercise.layout %>
48
50
 
49
51
  <div style="display: none" id="processing-template">
50
52
  <div class="bs-callout bs-callout-info">
@@ -11,8 +11,7 @@
11
11
  <%= open_graph_tags subject %>
12
12
  <%= assets_include_tags %>
13
13
  <%= csrf_meta_tags %>
14
- <%= locale_tags %>
15
- <%= version_tags %>
14
+ <%= globals_tags %>
16
15
 
17
16
  <%= login_form.header_html %>
18
17
  </head>
@@ -1 +1 @@
1
- <% content.completion_percentage_for(current_user) %>
1
+ <% content.completion_percentage_for(current_user) if current_user? %>
@@ -1,6 +1,12 @@
1
1
  <div class="progress-list-flex">
2
2
  <% guide.exercises.each do |e| %>
3
- <a <%= turbolinks_enable_for e %> href="<%= exercise_path(e)%>" aria-label="<%= e.navigable_name %>" title="<%= e.navigable_name %>" class="<%= class_for_progress_list_item(e, e == actual)%>">
3
+ <a
4
+ <%= turbolinks_enable_for e %>
5
+ href="<%= exercise_path(e)%>"
6
+ aria-label="<%= e.navigable_name %>"
7
+ title="<%= e.navigable_name %>"
8
+ data-mu-exercise-id="<%= e.id %>"
9
+ class="<%= class_for_progress_list_item(e, e == actual)%>">
4
10
  </a>
5
11
  <% end %>
6
12
  </div>
@@ -17,7 +17,7 @@
17
17
  <% end %>
18
18
  </div>
19
19
  <div class="mu-navbar-avatar">
20
- <% if current_user? %>
20
+ <% if current_logged_user? %>
21
21
  <div class="dropdown">
22
22
  <span>
23
23
  <a class="notifications-box <%= has_notifications? ? '' : 'notifications-box-empty' %>" href=<%= "#{user_notifications_path}" %>>
@@ -7,6 +7,7 @@ require_relative './controllers/current_organization'
7
7
  require_relative './controllers/dynamic_errors'
8
8
  require_relative './controllers/notifications'
9
9
  require_relative './controllers/embedded_mode'
10
+ require_relative './controllers/incognito_mode'
10
11
  require_relative './controllers/nested_in_exercise'
11
12
  require_relative './controllers/results_rendering'
12
13
  require_relative './controllers/exercise_seed'
@@ -0,0 +1,28 @@
1
+ module Mumuki::Laboratory::Controllers::IncognitoMode
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ helper_method :current_incognito_user?,
6
+ :current_logged_user?
7
+ end
8
+
9
+ def current_user?
10
+ super || incognito_mode_enabled?
11
+ end
12
+
13
+ def current_user
14
+ @current_user ||= incognito_mode_enabled? ? (super rescue Mumuki::Domain::Incognito) : super
15
+ end
16
+
17
+ def current_incognito_user?
18
+ current_user? && current_user.incognito?
19
+ end
20
+
21
+ def current_logged_user?
22
+ current_user? && !current_user.incognito?
23
+ end
24
+
25
+ def incognito_mode_enabled?
26
+ !from_sessions? && Organization.current.incognito_mode_enabled?
27
+ end
28
+ end
@@ -93,7 +93,9 @@ en:
93
93
  first_name: First Name
94
94
  forbidden_explanation: You are not allowed to see this content.
95
95
  format: Format
96
+ fullscreen: "Fullscreen"
96
97
  gender: Gender
98
+ get_messages: "View messages"
97
99
  go_to: 'Go to %{organization}'
98
100
  gone_explanation: This content is no longer available.
99
101
  guide: Guide
@@ -162,6 +164,7 @@ en:
162
164
  not_in_any_organizations: It seems you aren't in any organizations yet!
163
165
  notify_problem_with_exercise: Report a bug
164
166
  office: Office
167
+ only_landscape_support: Please, rotate your tablet or cellphone to continue practicing
165
168
  opened: Open
166
169
  opened_count: '%{count} opened'
167
170
  other: Other
@@ -230,6 +233,7 @@ en:
230
233
  submissions_for: Submissions for %{exercise}
231
234
  subscribe: Subscribe
232
235
  tag: Tags
236
+ task: Task
233
237
  teacher_info: Information for teachers
234
238
  tell_us_how: Please tell us how this happened!
235
239
  tell_us_if_our_error: If you think this is our fault, %{issues}
@@ -260,11 +264,9 @@ en:
260
264
  view_details: View details
261
265
  want_permissions: The next user requires permissions
262
266
  we_miss_you: We miss you!
267
+ welcome: Welcome to %{name}!
263
268
  working: "Working"
264
269
  wrong_answer: The answer is wrong
265
270
  you_must_sign_in_before_submitting: You must sign in before submitting your solutions
266
271
  you_never_submitted_solutions: It seems that you've never submitted solutions since you created your account.
267
- fullscreen: "Fullscreen"
268
- get_messages: "View messages"
269
- task: Task
270
- only_landscape_support: Please, rotate your tablet or cellphone to continue practicing
272
+ your_new_organization: your new organization
@@ -99,7 +99,9 @@ es:
99
99
  first_name: Nombre
100
100
  forbidden_explanation: Es decir que no tenés autorización para ver este contenido. <br> ¿Puede que hayas ingresado con una cuenta incorrecta?
101
101
  format: Dar formato
102
+ fullscreen: "Pantalla completa"
102
103
  gender: Género
104
+ get_messages: "Ver mensajes"
103
105
  go_to: 'Ir a %{organization}'
104
106
  gone_explanation: Este contenido ya no está disponible.
105
107
  guide: Lección
@@ -176,6 +178,7 @@ es:
176
178
  not_in_any_organizations: ¡Parece que no estás en ninguna organización todavía!
177
179
  notify_problem_with_exercise: Reportá un bug
178
180
  office: Secretaría
181
+ only_landscape_support: Por favor, rotá tu tablet o celular para realizar ejercicios
179
182
  opened: Abierta
180
183
  opened_count:
181
184
  one: '1 abierta'
@@ -253,6 +256,7 @@ es:
253
256
  submissions_count: Soluciones
254
257
  submissions_for: Soluciones para %{exercise}
255
258
  tag: Etiquetas
259
+ task: Consigna
256
260
  teacher_info: Información para docentes
257
261
  tell_us_how: ¡Contanos cómo te pasó esto!
258
262
  tell_us_if_our_error: Si pensás que es un error nuestro, %{issues}
@@ -284,6 +288,7 @@ es:
284
288
  view_details: Ver detalles
285
289
  want_permissions: El siguiente usuario requiere permisos
286
290
  we_miss_you: ¡Te extrañamos!
291
+ welcome: Te damos la bienvenida a %{name}!
287
292
  will_paginate:
288
293
  previous_label: "&#8592; Anterior"
289
294
  next_label: "Siguiente &#8594;"
@@ -292,7 +297,4 @@ es:
292
297
  wrong_answer: La respuesta no es correcta
293
298
  you_must_sign_in_before_submitting: Tenés que iniciar sesión antes de empezar a enviar tus soluciones
294
299
  you_never_submitted_solutions: Parece que nunca enviaste soluciones desde que creaste tu cuenta.
295
- fullscreen: "Pantalla completa"
296
- get_messages: "Ver mensajes"
297
- task: Consigna
298
- only_landscape_support: Por favor, rotá tu tablet o celular para realizar ejercicios
300
+ your_new_organization: tu nueva organización
@@ -171,6 +171,7 @@ pt:
171
171
  not_in_any_organizations: Parece que você ainda não está em nenhuma organização!
172
172
  notify_problem_with_exercise: Relatar um erro
173
173
  office: Secretariado
174
+ only_landscape_support: Por favor, gire seu tablet ou celular para realizar exercícios
174
175
  opened: Aberto
175
176
  opened_count: '%{count} aberto'
176
177
  organizations: Organizações
@@ -240,6 +241,7 @@ pt:
240
241
  submissions_for: Soluções para %{exercise}
241
242
  subscribe: se inscrever
242
243
  tag: Etiquetas
244
+ task: Tarefa
243
245
  teacher_info: Informação para professores
244
246
  tell_us_how: Conte-nos como isso aconteceu com você!
245
247
  tell_us_if_our_error: Se você acha que é nosso erro, %{issues}
@@ -265,8 +267,8 @@ pt:
265
267
  username: Nome de usuário
266
268
  view_details: Ver detalhes
267
269
  want_permissions: O próximo usuário requer permissões
270
+ welcome: Convidamos você a {name}!
268
271
  working: Processamento
269
272
  wrong_answer: A resposta não é correta
270
273
  you_must_sign_in_before_submitting: Você deve fazer o login antes de começar a enviar suas soluções
271
- task: Tarefa
272
- only_landscape_support: Por favor, gire seu tablet ou celular para realizar exercícios
274
+ your_new_organization: sua nova organização
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Laboratory
3
- VERSION = '7.7.6'
3
+ VERSION = '7.8.0'
4
4
  end
5
5
  end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 20200731081757) do
13
+ ActiveRecord::Schema.define(version: 20200804191643) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -309,6 +309,7 @@ ActiveRecord::Schema.define(version: 20200731081757) do
309
309
  t.text "theme", default: "{}", null: false
310
310
  t.text "profile", default: "{}", null: false
311
311
  t.integer "progressive_display_lookahead"
312
+ t.boolean "incognito_mode_enabled"
312
313
  t.index ["book_id"], name: "index_organizations_on_book_id"
313
314
  t.index ["name"], name: "index_organizations_on_name", unique: true
314
315
  end
@@ -50,4 +50,21 @@ feature 'Chapters flow', organization_workspace: :test do
50
50
  expect(page).to have_text('endofunctors')
51
51
  end
52
52
  end
53
+
54
+ context 'incognito user' do
55
+ before { Organization.current.update! incognito_mode_enabled: true }
56
+ scenario 'show chapter, no appendix' do
57
+ visit "/chapters/#{chapter.id}"
58
+
59
+ expect(page).to have_text('Functional Programming')
60
+ expect(page).to have_text('The Basic Values')
61
+
62
+ expect(page).to have_text('Monads and Functors')
63
+ expect(page).to have_text('The Maybe Functor')
64
+
65
+ expect(page).to_not have_text('Appendix')
66
+
67
+ expect(page).to have_text('Sign in')
68
+ end
69
+ end
53
70
  end
@@ -13,8 +13,8 @@ feature 'Exercise Flow', organization_workspace: :test do
13
13
  let(:problem_5) { build(:problem, name: 'Succ5', description: 'Description of Succ5', layout: :input_right, editor: :upload, hint: 'lele', language: gobstones) }
14
14
  let(:problem_6) { build(:problem, name: 'Succ6', description: 'Description of Succ6', layout: :input_right, editor: :hidden, language: haskell) }
15
15
  let(:problem_7) { build(:problem, name: 'Succ7', description: 'Description of Succ7', editor: :single_choice, choices: [{value: 'some choice', checked: true}]) }
16
- let(:playground_1) { build(:playground, name: 'Succ5', description: 'Description of Succ4', layout: :input_right) }
17
- let(:playground_2) { build(:playground, name: 'Succ6', description: 'Description of Succ4', layout: :input_right, extra: 'x = 4') }
16
+ let(:playground_1) { build(:playground, name: 'Succ5', description: 'Description of Succ4', layout: :input_bottom) }
17
+ let(:playground_2) { build(:playground, name: 'Succ6', description: 'Description of Succ4', layout: :input_bottom, extra: 'x = 4') }
18
18
  let!(:reading) { build(:reading, name: 'Reading about Succ', description: 'Lets understand succ history') }
19
19
  let!(:exercise_not_in_path) { create :exercise }
20
20
  let(:kids_problem) { build(:problem, name: 'Kids prob', description: 'Description of kids prob', layout: :input_primary, hint: 'lele', language: gobstones) }
@@ -129,6 +129,12 @@ feature 'Exercise Flow', organization_workspace: :test do
129
129
  expect(page).to have_text('Solution')
130
130
  expect(page).to have_text('need a hint?')
131
131
  expect(page).to_not have_selector('.upload')
132
+
133
+ expect(page).to have_selector('#mu-exercise-id', )
134
+ expect(page).to have_selector('#mu-exercise-layout')
135
+
136
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_1.id.to_s)
137
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_right')
132
138
  end
133
139
 
134
140
  scenario 'visit exercise by id, hidden layout, no hint, not queriable language' do
@@ -142,6 +148,9 @@ feature 'Exercise Flow', organization_workspace: :test do
142
148
  expect(page).to_not have_text('Solution')
143
149
  expect(page).to_not have_text('need a hint?')
144
150
  expect(page).to_not have_selector('.upload')
151
+
152
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_2.id.to_s)
153
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_right')
145
154
  end
146
155
 
147
156
  scenario 'visit exercise by id, hidden layout, no hint, queriable language' do
@@ -152,6 +161,9 @@ feature 'Exercise Flow', organization_workspace: :test do
152
161
  expect(page).to_not have_text('Solution')
153
162
  expect(page).to_not have_text('need a hint?')
154
163
  expect(page).to_not have_selector('.upload')
164
+
165
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_6.id.to_s)
166
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_right')
155
167
  end
156
168
 
157
169
 
@@ -163,6 +175,9 @@ feature 'Exercise Flow', organization_workspace: :test do
163
175
  expect(page).to have_text('Solution')
164
176
  expect(page).to have_text('need a hint?')
165
177
  expect(page).to have_selector('.upload')
178
+
179
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_3.id.to_s)
180
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_right')
166
181
  end
167
182
 
168
183
  scenario 'visit exercise by id, upload layout, not queriable language' do
@@ -174,6 +189,9 @@ feature 'Exercise Flow', organization_workspace: :test do
174
189
  expect(page).to have_selector('.upload')
175
190
  expect(problem_5.language.extension).to eq('gbs')
176
191
  expect(page.find("//div[@class = 'form-group']/input")['accept']).to eq(".gbs")
192
+
193
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_5.id.to_s)
194
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_right')
177
195
  end
178
196
 
179
197
  scenario 'visit exercise by id, input_bottom layout, extra, no hint' do
@@ -185,6 +203,9 @@ feature 'Exercise Flow', organization_workspace: :test do
185
203
  expect(page).to have_text('Solution')
186
204
  expect(page).to_not have_text('need a hint?')
187
205
  expect(page).to_not have_selector('.upload')
206
+
207
+ expect(page.find("#mu-exercise-id")['value']).to eq(problem_4.id.to_s)
208
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_bottom')
188
209
  end
189
210
 
190
211
  scenario 'visit playground by id, no extra, no hint' do
@@ -195,6 +216,9 @@ feature 'Exercise Flow', organization_workspace: :test do
195
216
  expect(page).to_not have_text('Solution')
196
217
  expect(page).to_not have_text('need a hint?')
197
218
  expect(page).to_not have_selector('.upload')
219
+
220
+ expect(page.find("#mu-exercise-id")['value']).to eq(playground_1.id.to_s)
221
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_bottom')
198
222
  end
199
223
 
200
224
  scenario 'visit playground by id, with extra, no hint' do
@@ -206,6 +230,9 @@ feature 'Exercise Flow', organization_workspace: :test do
206
230
  expect(page).to_not have_text('need a hint?')
207
231
  expect(page).to have_text('x = 4')
208
232
  expect(page).to_not have_selector('.upload')
233
+
234
+ expect(page.find("#mu-exercise-id")['value']).to eq(playground_2.id.to_s)
235
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_bottom')
209
236
  end
210
237
 
211
238
  scenario 'visit inner reading by id' do
@@ -218,6 +245,9 @@ feature 'Exercise Flow', organization_workspace: :test do
218
245
  expect(page).to_not have_text('Solution')
219
246
  expect(page).to_not have_text('need a hint?')
220
247
  expect(page).to_not have_selector('.upload')
248
+
249
+ expect(page.find("#mu-exercise-id")['value']).to eq(reading.id.to_s)
250
+ expect(page.find("#mu-exercise-layout")['value']).to eq('input_bottom')
221
251
  end
222
252
 
223
253
  scenario 'visit solved choices exercise' do
@@ -246,4 +276,19 @@ feature 'Exercise Flow', organization_workspace: :test do
246
276
  expect(page).to have_xpath("//a[@title='Edit']")
247
277
  end
248
278
  end
279
+
280
+ context 'incognito user' do
281
+ before { Organization.current.update! incognito_mode_enabled: true }
282
+
283
+ scenario 'visit exercise transparently' do
284
+ visit "/exercises/#{problem_1.transparent_id}"
285
+
286
+ expect(page).to have_text('Succ1')
287
+ expect(page).to have_text('Console')
288
+ expect(page).to have_text('need a hint?')
289
+ expect(page).to have_text('Description of Succ1')
290
+
291
+ expect(page).to have_text('Sign in')
292
+ end
293
+ end
249
294
  end
@@ -91,4 +91,20 @@ feature 'public org', organization_workspace: :test do
91
91
  expect(user.reload.last_organization).to eq current_organization
92
92
  end
93
93
  end
94
+
95
+ context 'incognito user' do
96
+ before { current_organization.update! incognito_mode_enabled: true }
97
+ scenario 'from inside' do
98
+ Capybara.current_session.driver.header 'Referer', 'http://google.com'
99
+
100
+ visit '/'
101
+
102
+ expect(page).to have_text('ム mumuki')
103
+ expect(page).to have_text('First Steps')
104
+ expect(page).to have_selector('.chapter', text: 'Functional Programming')
105
+ expect(page).to have_text(current_organization.book.name)
106
+
107
+ expect(page).to have_text('Sign in')
108
+ end
109
+ end
94
110
  end