Skip to content

Commit

Permalink
Merge branch 'feature/issue-25-replace-in-memory-backend-in-the-api-w…
Browse files Browse the repository at this point in the history
…ith-generic-switchable-backend' into develop
  • Loading branch information
Trevor committed Jul 16, 2015
2 parents 7504f2e + ecbdd71 commit c8cdfa5
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 66 deletions.
53 changes: 7 additions & 46 deletions opt_out_http_api/api_methods.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
import uuid

from klein import Klein

Expand All @@ -19,46 +18,8 @@ class OptOutNotDeleted(Exception):
class API(object):
app = Klein()

def __init__(self):
self._optouts = [
{"id": "2468", "address_type": "msisdn", "address": "+273121100"},
{"id": "5678", "address_type": "twitter",
"address": "@twitter_handle"}
]

# Get Opt Out Address

def get_opt_out(self, addresstype, address):
opt_outs = [
o for o in self._optouts
if o["address_type"] == addresstype and o["address"] == address
]
if opt_outs:
return opt_outs[0]
return None

# Save Opt Out Address

def save_opt_out(self, addresstype, address):
opt_id = str(uuid.uuid4())
opt_out = {
"id": opt_id,
"address_type": addresstype,
"address": address,
}
self._optouts.append(opt_out)
return opt_out

# Delete Opt Out Address

def delete_opt_out(self, addresstype, address):
opt_out = self.get_opt_out(addresstype, address)
if opt_out is not None:
self._optouts.remove(opt_out)
return opt_out

def count_opt_outs(self):
return len(self._optouts)
def __init__(self, backend):
self._backend = backend

def response(self, request, status_code=200, status_reason="OK", **data):
request.setResponseCode(status_code)
Expand Down Expand Up @@ -99,29 +60,29 @@ def addresses(self, request):
@app.route('/optouts/<string:addresstype>/<string:address>',
methods=['GET'])
def get_address(self, request, addresstype, address):
opt_out = self.get_opt_out(addresstype, address)
opt_out = self._backend.get(addresstype, address)
if opt_out is None:
raise OptOutNotFound()
return self.response(request, opt_out=opt_out)

@app.route('/optouts/<string:addresstype>/<string:address>',
methods=['PUT'])
def save_address(self, request, addresstype, address):
opt_out = self.get_opt_out(addresstype, address)
opt_out = self._backend.get(addresstype, address)
if opt_out is not None:
raise OptOutAlreadyExists()
opt_out = self.save_opt_out(addresstype, address)
opt_out = self._backend.put(addresstype, address)
return self.response(request, opt_out=opt_out)

@app.route('/optouts/<string:addresstype>/<string:address>',
methods=['DELETE'])
def delete_address(self, request, addresstype, address):
opt_out = self.delete_opt_out(addresstype, address)
opt_out = self._backend.delete(addresstype, address)
if opt_out is None:
raise OptOutNotDeleted()
return self.response(request, opt_out=opt_out)

@app.route('/optouts/count', methods=['GET'])
def get_opt_out_count(self, request):
count = self.count_opt_outs()
count = self._backend.count()
return self.response(request, opt_out_count=count)
3 changes: 2 additions & 1 deletion opt_out_http_api/run.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from api_methods import API
from store.memory import OptOutMemory

app = API()
app = API(OptOutMemory())

app.app.run('localhost', 8080)
4 changes: 2 additions & 2 deletions opt_out_http_api/store/tests/test_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ def test_count_one(self):

def test_count_many(self):
store = OptOutMemory()
opt_count_one_many = store.count()
self.assertEqual(opt_count_one_many, 0)
opt_count = store.count()
self.assertEqual(opt_count, 0)
store.put("facebook", "trevor_fb")
store.put("mxit", "trevor_mxit")
opt_count = store.count()
Expand Down
51 changes: 34 additions & 17 deletions opt_out_http_api/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from opt_out_http_api.api_methods import API
import treq
import uuid
from twisted.trial.unittest import TestCase
from twisted.web.server import Site
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from opt_out_http_api.store.memory import OptOutMemory


class TestApi(TestCase):
Expand All @@ -18,7 +18,8 @@ def tearDown(self):

