diff --git a/backend/app.py b/backend/app.py index c9fbd5b..237f8a5 100755 --- a/backend/app.py +++ b/backend/app.py @@ -1,31 +1,59 @@ from flask import Flask, request, jsonify -# declare constants +comments = [] +comment_id_counter = 1 + HOST = '0.0.0.0' PORT = 5000 -# initialize flask application app = Flask(__name__) -# sample hello world page @app.route('/') def hello(): return "

Hello World

" -# sample api endpoint @app.route('/api/test', methods=['GET', 'POST']) def test(): if request.method == 'POST': - # get parameters from post request parameters = request.get_json() - if 'test' in parameters: + if parameters and 'test' in parameters: return jsonify({'value': parameters['test']}) - return jsonify({'error'}) - else: - return jsonify({'test': 'success'}) + return jsonify({'error': 'Invalid request'}), 400 + return jsonify({'test': 'success'}) + +@app.route('/comments', methods=['POST']) +def add_comment(): + global comment_id_counter + data = request.get_json() + if not data or 'task_id' not in data or 'text' not in data: + return jsonify({'error': 'task_id and text are required'}), 400 + comment = { + 'id': comment_id_counter, + 'task_id': data['task_id'], + 'text': data['text'] + } + comments.append(comment) + comment_id_counter += 1 + return jsonify(comment), 201 + +@app.route('/comments/', methods=['PUT']) +def update_comment(comment_id): + data = request.get_json() + if not data or 'text' not in data: + return jsonify({'error': 'text is required'}), 400 + for comment in comments: + if comment['id'] == comment_id: + comment['text'] = data['text'] + return jsonify(comment), 200 + return jsonify({'error': 'Comment not found'}), 404 +@app.route('/comments/', methods=['DELETE']) +def delete_comment(comment_id): + for comment in comments: + if comment['id'] == comment_id: + comments.remove(comment) + return jsonify({'message': 'Comment deleted'}), 200 + return jsonify({'error': 'Comment not found'}), 404 if __name__ == '__main__': - app.run(host=HOST, - debug=True, - port=PORT) + app.run(host=HOST, port=PORT, debug=True) diff --git a/backend/tests/test_comments.py b/backend/tests/test_comments.py new file mode 100644 index 0000000..832bec6 --- /dev/null +++ b/backend/tests/test_comments.py @@ -0,0 +1,304 @@ +import json +import pytest +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname(__file__))) + +from app import app + + +@pytest.fixture +def client(): + app.testing = True + with app.test_client() as client: + yield client + + +# ===================================================== +# POST /comments — POSITIVE TEST CASES (4) +# ===================================================== + +def test_post_comment_success(client): + res = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Valid comment"}), + content_type="application/json" + ) + assert res.status_code == 201 + assert "id" in res.get_json() + + +def test_post_comment_different_task_id(client): + res = client.post( + "/comments", + data=json.dumps({"task_id": 99, "text": "Another comment"}), + content_type="application/json" + ) + assert res.status_code == 201 + + +def test_post_comment_long_text(client): + res = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "A" * 200}), + content_type="application/json" + ) + assert res.status_code == 201 + + +def test_post_multiple_comments(client): + for i in range(3): + res = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": f"Comment {i}"}), + content_type="application/json" + ) + assert res.status_code == 201 + + +# ===================================================== +# POST /comments — NEGATIVE TEST CASES (4) +# ===================================================== + +def test_post_comment_missing_text(client): + res = client.post( + "/comments", + data=json.dumps({"task_id": 1}), + content_type="application/json" + ) + assert res.status_code == 400 + + +def test_post_comment_missing_task_id(client): + res = client.post( + "/comments", + data=json.dumps({"text": "No task"}), + content_type="application/json" + ) + assert res.status_code == 400 + + +def test_post_comment_empty_body(client): + res = client.post( + "/comments", + data=json.dumps({}), + content_type="application/json" + ) + assert res.status_code == 400 + + +def test_post_comment_no_json_header(client): + res = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "No header"}) + ) + assert res.status_code == 415 + + +# ===================================================== +# PUT /comments/ — POSITIVE TEST CASES (4) +# ===================================================== + +def test_put_comment_success(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Old"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.put( + f"/comments/{cid}", + data=json.dumps({"text": "Updated"}), + content_type="application/json" + ) + assert res.status_code == 200 + + +def test_put_comment_multiple_updates(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Init"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + for i in range(3): + res = client.put( + f"/comments/{cid}", + data=json.dumps({"text": f"Update {i}"}), + content_type="application/json" + ) + assert res.status_code == 200 + + +def test_put_comment_long_text(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Short"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.put( + f"/comments/{cid}", + data=json.dumps({"text": "B" * 300}), + content_type="application/json" + ) + assert res.status_code == 200 + + +def test_put_comment_special_characters(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Text"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.put( + f"/comments/{cid}", + data=json.dumps({"text": "@#$%^&*()"}), + content_type="application/json" + ) + assert res.status_code == 200 + + +# ===================================================== +# PUT /comments/ — NEGATIVE TEST CASES (4) +# ===================================================== + +def test_put_comment_not_found(client): + res = client.put( + "/comments/999", + data=json.dumps({"text": "No comment"}), + content_type="application/json" + ) + assert res.status_code == 404 + + +def test_put_comment_missing_text(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Valid"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.put( + f"/comments/{cid}", + data=json.dumps({}), + content_type="application/json" + ) + assert res.status_code == 400 + + +def test_put_comment_no_json_header(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Valid"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.put( + f"/comments/{cid}", + data=json.dumps({"text": "Updated"}) + ) + assert res.status_code == 415 + + +def test_put_comment_invalid_id(client): + res = client.put( + "/comments/abc", + data=json.dumps({"text": "Invalid"}), + content_type="application/json" + ) + assert res.status_code == 404 + + +# ===================================================== +# DELETE /comments/ — POSITIVE TEST CASES (4) +# ===================================================== + +def test_delete_comment_success(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 2, "text": "Delete"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + res = client.delete(f"/comments/{cid}") + assert res.status_code == 200 + + +def test_delete_multiple_comments(client): + ids = [] + for i in range(3): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": f"Del {i}"}), + content_type="application/json" + ) + ids.append(c.get_json()["id"]) + + for cid in ids: + res = client.delete(f"/comments/{cid}") + assert res.status_code == 200 + + +def test_delete_comment_after_update(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Temp"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + client.put( + f"/comments/{cid}", + data=json.dumps({"text": "Updated"}), + content_type="application/json" + ) + + res = client.delete(f"/comments/{cid}") + assert res.status_code == 200 + + +def test_delete_comment_high_id(client): + res = client.delete("/comments/100000") + assert res.status_code == 404 + + +# ===================================================== +# DELETE /comments/ — NEGATIVE TEST CASES (4) +# ===================================================== + +def test_delete_comment_twice(client): + c = client.post( + "/comments", + data=json.dumps({"task_id": 1, "text": "Once"}), + content_type="application/json" + ) + cid = c.get_json()["id"] + + client.delete(f"/comments/{cid}") + res = client.delete(f"/comments/{cid}") + assert res.status_code == 404 + + +def test_delete_comment_not_found(client): + res = client.delete("/comments/999") + assert res.status_code == 404 + + +def test_delete_comment_invalid_id(client): + res = client.delete("/comments/abc") + assert res.status_code == 404 + + +def test_delete_comment_negative_id(client): + res = client.delete("/comments/-1") + assert res.status_code == 404