Improve collection editing and rendering
This commit is contained in:
+92
-4
@@ -2,8 +2,8 @@ from django.contrib.auth import get_user_model
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from .models import Collection, CollectionSection, Item, Tag, Team, TeamMembership, UserPreference
|
||||
from .templatetags.markdown_extras import markdown
|
||||
from .models import ApiKey, Collection, CollectionSection, Item, Tag, Team, TeamMembership, UserPreference
|
||||
from .templatetags.markdown_extras import markdown, markdown_title
|
||||
from .views import parse_due_command, parse_quick_content
|
||||
|
||||
|
||||
@@ -98,15 +98,25 @@ class MarkdownHeadingTests(TestCase):
|
||||
|
||||
def test_heading_with_space_remains_a_heading(self):
|
||||
self.assertIn('<h1>Project</h1>', str(markdown('# Project')))
|
||||
self.assertIn('<h2>Section</h2>', str(markdown('## Section')))
|
||||
|
||||
def test_hash_in_fenced_code_is_unchanged(self):
|
||||
rendered = str(markdown('```python\n# comment\n```'))
|
||||
self.assertIn('# comment', rendered)
|
||||
self.assertNotIn('\\# comment', rendered)
|
||||
self.assertNotIn('<h1>', rendered)
|
||||
|
||||
def test_hash_in_inline_code_is_not_a_heading(self):
|
||||
rendered = str(markdown('```# Das ist Kommentar im Code```'))
|
||||
self.assertIn('<code># Das ist Kommentar im Code</code>', rendered)
|
||||
self.assertNotIn('<h1>', rendered)
|
||||
|
||||
def test_underline_is_allowed(self):
|
||||
self.assertIn('<u>underlined</u>', str(markdown('<u>underlined</u>')))
|
||||
|
||||
def test_markdown_title_strips_heading_marker(self):
|
||||
self.assertEqual(markdown_title('## Ziel von my2dos\n\nText'), 'Ziel von my2dos')
|
||||
|
||||
|
||||
class FormattingToolbarTests(TestCase):
|
||||
def test_toolbar_and_shortcuts_are_available(self):
|
||||
@@ -179,6 +189,21 @@ class TeamItemEditTests(TestCase):
|
||||
response = self.client.get(reverse('item_editor', args=[item.id]))
|
||||
self.assertContains(response, '<option value="team" selected>', html=False)
|
||||
|
||||
def test_team_item_can_be_made_public_even_with_team_tag(self):
|
||||
item = Item.objects.create(
|
||||
owner=self.user, team=self.team, content='Original #docs', visibility=Item.Visibility.TEAM,
|
||||
)
|
||||
item.sync_metadata()
|
||||
|
||||
response = self.client.post(reverse('item_editor', args=[item.id]), {
|
||||
'content': 'Updated #docs', 'comment': '', 'visibility': Item.Visibility.PUBLIC, 'url': '',
|
||||
})
|
||||
|
||||
self.assertRedirects(response, item.get_absolute_url())
|
||||
item.refresh_from_db()
|
||||
self.assertEqual(item.visibility, Item.Visibility.PUBLIC)
|
||||
self.assertIsNone(item.team)
|
||||
|
||||
|
||||
class CollectionTests(TestCase):
|
||||
def setUp(self):
|
||||
@@ -274,8 +299,10 @@ class CollectionTests(TestCase):
|
||||
response = self.client.get(collection.get_absolute_url())
|
||||
html = response.content.decode()
|
||||
self.assertContains(response, 'Tag-Sammlung')
|
||||
self.assertLess(html.index('First #guide'), html.index('Second #guide'))
|
||||
self.assertNotContains(response, 'Ignored #guide')
|
||||
self.assertLess(html.index('First'), html.index('Second'))
|
||||
self.assertNotContains(response, 'First #guide')
|
||||
self.assertNotContains(response, 'Second #guide')
|
||||
self.assertNotContains(response, 'Ignored')
|
||||
self.assertContains(response, reverse('collection_edit', args=[collection.id]))
|
||||
self.assertNotContains(response, reverse('collection_manage', args=[collection.id]))
|
||||
|
||||
@@ -294,6 +321,26 @@ class CollectionTests(TestCase):
|
||||
self.assertNotContains(response, 'Add existing note')
|
||||
self.assertNotContains(response, 'section_id')
|
||||
|
||||
def test_collection_reading_view_hides_note_tags(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Reading view')
|
||||
note = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='## Section #tutorial\nText #my2dos and `#code`')
|
||||
CollectionSection.objects.create(collection=collection, item=note, position=0)
|
||||
response = self.client.get(collection.get_absolute_url())
|
||||
self.assertContains(response, '<h2>Section</h2>', html=True)
|
||||
self.assertContains(response, '<code>#code</code>', html=True)
|
||||
self.assertNotContains(response, '#tutorial')
|
||||
self.assertNotContains(response, '#my2dos')
|
||||
|
||||
def test_collection_manage_links_note_editor_back_to_collection(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Reading view')
|
||||
note = Item.objects.create(owner=self.user, kind=Item.Kind.NOTE, content='## Section')
|
||||
CollectionSection.objects.create(collection=collection, item=note, position=0)
|
||||
manage_url = reverse('collection_manage', args=[collection.id])
|
||||
response = self.client.get(manage_url)
|
||||
self.assertContains(response, f'{reverse("item_editor", args=[note.id])}?next={manage_url}')
|
||||
self.assertContains(response, '>Section</')
|
||||
self.assertNotContains(response, '>## Section</')
|
||||
|
||||
def test_public_collection_is_visible_without_login(self):
|
||||
collection = Collection.objects.create(owner=self.user, title='Public', visibility=Item.Visibility.PUBLIC)
|
||||
self.client.logout()
|
||||
@@ -325,6 +372,47 @@ class CollectionTests(TestCase):
|
||||
self.assertEqual(note.visibility, Item.Visibility.PUBLIC)
|
||||
|
||||
|
||||
class ApiItemFilterTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = get_user_model().objects.create_user(username='api-filter', password='secret')
|
||||
self.help_tag = Tag.objects.create(name='help')
|
||||
self.api_key = ApiKey.objects.create(owner=self.user, name='Help CLI')
|
||||
self.api_key.tags.add(self.help_tag)
|
||||
|
||||
def create_item(self, content):
|
||||
item = Item.objects.create(owner=self.user, content=content)
|
||||
item.sync_metadata()
|
||||
return item
|
||||
|
||||
def test_api_key_scope_and_request_tags_are_combined(self):
|
||||
matching = self.create_item('Keyboard shortcuts #help #tasten')
|
||||
self.create_item('Git help #help #git')
|
||||
self.create_item('Private keyboard note #tasten')
|
||||
|
||||
response = self.client.get(
|
||||
reverse('api_items'), {'tag': 'tasten', 'tag_mode': 'all'},
|
||||
HTTP_X_API_KEY=self.api_key.token,
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
ids = [item['id'] for item in response.json()['items']]
|
||||
self.assertEqual(ids, [matching.id])
|
||||
|
||||
def test_api_items_supports_limit_and_search(self):
|
||||
self.create_item('First #help #shell')
|
||||
second = self.create_item('Second #help #shell keyboard')
|
||||
|
||||
response = self.client.get(
|
||||
reverse('api_items'), {'tag': 'shell', 'q': 'keyboard', 'limit': '1'},
|
||||
HTTP_X_API_KEY=self.api_key.token,
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
items = response.json()['items']
|
||||
self.assertEqual(len(items), 1)
|
||||
self.assertEqual(items[0]['id'], second.id)
|
||||
|
||||
|
||||
class CopyButtonTests(TestCase):
|
||||
def test_item_has_copy_button_with_original_text(self):
|
||||
user = get_user_model().objects.create_user(username='tester', password='secret')
|
||||
|
||||
Reference in New Issue
Block a user