Source code for betty.test_utils.json.linked_data

"""
Test utilities for :py:mod:`betty.json.linked_data`.
"""

from __future__ import annotations

from collections.abc import Mapping, Sequence, Callable, Awaitable
from typing import TYPE_CHECKING

from typing_extensions import TypeVar

from betty.app import App
from betty.project import Project
from betty.serde.dump import Dump

if TYPE_CHECKING:
    from betty.json.schema import Schema
    from betty.json.linked_data import LinkedDataDumpable, LinkedDataDumpableProvider

_T = TypeVar("_T")
_DumpT = TypeVar("_DumpT", bound=Dump, default=Dump)


[docs] async def assert_dumps_linked_data(sut: LinkedDataDumpable[Schema, _DumpT]) -> _DumpT: """ Dump an object's linked data and assert it is valid. """ return await _assert_linked_data_dump(sut.linked_data_schema, sut.dump_linked_data)
[docs] async def assert_dumps_linked_data_for( sut: LinkedDataDumpableProvider[_T, Schema, _DumpT], target: _T ) -> _DumpT: """ Dump an object's linked data and assert it is valid. """ async def _dump(project: Project) -> _DumpT: return await sut.dump_linked_data_for(project, target) return await _assert_linked_data_dump(sut.linked_data_schema_for, _dump)
async def _assert_linked_data_dump( schema: Callable[[Project], Awaitable[Schema]], dump: Callable[[Project], Awaitable[_DumpT]], ) -> _DumpT: async with ( App.new_temporary() as app, app, Project.new_temporary(app) as project, project, ): actual = await dump(project) # Validate the raw dump. sut_schema = await schema(project) sut_schema.validate(actual) # Normalize the dump after validation (so we are assured it is absolutely valid), # but before returning, so calling code can use simpler comparisons. return _normalize(actual) def _normalize(dump: _DumpT) -> _DumpT: if isinstance(dump, Mapping): return { # type: ignore[return-value] key: _normalize(value) for key, value in dump.items() if not key.startswith("$") } if isinstance(dump, Sequence) and not isinstance(dump, str): return list(map(_normalize, dump)) # type: ignore[return-value] return dump # type: ignore[return-value]