Skip to content

Commit bb64fb8

Browse files
committed
[ft] Add buttons to trigger exportation and importations
* Create the export url action handler * Implement export and import workouts functionality * Test export and import workouts functions * Resolve flake8 errors * Remove unused modules * Remove unnecessary blank lines * Correct imports and structure of the try statements [Delivers #159236209]
1 parent 99991de commit bb64fb8

File tree

4 files changed

+441
-1
lines changed

4 files changed

+441
-1
lines changed

wger/manager/templates/workout/overview.html

+42
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,48 @@ <h4 class="list-group-item-heading">{{ workout }}</h4>
3636
{% endblock %}
3737

3838

39+
<!--
40+
Side bar
41+
-->
42+
{% block sidebar %}
43+
<h4>{% trans "Export Workouts" %}</h4>
44+
<div class="row">
45+
<div class="col-sm-3">
46+
{% if workouts|length < 1 %}
47+
<button class="btn btn-success" disabled type="button" >
48+
Export
49+
</button>
50+
{% else %}
51+
<a href="{% url 'manager:workout:export'%}">
52+
<button class="btn btn-success" type="button">
53+
Export
54+
</button>
55+
</a>
56+
{% endif %}
57+
</div>
58+
</div>
59+
60+
<br/>
61+
<h4>{% trans "Import Workouts" %}</h4>
62+
<form class="form-inline" method="post" enctype="multipart/form-data">
63+
{% csrf_token %}
64+
<div class="row">
65+
<div class="col-sm-3">
66+
<input class="btn btn-success form-control" value="Import" type="submit" />
67+
</div>
68+
69+
<div class="col-sm-9">
70+
<input type="file" name="workoutfile" class="form-control" accept=".json" />
71+
</div>
72+
</div>
73+
</form>
74+
75+
{% if messages %}
76+
<div class="alert alert-{{ message.tags }}">{{ message }}</div>
77+
{% endif %}
78+
79+
{% endblock %}
80+
3981
{% block options %}
4082
<div class="dropdown">
4183
<button class="btn btn-success dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">

wger/manager/tests/test_workout.py

+202
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
from wger.core.tests.base_testcase import WorkoutManagerEditTestCase
2222
from wger.core.tests.base_testcase import WorkoutManagerTestCase
2323
from wger.manager.models import Workout
24+
from wger.manager.views.workout import export_user_workouts
25+
import tempfile
26+
from django.contrib.messages import get_messages
2427

2528

2629
class WorkoutShareButtonTestCase(WorkoutManagerTestCase):
@@ -124,6 +127,205 @@ def test_create_workout_logged_in(self):
124127
self.user_logout()
125128

126129

130+
class ExportWorkoutTestCase(WorkoutManagerTestCase):
131+
'''
132+
Tests adding a Workout
133+
'''
134+
135+
def create_workout(self):
136+
'''
137+
Helper function to test creating workouts
138+
'''
139+
140+
# Create a workout
141+
count_before = Workout.objects.count()
142+
response = self.client.get(reverse('manager:workout:add'))
143+
count_after = Workout.objects.count()
144+
145+
# There is always a redirect
146+
self.assertEqual(response.status_code, 302)
147+
148+
# Test creating workout
149+
self.assertGreater(count_after, count_before)
150+
151+
# Test accessing workout
152+
response = self.client.get(
153+
reverse('manager:workout:view', kwargs={'pk': 1}))
154+
155+
workout = Workout.objects.get(pk=1)
156+
self.assertEqual(response.context['workout'], workout)
157+
self.assertEqual(response.status_code, 200)
158+
159+
def export_workouts(self):
160+
'''
161+
Helper function to test exporting workouts
162+
'''
163+
164+
# Export workout(s)
165+
response = self.client.get(reverse('manager:workout:export'))
166+
self.assertEqual(response.status_code, 200)
167+
168+
def test_export_workout_logged_in(self):
169+
'''
170+
Test creating a workout a logged in user
171+
'''
172+
173+
self.user_login()
174+
self.create_workout()
175+
self.export_workouts()
176+
self.user_logout()
177+
178+
179+
class ImportWorkoutTestCase(WorkoutManagerTestCase):
180+
'''
181+
Tests Importing Workout(s)
182+
'''
183+
184+
def import_workouts(self):
185+
'''
186+
Helper function to test importing workouts
187+
'''
188+
workout = [
189+
{
190+
"id": 1,
191+
"cycle_kind": "microcycle",
192+
"comment": "",
193+
"creation_date": "2018-08-27",
194+
"day": [
195+
{
196+
"id": 46,
197+
"description": "Run through the amazon",
198+
"daysofweek": [{"dayofweek": 1}],
199+
"sets": [
200+
{
201+
"id": 20,
202+
"sets": 4,
203+
"order": 1,
204+
"exercises": [
205+
{
206+
"id": 269,
207+
"license_author": "foguinho.peruca",
208+
"status": "2",
209+
"description": "<p>Run on a treadmill</p>",
210+
"name": "Run - treadmill",
211+
"creation_date": "2014-09-03",
212+
"uuid": "51d56238-31a1-4e5a-b747-da30eece4871",
213+
"category": 9,
214+
"muscles": [],
215+
"muscles_secondary": [],
216+
"equipment": [],
217+
"settings": [
218+
{
219+
"reps": 5,
220+
"order": 1,
221+
"comment": "",
222+
"weight": "1.00",
223+
"repetition_unit_id": 6,
224+
"weight_unit_id": 6
225+
},
226+
{
227+
"reps": 5,
228+
"order": 1,
229+
"comment": "",
230+
"weight": "1.00",
231+
"repetition_unit_id": 6,
232+
"weight_unit_id": 6
233+
},
234+
{
235+
"reps": 5,
236+
"order": 1,
237+
"comment": "",
238+
"weight": "1.00",
239+
"repetition_unit_id": 6,
240+
"weight_unit_id": 6
241+
},
242+
{
243+
"reps": 5,
244+
"order": 1,
245+
"comment": "",
246+
"weight": "1.00",
247+
"repetition_unit_id": 6,
248+
"weight_unit_id": 6
249+
}
250+
]
251+
}
252+
]
253+
}
254+
]
255+
}
256+
]
257+
}
258+
]
259+
260+
tmp_file = tempfile.NamedTemporaryFile(suffix='.json')
261+
with open(tmp_file.name, 'w') as f:
262+
f.write(str(workout))
263+
264+
response = self.client.post(
265+
reverse('manager:workout:overview'),
266+
{'workoutfile': tmp_file},
267+
format='multipart'
268+
)
269+
self.assertEqual(302, response.status_code)
270+
271+
def test_import_workout_logged_in(self):
272+
'''
273+
Test importing workout(s) with a logged in user
274+
'''
275+
276+
self.user_login()
277+
self.import_workouts()
278+
self.user_logout()
279+
280+
def test_import_workout_logged_in_without_json_file(self):
281+
'''
282+
Test importing workout(s) with a logged in user without json file
283+
'''
284+
285+
self.user_login()
286+
response = self.client.post(reverse('manager:workout:overview'))
287+
288+
self.assertEqual(response.status_code, 302)
289+
self.assertRedirects(response, '/en/workout/overview')
290+
291+
all_messages = [msg for msg in get_messages(response.wsgi_request)]
292+
293+
# here's how you test the first message
294+
self.assertEqual(all_messages[0].tags, "info")
295+
self.assertEqual(all_messages[0].message, "No File was Chosen for Importation!")
296+
self.user_logout()
297+
298+
def test_import_workout_logged_in_invalid_json(self):
299+
300+
self.user_login()
301+
302+
incorrect_json_data = [
303+
{
304+
"id": 1,
305+
"cycle_kind": "microcycle",
306+
"comment": "",
307+
"creation_date": "2018-08-27",
308+
"day": [
309+
],
310+
}
311+
]
312+
tmp_file = tempfile.NamedTemporaryFile(suffix='.json')
313+
with open(tmp_file.name, 'w') as f:
314+
f.write(str(incorrect_json_data))
315+
316+
response = self.client.post(
317+
reverse('manager:workout:overview'),
318+
{'workoutfile': tmp_file},
319+
format='multipart'
320+
)
321+
all_messages = [msg for msg in get_messages(response.wsgi_request)]
322+
323+
# here's how you test the first message
324+
self.assertEqual(all_messages[0].tags, "info")
325+
self.assertEqual(all_messages[0].message, "The Workout JSON file is invalid.")
326+
self.user_logout()
327+
328+
127329
class DeleteTestWorkoutTestCase(WorkoutManagerDeleteTestCase):
128330
'''
129331
Tests deleting a Workout

wger/manager/urls.py

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
url(r'^overview$',
5050
workout.overview,
5151
name='overview'),
52+
url(r'^export/$',
53+
workout.export_user_workouts,
54+
name='export'),
5255
url(r'^add$',
5356
workout.add,
5457
name='add'),

0 commit comments

Comments
 (0)