import pytest from scrobbles.scrobblers import ( _clean_org_note_content, _convert_org_links, _convert_org_src_blocks, _truncate_at_org_header, ) def test_truncate_at_org_header_stops_at_subheading(): content = "first part\n*** Description\nignored part" assert _truncate_at_org_header(content) == "first part" @pytest.mark.parametrize( "content, expected", [ ( "[[id:f6fc4950-07e6-459b-a256-c18282ca9256]" "[Mobile Transition Plan: Cookbooks V3 Nested → Flattened Fields]]", "[Mobile Transition Plan: Cookbooks V3 Nested → Flattened Fields]" "(id:f6fc4950-07e6-459b-a256-c18282ca9256)", ), ("[[https://example.com]]", "[https://example.com](https://example.com)"), ("plain text", "plain text"), ], ) def test_convert_org_links(content, expected): assert _convert_org_links(content) == expected def test_convert_org_src_blocks_with_language(): content = "#+begin_src sh\n echo 'hi'\n#+end_src" assert _convert_org_src_blocks(content) == "```sh\n echo 'hi'\n```" def test_convert_org_src_blocks_without_language(): content = "#+begin_src\nprint('hi')\n#+end_src" assert _convert_org_src_blocks(content) == "```\nprint('hi')\n```" def test_convert_org_src_blocks_with_header_args(): content = "#+begin_src python :results none\nx = 1\n#+end_src" assert _convert_org_src_blocks(content) == "```python\nx = 1\n```" def test_clean_org_note_content_strips_note_header_lines(): content = ( "- Note taken on [2025-09-25 Thu 10:37] \\\\\n" "\n" "\n" " This may already be fixed ... need to check.\n" "- Note taken on [2025-02-25 12:34] \\\\\n" "\n" " The page data has the canonical date.\n" ) expected = ( "This may already be fixed ... need to check.\n" "\n" "The page data has the canonical date." ) assert _clean_org_note_content(content) == expected def test_clean_org_note_content_combined(): content = ( "- Note taken on [2026-06-09 Tue 13:14]\n" " The full stack trace:\n" " #+begin_src sh\n" ' File "x.py", line 1\n' " #+end_src\n" "\n" " See [[id:f6fc4950-07e6-459b-a256-c18282ca9256][Mobile Transition Plan]]\n" ) result = _clean_org_note_content(content) assert "```sh" in result assert "```" in result assert 'File "x.py", line 1' in result assert "[[id:" not in result assert "[Mobile Transition Plan](id:f6fc4950-07e6-459b-a256-c18282ca9256)" in result def test_clean_org_note_content_truncates_at_subheading(): content = "my note text\n*** Something Else\ntrailing junk" assert _clean_org_note_content(content) == "my note text" @pytest.mark.django_db def test_emacs_scrobble_update_task_stores_cleaned_notes(): from datetime import datetime, timezone from django.contrib.auth import get_user_model from scrobbles.models import Scrobble from scrobbles.scrobblers import emacs_scrobble_update_task from tasks.models import Task user = get_user_model().objects.create(username="testuser") task = Task.find_or_create("My Org Task") scrobble = Scrobble.objects.create( user=user, task=task, media_type=Scrobble.MediaType.TASK, source="Org-mode", in_progress=True, timestamp=datetime(2026, 6, 1, 10, 0, tzinfo=timezone.utc), log={ "title": "My Org Task", "orgmode_id": "org-123", "notes": {}, }, ) emacs_notes = [ { "timestamp": "2026-06-09 13:14", "content": ( "- Note taken on [2026-06-09 Tue 13:14]\n" " The full stack trace:\n" " #+begin_src sh\n" ' File "x.py", line 1\n' " #+end_src\n" ), }, { "timestamp": "2026-06-10 09:00", "content": ( "- Note taken on [2026-06-10 Wed 09:00] \\\\\n" "\n" "\n" " See [[id:f6fc4950-07e6-459b-a256-c18282ca9256]" "[Mobile Transition Plan: Cookbooks V3 Nested → Flattened Fields]]\n" ), }, ] emacs_scrobble_update_task("org-123", emacs_notes, user.id) scrobble.refresh_from_db() notes = scrobble.log["notes"] assert "- Note taken on" not in notes["2026-06-09 13:14"] assert "```sh" in notes["2026-06-09 13:14"] assert 'File "x.py", line 1' in notes["2026-06-09 13:14"] assert "- Note taken on" not in notes["2026-06-10 09:00"] assert ( "[Mobile Transition Plan: Cookbooks V3 Nested → Flattened Fields]" "(id:f6fc4950-07e6-459b-a256-c18282ca9256)" ) in notes["2026-06-10 09:00"]