diff --git a/app/main.py b/app/main.py index ae032d8..16a6dcf 100644 --- a/app/main.py +++ b/app/main.py @@ -55,6 +55,7 @@ async def create_entry(payload: helpers.MessagePayload, settings: Annotated[conf response = helpers.generate_response( user_phone, content, date_sent, settings) to_return = await helpers.send_message(user_phone, response, settings) + logger.info(to_return) return to_return @@ -63,7 +64,8 @@ async def create_user(user: schemas.UserCreate, settings: Annotated[config.Setti db_user = crud.get_user_by_phone_number(db, user.phone_number) if db_user: raise HTTPException( - status_code=400, detail="Email already registered!") - crud.create_user(db=db, user=user) - response = await helpers.send_message(user.phone_number, constants.welcome_message, settings) + status_code=400, detail="User already registered.") + response = crud.create_user(db=db, user=user) return response + # response = await helpers.send_message(user.phone_number, constants.welcome_message, settings) + # return response diff --git a/app/test.ipynb b/app/notebooks/test.ipynb similarity index 100% rename from app/test.ipynb rename to app/notebooks/test.ipynb diff --git a/app/tokenizer.ipynb b/app/notebooks/tokenizer.ipynb similarity index 100% rename from app/tokenizer.ipynb rename to app/notebooks/tokenizer.ipynb diff --git a/app/test_main.py b/app/test_main.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/tests/__init__.py b/app/tests/__init__.py new file mode 100644 index 0000000..92afc4f --- /dev/null +++ b/app/tests/__init__.py @@ -0,0 +1 @@ +from unittest.mock import Mock diff --git a/app/tests/mocks/__init__.py b/app/tests/mocks/__init__.py new file mode 100644 index 0000000..1c0d7c5 --- /dev/null +++ b/app/tests/mocks/__init__.py @@ -0,0 +1,77 @@ +from app.models import EmotionsEnum + + +mock_create_user_payload = { + "phone_number": "+16788973910", + "password": "MockHashedPassword" +} + +mock_create_user_response = { + "phone_number": "+16788973910", + "id": 5, + "created_at": "2024-07-22T23:50:13.782002", + "entries": [] +} + +mock_get_user_response = { + "id": 1, + "phone_number": "+16788973910", + "created_at": "2024-07-22T23:50:13.782002", + "hashed_password": "MockHashedPassword" +} + +mock_create_user_entry_response = { + "id": 1, + "created_at": "2024-07-24T12:00:00.000000", + "date": "2024-07-24", + "emotions": ["happiness", "surprise"], + "content": "This is a mock entry content.", + "embedding": None, + "author_id": 1, + "created_by": { + "id": 1, + "phone_number": "+16788973910", + "created_at": "2024-07-01T10:00:00.000000" + } +} + +mock_message_payload = { + "accountEmail": "varoon.kodithala@gmail.com", + "content": "MockMessage", + "is_outbound": False, + "status": "RECEIVED", + "error_code": None, + "error_message": None, + "error_reason": None, + "message_handle": "E0F8050E-1357-4B21-9954-3C3AC3921FD2", + "date_sent": "2024-07-23T03:37:08.648Z", + "date_updated": "2024-07-23T03:37:09.283Z", + "from_number": "+16788973910", + "number": "+16788973910", + "to_number": "+16193138272", + "was_downgraded": None, + "plan": "blue", + "media_url": "", + "message_type": "message", + "group_id": "", + "participants": [ + "+16788973910" + ], + "send_style": "", + "opted_out": False, + "error_detail": None +} + +mock_send_message_response = { + "status_code": 202, +} + +mock_entry_create_response = { + "id": 1, + "created_at": "2024-07-01T10:00:00.000000", + "date": "2024-07-01", + "author_id": 3, + "emotions": [EmotionsEnum.HAPPINESS, EmotionsEnum.SURPRISE], + "content": "Today was an amazing day! I got a promotion at work and my best friend threw me a surprise party.", + "embedding": [0.1, 0.2, 0.3, 0.4, 0.5] +} diff --git a/app/tests/test_main.py b/app/tests/test_main.py new file mode 100644 index 0000000..2e2a764 --- /dev/null +++ b/app/tests/test_main.py @@ -0,0 +1,82 @@ +from datetime import datetime +import unittest +from unittest.mock import Mock, patch +from fastapi import FastAPI +from fastapi.testclient import TestClient +from sqlalchemy.orm import Session +from app.main import app +from app.tests.mocks import mock_create_user_response, mock_create_user_payload, mock_get_user_response, mock_create_user_entry_response, mock_send_message_response, mock_message_payload, mock_entry_create_response + + +class TestCreateUser(unittest.TestCase): + def setUp(self): + self.client = TestClient(app) + + @patch('app.crud.get_user_by_phone_number') + @patch('app.crud.create_user') + def test_create_user_success(self, mock_create_user: Mock, mock_get_user: Mock): + mock_get_user.return_value = None + mock_create_user.return_value = mock_create_user_response + + response = self.client.post("/users/", json=mock_create_user_payload) + + self.assertEqual(response.status_code, 200) + + self.assertEqual(response.json(), mock_create_user_response) + + mock_get_user.assert_called_once() + args = mock_get_user.call_args[0] + self.assertIsInstance(args[0], Session) + self.assertEqual(args[1], "+16788973910") + + @patch('app.crud.get_user_by_phone_number') + def test_create_user_already_exists(self, mock_get_user: Mock): + mock_get_user.return_value = mock_create_user_response + + response = self.client.post("/users/", json=mock_create_user_payload) + + self.assertEqual(response.status_code, 400) + self.assertIn("User already registered.", response.json()["detail"]) + + +class TestCreateEntry(unittest.TestCase): + def setUp(self): + self.client = TestClient(app) + + @patch('app.crud.get_user_by_phone_number') + @patch('app.tokenizer.embed') + @patch('app.schemas.EntryCreate') + @patch('app.crud.create_user_entry') + @patch('app.crud.query_embeddings') + @patch('app.helpers.generate_response') + @patch('app.helpers.send_message') + def test_create_entry_success(self, mock_send_message: Mock, mock_generate_response: Mock, mock_query_embeddings: Mock, mock_create_user_entry: Mock, mock_entry_create: Mock, mock_embed: Mock, mock_get_user: Mock): + mock_get_user.return_value = mock_get_user_response + mock_entry_create.return_value = mock_entry_create_response + mock_create_user_entry.return_value = mock_create_user_entry_response + mock_send_message.return_value = mock_send_message_response + + response = self.client.post("/entries/", json=mock_message_payload) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), mock_send_message_response) + + # crud.get_user_by_phone_number was called correctly + mock_get_user.assert_called_once() + args = mock_get_user.call_args[0] + self.assertEqual(args[1], mock_message_payload["from_number"]) + + # tokenizer.embed, crud.create_user_entry, crud_query_embeddings, and helpers.generate_response were called + mock_embed.assert_called() + mock_create_user_entry.assert_called_once() + mock_query_embeddings.assert_called_once() + mock_generate_response.assert_called_once() + + # crud.create_user_entry was called correctly + args = mock_create_user_entry.call_args[0] + self.assertEqual(args[1], mock_entry_create_response) + + # helpers.send_message was called correctly + mock_send_message.assert_called_once() + args = mock_create_user_entry.call_args[0] + self.assertEqual(args[1], mock_send_message_response) diff --git a/requirements.txt b/requirements.txt index 1bb7433..b8cb444 100644 --- a/requirements.txt +++ b/requirements.txt @@ -49,6 +49,7 @@ httptools==0.6.1 httpx==0.27.0 huggingface-hub==0.24.0 idna==3.7 +iniconfig==2.0.0 ipykernel==6.29.5 ipython==8.26.0 jedi==0.19.1 @@ -114,6 +115,7 @@ pexpect==4.9.0 pgvector==0.2.5 pillow==10.4.0 platformdirs==4.2.2 +pluggy==1.5.0 prettytable==3.10.2 prompt_toolkit==3.0.47 protobuf==4.25.3 @@ -129,6 +131,7 @@ pydantic-settings==2.3.4 pydantic_core==2.18.4 Pygments==2.18.0 pypdf==4.3.0 +pytest==8.3.1 python-dateutil==2.9.0.post0 python-dotenv==1.0.1 python-multipart==0.0.9