"""Unit tests for ``replace_single_quotes``. This is the cleanest function to test: pure, recursive, no I/O. It escapes single quotes (``'`` -> ``''``) for the Neo4j import, recursing through dicts and lists and leaving non-strings untouched. """ import pytest from hypothesis import given, strategies as st import import_fhir_to_nx_diGraph as pipeline def test_single_quote_in_string_is_doubled(): assert pipeline.replace_single_quotes("O'Brien") == "O''Brien" def test_string_without_quotes_unchanged(): assert pipeline.replace_single_quotes("Mueller") == "Mueller" def test_empty_string_unchanged(): assert pipeline.replace_single_quotes("") == "" @pytest.mark.parametrize("value", [0, 1, 3.14, None, True, False]) def test_non_string_scalars_unchanged(value): assert pipeline.replace_single_quotes(value) is value def test_nested_dict_recurses(): data = {"name": "O'Hara", "nested": {"note": "it's fine"}} assert pipeline.replace_single_quotes(data) == { "name": "O''Hara", "nested": {"note": "it''s fine"}, } def test_list_recurses(): assert pipeline.replace_single_quotes(["a'b", 2, "c"]) == ["a''b", 2, "c"] def test_dict_keys_are_not_escaped(): # Only values are recursed into; keys are left as-is. result = pipeline.replace_single_quotes({"it's": "fine"}) assert list(result.keys()) == ["it's"] assert result["it's"] == "fine" # --- Property-based checks ------------------------------------------------- @given(st.text()) def test_every_quote_is_doubled(text): # The function is intentionally NOT idempotent: each pass doubles the # quote count. This pins that contract so a future "fix" is a conscious # choice rather than a silent behaviour change. result = pipeline.replace_single_quotes(text) assert result.count("'") == 2 * text.count("'") @given(st.lists(st.one_of(st.integers(), st.text()))) def test_list_length_preserved(items): assert len(pipeline.replace_single_quotes(items)) == len(items)