summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xeffiapi42
-rw-r--r--yarns/000.yarn37
-rw-r--r--yarns/lib.py3
3 files changed, 70 insertions, 12 deletions
diff --git a/effiapi b/effiapi
index f3894fc..5f92901 100755
--- a/effiapi
+++ b/effiapi
@@ -81,7 +81,7 @@ class FakeHTTPAPI(HTTPAPI):
def POST(self, url, headers, body):
logging.debug(
- 'FakeHTTPAPI.POST url=%r headers=%r body=r',
+ 'FakeHTTPAPI.POST url=%r headers=%r body=%r',
url, headers, body)
rid = str(uuid.uuid4())
@@ -93,7 +93,7 @@ class FakeHTTPAPI(HTTPAPI):
def PUT(self, url, headers, body):
logging.debug(
- 'FakeHTTPAPI.PUT url=%r headers=%r body=r',
+ 'FakeHTTPAPI.PUT url=%r headers=%r body=%r',
url, headers, body)
rid = headers.get('Muck-Id')
@@ -117,7 +117,7 @@ class FakeHTTPAPI(HTTPAPI):
if url.endswith('/res'):
return self._get_resource(headers)
- logging.error('Cannot server url')
+ logging.error('Cannot serve url')
assert 0
def _get_status(self):
@@ -136,6 +136,10 @@ class FakeHTTPAPI(HTTPAPI):
logging.warning('FakeHTTPAPI.GET: empty resource id in headers')
return FakeResponse(404, {}, 'No such member')
+ if rid not in self._memb:
+ logging.debug('Members: %r', self._memb)
+ return FakeResponse(404, {}, 'Retrieving member that does not exist')
+
memb = self._memb[rid]
headers = {
'Muck-Id': rid,
@@ -144,7 +148,19 @@ class FakeHTTPAPI(HTTPAPI):
return FakeResponse(200, headers, memb)
def DELETE(self, url, headers):
- raise NotImplementedError()
+ logging.debug('FakeHTTPAPI.DELETE url=%r headers=%r', url, headers)
+
+ rid = headers.get('Muck-Id')
+ if not rid:
+ logging.warning('FakeHTTPAPI.DELETE: empty resource id in headers')
+ return FakeResponse(404, {}, 'No such member')
+
+ if rid not in self._memb:
+ logging.debug('Members: %r', self._memb)
+ return FakeResponse(404, {}, 'Deleting member that does not exist')
+
+ del self._memb[rid]
+ return FakeResponse(200, {}, {})
class MuckError(Exception):
@@ -214,6 +230,14 @@ class MuckAPI:
def update(self, member):
return self._write(member, self._httpapi.PUT)
+ def delete(self):
+ url = self.url('/res')
+ headers = self._get_headers()
+ r = self._httpapi.DELETE(url, headers)
+ logging.info('Delete result: %s %s', r.status_code, r.text)
+ if not r.ok:
+ raise MuckError('{} {}'.format(r.status_code, r.text))
+
def search(self, cond):
url = self.url('/search')
headers = self._get_headers()
@@ -258,6 +282,11 @@ class API:
'path': '/memb',
'callback': self._call(self._update),
},
+ {
+ 'method': 'DELETE',
+ 'path': '/memb',
+ 'callback': self._call(self._delete),
+ },
]
for route in routes:
@@ -335,6 +364,11 @@ class API:
rid, newobj = self._muck.update(obj)
return response(200, rid, newobj)
+ def _delete(self):
+ r = bottle.request
+ self._muck.delete()
+ return response(200, None, None)
+
def response(status, rid, body):
headers = {
diff --git a/yarns/000.yarn b/yarns/000.yarn
index adff964..79e398d 100644
--- a/yarns/000.yarn
+++ b/yarns/000.yarn
@@ -33,17 +33,20 @@ Examples will be provided.
## Manage memberships
-This section shows the API calls to manage a memberhip: to create the
-member, to update and retrieve it, and to search memberships.
+This section shows the API calls to manage a memberhip.
SCENARIO Manage memberships
GIVEN An effiapi instance
+First make sure the register is empty.
+
WHEN admin requests GET /status
THEN HTTP status is 200
AND body matches { "resources": 0 }
+Create a member.
+
WHEN admin requests POST /memb with body { "fullname": "James Bond" }
THEN HTTP status is 201
AND remember header Muck-Id as ID
@@ -58,6 +61,8 @@ member, to update and retrieve it, and to search memberships.
AND body matches { "fullname": "James Bond" }
AND header Muck-Revision is ${REV1}
+Update the member.
+
WHEN admin requests PUT /memb with id ${ID}, revision ${REV1},
... and body { "fullname": "Alfred Pennyworth" }
THEN HTTP status is 200
@@ -68,12 +73,24 @@ member, to update and retrieve it, and to search memberships.
AND body matches { "fullname": "Alfred Pennyworth" }
AND header Muck-Revision is ${REV2}
+Delete the member.
+
+ WHEN admin requests DELETE /memb with id ${ID}
+ THEN HTTP status is 200
+
+ WHEN admin requests GET /status
+ THEN HTTP status is 200
+ AND body matches { "resources": 0 }
+
+ WHEN admin requests GET /memb with header Muck-Id: ${ID}
+ THEN HTTP status is 404
+
+Done.
+
FINALLY Effiapi is terminated
TODO:
-* update
-* delete
* search
* members can see their own data, and can't see each others'
* member follows authn link emailed to them
@@ -119,12 +136,16 @@ TODO:
headers = {
header: value,
}
- V['xx'] = {
- 'header': header,
- 'value': value,
- }
effiapi.GET('/memb', headers, None)
+ IMPLEMENTS WHEN admin requests DELETE /memb with id (\S+)
+ rid = get_expanded_match()
+ print('rid', repr(rid))
+ headers = {
+ 'Muck-id': rid,
+ }
+ effiapi.DELETE('/memb', headers, None)
+
## Inspect HTTP responses
IMPLEMENTS THEN HTTP status is (\d+)
diff --git a/yarns/lib.py b/yarns/lib.py
index 100511e..2e76b88 100644
--- a/yarns/lib.py
+++ b/yarns/lib.py
@@ -104,6 +104,9 @@ class EffiAPI:
def GET(self, path, headers, body):
self.request(requests.get, path, headers, body)
+ def DELETE(self, path, headers, body):
+ self.request(requests.delete, path, headers, body)
+
def request(self, func, path, headers, body):
url = '{}{}'.format(self.v['baseurl'], path)
self.v['request'] = {