Commit ca4c23b6 authored by Einar Uvsløkk's avatar Einar Uvsløkk
Browse files

Add test cases for workout-list and workout-detail

Note: The test for adding workout files is not working. Need to figure
out how to properly include files in the payload.
parent 84002421
[
{
"model": "workouts.exercise",
"pk": 1,
"fields": {
"name": "Foo",
"description": "Do a foo forever.",
"unit": "reps"
}
},
{
"model": "workouts.exercise",
"pk": 2,
"fields": {
"name": "Bar",
"description": "Try to lift the bar as high as possible.",
"unit": "reps"
}
},
{
"model": "workouts.exercise",
"pk": 3,
"fields": {
"name": "Baz",
"description": "Nobody quite knows what this is all about.",
"unit": "reps"
}
}
]
[
{
"model": "users.user",
"pk": 1,
"fields": {
"username": "arya",
"email": "arya@stark.io",
"password": "pbkdf2_sha256$216000$glNd7zmKsCPk$Et1Wg9R1857TSb3eiaV6p4OZKi46AEwupcix2pAIS+I=",
"coach": 1
}
}
]
[
{
"model": "workouts.workout",
"pk": 1,
"fields": {
"name": "Test workout",
"date": "2021-04-15T18:49:43.00000Z",
"notes": "Notes for Test workout",
"visibility": "PU",
"owner": 1
}
},
{
"model": "workouts.exerciseinstance",
"pk": 1,
"fields": {
"workout": 1,
"exercise": 1,
"sets": 3,
"number": 8
}
},
{
"model": "workouts.exerciseinstance",
"pk": 2,
"fields": {
"workout": 1,
"exercise": 2,
"sets": 3,
"number": 8
}
}
]
import json
import pathlib
import unittest
from dataclasses import dataclass
from datetime import datetime
from django.contrib.auth import get_user_model
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APIClient
from rest_framework.test import APIRequestFactory
from rest_framework.test import APITestCase
from workouts.models import Workout
from workouts.serializers import WorkoutSerializer
here = pathlib.Path(__file__).parent.resolve()
data_dir = here / "data"
@dataclass
class LoginData(dict):
username: str
password: str
test_user = LoginData("arya", "dOnOtCaLlMeMiLaDy")
def user_factory(user: LoginData):
return get_user_model().objects.get(username=user.username)
def exercise_instance_factory(pk, sets=3, number=8):
return dict(
exercise=reverse("exercise-detail", kwargs=dict(pk=pk)),
sets=sets,
number=number,
)
def workout_data_factory(name, *exercise_pks):
return dict(
name=name,
date=datetime.now().isoformat(),
notes=f"Notes for {name}",
visibility=Workout.PUBLIC,
exercise_instances=[exercise_instance_factory(pk) for pk in exercise_pks],
)
def create_payload(data):
"""Returns a proper workout payload for a request."""
data["exercise_instances"] = json.dumps(data["exercise_instances"])
return data
class WorkoutListTest(TestCase):
"""Test case for the WorkoutList view class."""
fixtures = [
data_dir / "users.json",
data_dir / "exercises.json",
]
def setUp(self):
self.user = user_factory(test_user)
self.client = APIClient()
@property
def url(self):
return reverse("workout-list")
def test_get(self):
"""Test GET request on the WorkoutList view."""
self.client.force_authenticate(self.user)
response = self.client.get(self.url)
data = response.json()
self.assertTrue(status.is_success(response.status_code))
self.assertEqual(data["count"], 0)
self.assertEqual(data["results"], [])
def test_post(self):
"""Test that a new workout is added with a POST request."""
self.client.force_authenticate(self.user)
workout_name = "Test workout"
workout_data = workout_data_factory(workout_name, 1)
response = self.client.post(
self.url,
create_payload(workout_data),
format="multipart",
)
self.assertTrue(status.is_success(response.status_code))
response_data = response.json()
self.assertEqual(response_data["id"], 1)
self.assertEqual(response_data["name"], workout_name)
self.assertEqual(len(response_data["exercise_instances"]), 1)
class WorkoutDetailTest(APITestCase):
"""Test case for the workout-detail view."""
fixtures = [
data_dir / "users.json",
data_dir / "exercises.json",
data_dir / "workouts.json",
]
def setUp(self):
self.user = user_factory(test_user)
self.client = APIClient()
self.client.force_authenticate(self.user)
self.factory = APIRequestFactory()
self.context = dict(request=self.factory.get("/"))
def url(self, pk):
return reverse("workout-detail", kwargs=dict(pk=pk))
def put(self, workout_id, data):
"""Returns the response from a PUT request on a workout resource."""
return self.client.put(
self.url(workout_id),
create_payload(data),
format="multipart",
)
def serialize(self, workout):
"""Returns serialized data for a workout."""
serializer = WorkoutSerializer(instance=workout, context=self.context)
return serializer.data
def test_get_workout(self):
"""Tests that a workout is retrived."""
self.client.force_authenticate(self.user)
response = self.client.get(self.url(1))
self.assertTrue(status.is_success(response.status_code))
response_data = response.json()
self.assertEqual(response_data["id"], 1)
self.assertEqual(response_data["name"], "Test workout")
self.assertEqual(len(response_data["exercise_instances"]), 2)
def test_update_workout(self):
"""Tests that a workout is updated."""
self.client.force_authenticate(self.user)
workout = Workout.objects.get(pk=1)
data = self.serialize(workout)
data["name"] = "New workout name"
response = self.put(1, data)
response_data = response.json()
self.assertTrue(status.is_success(response.status_code))
self.assertNotEqual(response_data["name"], "Test workout")
self.assertEqual(response_data["name"], "New workout name")
def test_update_workout_add_exercise(self):
"""Tests that an exercise instance is added to a workout."""
self.client.force_authenticate(self.user)
workout = Workout.objects.get(pk=1)
data = self.serialize(workout)
self.assertEqual(len(workout.exercise_instances.all()), 2)
exercise = exercise_instance_factory(3)
data["exercise_instances"].append(exercise)
response = self.put(1, data)
response_data = response.json()
self.assertTrue(status.is_success(response.status_code))
self.assertEqual(len(response_data["exercise_instances"]), 3)
def test_update_workout_remove_exercise(self):
"""Test that an exercise instance is removed from a workout."""
self.client.force_authenticate(self.user)
workout = Workout.objects.get(pk=1)
data = self.serialize(workout)
self.assertEqual(len(workout.exercise_instances.all()), 2)
exercise_instance = data["exercise_instances"].pop()
self.assertEqual(exercise_instance.get("id"), 2)
response = self.put(1, data)
response_data = response.json()
self.assertTrue(status.is_success(response.status_code))
self.assertEqual(len(response_data["exercise_instances"]), 1)
@unittest.skip("Need to figure out how to include files in the payload.")
def test_update_workout_add_files(self):
"""Tests that a file is added to a workout."""
self.client.force_authenticate(self.user)
workout = Workout.objects.get(pk=1)
data = self.serialize(workout)
file_path = data_dir / "test-file.txt"
file_obj = SimpleUploadedFile(
file_path.name,
File(open(file_path, "rb")).read(),
content_type="multipart/form-data",
)
data["files"].append(dict(file=file_obj))
dump_data(data, "Raw Payload Data")
response = self.put(1, data)
# XXX Alternative using the APIRequestFactory
# view = WorkoutDetail.as_view()
# request = self.factory.put(
# self.url(1), create_payload(data), format="multipart"
# )
# force_authenticate(request, self.user)
# response = view(request, pk=1)
dump_data(response.data, "Response data")
self.assertTrue(status.is_success(response.status_code))
self.assertEqual(len(response.data["files"]), len(data["files"]))
def test_delete_workout(self):
"""Tests that a workout is deleted."""
self.client.force_authenticate(self.user)
response = self.client.delete(self.url(1))
self.assertTrue(status.is_success(response.status_code))
workouts = Workout.objects.all()
self.assertListEqual(list(workouts), list())
def dump_data(data, name=None):
from pprint import pprint
line = "-" * 50
print("\n" + line)
if name:
print(name)
pprint(data)
print(line + "\n")
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment