diff --git a/zerver/tests/test_drafts.py b/zerver/tests/test_drafts.py index da4af56ac5..cfd4127ab8 100644 --- a/zerver/tests/test_drafts.py +++ b/zerver/tests/test_drafts.py @@ -473,3 +473,69 @@ class DraftDeleteTests(ZulipTestCase): existing_draft = Draft.objects.get(id=new_draft_id, user_profile=hamlet) existing_draft_dict = existing_draft.to_dict() self.assertEqual(existing_draft_dict, draft_dict) + +class DraftFetchTest(ZulipTestCase): + def test_fetch_drafts(self) -> None: + self.assertEqual(Draft.objects.count(), 0) + + hamlet = self.example_user("hamlet") + zoe = self.example_user("ZOE") + othello = self.example_user("othello") + visible_stream_id = self.get_stream_id(self.get_streams(hamlet)[0]) + draft_dicts = [ + { + "type": "stream", + "to": [visible_stream_id], + "topic": "thinking out loud", + "content": "What if pigs really could fly?", + "timestamp": 1595479019.439159, + }, + { + "type": "private", + "to": [zoe.id], + "topic": "", + "content": "What if made it possible to sync drafts in Zulip?", + "timestamp": 1595479020.439160, + }, + { + "type": "private", + "to": [zoe.id, othello.id], + "topic": "", + "content": "What if made it possible to sync drafts in Zulip?", + "timestamp": 1595479021.439161, + }, + ] + payload = {"drafts": ujson.dumps(draft_dicts)} + resp = self.api_post(hamlet, "/api/v1/drafts", payload) + self.assert_json_success(resp) + + self.assertEqual(Draft.objects.count(), 3) + + zoe_draft_dicts = [ + { + "type": "private", + "to": [hamlet.id], + "topic": "", + "content": "Hello there!", + "timestamp": 1595479019.439159, + }, + ] + payload = {"drafts": ujson.dumps(zoe_draft_dicts)} + resp = self.api_post(zoe, "/api/v1/drafts", payload) + self.assert_json_success(resp) + + self.assertEqual(Draft.objects.count(), 4) + + # Now actually fetch the drafts. Make sure that hamlet gets only + # his drafts and exactly as he made them. + resp = self.api_get(hamlet, "/api/v1/drafts") + self.assert_json_success(resp) + data = ujson.loads(resp.content) + self.assertEqual(data["count"], 3) + + first_draft_id = Draft.objects.order_by("id")[0].id + expected_draft_contents = { + "{}".format(i+first_draft_id): draft_dicts[i] for i in range(0, 3) + } # In JSON, all keys must be strings. + + self.assertEqual(data["drafts"], expected_draft_contents) diff --git a/zerver/views/drafts.py b/zerver/views/drafts.py index 13cacf0c04..1ce26b9c40 100644 --- a/zerver/views/drafts.py +++ b/zerver/views/drafts.py @@ -84,6 +84,11 @@ def further_validated_draft_dict(draft_dict: Dict[str, Any], "last_edit_time": last_edit_time, } +def fetch_drafts(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: + user_drafts = Draft.objects.filter(user_profile=user_profile).order_by("last_edit_time") + draft_dicts = {draft.id: draft.to_dict() for draft in user_drafts} + return json_success({"count": user_drafts.count(), "drafts": draft_dicts}) + @has_request_variables def create_drafts(request: HttpRequest, user_profile: UserProfile, draft_dicts: List[Dict[str, Any]]=REQ("drafts", diff --git a/zproject/urls.py b/zproject/urls.py index 0b242ac0e7..fe3560c29e 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -195,7 +195,9 @@ v1_api_and_json_patterns = [ # Endpoints for syncing drafts. path('drafts', rest_dispatch, - {'POST': ('zerver.views.drafts.create_drafts', + {'GET': ('zerver.views.drafts.fetch_drafts', + {'intentionally_undocumented'}), + 'POST': ('zerver.views.drafts.create_drafts', {'intentionally_undocumented'})}), path('drafts/', rest_dispatch, {'PATCH': ('zerver.views.drafts.edit_draft',