Skip to content

Commit

Permalink
Merge pull request City-of-Helsinki#46 from suutari-ai/enforcement-op…
Browse files Browse the repository at this point in the history
…erators

api/enforcement: Add endpoint for operators
  • Loading branch information
suutari-ai authored Dec 12, 2017
2 parents e79bcf4 + 4716c3b commit 0100975
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 1 deletion.
22 changes: 22 additions & 0 deletions parkings/api/enforcement/operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from rest_framework import permissions, serializers, viewsets

from ...authentication import ApiKeyAuthentication
from ...models import Operator


class OperatorSerializer(serializers.ModelSerializer):
class Meta:
model = Operator
fields = [
'id',
'created_at',
'modified_at',
'name',
]


class OperatorViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Operator.objects.order_by('name')
serializer_class = OperatorSerializer
authentication_classes = [ApiKeyAuthentication]
permission_classes = [permissions.IsAdminUser]
2 changes: 2 additions & 0 deletions parkings/api/enforcement/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.conf.urls import include, url
from rest_framework.routers import DefaultRouter

from .operator import OperatorViewSet
from .valid_parking import ValidParkingViewSet

router = DefaultRouter()
router.register('operator', OperatorViewSet, base_name='operator')
router.register('valid_parking', ValidParkingViewSet,
base_name='valid_parking')

Expand Down
1 change: 1 addition & 0 deletions parkings/api/enforcement/valid_parking.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Meta:
'time_start',
'time_end',
'zone',
'operator',
'operator_name',
]

Expand Down
71 changes: 71 additions & 0 deletions parkings/tests/api/enforcement/test_operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import pytest
from django.core.urlresolvers import reverse
from rest_framework.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN

from parkings.models import Operator

from ..utils import ALL_METHODS, check_list_endpoint_base_fields, check_method_status_codes, get

list_url = reverse('enforcement:v1:operator-list')


def get_url(kind, operator):
if kind == 'list':
return list_url
elif kind == 'detail':
return reverse('enforcement:v1:operator-detail',
kwargs={'pk': operator.pk})


ALL_URL_KINDS = ['list', 'detail']


@pytest.mark.parametrize('url_kind', ALL_URL_KINDS)
def test_permission_checks(api_client, operator_api_client, operator, url_kind):
url = get_url(url_kind, operator)
check_method_status_codes(
api_client, [url], ALL_METHODS, HTTP_401_UNAUTHORIZED)
check_method_status_codes(
operator_api_client, [url], ALL_METHODS, HTTP_403_FORBIDDEN,
error_code='permission_denied')


@pytest.mark.parametrize('url_kind', ALL_URL_KINDS)
def test_disallowed_methods(staff_api_client, operator, url_kind):
url = get_url(url_kind, operator)
disallowed_methods = ('post', 'put', 'patch', 'delete')
check_method_status_codes(
staff_api_client, [url], disallowed_methods, 405)


def test_list_endpoint_base_fields(staff_api_client):
operator_data = get(staff_api_client, list_url)
check_list_endpoint_base_fields(operator_data)


def test_list_endpoint_data(staff_api_client, operator):
assert Operator.objects.count() == 1
data = get(staff_api_client, list_url)
assert len(data['results']) == 1
operator_data = data['results'][0]
check_operator_data_keys(operator_data)
check_operator_data_matches_operator_object(data['results'][0], operator)


def check_operator_data_keys(operator_data):
assert set(operator_data.keys()) == {
'id', 'created_at', 'modified_at', 'name'}


def check_operator_data_matches_operator_object(operator_data, operator_obj):
"""
Check that a operator data dict and an actual Operator object match.
"""
assert operator_data['id'] == str(operator_obj.id) # UUID -> str
assert operator_data['created_at'] == iso8601_us(operator_obj.created_at)
assert operator_data['modified_at'] == iso8601_us(operator_obj.modified_at)
assert operator_data['name'] == operator_obj.name


def iso8601_us(dt):
return dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
3 changes: 2 additions & 1 deletion parkings/tests/api/enforcement/test_valid_parking.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def check_parking_data_keys(parking_data):
'id', 'created_at', 'modified_at',
'registration_number',
'time_start', 'time_end', 'zone',
'operator_name',
'operator', 'operator_name',
}


Expand All @@ -89,6 +89,7 @@ def check_parking_data_matches_parking_object(parking_data, parking_obj):
assert parking_data[field] == getattr(parking_obj, field)

assert parking_data['id'] == str(parking_obj.id) # UUID -> str
assert parking_data['operator'] == str(parking_obj.operator.id)
assert parking_data['created_at'] == iso8601_us(parking_obj.created_at)
assert parking_data['modified_at'] == iso8601_us(parking_obj.modified_at)
assert parking_data['time_start'] == iso8601(parking_obj.time_start)
Expand Down

0 comments on commit 0100975

Please sign in to comment.