@inlineCallbacks
def start_server(self):
self.app = API()
self.backend = OptOutMemory()
self.app = API(self.backend)
self.server = yield reactor.listenTCP(0, Site(self.app.app.resource()))
addr = self.server.getHost()
self.url = "http://%s:%s" % (addr.host, addr.port)
Expand All @@ -39,13 +40,12 @@ def api_delete(self, path):
def api_count(self, path):
return treq.get("%s%s" % (self.url, path), persistent=False)

def add_opt_out(self, address_type, address):
self.app.save_opt_out(address_type, address)

# Tests

@inlineCallbacks
def test_opt_out_found(self):
existing_opt_out = self.backend.put("msisdn", "+273121100")
resp = yield self.api_call("/optouts/msisdn/+273121100")
self.assertEqual(resp.code, 200)
data = yield resp.json()
Expand All @@ -55,7 +55,7 @@ def test_opt_out_found(self):
"reason": "OK",
},
"opt_out": {
"id": "2468",
"id": existing_opt_out["id"],
"address_type": "msisdn",
"address": "+273121100",
},
Expand All @@ -75,10 +75,8 @@ def test_opt_out_not_found(self):

@inlineCallbacks
def test_opt_out_created(self):
def fixed_uuid():
return '1234'
self.patch(uuid, 'uuid4', fixed_uuid)
resp = yield self.api_put("/optouts/linkedin/+1029384756")
resp = yield self.api_put("/optouts/msisdn/+273121100")
created_opt_out = self.backend.get("msisdn", "+273121100")
self.assertEqual(resp.code, 200)
data = yield resp.json()
self.assertEqual(data, {
Expand All @@ -87,14 +85,15 @@ def fixed_uuid():
"reason": "OK",
},
"opt_out": {
"id": "1234",
"address_type": "linkedin",
"address": "+1029384756"
"id": created_opt_out["id"],
"address_type": "msisdn",
"address": "+273121100"
},
})

@inlineCallbacks
def test_opt_out_conflict(self):
self.backend.put("msisdn", "+273121100")
response = yield self.api_put("/optouts/msisdn/+273121100")
self.assertEqual(response.code, 409)
data = yield response.json()
Expand All @@ -107,7 +106,8 @@ def test_opt_out_conflict(self):

@inlineCallbacks
def test_opt_out_deleted(self):
resp = yield self.api_delete("/optouts/twitter/@twitter_handle")
delete_opt_out = self.backend.put("whatsapp", "@whatsup")
resp = yield self.api_delete("/optouts/whatsapp/@whatsup")
self.assertEqual(resp.code, 200)
data = yield resp.json()
self.assertEqual(data, {
Expand All @@ -116,9 +116,9 @@ def test_opt_out_deleted(self):
"reason": "OK",
},
"opt_out": {
"id": "5678",
"address_type": "twitter",
"address": "@twitter_handle"
"id": delete_opt_out["id"],
"address_type": "whatsapp",
"address": "@whatsup"
},
})

Expand All @@ -134,8 +134,23 @@ def test_opt_out_nothing_to_delete(self):
},
})

@inlineCallbacks
def test_opt_out_count_zero_opt_out(self):
resp = yield self.api_count("/optouts/count")
self.assertEqual(resp.code, 200)
data = yield resp.json()
self.assertEqual(data, {
"opt_out_count": 0,
"status": {
"code": 200,
"reason": "OK"
},
})

@inlineCallbacks
def test_opt_out_count_two_opt_outs(self):
self.backend.put("slack", "@slack")
self.backend.put("twitter_handle", "@trevor_october")
resp = yield self.api_count("/optouts/count")
self.assertEqual(resp.code, 200)
data = yield resp.json()
Expand All @@ -149,7 +164,9 @@ def test_opt_out_count_two_opt_outs(self):

@inlineCallbacks
def test_opt_out_count_three_opt_outs(self):
self.add_opt_out("msisdn", "+271345")
self.backend.put("whatsapp", "+27782635432")
self.backend.put("mxit", "@trevor_mxit")
self.backend.put("facebook", "fb")
resp = yield self.api_count("/optouts/count")
self.assertEqual(resp.code, 200)
data = yield resp.json()
Expand Down

0 comments on commit c8cdfa5

Please sign in to comment.