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