mirror of
https://github.com/natelandau/obsidian-metadata.git
synced 2025-11-10 06:03:48 -05:00
1234 lines
40 KiB
Python
1234 lines
40 KiB
Python
# type: ignore
|
|
"""Test notes.py."""
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import typer
|
|
|
|
from obsidian_metadata.models.enums import InsertLocation, MetadataType
|
|
from obsidian_metadata.models.exceptions import InlineMetadataError, InlineTagError
|
|
from obsidian_metadata.models.notes import Note
|
|
from tests.helpers import Regex
|
|
|
|
|
|
def test_note_not_exists() -> None:
|
|
"""Test target not found.
|
|
|
|
GIVEN a path to a non-existent file
|
|
WHEN a Note object is created pointing to that file
|
|
THEN a typer.Exit exception is raised
|
|
"""
|
|
with pytest.raises(typer.Exit):
|
|
Note(note_path="nonexistent_file.md")
|
|
|
|
|
|
def test_create_note_1(sample_note):
|
|
"""Test creating a note object.
|
|
|
|
GIVEN a path to a markdown file
|
|
WHEN a Note object is created pointing to that file
|
|
THEN the Note object is created
|
|
"""
|
|
note = Note(note_path=sample_note, dry_run=True)
|
|
assert note.note_path == Path(sample_note)
|
|
assert note.dry_run is True
|
|
assert "Lorem ipsum dolor" in note.file_content
|
|
assert note.encoding == "utf_8"
|
|
assert note.frontmatter.dict == {
|
|
"date_created": ["2022-12-22"],
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"shared_key1": ["shared_key1_value", "shared_key1_value3"],
|
|
"shared_key2": ["shared_key2_value1"],
|
|
"tags": [
|
|
"frontmatter_tag1",
|
|
"frontmatter_tag2",
|
|
"shared_tag",
|
|
"📅/frontmatter_tag3",
|
|
],
|
|
}
|
|
|
|
assert note.tags.list == [
|
|
"inline_tag_bottom1",
|
|
"inline_tag_bottom2",
|
|
"inline_tag_top1",
|
|
"inline_tag_top2",
|
|
"intext_tag1",
|
|
"intext_tag2",
|
|
"shared_tag",
|
|
]
|
|
assert note.inline_metadata.dict == {
|
|
"bottom_key1": ["bottom_key1_value"],
|
|
"bottom_key2": ["bottom_key2_value"],
|
|
"intext_key": ["intext_value"],
|
|
"key📅": ["📅_key_value"],
|
|
"shared_key1": ["shared_key1_value", "shared_key1_value2"],
|
|
"shared_key2": ["shared_key2_value2"],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value_as_link"],
|
|
}
|
|
|
|
with sample_note.open():
|
|
content = sample_note.read_text()
|
|
|
|
assert note.file_content == content
|
|
assert note.original_file_content == content
|
|
|
|
|
|
def test_create_note_2() -> None:
|
|
"""Test creating a note object.
|
|
|
|
GIVEN a text file with invalid frontmatter
|
|
WHEN the note is initialized
|
|
THEN a typer exit is raised
|
|
"""
|
|
broken_fm = Path("tests/fixtures/broken_frontmatter.md")
|
|
with pytest.raises(typer.Exit):
|
|
Note(note_path=broken_fm)
|
|
|
|
|
|
def test_create_note_3(sample_note, mocker) -> None:
|
|
"""Test creating a note object.
|
|
|
|
GIVEN a text file with invalid inline metadata
|
|
WHEN the note is initialized
|
|
THEN a typer exit is raised
|
|
"""
|
|
mocker.patch(
|
|
"obsidian_metadata.models.notes.InlineMetadata",
|
|
side_effect=InlineMetadataError("error message"),
|
|
)
|
|
|
|
with pytest.raises(typer.Exit):
|
|
Note(note_path=sample_note)
|
|
|
|
|
|
def test_create_note_4(sample_note, mocker) -> None:
|
|
"""Test creating a note object.
|
|
|
|
GIVEN a text file
|
|
WHEN there is an error parsing the inline tags
|
|
THEN a typer exit is raised
|
|
"""
|
|
mocker.patch(
|
|
"obsidian_metadata.models.notes.InlineTags",
|
|
side_effect=InlineTagError("error message"),
|
|
)
|
|
|
|
with pytest.raises(typer.Exit):
|
|
Note(note_path=sample_note)
|
|
|
|
|
|
def test_add_metadata_method_1(short_notes):
|
|
"""Test adding metadata.
|
|
|
|
GIVEN calling the add_metadata method
|
|
WHEN a key is passed without a value
|
|
THEN the key is added to to the InlineMetadata object and the file content
|
|
"""
|
|
note = Note(note_path=short_notes[0])
|
|
assert note.inline_metadata.dict == {}
|
|
|
|
assert (
|
|
note.add_metadata(MetadataType.INLINE, location=InsertLocation.BOTTOM, key="new_key1")
|
|
is True
|
|
)
|
|
assert note.inline_metadata.dict == {"new_key1": []}
|
|
assert "new_key1::" in note.file_content.strip()
|
|
|
|
|
|
def test_add_metadata_method_2(short_notes):
|
|
"""Test adding metadata.
|
|
|
|
GIVEN calling the add_metadata method
|
|
WHEN a key is passed with a value
|
|
THEN the key and value is added to to the InlineMetadata object and the file content
|
|
"""
|
|
note = Note(note_path=short_notes[0])
|
|
assert note.inline_metadata.dict == {}
|
|
|
|
assert (
|
|
note.add_metadata(
|
|
MetadataType.INLINE, key="new_key2", value="new_value1", location=InsertLocation.TOP
|
|
)
|
|
is True
|
|
)
|
|
assert note.inline_metadata.dict == {"new_key2": ["new_value1"]}
|
|
assert "new_key2:: new_value1" in note.file_content
|
|
|
|
|
|
def test_add_metadata_method_3(short_notes):
|
|
"""Test adding metadata.
|
|
|
|
GIVEN calling the add_metadata method
|
|
WHEN a key is passed that already exists
|
|
THEN the the method returns False
|
|
"""
|
|
note = Note(note_path=short_notes[0])
|
|
note.inline_metadata.dict = {"new_key1": []}
|
|
assert (
|
|
note.add_metadata(MetadataType.INLINE, location=InsertLocation.BOTTOM, key="new_key1")
|
|
is False
|
|
)
|
|
|
|
|
|
def test_add_metadata_method_4(short_notes):
|
|
"""Test adding metadata.
|
|
|
|
GIVEN calling the add_metadata method
|
|
WHEN a key is passed with a value that already exists
|
|
THEN the the method returns False
|
|
"""
|
|
note = Note(note_path=short_notes[0])
|
|
note.inline_metadata.dict = {"new_key2": ["new_value1"]}
|
|
assert (
|
|
note.add_metadata(
|
|
MetadataType.INLINE, key="new_key2", value="new_value1", location=InsertLocation.TOP
|
|
)
|
|
is False
|
|
)
|
|
|
|
|
|
def test_add_metadata_method_5(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN add_metadata() is called with a key or value that already exists in the frontmatter
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "frontmatter_Key1") is False
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "shared_key1", "shared_key1_value") is False
|
|
|
|
|
|
def test_add_metadata_method_6(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN add_metadata() is called with a new key
|
|
THEN the key is added to the frontmatter
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "new_key1" not in note.frontmatter.dict
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "new_key1") is True
|
|
assert "new_key1" in note.frontmatter.dict
|
|
|
|
|
|
def test_add_metadata_method_7(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN add_metadata() is called with a new key and value
|
|
THEN the key and value is added to the frontmatter
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "new_key" not in note.frontmatter.dict
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "new_key", "new_value") is True
|
|
assert note.frontmatter.dict["new_key"] == ["new_value"]
|
|
|
|
|
|
def test_add_metadata_method_8(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN add_metadata() is called with an existing key and new value
|
|
THEN the new value is appended to the existing key
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "new_key" not in note.frontmatter.dict
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "new_key", "new_value") is True
|
|
assert note.frontmatter.dict["new_key"] == ["new_value"]
|
|
assert note.add_metadata(MetadataType.FRONTMATTER, "new_key", "new_value2") is True
|
|
assert note.frontmatter.dict["new_key"] == ["new_value", "new_value2"]
|
|
|
|
|
|
def test_add_metadata_method_9(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN add_metadata() is with an existing tag
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert (
|
|
note.add_metadata(MetadataType.TAGS, value="shared_tag", location=InsertLocation.TOP)
|
|
is False
|
|
)
|
|
|
|
|
|
def test_add_metadata_method_10(sample_note):
|
|
"""Test add_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN add_metadata() is called with a new tag
|
|
THEN the tag is added to the InlineTags object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "new_tag2" not in note.tags.list
|
|
assert (
|
|
note.add_metadata(MetadataType.TAGS, value="new_tag2", location=InsertLocation.BOTTOM)
|
|
is True
|
|
)
|
|
assert "new_tag2" in note.tags.list
|
|
assert "#new_tag2" in note.file_content
|
|
|
|
|
|
def test_commit_1(sample_note, tmp_path) -> None:
|
|
"""Test commit() method.
|
|
|
|
GIVEN a note object with commit() called
|
|
WHEN the note is modified
|
|
THEN the updated note is committed to the file system
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.sub(pattern="Heading 1", replacement="Heading 2")
|
|
|
|
note.commit()
|
|
note = Note(note_path=sample_note)
|
|
assert "Heading 2" in note.file_content
|
|
assert "Heading 1" not in note.file_content
|
|
|
|
new_path = Path(tmp_path / "new_note.md")
|
|
note.commit(new_path)
|
|
note2 = Note(note_path=new_path)
|
|
assert "Heading 2" in note2.file_content
|
|
assert "Heading 1" not in note2.file_content
|
|
|
|
|
|
def test_commit_2(sample_note) -> None:
|
|
"""Test commit() method.
|
|
|
|
GIVEN a note object with commit() called
|
|
WHEN the note is modified and dry_run is True
|
|
THEN the note is not committed to the file system
|
|
"""
|
|
note = Note(note_path=sample_note, dry_run=True)
|
|
note.sub(pattern="Heading 1", replacement="Heading 2")
|
|
|
|
note.commit()
|
|
note = Note(note_path=sample_note)
|
|
assert "Heading 1" in note.file_content
|
|
|
|
|
|
def test_contains_tag(sample_note) -> None:
|
|
"""Test contains_tag method.
|
|
|
|
GIVEN a note object
|
|
WHEN contains_tag() is called
|
|
THEN the method returns True if the tag is found and False if not
|
|
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.contains_tag("intext_tag1") is True
|
|
assert note.contains_tag("nonexistent_tag") is False
|
|
assert note.contains_tag(r"\d$", is_regex=True) is True
|
|
assert note.contains_tag(r"^\d", is_regex=True) is False
|
|
|
|
|
|
def test_contains_metadata(sample_note) -> None:
|
|
"""Test contains_metadata method.
|
|
|
|
GIVEN a note object
|
|
WHEN contains_metadata() is called
|
|
THEN the method returns True if the key and/or value are found and False if not
|
|
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
assert note.contains_metadata("no key") is False
|
|
assert note.contains_metadata("frontmatter_Key2") is True
|
|
assert note.contains_metadata(r"^\d", is_regex=True) is False
|
|
assert note.contains_metadata(r"^[\w_]+\d", is_regex=True) is True
|
|
assert note.contains_metadata("frontmatter_Key2", "no value") is False
|
|
assert note.contains_metadata("frontmatter_Key2", "article") is True
|
|
assert note.contains_metadata("bottom_key1", "bottom_key1_value") is True
|
|
assert note.contains_metadata(r"bottom_key\d$", r"bottom_key\d_value", is_regex=True) is True
|
|
|
|
|
|
def test_delete_all_metadata(sample_note):
|
|
"""Test delete_all_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_all_metadata() is called
|
|
THEN all tags, frontmatter, and inline metadata are deleted
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.delete_all_metadata()
|
|
assert note.tags.list == []
|
|
assert note.frontmatter.dict == {}
|
|
assert note.inline_metadata.dict == {}
|
|
assert note.file_content == Regex("consequat. Duis")
|
|
assert "codeblock_key:: some text" in note.file_content
|
|
assert "#ffffff" in note.file_content
|
|
assert "---" not in note.file_content
|
|
|
|
|
|
def test_delete_tag(sample_note) -> None:
|
|
"""Test delete_tag method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_tag() is called
|
|
THEN the method returns True if the tag is found and deleted and False if not
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.delete_tag("not_a_tag") is False
|
|
assert note.delete_tag("intext_tag[1]") is True
|
|
assert "intext_tag1" not in note.tags.list
|
|
assert note.file_content == Regex("consequat. Duis")
|
|
|
|
|
|
def test_delete_metadata_1(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with a keys or values that do not exist
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.delete_metadata("nonexistent_key") is False
|
|
assert note.delete_metadata("frontmatter_Key1", "no value") is False
|
|
|
|
|
|
def test_delete_metadata_2(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with a frontmatter key and no value
|
|
THEN the entire key and all values are deleted
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "frontmatter_Key1" in note.frontmatter.dict
|
|
assert note.delete_metadata("frontmatter_Key1") is True
|
|
assert "frontmatter_Key1" not in note.frontmatter.dict
|
|
|
|
|
|
def test_delete_metadata_3(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with a frontmatter key and value
|
|
THEN the value is deleted from the key
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.frontmatter.dict["frontmatter_Key2"] == ["article", "note"]
|
|
assert note.delete_metadata("frontmatter_Key2", "article") is True
|
|
assert note.frontmatter.dict["frontmatter_Key2"] == ["note"]
|
|
|
|
|
|
def test_delete_metadata_4(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with an inline key and value
|
|
THEN the value is deleted from the InlineMetadata object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.inline_metadata.dict["bottom_key1"] == ["bottom_key1_value"]
|
|
assert note.file_content == Regex(r"bottom_key1:: bottom_key1_value\n")
|
|
assert note.delete_metadata("bottom_key1", "bottom_key1_value") is True
|
|
assert note.inline_metadata.dict["bottom_key1"] == []
|
|
assert note.file_content == Regex(r"bottom_key1::\n")
|
|
|
|
|
|
def test_delete_metadata_5(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with an inline key and no value
|
|
THEN the key and all values are deleted from the InlineMetadata object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.inline_metadata.dict["bottom_key2"] == ["bottom_key2_value"]
|
|
assert note.delete_metadata("bottom_key2") is True
|
|
assert "bottom_key2" not in note.inline_metadata.dict
|
|
assert note.file_content != Regex(r"bottom_key2")
|
|
|
|
|
|
def test_delete_metadata_6(sample_note):
|
|
"""Test delete_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN delete_metadata() is called with an inline key and a single value
|
|
THEN the specified value is removed from the InlineMetadata object and the file content and remaining values are untouched
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.inline_metadata.dict["shared_key1"] == ["shared_key1_value", "shared_key1_value2"]
|
|
assert (
|
|
note.delete_metadata("shared_key1", "shared_key1_value2", area=MetadataType.INLINE) is True
|
|
)
|
|
assert note.inline_metadata.dict["shared_key1"] == ["shared_key1_value"]
|
|
assert note.file_content == Regex(r"shared_key1_value")
|
|
assert note.file_content != Regex(r"shared_key1_value2")
|
|
|
|
|
|
def test_has_changes(sample_note) -> None:
|
|
"""Test has_changes() method.
|
|
|
|
GIVEN a note object
|
|
WHEN has_changes() is called
|
|
THEN the method returns True if the note has changes and False if not
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.has_changes() is False
|
|
note.write_string("This is a test string.", location=InsertLocation.BOTTOM)
|
|
assert note.has_changes() is True
|
|
|
|
note = Note(note_path=sample_note)
|
|
assert note.has_changes() is False
|
|
note.delete_metadata("frontmatter_Key1")
|
|
assert note.has_changes() is True
|
|
|
|
note = Note(note_path=sample_note)
|
|
assert note.has_changes() is False
|
|
note.delete_metadata("bottom_key2")
|
|
assert note.has_changes() is True
|
|
|
|
note = Note(note_path=sample_note)
|
|
assert note.has_changes() is False
|
|
note.delete_tag("intext_tag1")
|
|
assert note.has_changes() is True
|
|
|
|
|
|
def test_print_diff(sample_note, capsys) -> None:
|
|
"""Test print_diff() method.
|
|
|
|
GIVEN a note object
|
|
WHEN print_diff() is called
|
|
THEN the note's diff is printed to stdout
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
note.write_string("This is a test string.", location=InsertLocation.BOTTOM)
|
|
note.print_diff()
|
|
captured = capsys.readouterr()
|
|
assert "+ This is a test string." in captured.out
|
|
|
|
note.sub("The quick brown fox", "The quick brown hedgehog")
|
|
note.print_diff()
|
|
captured = capsys.readouterr()
|
|
assert "- The quick brown fox" in captured.out
|
|
assert "+ The quick brown hedgehog" in captured.out
|
|
|
|
|
|
def test_print_note(sample_note, capsys) -> None:
|
|
"""Test print_note() method.
|
|
|
|
GIVEN a note object
|
|
WHEN print_note() is called
|
|
THEN the note's new content is printed to stdout
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.print_note()
|
|
captured = capsys.readouterr()
|
|
assert "```python" in captured.out
|
|
assert "---" in captured.out
|
|
assert "#shared_tag" in captured.out
|
|
|
|
|
|
def test_rename_tag_1(sample_note) -> None:
|
|
"""Test rename_tag() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_tag() is called with a tag that does not exist
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.rename_tag("no_note_tag", "intext_tag2") is False
|
|
|
|
|
|
def test_rename_tag_2(sample_note) -> None:
|
|
"""Test rename_tag() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_tag() is called with a tag exists
|
|
THEN the tag is renamed in the InlineTag object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "intext_tag1" in note.tags.list
|
|
assert note.rename_tag("intext_tag1", "intext_tag26") is True
|
|
assert "intext_tag1" not in note.tags.list
|
|
assert "intext_tag26" in note.tags.list
|
|
assert note.file_content == Regex(r"#intext_tag26")
|
|
assert note.file_content != Regex(r"#intext_tag1")
|
|
|
|
|
|
def test_rename_metadata_1(sample_note) -> None:
|
|
"""Test rename_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_metadata() is called with a key and/or value that does not exist
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.rename_metadata("nonexistent_key", "new_key") is False
|
|
assert note.rename_metadata("frontmatter_Key1", "nonexistent_value", "article") is False
|
|
|
|
|
|
def test_rename_metadata_2(sample_note) -> None:
|
|
"""Test rename_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_metadata() is called with key that matches a frontmatter key
|
|
THEN the key is renamed in the Frontmatter object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.frontmatter.dict["frontmatter_Key1"] == ["author name"]
|
|
assert note.rename_metadata("frontmatter_Key1", "new_key") is True
|
|
assert "frontmatter_Key1" not in note.frontmatter.dict
|
|
assert "new_key" in note.frontmatter.dict
|
|
assert note.frontmatter.dict["new_key"] == ["author name"]
|
|
assert note.file_content == Regex(r"new_key: author name")
|
|
|
|
|
|
def test_rename_metadata_3(sample_note) -> None:
|
|
"""Test rename_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_metadata() is called with key/value that matches a frontmatter key/value
|
|
THEN the key/value is renamed in the Frontmatter object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.frontmatter.dict["frontmatter_Key2"] == ["article", "note"]
|
|
assert note.rename_metadata("frontmatter_Key2", "article", "new_key") is True
|
|
assert note.frontmatter.dict["frontmatter_Key2"] == ["new_key", "note"]
|
|
assert note.file_content == Regex(r" - new_key")
|
|
assert note.file_content != Regex(r" - article")
|
|
|
|
|
|
def test_rename_metadata_4(sample_note) -> None:
|
|
"""Test rename_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_metadata() is called with key that matches an inline key
|
|
THEN the key is renamed in the InlineMetada object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.rename_metadata("bottom_key1", "new_key") is True
|
|
assert "bottom_key1" not in note.inline_metadata.dict
|
|
assert "new_key" in note.inline_metadata.dict
|
|
assert note.file_content == Regex(r"new_key:: bottom_key1_value")
|
|
|
|
|
|
def test_rename_metadata_5(sample_note) -> None:
|
|
"""Test rename_metadata() method.
|
|
|
|
GIVEN a note object
|
|
WHEN rename_metadata() is called with key/value that matches an inline key/value
|
|
THEN the key/value is renamed in the InlineMetada object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.rename_metadata("bottom_key1", "bottom_key1_value", "new_value") is True
|
|
assert note.inline_metadata.dict["bottom_key1"] == ["new_value"]
|
|
assert note.file_content == Regex(r"bottom_key1:: new_value")
|
|
|
|
|
|
def test_sub(sample_note) -> None:
|
|
"""Test the sub() method.
|
|
|
|
GIVEN a note object
|
|
WHEN sub() is called with a string that exists in the note
|
|
THEN the string is replaced in the note's file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.sub("#shared_tag", "#unshared_tags", is_regex=True)
|
|
assert note.file_content != Regex(r"#shared_tag")
|
|
assert note.file_content == Regex(r"#unshared_tags")
|
|
|
|
note.sub(" ut ", "")
|
|
assert note.file_content != Regex(r" ut ")
|
|
assert note.file_content == Regex(r"laboriosam, nisialiquid ex ea")
|
|
|
|
|
|
def test_transpose_metadata_1(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a metadata object is empty
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.frontmatter.dict = {}
|
|
assert note.transpose_metadata(begin=MetadataType.FRONTMATTER, end=MetadataType.INLINE) is False
|
|
|
|
note = Note(note_path=sample_note)
|
|
note.inline_metadata.dict = {}
|
|
assert note.transpose_metadata(begin=MetadataType.INLINE, end=MetadataType.FRONTMATTER) is False
|
|
|
|
|
|
def test_transpose_metadata_2(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a specified key and/or value does not exist
|
|
THEN the method returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="not_a_key",
|
|
)
|
|
is False
|
|
)
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="frontmatter_Key2",
|
|
value="not_a_value",
|
|
)
|
|
is False
|
|
)
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="frontmatter_Key2",
|
|
value=["not_a_value", "not_a_value2"],
|
|
)
|
|
is False
|
|
)
|
|
|
|
|
|
def test_transpose_metadata_3(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN FRONTMATTER to INLINE and no key or value is specified
|
|
THEN all frontmatter is removed and added to the inline metadata object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.transpose_metadata(begin=MetadataType.FRONTMATTER, end=MetadataType.INLINE) is True
|
|
assert note.frontmatter.dict == {}
|
|
assert note.inline_metadata.dict == {
|
|
"bottom_key1": ["bottom_key1_value"],
|
|
"bottom_key2": ["bottom_key2_value"],
|
|
"date_created": ["2022-12-22"],
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_value"],
|
|
"key📅": ["📅_key_value"],
|
|
"shared_key1": [
|
|
"shared_key1_value",
|
|
"shared_key1_value2",
|
|
"shared_key1_value3",
|
|
],
|
|
"shared_key2": ["shared_key2_value2", "shared_key2_value1"],
|
|
"tags": [
|
|
"frontmatter_tag1",
|
|
"frontmatter_tag2",
|
|
"shared_tag",
|
|
"📅/frontmatter_tag3",
|
|
],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value_as_link"],
|
|
}
|
|
|
|
|
|
def test_transpose_metadata_4(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN INLINE to FRONTMATTER and no key or value is specified
|
|
THEN all inline metadata is removed and added to the frontmatter object and the file content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.transpose_metadata(begin=MetadataType.INLINE, end=MetadataType.FRONTMATTER) is True
|
|
assert note.inline_metadata.dict == {}
|
|
assert note.frontmatter.dict == {
|
|
"bottom_key1": ["bottom_key1_value"],
|
|
"bottom_key2": ["bottom_key2_value"],
|
|
"date_created": ["2022-12-22"],
|
|
"frontmatter_Key1": ["author name"],
|
|
"frontmatter_Key2": ["article", "note"],
|
|
"intext_key": ["intext_value"],
|
|
"key📅": ["📅_key_value"],
|
|
"shared_key1": [
|
|
"shared_key1_value",
|
|
"shared_key1_value2",
|
|
"shared_key1_value3",
|
|
],
|
|
"shared_key2": ["shared_key2_value1", "shared_key2_value2"],
|
|
"tags": [
|
|
"frontmatter_tag1",
|
|
"frontmatter_tag2",
|
|
"shared_tag",
|
|
"📅/frontmatter_tag3",
|
|
],
|
|
"top_key1": ["top_key1_value"],
|
|
"top_key2": ["top_key2_value"],
|
|
"top_key3": ["top_key3_value_as_link"],
|
|
}
|
|
|
|
|
|
def test_transpose_metadata_5(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a key exists in both frontmatter and inline metadata
|
|
THEN the values for the key are merged in the specified metadata object
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert note.frontmatter.dict["shared_key1"] == ["shared_key1_value", "shared_key1_value3"]
|
|
assert note.inline_metadata.dict["shared_key1"] == ["shared_key1_value", "shared_key1_value2"]
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="shared_key1",
|
|
)
|
|
is True
|
|
)
|
|
assert "shared_key1" not in note.frontmatter.dict
|
|
assert note.inline_metadata.dict["shared_key1"] == [
|
|
"shared_key1_value",
|
|
"shared_key1_value2",
|
|
"shared_key1_value3",
|
|
]
|
|
|
|
|
|
def test_transpose_metadata_6(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a specified key with no value is specified
|
|
THEN the key is removed from the specified metadata object and added to the target metadata object
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert "top_key1" not in note.frontmatter.dict
|
|
assert "top_key1" in note.inline_metadata.dict
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.INLINE,
|
|
end=MetadataType.FRONTMATTER,
|
|
key="top_key1",
|
|
)
|
|
is True
|
|
)
|
|
assert "top_key1" not in note.inline_metadata.dict
|
|
assert note.frontmatter.dict["top_key1"] == ["top_key1_value"]
|
|
|
|
|
|
def test_transpose_metadata_7(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a specified value is a list
|
|
THEN the key/value is removed from the specified metadata object and added to the target metadata object
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="frontmatter_Key2",
|
|
value=["article", "note"],
|
|
)
|
|
is True
|
|
)
|
|
assert "frontmatter_Key2" not in note.frontmatter.dict
|
|
assert note.inline_metadata.dict["frontmatter_Key2"] == ["article", "note"]
|
|
|
|
|
|
def test_transpose_metadata_8(sample_note):
|
|
"""Test transpose_metadata() method.
|
|
|
|
GIVEN a note object with transpose_metadata() is called
|
|
WHEN a specified value is a string
|
|
THEN the key/value is removed from the specified metadata object and added to the target metadata object
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
assert (
|
|
note.transpose_metadata(
|
|
begin=MetadataType.FRONTMATTER,
|
|
end=MetadataType.INLINE,
|
|
key="frontmatter_Key2",
|
|
value="note",
|
|
)
|
|
is True
|
|
)
|
|
assert note.frontmatter.dict["frontmatter_Key2"] == ["article"]
|
|
assert note.inline_metadata.dict["frontmatter_Key2"] == ["note"]
|
|
|
|
|
|
def test_write_delete_inline_metadata_1(sample_note) -> None:
|
|
"""Twrite_delete_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_delete_inline_metadata() called
|
|
WHEN a key is specified that is not in the inline metadata
|
|
THEN the file content is not changed
|
|
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.write_delete_inline_metadata("nonexistent_key")
|
|
assert note.file_content == note.original_file_content
|
|
note.write_delete_inline_metadata("frontmatter_Key1")
|
|
assert note.file_content == note.original_file_content
|
|
|
|
|
|
def test_write_delete_inline_metadata_2(sample_note) -> None:
|
|
"""Twrite_delete_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_delete_inline_metadata() called
|
|
WHEN a key is specified that is within a body of text
|
|
THEN the key and all associated values are removed from the note content
|
|
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.write_delete_inline_metadata("intext_key", is_regex=False)
|
|
assert note.file_content == Regex(r"dolore eu fugiat", re.DOTALL)
|
|
|
|
|
|
def test_write_delete_inline_metadata_3(sample_note) -> None:
|
|
"""Twrite_delete_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_delete_inline_metadata() called
|
|
WHEN a key is specified that is not within a body of text
|
|
THEN the key/value is removed from the note content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.write_delete_inline_metadata("bottom_key2", "bottom_key2_value", is_regex=False)
|
|
assert note.file_content != Regex(r"bottom_key2_value")
|
|
assert note.file_content == Regex(r"bottom_key2::")
|
|
note.write_delete_inline_metadata("bottom_key1")
|
|
assert note.file_content != Regex(r"bottom_key1::")
|
|
|
|
|
|
def test_write_delete_inline_metadata_4(sample_note) -> None:
|
|
"""Twrite_delete_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_delete_inline_metadata() called
|
|
WHEN no key or value is specified
|
|
THEN all inline metadata is removed from the note content
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.write_delete_inline_metadata()
|
|
assert note.file_content == Regex(r"codeblock_key::")
|
|
assert note.file_content != Regex(r"key📅::")
|
|
assert note.file_content != Regex(r"top_key1::")
|
|
assert note.file_content != Regex(r"top_key3::")
|
|
assert note.file_content != Regex(r"intext_key::")
|
|
assert note.file_content != Regex(r"shared_key1::")
|
|
assert note.file_content != Regex(r"shared_key2::")
|
|
assert note.file_content != Regex(r"bottom_key1::")
|
|
assert note.file_content != Regex(r"bottom_key2::")
|
|
|
|
|
|
def test_write_frontmatter_1(sample_note) -> None:
|
|
"""Test writing frontmatter.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN the frontmatter object is different
|
|
THEN the old frontmatter is replaced with the new frontmatter
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
assert note.rename_metadata("frontmatter_Key1", "author name", "some_new_key_here") is True
|
|
assert note.write_frontmatter() is True
|
|
new_frontmatter = """---
|
|
date_created: '2022-12-22'
|
|
tags:
|
|
- frontmatter_tag1
|
|
- frontmatter_tag2
|
|
- shared_tag
|
|
- 📅/frontmatter_tag3
|
|
frontmatter_Key1: some_new_key_here
|
|
frontmatter_Key2:
|
|
- article
|
|
- note
|
|
shared_key1:
|
|
- shared_key1_value
|
|
- shared_key1_value3
|
|
shared_key2: shared_key2_value1
|
|
---"""
|
|
assert new_frontmatter in note.file_content
|
|
assert "# Heading 1" in note.file_content
|
|
assert "```python" in note.file_content
|
|
|
|
|
|
def test_write_frontmatter_2() -> None:
|
|
"""Test replacing frontmatter.
|
|
|
|
GIVEN a note with no frontmatter
|
|
WHEN the frontmatter object has values
|
|
THEN the frontmatter is added to the note
|
|
"""
|
|
note = Note(note_path="tests/fixtures/test_vault/no_metadata.md")
|
|
|
|
note.frontmatter.dict = {"key1": "value1", "key2": "value2"}
|
|
assert note.write_frontmatter() is True
|
|
new_frontmatter = """---
|
|
key1: value1
|
|
key2: value2
|
|
---"""
|
|
assert new_frontmatter in note.file_content
|
|
assert "Lorem ipsum dolor sit amet" in note.file_content
|
|
|
|
|
|
def test_write_frontmatter_3(sample_note) -> None:
|
|
"""Test replacing frontmatter.
|
|
|
|
GIVEN a note with frontmatter
|
|
WHEN the frontmatter object is empty
|
|
THEN the frontmatter is removed from the note
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
note.frontmatter.dict = {}
|
|
assert note.write_frontmatter() is True
|
|
assert "---" not in note.file_content
|
|
assert note.file_content != Regex("date_created:")
|
|
assert "Lorem ipsum dolor sit amet" in note.file_content
|
|
|
|
|
|
def test_write_frontmatter_4() -> None:
|
|
"""Test replacing frontmatter.
|
|
|
|
GIVEN a note with no frontmatter
|
|
WHEN the frontmatter object is empty
|
|
THEN the frontmatter is not added to the note
|
|
"""
|
|
note = Note(note_path="tests/fixtures/test_vault/no_metadata.md")
|
|
note.frontmatter.dict = {}
|
|
assert note.write_frontmatter() is False
|
|
assert "---" not in note.file_content
|
|
assert "Lorem ipsum dolor sit amet" in note.file_content
|
|
|
|
|
|
def test_write_all_inline_metadata_1(sample_note) -> None:
|
|
"""Test write_all_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_metadata_all() called
|
|
WHEN the note has inline metadata
|
|
THEN the inline metadata is written to the note
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
metadata_block = """
|
|
bottom_key1:: bottom_key1_value
|
|
bottom_key2:: bottom_key2_value
|
|
intext_key:: intext_value
|
|
key📅:: 📅_key_value
|
|
shared_key1:: shared_key1_value
|
|
shared_key1:: shared_key1_value2
|
|
shared_key2:: shared_key2_value2
|
|
top_key1:: top_key1_value
|
|
top_key2:: top_key2_value
|
|
top_key3:: top_key3_value_as_link"""
|
|
assert metadata_block not in note.file_content
|
|
assert note.write_all_inline_metadata(location=InsertLocation.BOTTOM) is True
|
|
assert metadata_block in note.file_content
|
|
|
|
|
|
def test_write_all_inline_metadata_2(sample_note) -> None:
|
|
"""Test write_all_inline_metadata() method.
|
|
|
|
GIVEN a note object with write_metadata_all() called
|
|
WHEN the note has no inline metadata
|
|
THEN write_all_inline_metadata returns False
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.inline_metadata.dict = {}
|
|
assert note.write_all_inline_metadata(location=InsertLocation.BOTTOM) is False
|
|
|
|
|
|
def test_write_inline_metadata_change_1(sample_note):
|
|
"""Test write_inline_metadata_change() method.
|
|
|
|
GIVEN a note object with write_inline_metadata_change() called
|
|
WHEN the key and/or value is not in the note
|
|
THEN the key and/or value is not added to the note
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
note.write_inline_metadata_change("nonexistent_key", "new_key")
|
|
assert note.file_content == note.original_file_content
|
|
note.write_inline_metadata_change("bottom_key1", "no_value", "new_value")
|
|
assert note.file_content == note.original_file_content
|
|
|
|
|
|
def test_write_inline_metadata_change_2(sample_note):
|
|
"""Test write_inline_metadata_change() method.
|
|
|
|
GIVEN a note object with write_inline_metadata_change() called
|
|
WHEN the key is in the note
|
|
THEN the key is changed to the new key
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
|
|
note.write_inline_metadata_change("bottom_key1", "new_key")
|
|
assert note.file_content != Regex(r"bottom_key1::")
|
|
assert note.file_content == Regex(r"new_key:: bottom_key1_value")
|
|
|
|
|
|
def test_write_inline_metadata_change_3(sample_note):
|
|
"""Test write_inline_metadata_change() method.
|
|
|
|
GIVEN a note object with write_inline_metadata_change() called
|
|
WHEN the key and value is in the note
|
|
THEN the value is changed
|
|
"""
|
|
note = Note(note_path=sample_note)
|
|
note.write_inline_metadata_change("key📅", "📅_key_value", "new_value")
|
|
assert note.file_content != Regex(r"key📅:: ?📅_key_value")
|
|
assert note.file_content == Regex(r"key📅:: ?new_value")
|
|
|
|
|
|
def test_write_string_1(short_notes) -> None:
|
|
"""Test the write_string() method.
|
|
|
|
GIVEN a note object with write_string() called
|
|
WHEN the specified location is BOTTOM
|
|
THEN the string is written to the bottom of the note
|
|
"""
|
|
path1, path2 = short_notes
|
|
note = Note(note_path=str(path1))
|
|
note2 = Note(note_path=str(path2))
|
|
|
|
string1 = "This is a test string."
|
|
string2 = "This is"
|
|
|
|
correct_content = """
|
|
---
|
|
key: value
|
|
---
|
|
|
|
# header 1
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
|
|
This is a test string.
|
|
"""
|
|
correct_content2 = """
|
|
---
|
|
key: value
|
|
---
|
|
|
|
# header 1
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
|
|
This is a test string.
|
|
This is
|
|
"""
|
|
correct_content3 = """
|
|
Lorem ipsum dolor sit amet.
|
|
|
|
This is a test string.
|
|
"""
|
|
note.write_string(new_string=string1, location=InsertLocation.BOTTOM)
|
|
assert note.file_content == correct_content.strip()
|
|
|
|
note.write_string(new_string=string2, location=InsertLocation.BOTTOM)
|
|
assert note.file_content == correct_content.strip()
|
|
|
|
note.write_string(new_string=string2, allow_multiple=True, location=InsertLocation.BOTTOM)
|
|
assert note.file_content == correct_content2.strip()
|
|
|
|
note2.write_string(new_string=string1, location=InsertLocation.BOTTOM)
|
|
assert note2.file_content == correct_content3.strip()
|
|
|
|
|
|
def test_write_string_2(short_notes) -> None:
|
|
"""Test the write_string() method.
|
|
|
|
GIVEN a note object with write_string() called
|
|
WHEN the specified location is TOP
|
|
THEN the string is written to the top of the note
|
|
"""
|
|
path1, path2 = short_notes
|
|
note = Note(note_path=str(path1))
|
|
note2 = Note(note_path=str(path2))
|
|
|
|
string1 = "This is a test string."
|
|
string2 = "This is"
|
|
correct_content = """
|
|
---
|
|
key: value
|
|
---
|
|
This is a test string.
|
|
|
|
# header 1
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
|
|
correct_content2 = """
|
|
---
|
|
key: value
|
|
---
|
|
This is
|
|
This is a test string.
|
|
|
|
# header 1
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
correct_content3 = """
|
|
This is a test string.
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
|
|
note.write_string(new_string=string1, location=InsertLocation.TOP)
|
|
assert note.file_content.strip() == correct_content.strip()
|
|
|
|
note.write_string(new_string=string2, allow_multiple=True, location=InsertLocation.TOP)
|
|
assert note.file_content.strip() == correct_content2.strip()
|
|
|
|
note2.write_string(new_string=string1, location=InsertLocation.TOP)
|
|
assert note2.file_content.strip() == correct_content3.strip()
|
|
|
|
|
|
def test_write_string_3(short_notes) -> None:
|
|
"""Test the write_string() method.
|
|
|
|
GIVEN a note object with write_string() called
|
|
WHEN the specified location is AFTER_TITLE
|
|
THEN the string is written after the title of the note
|
|
"""
|
|
path1, path2 = short_notes
|
|
note = Note(note_path=str(path1))
|
|
note2 = Note(note_path=str(path2))
|
|
|
|
string1 = "This is a test string."
|
|
string2 = "This is"
|
|
correct_content = """
|
|
---
|
|
key: value
|
|
---
|
|
|
|
# header 1
|
|
This is a test string.
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
|
|
correct_content2 = """
|
|
---
|
|
key: value
|
|
---
|
|
|
|
# header 1
|
|
This is
|
|
This is a test string.
|
|
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
correct_content3 = """
|
|
This is a test string.
|
|
Lorem ipsum dolor sit amet.
|
|
"""
|
|
|
|
note.write_string(new_string=string1, location=InsertLocation.AFTER_TITLE)
|
|
assert note.file_content.strip() == correct_content.strip()
|
|
|
|
note.write_string(new_string=string2, allow_multiple=True, location=InsertLocation.AFTER_TITLE)
|
|
assert note.file_content.strip() == correct_content2.strip()
|
|
|
|
note2.write_string(new_string=string1, location=InsertLocation.AFTER_TITLE)
|
|
assert note2.file_content.strip() == correct_content3.strip()
|