Skip to content

Commit

Permalink
Merge pull request #113 from cfpb/ratechecker-api-status
Browse files Browse the repository at this point in the history
Add new API endpoint to get ratechecker data load timestamp
  • Loading branch information
chosak authored Mar 16, 2017
2 parents 7404a01 + 3edd2df commit 3e6acc5
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ We follow the [Semantic Versioning 2.0.0](http://semver.org/) format.

## Unreleased
- Enforce non-zero price in ratechecker API.
- Add new ratechecker API endpoint to check data load timestamp.

## 0.9.94 - 2017-02-02
- Add a monitor to watch for changes in census county values
Expand Down
60 changes: 56 additions & 4 deletions ratechecker/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import json

from datetime import datetime, timedelta
from decimal import Decimal
from django.core.urlresolvers import reverse
from django.test import override_settings
from django.utils import timezone
from model_mommy import mommy
from rest_framework import status
from rest_framework.test import APITestCase

from django.utils import timezone

from decimal import Decimal

from ratechecker.models import Region, Product, Rate, Adjustment, Fee
from ratechecker.views import set_lock_max_min

Expand Down Expand Up @@ -169,3 +172,52 @@ def test_rate_checker__valid(self):
self.assertEqual(response.data['fees']['origination_percent'], 0.0)
tparty = abs(response.data['fees']['third_party'] - 587.27)
self.assertTrue(tparty < threshold)


@override_settings(URLCONF='ratechecker.urls')
class RateCheckerStatusTest(APITestCase):
def get(self):
return self.client.get(
reverse('rate-checker-status'),
headers={'Accepts': 'application/json'}
)

def test_no_data_returns_200(self):
response = self.get()
self.assertEqual(response.status_code, 200)

def test_no_data_returns_json(self):
response = self.get()
self.assertEqual(response['Content-type'], 'application/json')

def test_no_data_returns_none(self):
response = self.get()
self.assertEqual(json.loads(response.content), {'load': None})

def test_data_returns_200(self):
mommy.make(Region)
response = self.get()
self.assertEqual(response.status_code, 200)

def test_data_returns_json(self):
mommy.make(Region)
response = self.get()
self.assertEqual(response['Content-type'], 'application/json')

def test_data_returns_timestamp(self):
region = mommy.make(Region)
response = self.get()
ts = datetime.strptime(
json.loads(response.content)['load'],
'%Y-%m-%dT%H:%M:%S.%fZ'
)
ts = timezone.make_aware(ts, timezone=timezone.utc)

# These might not match exactly due to ISO8601 JSON formatting.
self.assertTrue(abs(ts - region.data_timestamp) < timedelta(seconds=1))

def test_data_format_iso8601(self):
timestamp = datetime(2017, 1, 2, 3, 4, 56, tzinfo=timezone.utc)
mommy.make(Region, data_timestamp=timestamp)
response = self.get()
self.assertIn('2017-01-02T03:04:56Z', response.content)
7 changes: 6 additions & 1 deletion ratechecker/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from django.conf.urls import url

from ratechecker.views import rate_checker, rate_checker_fees
from ratechecker.views import (
RateCheckerStatus, rate_checker, rate_checker_fees
)


urlpatterns = [
url(r'rate-checker$',
rate_checker, name='rate-checker'),
url(r'rate-checker/status$',
RateCheckerStatus.as_view(), name='rate-checker-status'),
url(r'rate-checker-fees$',
rate_checker_fees, name='rate-checker-fees'),
]
11 changes: 11 additions & 0 deletions ratechecker/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView

from ratechecker.models import Region, Rate, Adjustment, Fee
from ratechecker.ratechecker_parameters import ParamsSerializer
Expand Down Expand Up @@ -201,3 +202,13 @@ def rate_checker_fees(request):
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)


class RateCheckerStatus(APIView):
def get(self, request, format=None):
try:
load_ts = Region.objects.latest('data_timestamp').data_timestamp
except Region.DoesNotExist:
load_ts = None

return Response({'load': load_ts})
1 change: 1 addition & 0 deletions requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

coverage==4.2
mock==2.0.0
model_mommy==1.2.6
csvkit==0.9.1

0 comments on commit 3e6acc5

Please sign in to comment.