mumuki-laboratory 9.3.0 → 9.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +15 -0
- data/app/assets/javascripts/mumuki_laboratory/application/faqs.js +6 -6
- data/app/assets/javascripts/mumuki_laboratory/application/toast.js +12 -1
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_discussion.scss +0 -25
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_faqs.scss +4 -3
- data/app/controllers/discussions_controller.rb +29 -2
- data/app/controllers/exam_authorization_requests_controller.rb +7 -1
- data/app/helpers/discussions_helper.rb +26 -2
- data/app/views/discussions/_description_message.html.erb +1 -1
- data/app/views/discussions/_message.html.erb +1 -1
- data/app/views/discussions/_new_message.html.erb +1 -1
- data/app/views/discussions/new.html.erb +1 -1
- data/app/views/discussions/show.html.erb +6 -0
- data/app/views/exam_authorization_requests/_approved.html.erb +1 -1
- data/app/views/exam_authorization_requests/_pending.html.erb +2 -2
- data/app/views/exam_registrations/show.html.erb +3 -2
- data/app/views/exercises/_read_only.html.erb +5 -6
- data/app/views/faqs/index.html.erb +1 -1
- data/app/views/layouts/_discussions.html.erb +3 -3
- data/app/views/layouts/_main.html.erb +4 -10
- data/app/views/layouts/_toast.html.erb +7 -0
- data/app/views/users/activity.html.erb +8 -6
- data/app/views/users/exam_authorizations.html.erb +1 -1
- data/config/routes.rb +2 -0
- data/lib/mumuki/laboratory/locales/en.yml +13 -5
- data/lib/mumuki/laboratory/locales/es-CL.yml +12 -3
- data/lib/mumuki/laboratory/locales/es.yml +12 -4
- data/lib/mumuki/laboratory/locales/pt.yml +12 -4
- data/lib/mumuki/laboratory/version.rb +1 -1
- data/lib/tasks/exams.rake +15 -0
- data/spec/controllers/discussions_controller_spec.rb +42 -0
- data/spec/dummy/db/schema.rb +3 -3
- data/spec/features/discussion_flow_spec.rb +38 -14
- data/spec/features/user_activity_flow_spec.rb +30 -10
- data/spec/helpers/with_navigation_spec.rb +22 -0
- metadata +114 -112
@@ -5,7 +5,7 @@
|
|
5
5
|
<div class="row">
|
6
6
|
<%= render partial: 'layouts/user_menu' %>
|
7
7
|
|
8
|
-
<div class="col-md-9">
|
8
|
+
<div class="col-md-9 mu-tab-body">
|
9
9
|
<div class="mu-user-header">
|
10
10
|
<h1><%= t(:activity) %></h1>
|
11
11
|
</div>
|
@@ -17,11 +17,13 @@
|
|
17
17
|
stats: exercises_activity_stats
|
18
18
|
} %>
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
<% if Organization.current.forum_enabled? %>
|
21
|
+
<%= render partial: 'activity_indicator',
|
22
|
+
locals: {
|
23
|
+
title: t(:forum),
|
24
|
+
stats: messages_activity_stats
|
25
|
+
} %>
|
26
|
+
<% end %>
|
25
27
|
</div>
|
26
28
|
<div class="col-lg-4 mu-tab-body">
|
27
29
|
<div class="nav nav-pills flex-column">
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#<%= "exam_authorization_collapse_item_#{index}" %>" aria-expanded="false" aria-controls="<%= "exam_authorization_collapse_item_#{index}" %>">
|
23
23
|
<span class="fa fa-fw fa-<%= it.icon[:class] %> text-<%= it.icon[:type] %>" data-bs-toggle="tooltip" title="<%= t(it.status).humanize %>"></span>
|
24
24
|
<span class="divider-vertical"></span>
|
25
|
-
<span><strong><%= it.exam_registration.description %></strong> - <small><%= l(it.exam.start_time, format: :long) %></small></span>
|
25
|
+
<span><strong><%= it.exam_registration.description %></strong> - <small><%= l(it.exam.start_time.in_time_zone(-3), format: :long) %></small></span>
|
26
26
|
</button>
|
27
27
|
</h2>
|
28
28
|
<div id="<%= "exam_authorization_collapse_item_#{index}" %>" class="accordion-collapse collapse" aria-labelledby="<%= "exam_authorization_accordion_item_#{index}" %>" data-bs-parent="#exam_authorization_accordion">
|
data/config/routes.rb
CHANGED
@@ -12,6 +12,8 @@ Rails.application.routes.draw do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
post '/discussions/:id/responsible' => 'discussions#responsible', as: :responsible_discussion
|
16
|
+
|
15
17
|
get '/discussions/terms' => 'book_discussions#terms'
|
16
18
|
concerns :debatable, controller: 'book_discussions', only: :index
|
17
19
|
|
@@ -168,7 +168,6 @@ en:
|
|
168
168
|
kids_default_success: You did it great!
|
169
169
|
language: Language
|
170
170
|
last_name: Last Name
|
171
|
-
last_seen: "Seen by %{name}"
|
172
171
|
last_submission_date: Last submission
|
173
172
|
latest_exercises: Latest exercises
|
174
173
|
learning: Learning
|
@@ -186,18 +185,24 @@ en:
|
|
186
185
|
male: Male
|
187
186
|
manual_evaluation_pending: Thanks for submitting your solution! It will be revised by the course teachers soon
|
188
187
|
medal: Medal
|
189
|
-
message_count:
|
190
|
-
one: 1 message
|
191
|
-
other: '%{count} messages'
|
192
188
|
message: Message
|
193
189
|
message_deleted: This message was deleted because it %{motive}, which violates the %{forum_terms}.
|
194
190
|
messages: Messages
|
195
191
|
messages_error: Previous messages are unavailable. Please try again later.
|
196
|
-
moderation: Mentoring
|
197
192
|
messages_pluralized:
|
198
193
|
one: Message
|
199
194
|
other: Messages
|
195
|
+
moderation: Mentoring
|
200
196
|
moderator: Mentor
|
197
|
+
moderator_take_care:
|
198
|
+
i_will: I'll take care of it
|
199
|
+
i_wont: I won't take care of it
|
200
|
+
moderator_is: "%{moderator} is taking care of it"
|
201
|
+
status_changed: The discussion status changed. Please refresh the page.
|
202
|
+
someone_else_will: Someone else already marked they'll take care of it.
|
203
|
+
you_are: You're taking care of it
|
204
|
+
you_will_confirmation: You'll take care of this discussion. If you change your mind, click the button again.
|
205
|
+
you_wont_confirmation: You won't take care of this discussion.
|
201
206
|
more_messages: More
|
202
207
|
my_account: My account
|
203
208
|
my_doubts: My doubts
|
@@ -255,6 +260,9 @@ en:
|
|
255
260
|
progress: Progresss
|
256
261
|
read: Read
|
257
262
|
refresh_or_wait: Please press F5 if results are not displayed after a few seconds
|
263
|
+
reply_count:
|
264
|
+
one: 1 reply
|
265
|
+
other: '%{count} replies'
|
258
266
|
requires_attention: Requires attention
|
259
267
|
reset_query: Clear current search filters
|
260
268
|
responses_count_asc: By less validated replies
|
@@ -186,9 +186,6 @@ es-CL:
|
|
186
186
|
male: Hombre
|
187
187
|
manual_evaluation_pending: ¡Gracias por enviar tu solución! Tus docentes la corregirán pronto
|
188
188
|
medal: Medalla
|
189
|
-
message_count:
|
190
|
-
one: 1 mensaje
|
191
|
-
other: '%{count} mensajes'
|
192
189
|
message: Mensaje
|
193
190
|
message_deleted: Este mensaje fue eliminado porque %{motive}, lo cual infringe las %{forum_terms}.
|
194
191
|
messages: Mensajes
|
@@ -200,6 +197,15 @@ es-CL:
|
|
200
197
|
minutes: minutos
|
201
198
|
moderation: Mentoría
|
202
199
|
moderator: Mentor
|
200
|
+
moderator_take_care:
|
201
|
+
i_will: Yo me ocupo
|
202
|
+
i_wont: Mejor no me ocupo
|
203
|
+
moderator_is: "%{moderator} se está ocupando"
|
204
|
+
status_changed: La consulta cambió de estado. Por favor, actualiza la página.
|
205
|
+
someone_else_will: Alguien más ya marcó que se va a ocupar.
|
206
|
+
you_are: Te estás ocupando
|
207
|
+
you_will_confirmation: Te vas a ocupar de esta consulta. Si cambias de parecer, toca nuevamente el botón.
|
208
|
+
you_wont_confirmation: No te vas a ocupar de esta consulta.
|
203
209
|
more_messages: Ver mensajes anteriores
|
204
210
|
my_account: Mi cuenta
|
205
211
|
my_doubts: Mis consultas
|
@@ -262,6 +268,9 @@ es-CL:
|
|
262
268
|
read: Leído
|
263
269
|
read_messages: Ver mensajes
|
264
270
|
refresh_or_wait: Si no se muestra automáticamente en unos segundos, presiona F5
|
271
|
+
reply_count:
|
272
|
+
one: 1 respuesta
|
273
|
+
other: '%{count} respuestas'
|
265
274
|
reset_query: Borrar los filtros de búsqueda actuales
|
266
275
|
restart: Reiniciar
|
267
276
|
results_hidden: ¡Tu solución fue enviada con éxito!
|
@@ -179,7 +179,6 @@ es:
|
|
179
179
|
language: Lenguaje
|
180
180
|
languages: Lenguajes
|
181
181
|
last_name: Apellido
|
182
|
-
last_seen: "Visto por %{name}"
|
183
182
|
last_submission_date: Última solución
|
184
183
|
latest_exercises: Últimos ejercicios
|
185
184
|
learning: Aprendizaje
|
@@ -197,9 +196,6 @@ es:
|
|
197
196
|
male: Hombre
|
198
197
|
manual_evaluation_pending: ¡Gracias por enviar tu solución! Tus docentes la corregirán pronto
|
199
198
|
medal: Medalla
|
200
|
-
message_count:
|
201
|
-
one: 1 mensaje
|
202
|
-
other: '%{count} mensajes'
|
203
199
|
message: Mensaje
|
204
200
|
message_deleted: Este mensaje fue eliminado porque %{motive}, lo cual infringe las %{forum_terms}.
|
205
201
|
messages: Mensajes
|
@@ -211,6 +207,15 @@ es:
|
|
211
207
|
minutes: minutos
|
212
208
|
moderation: Mentoría
|
213
209
|
moderator: Mentor
|
210
|
+
moderator_take_care:
|
211
|
+
i_will: Yo me ocupo
|
212
|
+
i_wont: Mejor no me ocupo
|
213
|
+
moderator_is: "%{moderator} se está ocupando"
|
214
|
+
status_changed: La consulta cambió de estado. Por favor, actualizá la página.
|
215
|
+
someone_else_will: Alguien más ya marcó que se va a ocupar.
|
216
|
+
you_are: Te estás ocupando
|
217
|
+
you_will_confirmation: Te vas a ocupar de esta consulta. Si cambiás de parecer, tocá nuevamente el botón.
|
218
|
+
you_wont_confirmation: No te vas a ocupar de esta consulta.
|
214
219
|
more_messages: Ver mensajes anteriores
|
215
220
|
my_account: Mi cuenta
|
216
221
|
my_doubts: Mis consultas
|
@@ -274,6 +279,9 @@ es:
|
|
274
279
|
read: Leido
|
275
280
|
read_messages: Ver mensajes
|
276
281
|
refresh_or_wait: Si no se muestra automáticamente en unos segundos, presioná F5
|
282
|
+
reply_count:
|
283
|
+
one: 1 respuesta
|
284
|
+
other: '%{count} respuestas'
|
277
285
|
requires_attention: Requiere atención
|
278
286
|
reset_query: Borrar los filtros de búsqueda actuales
|
279
287
|
responses_count_asc: Con menos respuestas validadas
|
@@ -172,7 +172,6 @@ pt:
|
|
172
172
|
language: Linguagem
|
173
173
|
languages: Linguagens
|
174
174
|
last_name: Sobrenome
|
175
|
-
last_seen: "Visto por %{name}"
|
176
175
|
last_submission_date: Última solução
|
177
176
|
latest_exercises: Últimos exercícios
|
178
177
|
learning: Aprendendo
|
@@ -190,9 +189,6 @@ pt:
|
|
190
189
|
male: Masculino
|
191
190
|
manual_evaluation_pending: Obrigado por enviar sua solução! Seus professores irão corrigi-lo em breve
|
192
191
|
medal: Medalha
|
193
|
-
message_count:
|
194
|
-
one: 1 mensagem
|
195
|
-
other: '%{count} mensagens'
|
196
192
|
message: Mensagem
|
197
193
|
message_deleted: Esta mensagem foi excluída porque %{motive}, o que viola as %{forum_terms}.
|
198
194
|
messages: Mensagens
|
@@ -205,6 +201,15 @@ pt:
|
|
205
201
|
minutes: minutos
|
206
202
|
moderation: Mentoria
|
207
203
|
moderator: Mentor
|
204
|
+
moderator_take_care:
|
205
|
+
i_will: Eu cuidarei disso
|
206
|
+
i_wont: Eu não vou cuidar
|
207
|
+
moderator_is: "%{moderator} está cuidando"
|
208
|
+
status_changed: A consulta mudou de estado. Por favor, atualize para ver a consulta atualizada.
|
209
|
+
someone_else_will: Alguém já marcou que vai cuidar disso.
|
210
|
+
you_are: Você está cuidando
|
211
|
+
you_will_confirmation: Você vai cuidar dessa consulta. Se mudar de ideia, clique no botão novamente.
|
212
|
+
you_wont_confirmation: Você não vai cuidar dessa consulta.
|
208
213
|
more_messages: Ver as mensagens anteriores
|
209
214
|
my_account: Minha conta
|
210
215
|
my_doubts: Minhas duvidas
|
@@ -265,6 +270,9 @@ pt:
|
|
265
270
|
read: Ler
|
266
271
|
read_messages: Ver mensagens
|
267
272
|
refresh_or_wait: Se não mostrar automaticamente em alguns segundos, pressione F5
|
273
|
+
reply_count:
|
274
|
+
one: 1 resposta
|
275
|
+
other: '%{count} respostas'
|
268
276
|
requires_attention: Requer atenção
|
269
277
|
reset_query: Limpar filtros de pesquisa atuais
|
270
278
|
restart: Reiniciar
|
@@ -0,0 +1,15 @@
|
|
1
|
+
logger = ::Logger.new(STDOUT)
|
2
|
+
|
3
|
+
namespace :laboratory do
|
4
|
+
namespace :exams do
|
5
|
+
task authorize_requests: :environment do
|
6
|
+
logger.info "Exam Authorization Requests task"
|
7
|
+
ExamRegistration.should_process.find_each do |exam_registration|
|
8
|
+
logger.info "Processing exam registration '#{exam_registration.description}'"
|
9
|
+
exam_registration.process_requests!
|
10
|
+
rescue
|
11
|
+
logger.error "Something wrong happened while processing '#{exam_registration.description}'"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -62,6 +62,48 @@ describe DiscussionsController, organization_workspace: :test do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
describe 'responsible' do
|
66
|
+
let(:discussion) { create(:discussion, {organization: Organization.current}) }
|
67
|
+
|
68
|
+
describe 'user wants to be responsible' do
|
69
|
+
before { post :responsible, params: {id: discussion.id} }
|
70
|
+
|
71
|
+
it { expect(response.status).to eq 403 }
|
72
|
+
it { expect(discussion.reload.responsible? user).to be false }
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'moderator' do
|
76
|
+
let(:moderator) { create(:user, permissions: {student: '*', moderator: '*'}) }
|
77
|
+
before { set_current_user! moderator }
|
78
|
+
|
79
|
+
describe 'wants to be responsible' do
|
80
|
+
before { post :responsible, params: {id: discussion.id} }
|
81
|
+
|
82
|
+
it { expect(response.status).to eq 200 }
|
83
|
+
it { expect(discussion.reload.responsible? moderator).to be true }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'wants to be responsible but changes their mind' do
|
87
|
+
before { 2.times{ post :responsible, params: {id: discussion.id} } }
|
88
|
+
|
89
|
+
it { expect(response.status).to eq 200 }
|
90
|
+
it { expect(discussion.reload.responsible? moderator).to be false }
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'wants to be responsible but someone else already is' do
|
94
|
+
let(:another_moderator) { create(:user, permissions: {student: '*', moderator: '*'}) }
|
95
|
+
before do
|
96
|
+
discussion.toggle_responsible! another_moderator
|
97
|
+
post :responsible, params: {id: discussion.id}
|
98
|
+
end
|
99
|
+
|
100
|
+
it { expect(response.status).to eq 409 }
|
101
|
+
it { expect(discussion.reload.responsible? moderator).to be false }
|
102
|
+
it { expect(discussion.reload.responsible? another_moderator).to be true }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
65
107
|
describe 'when the minimal role for discussions is teacher' do
|
66
108
|
before { Organization.current.tap { |it| it.forum_discussions_minimal_role = 'teacher' }.save! }
|
67
109
|
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -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:
|
13
|
+
ActiveRecord::Schema.define(version: 20210518100153) do
|
14
14
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
16
16
|
enable_extension "plpgsql"
|
@@ -151,8 +151,8 @@ ActiveRecord::Schema.define(version: 20210330175706) do
|
|
151
151
|
t.integer "messages_count", default: 0
|
152
152
|
t.integer "validated_messages_count", default: 0
|
153
153
|
t.boolean "requires_moderator_response", default: true
|
154
|
-
t.string "
|
155
|
-
t.datetime "
|
154
|
+
t.string "responsible_moderator_by_id"
|
155
|
+
t.datetime "responsible_moderator_at"
|
156
156
|
t.bigint "status_updated_by_id"
|
157
157
|
t.datetime "status_updated_at"
|
158
158
|
t.index ["initiator_id"], name: "index_discussions_on_initiator_id"
|
@@ -174,6 +174,7 @@ feature 'Discussion Flow', organization_workspace: :test do
|
|
174
174
|
expect(page).to have_text(problem_2.name)
|
175
175
|
expect(page).to have_text('Open')
|
176
176
|
expect(page).to have_text('Messages')
|
177
|
+
expect(page).to_not have_text('I\'ll take care')
|
177
178
|
expect(page).not_to have_text('Preview')
|
178
179
|
expect(page).to have_text(problem_2_discussion_message.content)
|
179
180
|
expect(page).not_to have_text(another_problem_2_discussion_message.content)
|
@@ -188,20 +189,43 @@ feature 'Discussion Flow', organization_workspace: :test do
|
|
188
189
|
context 'for moderator' do
|
189
190
|
before { set_current_user! moderator }
|
190
191
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
192
|
+
context 'on a newly created discussion' do
|
193
|
+
scenario do
|
194
|
+
visit current_path
|
195
|
+
expect(page).to have_text(problem_2.name)
|
196
|
+
expect(page).to have_text('Open')
|
197
|
+
expect(page).to have_text('Messages')
|
198
|
+
expect(page).to have_text('I\'ll take care')
|
199
|
+
expect(page).to have_text('Preview')
|
200
|
+
expect(page).to have_text(problem_2_discussion_message.content)
|
201
|
+
expect(page).to have_text(another_problem_2_discussion_message.content)
|
202
|
+
expect(page).to have_xpath("//div[@class='discussion-actions']")
|
203
|
+
expect(page).to have_text('Includes inappropriate content')
|
204
|
+
expect(page).to have_text('Shares the correct solution')
|
205
|
+
expect(page).to have_text('Discloses personal information')
|
206
|
+
expect(page).to have_text('included inappropriate content')
|
207
|
+
expect(page).to have_text ("Deleted by #{moderator.name}")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'on a discussion where they are responsible' do
|
212
|
+
before { problem_2_discussions.first.toggle_responsible! moderator }
|
213
|
+
|
214
|
+
scenario do
|
215
|
+
visit current_path
|
216
|
+
expect(page).to have_text('I won\'t take care')
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'on a discussion where someone else is responsible' do
|
221
|
+
let(:another_moderator) { create(:user, permissions: {moderator: '*', student: '*'}) }
|
222
|
+
before { problem_2_discussions.first.toggle_responsible! another_moderator }
|
223
|
+
|
224
|
+
scenario do
|
225
|
+
visit current_path
|
226
|
+
expect(page).not_to have_text('I\'ll take care')
|
227
|
+
expect(page).not_to have_text('I won\'t take care')
|
228
|
+
end
|
205
229
|
end
|
206
230
|
end
|
207
231
|
end
|
@@ -2,6 +2,8 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
feature 'User Activity Flow', organization_workspace: :test do
|
4
4
|
let(:user) { create(:user) }
|
5
|
+
let(:organization) { Organization.locate!('test') }
|
6
|
+
|
5
7
|
before { set_current_user!(user) }
|
6
8
|
|
7
9
|
let(:fake_stats) { double('stats') }
|
@@ -30,21 +32,39 @@ feature 'User Activity Flow', organization_workspace: :test do
|
|
30
32
|
expect(page).to have_text('solved')
|
31
33
|
end
|
32
34
|
|
33
|
-
scenario 'displays messages count' do
|
34
|
-
expect(page).to have_text('12')
|
35
|
-
expect(page).to have_text('messages')
|
36
|
-
end
|
37
|
-
|
38
|
-
scenario 'displays validated messages count' do
|
39
|
-
expect(page).to have_text('6')
|
40
|
-
expect(page).to have_text('validated')
|
41
|
-
end
|
42
|
-
|
43
35
|
scenario 'displays recent weeks' do
|
44
36
|
expect(page).to have_text 'Week of 2020-10-12'
|
45
37
|
expect(page).to have_text 'Week of 2020-10-05'
|
46
38
|
expect(page).to have_text 'Week of 2020-09-28'
|
47
39
|
end
|
40
|
+
|
41
|
+
context 'on organization with no forum' do
|
42
|
+
scenario 'does not display messages count' do
|
43
|
+
expect(page).to_not have_text('messages')
|
44
|
+
end
|
45
|
+
|
46
|
+
scenario 'does not display validated messages count' do
|
47
|
+
expect(page).to_not have_text('validated')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'on organization with forum' do
|
52
|
+
before do
|
53
|
+
organization.update! forum_enabled: true
|
54
|
+
visit activity_user_path
|
55
|
+
end
|
56
|
+
|
57
|
+
scenario 'displays messages count' do
|
58
|
+
expect(page).to have_text('12')
|
59
|
+
expect(page).to have_text('messages')
|
60
|
+
end
|
61
|
+
|
62
|
+
scenario 'displays validated messages count' do
|
63
|
+
expect(page).to have_text('6')
|
64
|
+
expect(page).to have_text('validated')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
48
68
|
end
|
49
69
|
|
50
70
|
context 'selecting a specific week' do
|