M src/groceries/model.py => src/groceries/model.py +1 -0
@@ 51,6 51,7 @@ class GroceryList:
updated_item = attr.evolve(item, **fields)
self._repo.update(item_name, updated_item)
+ return updated_item
def delete_item(self, item_name):
try:
M src/groceries/web/api.py => src/groceries/web/api.py +14 -0
@@ 66,6 66,20 @@ def get_item(name):
return dictify(item)
+@bp.route("/items/<name>", methods=["PUT"])
+def update_item(name):
+ grocery_list = GroceryList(current_app.config["BACKEND"])
+
+ try:
+ updated_item = grocery_list.update_item(name, **request.json)
+ except TypeError:
+ abort(400, description="Invalid fields in request")
+ except LookupError as err:
+ abort(404, description=str(err))
+
+ return dictify(updated_item)
+
+
@bp.route("/items/<name>", methods=["DELETE"])
def delete_item(name):
grocery_list = GroceryList(current_app.config["BACKEND"])
M tests/test_rest_server.py => tests/test_rest_server.py +25 -0
@@ 120,3 120,28 @@ def test_create_existing_item(client):
assert response.get_json() == {
"error": "400 Bad Request: 'produce: apples' already in grocery list."
}
+
+
+def test_update_item(client):
+ item = client.get("/api/items/apples").get_json()
+ response = client.put("/api/items/apples", json={"section": "fruit"})
+ assert response.status_code == 200
+ expected = dict(item, section="fruit")
+ assert response.get_json() == expected
+ assert client.get("/api/items/apples").get_json() == expected
+
+
+def test_update_unknown_item(client):
+ response = client.put("/api/items/jabberwocky", json={"section": "pets"})
+ assert response.status_code == 404
+ assert response.get_json() == {
+ "error": "404 Not Found: 'jabberwocky' not found in grocery list."
+ }
+
+
+def test_update_item_with_invalid_fields(client):
+ response = client.put("/api/items/apples", json={"variety": "granny smith"})
+ assert response.status_code == 400
+ assert response.get_json() == {
+ "error": "400 Bad Request: Invalid fields in request"
+ }