Add versioned glossary YAML import and export
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from mka.application.glossary import GlossaryRepository
|
||||
from mka.application.glossary_yaml import (
|
||||
GlossaryYamlError,
|
||||
export_glossary_yaml,
|
||||
import_glossary_yaml,
|
||||
)
|
||||
|
||||
|
||||
def repository(tmp_path: Path) -> GlossaryRepository:
|
||||
result = GlossaryRepository(tmp_path / "glossary.sqlite3")
|
||||
result.initialize()
|
||||
return result
|
||||
|
||||
|
||||
def test_round_trip_preserves_ids_aliases_and_active_state(tmp_path: Path) -> None:
|
||||
source = repository(tmp_path / "source")
|
||||
active = source.create(
|
||||
"Größenmaß",
|
||||
"technical_term",
|
||||
aliases=("Groessenmass", "Größen-Maß"),
|
||||
description="Canonical UTF-8 spelling",
|
||||
)
|
||||
inactive = source.create("Legacy Product", "product", is_active=False)
|
||||
|
||||
encoded = export_glossary_yaml(source.list()).encode("utf-8")
|
||||
target = repository(tmp_path / "target")
|
||||
target.create("Will be replaced", "other")
|
||||
target.replace_all(import_glossary_yaml(encoded))
|
||||
|
||||
entries = target.list()
|
||||
assert [entry.id for entry in entries] == [active.id, inactive.id]
|
||||
assert entries[0].canonical_term == "Größenmaß"
|
||||
assert entries[0].aliases == ("Groessenmass", "Größen-Maß")
|
||||
assert entries[0].description == "Canonical UTF-8 spelling"
|
||||
assert entries[0].is_active is True
|
||||
assert entries[1].is_active is False
|
||||
|
||||
|
||||
def test_malformed_yaml_does_not_replace_existing_glossary(tmp_path: Path) -> None:
|
||||
glossary = repository(tmp_path)
|
||||
existing = glossary.create("PBAT", "acronym")
|
||||
|
||||
with pytest.raises(GlossaryYamlError, match="Malformed glossary YAML"):
|
||||
import_glossary_yaml(b"version: 1\nglossary: [")
|
||||
|
||||
assert glossary.list() == [existing]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"entries, message",
|
||||
[
|
||||
(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"canonical_term": "PBAT",
|
||||
"aliases": [],
|
||||
"category": "acronym",
|
||||
"description": None,
|
||||
"active": True,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"canonical_term": "pbat",
|
||||
"aliases": [],
|
||||
"category": "material",
|
||||
"description": None,
|
||||
"active": True,
|
||||
},
|
||||
],
|
||||
"duplicate canonical term or alias",
|
||||
),
|
||||
(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"canonical_term": "Secugrid",
|
||||
"aliases": ["Sikirgut", "SIKIRGUT"],
|
||||
"category": "product",
|
||||
"description": None,
|
||||
"active": True,
|
||||
},
|
||||
],
|
||||
"aliases must be unique",
|
||||
),
|
||||
(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"canonical_term": "Secugrid",
|
||||
"aliases": ["PBAT"],
|
||||
"category": "product",
|
||||
"description": None,
|
||||
"active": True,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"canonical_term": "PBAT",
|
||||
"aliases": [],
|
||||
"category": "acronym",
|
||||
"description": None,
|
||||
"active": False,
|
||||
},
|
||||
],
|
||||
"duplicate canonical term or alias",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_duplicate_terms_and_aliases_are_rejected(
|
||||
entries: list[dict[str, object]], message: str
|
||||
) -> None:
|
||||
import yaml
|
||||
|
||||
content = yaml.safe_dump({"version": 1, "glossary": entries})
|
||||
|
||||
with pytest.raises(GlossaryYamlError, match=message):
|
||||
import_glossary_yaml(content)
|
||||
|
||||
|
||||
def test_validation_failure_leaves_database_unchanged(tmp_path: Path) -> None:
|
||||
glossary = repository(tmp_path)
|
||||
existing = glossary.create("Existing", "other", aliases=("Existing alias",))
|
||||
invalid = b"""version: 1
|
||||
glossary:
|
||||
- id: 10
|
||||
canonical_term: Duplicate
|
||||
aliases: []
|
||||
category: other
|
||||
description: null
|
||||
active: true
|
||||
- id: 11
|
||||
canonical_term: duplicate
|
||||
aliases: []
|
||||
category: other
|
||||
description: null
|
||||
active: false
|
||||
"""
|
||||
|
||||
with pytest.raises(GlossaryYamlError):
|
||||
imported = import_glossary_yaml(invalid)
|
||||
glossary.replace_all(imported)
|
||||
|
||||
assert glossary.list() == [existing]
|
||||
Reference in New Issue
Block a user