Update collections and attachment uploads
This commit is contained in:
+146
-1
@@ -1,5 +1,10 @@
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.test import TestCase
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from .models import ApiKey, Collection, CollectionSection, Item, Tag, Team, TeamMembership, UserPreference
|
||||
@@ -103,6 +108,20 @@ class SlashMenuContextTests(TestCase):
|
||||
self.assertIn('/public', content)
|
||||
self.assertIn('/private', content)
|
||||
|
||||
@patch('core.views.fetch_page_title', return_value='Example page')
|
||||
def test_url_on_first_line_becomes_link_with_title_and_extra_text(self, _fetch_title):
|
||||
kind, _, content, url = parse_quick_content('https://example.com/page\nEigener Text #tag')
|
||||
self.assertEqual(kind, Item.Kind.LINK)
|
||||
self.assertEqual(url, 'https://example.com/page')
|
||||
self.assertEqual(content, 'Example page\nEigener Text #tag')
|
||||
|
||||
@patch('core.views.fetch_page_title', return_value='Example page')
|
||||
def test_explicit_link_command_uses_first_line_url_title(self, _fetch_title):
|
||||
kind, _, content, url = parse_quick_content('/link https://example.com/page\n#tag')
|
||||
self.assertEqual(kind, Item.Kind.LINK)
|
||||
self.assertEqual(url, 'https://example.com/page')
|
||||
self.assertEqual(content, 'Example page\n#tag')
|
||||
|
||||
|
||||
class MarkdownHeadingTests(TestCase):
|
||||
def test_tag_at_line_start_is_not_a_heading(self):
|
||||
@@ -171,6 +190,31 @@ class NavigationAndLayoutTests(TestCase):
|
||||
self.assertLess(toolbar_position, file_position)
|
||||
|
||||
|
||||
class AttachmentEditTests(TestCase):
|
||||
def setUp(self):
|
||||
self.media_root = tempfile.mkdtemp()
|
||||
self.override = override_settings(MEDIA_ROOT=self.media_root)
|
||||
self.override.enable()
|
||||
self.user = get_user_model().objects.create_user(username='attachment-editor', password='secret')
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def tearDown(self):
|
||||
self.override.disable()
|
||||
shutil.rmtree(self.media_root, ignore_errors=True)
|
||||
|
||||
def test_uploaded_file_is_visible_after_first_inline_edit_save(self):
|
||||
item = Item.objects.create(owner=self.user, content='Original')
|
||||
uploaded = SimpleUploadedFile('hello.txt', b'hello', content_type='text/plain')
|
||||
|
||||
response = self.client.post(reverse('edit_item', args=[item.id]), {
|
||||
'content': 'Original', 'comment': '', 'visibility': Item.Visibility.PRIVATE, 'url': '', 'files': uploaded,
|
||||
}, HTTP_HX_REQUEST='true')
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(item.attachments.count(), 1)
|
||||
self.assertContains(response, 'hello.txt')
|
||||
|
||||
|
||||
class TeamItemEditTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = get_user_model().objects.create_user(username='team-editor', password='secret')
|
||||
@@ -301,6 +345,107 @@ class CollectionTests(TestCase):
|
||||
self.assertEqual(list(form.fields['team'].queryset), [team])
|
||||
self.assertEqual(list(form.fields['filter_tags'].queryset.values_list('name', flat=True)), ['ordinary'])
|
||||
|
||||
def test_tutorial_is_listed_but_chapter_is_hidden_from_collection_overview(self):
|
||||
tutorial = Collection.objects.create(owner=self.user, title='my2dos Tutorial', mode=Collection.Mode.TUTORIAL)
|
||||
chapter = Collection.objects.create(owner=self.user, title='my2dos Typen', mode=Collection.Mode.CHAPTER)
|
||||
|
||||
response = self.client.get(reverse('collection_list'))
|
||||
|
||||
self.assertContains(response, tutorial.title)
|
||||
self.assertNotIn(chapter, [entry['collection'] for entry in response.context['entries']])
|
||||
|
||||
def test_collection_list_can_filter_collection_types(self):
|
||||
Collection.objects.create(owner=self.user, title='Manual', mode=Collection.Mode.MANUAL)
|
||||
Collection.objects.create(owner=self.user, title='Tutorial', mode=Collection.Mode.TUTORIAL)
|
||||
Collection.objects.create(owner=self.user, title='Tagged', mode=Collection.Mode.TAGS)
|
||||
Collection.objects.create(owner=self.user, title='Chapter', mode=Collection.Mode.CHAPTER)
|
||||
|
||||
response = self.client.get(f'{reverse("collection_list")}?mode=chapter')
|
||||
|
||||
self.assertEqual([entry['collection'].title for entry in response.context['entries']], ['Chapter'])
|
||||
|
||||
def test_orphan_chapters_are_shown_as_warning(self):
|
||||
Collection.objects.create(owner=self.user, title='Lonely chapter', mode=Collection.Mode.CHAPTER)
|
||||
|
||||
response = self.client.get(reverse('collection_list'))
|
||||
|
||||
self.assertContains(response, 'Verwaiste Kapitel')
|
||||
self.assertContains(response, 'Lonely chapter')
|
||||
|
||||
def test_tutorial_can_include_chapter_collection(self):
|
||||
tutorial = Collection.objects.create(owner=self.user, title='my2dos Tutorial', mode=Collection.Mode.TUTORIAL)
|
||||
chapter = Collection.objects.create(owner=self.user, title='my2dos Typen', mode=Collection.Mode.CHAPTER)
|
||||
note = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='## Todos')
|
||||
CollectionSection.objects.create(collection=chapter, item=note, position=0)
|
||||
manage_url = reverse('collection_manage', args=[tutorial.id])
|
||||
|
||||
response = self.client.post(manage_url, {'action': 'add_collection', 'collection_id': chapter.id})
|
||||
|
||||
self.assertRedirects(response, manage_url)
|
||||
self.assertTrue(tutorial.sections.filter(sub_collection=chapter).exists())
|
||||
response = self.client.get(tutorial.get_absolute_url())
|
||||
self.assertContains(response, '<h2>my2dos Typen</h2>', html=True)
|
||||
self.assertContains(response, '<h3>Todos</h3>', html=True)
|
||||
|
||||
def test_collection_overview_is_available_on_mobile(self):
|
||||
response = self.client.get(reverse('collection_list'))
|
||||
|
||||
self.assertNotContains(response, 'Collections are currently available on desktop only.')
|
||||
self.assertContains(response, 'Sammlungen')
|
||||
|
||||
def test_collection_manage_links_to_note_editor_with_return_target(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Reading view')
|
||||
manage_url = reverse('collection_manage', args=[collection.id])
|
||||
|
||||
response = self.client.get(manage_url)
|
||||
|
||||
self.assertContains(response, f'{reverse("new_item")}?kind=note&collection={collection.id}&next={manage_url}')
|
||||
|
||||
def test_create_note_for_collection_in_editor_adds_it_and_returns(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Reading view')
|
||||
manage_url = reverse('collection_manage', args=[collection.id])
|
||||
|
||||
response = self.client.post(f'{reverse("new_item")}?kind=note&collection={collection.id}&next={manage_url}', {
|
||||
'collection': collection.id, 'next': manage_url, 'content': '## Fresh note #new',
|
||||
})
|
||||
|
||||
note = Item.objects.get(content='## Fresh note #new')
|
||||
self.assertRedirects(response, manage_url)
|
||||
self.assertTrue(collection.sections.filter(item=note).exists())
|
||||
self.assertEqual(note.visibility, collection.visibility)
|
||||
self.assertEqual(list(note.tags.values_list('name', flat=True)), ['new'])
|
||||
|
||||
def test_create_chapter_from_tutorial_manage_adds_and_opens_it(self):
|
||||
tutorial = Collection.objects.create(owner=self.user, title='my2dos Tutorial', mode=Collection.Mode.TUTORIAL)
|
||||
|
||||
response = self.client.post(reverse('collection_manage', args=[tutorial.id]), {'action': 'create_chapter', 'title': 'Tags'})
|
||||
|
||||
chapter = Collection.objects.get(title='Tags')
|
||||
self.assertEqual(chapter.mode, Collection.Mode.CHAPTER)
|
||||
self.assertTrue(tutorial.sections.filter(sub_collection=chapter).exists())
|
||||
self.assertRedirects(response, reverse('collection_manage', args=[chapter.id]))
|
||||
|
||||
def test_collection_sections_can_be_reordered_by_position(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Reading view')
|
||||
first = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='First')
|
||||
second = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='Second')
|
||||
first_section = CollectionSection.objects.create(collection=collection, item=first, position=0)
|
||||
second_section = CollectionSection.objects.create(collection=collection, item=second, position=1)
|
||||
|
||||
response = self.client.post(reverse('collection_manage', args=[collection.id]), {
|
||||
'action': 'move_to', 'section_id': second_section.id, 'position': 0,
|
||||
})
|
||||
|
||||
self.assertRedirects(response, reverse('collection_manage', args=[collection.id]))
|
||||
self.assertEqual(list(collection.sections.order_by('position').values_list('id', flat=True)), [second_section.id, first_section.id])
|
||||
|
||||
def test_collection_detail_is_available_on_mobile(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Mobile reading')
|
||||
response = self.client.get(collection.get_absolute_url())
|
||||
|
||||
self.assertNotContains(response, 'Collections are currently available on desktop only.')
|
||||
self.assertContains(response, 'collection-document')
|
||||
|
||||
def test_tag_collection_is_dynamic_and_sorted_by_creation(self):
|
||||
first = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='First #guide #basics')
|
||||
first.sync_metadata()
|
||||
|
||||
Reference in New Issue
Block a user