diff --git a/bookmarks/api/serializers.py b/bookmarks/api/serializers.py index f52ee60..13e6570 100644 --- a/bookmarks/api/serializers.py +++ b/bookmarks/api/serializers.py @@ -19,6 +19,7 @@ class BookmarkSerializer(serializers.ModelSerializer): 'description', 'website_title', 'website_description', + 'is_archived', 'tag_names', 'date_added', 'date_modified' @@ -33,6 +34,7 @@ class BookmarkSerializer(serializers.ModelSerializer): # Override optional char fields to provide default value title = serializers.CharField(required=False, allow_blank=True, default='') description = serializers.CharField(required=False, allow_blank=True, default='') + is_archived = serializers.BooleanField(required=False, default=False) # Override readonly tag_names property to allow passing a list of tag names to create/update tag_names = TagListField(required=False, default=[]) @@ -41,6 +43,7 @@ class BookmarkSerializer(serializers.ModelSerializer): bookmark.url = validated_data['url'] bookmark.title = validated_data['title'] bookmark.description = validated_data['description'] + bookmark.is_archived = validated_data['is_archived'] tag_string = build_tag_string(validated_data['tag_names']) return create_bookmark(bookmark, tag_string, self.context['user']) diff --git a/bookmarks/tests/test_bookmarks_api.py b/bookmarks/tests/test_bookmarks_api.py index 4bbd05d..9b9f6b2 100644 --- a/bookmarks/tests/test_bookmarks_api.py +++ b/bookmarks/tests/test_bookmarks_api.py @@ -34,6 +34,7 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): expectation['description'] = bookmark.description expectation['website_title'] = bookmark.website_title expectation['website_description'] = bookmark.website_description + expectation['is_archived'] = bookmark.is_archived expectation['tag_names'] = tag_names expectation['date_added'] = bookmark.date_added.isoformat().replace('+00:00', 'Z') expectation['date_modified'] = bookmark.date_modified.isoformat().replace('+00:00', 'Z') @@ -49,6 +50,7 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): 'url': 'https://example.com/', 'title': 'Test title', 'description': 'Test description', + 'is_archived': False, 'tag_names': ['tag1', 'tag2'] } self.post(reverse('bookmarks:bookmark-list'), data, status.HTTP_201_CREATED) @@ -56,6 +58,7 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): self.assertEqual(bookmark.url, data['url']) self.assertEqual(bookmark.title, data['title']) self.assertEqual(bookmark.description, data['description']) + self.assertFalse(bookmark.is_archived, data['is_archived']) self.assertEqual(bookmark.tags.count(), 2) self.assertEqual(bookmark.tags.filter(name=data['tag_names'][0]).count(), 1) self.assertEqual(bookmark.tags.filter(name=data['tag_names'][1]).count(), 1) @@ -92,6 +95,30 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): response = self.get(reverse('bookmarks:bookmark-archived') + '?q=#' + self.tag1.name, expected_status_code=status.HTTP_200_OK) self.assertBookmarkListEqual(response.data['results'], [self.archived_bookmark1]) + def test_create_archived_bookmark(self): + data = { + 'url': 'https://example.com/', + 'title': 'Test title', + 'description': 'Test description', + 'is_archived': True, + 'tag_names': ['tag1', 'tag2'] + } + self.post(reverse('bookmarks:bookmark-list'), data, status.HTTP_201_CREATED) + bookmark = Bookmark.objects.get(url=data['url']) + self.assertEqual(bookmark.url, data['url']) + self.assertEqual(bookmark.title, data['title']) + self.assertEqual(bookmark.description, data['description']) + self.assertTrue(bookmark.is_archived) + self.assertEqual(bookmark.tags.count(), 2) + self.assertEqual(bookmark.tags.filter(name=data['tag_names'][0]).count(), 1) + self.assertEqual(bookmark.tags.filter(name=data['tag_names'][1]).count(), 1) + + def test_create_bookmark_minimal_payload_does_not_archive(self): + data = {'url': 'https://example.com/'} + self.post(reverse('bookmarks:bookmark-list'), data, status.HTTP_201_CREATED) + bookmark = Bookmark.objects.get(url=data['url']) + self.assertFalse(bookmark.is_archived) + def test_get_bookmark(self): url = reverse('bookmarks:bookmark-detail', args=[self.bookmark1.id]) response = self.get(url, expected_status_code=status.HTTP_200_OK) diff --git a/docs/API.md b/docs/API.md index b856008..3ccfce4 100644 --- a/docs/API.md +++ b/docs/API.md @@ -24,7 +24,7 @@ The following resources are available: GET /api/bookmarks/ ``` -List bookmarks. +List bookmarks. Parameters: @@ -65,7 +65,7 @@ Example response: GET /api/bookmarks/archived/ ``` -List archived bookmarks. +List archived bookmarks. Parameters and response are the same as for the regular list endpoint. @@ -83,7 +83,8 @@ Retrieves a single bookmark by ID. POST /api/bookmarks/ ``` -Creates a new bookmark. Tags are simply assigned using their names. +Creates a new bookmark. Tags are simply assigned using their names. Including +`is_archived: true` saves a bookmark directly to the archive. Example payload: @@ -92,6 +93,7 @@ Example payload: "url": "https://example.com", "title": "Example title", "description": "Example description", + "is_archived": false, "tag_names": [ "tag1", "tag2" @@ -201,4 +203,3 @@ Example payload: "name": "example" } ``` -