# type: ignore """Tests for the Vault module.""" from pathlib import Path from obsidian_metadata._config import Config from obsidian_metadata.models import Vault, VaultFilter from obsidian_metadata.models.enums import InsertLocation, MetadataType from tests.helpers import Regex def test_vault_creation(test_vault): """Test creating a Vault object.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.name == "vault" assert vault.vault_path == vault_path assert vault.insert_location == InsertLocation.BOTTOM assert vault.backup_path == Path(f"{vault_path}.bak") assert vault.dry_run is False assert str(vault.exclude_paths[0]) == Regex(r".*\.git") assert len(vault.all_notes) == 3 assert vault.metadata.dict == { "author": ["author name"], "bottom_key1": ["bottom_key1_value"], "bottom_key2": ["bottom_key2_value"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "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", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "top_key1": ["top_key1_value"], "top_key2": ["top_key2_value"], "top_key3": ["top_key3_value_as_link"], "type": ["article", "note"], } assert vault.metadata.tags == [ "ignored_file_tag2", "inline_tag_bottom1", "inline_tag_bottom2", "inline_tag_top1", "inline_tag_top2", "intext_tag1", "intext_tag2", "shared_tag", ] assert vault.metadata.inline_metadata == { "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"], } assert vault.metadata.frontmatter == { "author": ["author name"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "shared_key1": ["shared_key1_value", "shared_key1_value3"], "shared_key2": ["shared_key2_value1"], "tags": [ "frontmatter_tag1", "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "type": ["article", "note"], } def set_insert_location(test_vault): """Test setting a new insert location.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.name == "vault" assert vault.vault_path == vault_path assert vault.insert_location == InsertLocation.BOTTOM vault.insert_location = InsertLocation.TOP assert vault.insert_location == InsertLocation.TOP def test_add_metadata(test_vault) -> None: """Test adding metadata to the vault.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.add_metadata(MetadataType.FRONTMATTER, "new_key") == 3 assert vault.metadata.dict == { "author": ["author name"], "bottom_key1": ["bottom_key1_value"], "bottom_key2": ["bottom_key2_value"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "intext_key": ["intext_value"], "key📅": ["📅_key_value"], "new_key": [], "shared_key1": [ "shared_key1_value", "shared_key1_value2", "shared_key1_value3", ], "shared_key2": ["shared_key2_value1", "shared_key2_value2"], "tags": [ "frontmatter_tag1", "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "top_key1": ["top_key1_value"], "top_key2": ["top_key2_value"], "top_key3": ["top_key3_value_as_link"], "type": ["article", "note"], } assert vault.metadata.frontmatter == { "author": ["author name"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "new_key": [], "shared_key1": ["shared_key1_value", "shared_key1_value3"], "shared_key2": ["shared_key2_value1"], "tags": [ "frontmatter_tag1", "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "type": ["article", "note"], } assert vault.add_metadata(MetadataType.FRONTMATTER, "new_key2", "new_key2_value") == 3 assert vault.metadata.dict == { "author": ["author name"], "bottom_key1": ["bottom_key1_value"], "bottom_key2": ["bottom_key2_value"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "intext_key": ["intext_value"], "key📅": ["📅_key_value"], "new_key": [], "new_key2": ["new_key2_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", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "top_key1": ["top_key1_value"], "top_key2": ["top_key2_value"], "top_key3": ["top_key3_value_as_link"], "type": ["article", "note"], } assert vault.metadata.frontmatter == { "author": ["author name"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "new_key": [], "new_key2": ["new_key2_value"], "shared_key1": ["shared_key1_value", "shared_key1_value3"], "shared_key2": ["shared_key2_value1"], "tags": [ "frontmatter_tag1", "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "type": ["article", "note"], } def test_backup(test_vault, capsys): """Test backing up the vault.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) vault.backup() captured = capsys.readouterr() assert Path(f"{vault_path}.bak").exists() is True assert captured.out == Regex(r"SUCCESS +| backed up to") vault.info() captured = capsys.readouterr() assert captured.out == Regex(r"Backup path +\│[\s ]+/[\d\w]+") def test_commit(test_vault, tmp_path): """Test committing changes to content in the vault.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) content = Path(f"{tmp_path}/vault/test1.md").read_text() assert "new_key: new_key_value" not in content vault.add_metadata(MetadataType.FRONTMATTER, "new_key", "new_key_value") vault.commit_changes() assert "new_key: new_key_value" not in content def test_commit_dry_run(test_vault, tmp_path): """Test committing changes to content in the vault in dry run mode.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config, dry_run=True) content = Path(f"{tmp_path}/vault/test1.md").read_text() assert "new_key: new_key_value" not in content vault.add_metadata(MetadataType.FRONTMATTER, "new_key", "new_key_value") vault.commit_changes() assert "new_key: new_key_value" not in content def test_backup_dryrun(test_vault, capsys): """Test backing up the vault.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config, dry_run=True) print(f"vault.dry_run: {vault.dry_run}") vault.backup() captured = capsys.readouterr() assert vault.backup_path.exists() is False assert captured.out == Regex(r"DRYRUN +| Backup up vault to") def test_delete_backup(test_vault, capsys): """Test deleting the vault backup.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) vault.backup() vault.delete_backup() captured = capsys.readouterr() assert captured.out == Regex(r"Backup deleted") assert vault.backup_path.exists() is False vault.info() captured = capsys.readouterr() assert captured.out == Regex(r"Backup +\│ None") def test_delete_backup_dryrun(test_vault, capsys): """Test deleting the vault backup.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config, dry_run=True) Path.mkdir(vault.backup_path) vault.delete_backup() captured = capsys.readouterr() assert captured.out == Regex(r"DRYRUN +| Delete backup") assert vault.backup_path.exists() is True def test_delete_inline_tag(test_vault) -> None: """Test deleting an inline tag.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.delete_inline_tag("no tag") == 0 assert vault.delete_inline_tag("intext_tag2") == 2 assert vault.metadata.tags == [ "ignored_file_tag2", "inline_tag_bottom1", "inline_tag_bottom2", "inline_tag_top1", "inline_tag_top2", "intext_tag1", "shared_tag", ] def test_delete_metadata(test_vault) -> None: """Test deleting a metadata key/value.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.delete_metadata("no key") == 0 assert vault.delete_metadata("top_key1", "no_value") == 0 assert vault.delete_metadata("top_key1", "top_key1_value") == 2 assert vault.metadata.dict["top_key1"] == [] assert vault.delete_metadata("top_key2") == 2 assert "top_key2" not in vault.metadata.dict def test_export_csv(tmp_path, test_vault): """Test exporting the vault to a CSV file.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) export_file = Path(f"{tmp_path}/export.csv") vault.export_metadata(path=export_file, export_format="csv") assert export_file.exists() is True assert "frontmatter,date_created,2022-12-22" in export_file.read_text() def test_export_json(tmp_path, test_vault): """Test exporting the vault to a CSV file.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) export_file = Path(f"{tmp_path}/export.json") vault.export_metadata(path=export_file, export_format="json") assert export_file.exists() is True assert '"frontmatter": {' in export_file.read_text() def test_get_filtered_notes(sample_vault) -> None: """Test filtering notes.""" vault_path = sample_vault config = Config(config_path="tests/fixtures/sample_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] filters = [VaultFilter(path_filter="front")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 4 filters = [VaultFilter(path_filter="mixed")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 1 filters = [VaultFilter(key_filter="on_one_note")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 1 filters = [VaultFilter(key_filter="type", value_filter="book")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 10 filters = [VaultFilter(tag_filter="brunch")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 1 filters = [VaultFilter(tag_filter="brunch"), VaultFilter(path_filter="inbox")] vault = Vault(config=vault_config, filters=filters) assert len(vault.all_notes) == 13 assert len(vault.notes_in_scope) == 0 def test_info(test_vault, capsys): """Test printing vault information.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) vault.info() captured = capsys.readouterr() assert captured.out == Regex(r"Vault +\│ /[\d\w]+") assert captured.out == Regex(r"Notes in scope +\│ \d+") assert captured.out == Regex(r"Backup +\│ None") def test_list_editable_notes(test_vault, capsys) -> None: """Test listing editable notes.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) vault.list_editable_notes() captured = capsys.readouterr() assert captured.out == Regex("Notes in current scope") assert captured.out == Regex(r"\d +test1\.md") def test_rename_inline_tag(test_vault) -> None: """Test renaming an inline tag.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.rename_inline_tag("no tag", "new_tag") == 0 assert vault.rename_inline_tag("intext_tag2", "new_tag") == 2 assert vault.metadata.tags == [ "ignored_file_tag2", "inline_tag_bottom1", "inline_tag_bottom2", "inline_tag_top1", "inline_tag_top2", "intext_tag1", "new_tag", "shared_tag", ] def test_rename_metadata(test_vault) -> None: """Test renaming a metadata key/value.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.rename_metadata("no key", "new_key") == 0 assert vault.rename_metadata("tags", "nonexistent_value", "new_vaule") == 0 assert vault.rename_metadata("tags", "frontmatter_tag1", "new_vaule") == 2 assert vault.metadata.dict["tags"] == [ "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "new_vaule", "shared_tag", "📅/frontmatter_tag3", ] assert vault.rename_metadata("tags", "new_key") == 2 assert "tags" not in vault.metadata.dict assert vault.metadata.dict["new_key"] == [ "frontmatter_tag2", "frontmatter_tag3", "ignored_file_tag1", "new_vaule", "shared_tag", "📅/frontmatter_tag3", ] def test_transpose_metadata(test_vault) -> None: """Test transposing metadata.""" vault_path = test_vault config = Config(config_path="tests/fixtures/test_vault_config.toml", vault_path=vault_path) vault_config = config.vaults[0] vault = Vault(config=vault_config) assert vault.transpose_metadata(begin=MetadataType.INLINE, end=MetadataType.FRONTMATTER) == 2 assert vault.metadata.inline_metadata == {} assert vault.metadata.frontmatter == { "author": ["author name"], "bottom_key1": ["bottom_key1_value"], "bottom_key2": ["bottom_key2_value"], "date_created": ["2022-12-22"], "frontmatter_Key1": ["author name"], "frontmatter_Key2": ["article", "note"], "ignored_frontmatter": ["ignore_me"], "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", "frontmatter_tag3", "ignored_file_tag1", "shared_tag", "📅/frontmatter_tag3", ], "top_key1": ["top_key1_value"], "top_key2": ["top_key2_value"], "top_key3": ["top_key3_value_as_link"], "type": ["article", "note"], } assert ( vault.transpose_metadata( begin=MetadataType.INLINE, end=MetadataType.FRONTMATTER, location=InsertLocation.TOP ) == 0 )