# -*- coding: utf-8 -*- """Tests for the double itself -- because a kind double is a blindfold. `pyrevit_yaml_fake` stands in for pyRevit's YAML reader, and every guard in this repository that reads YAML is tested through it. Twice now the double has been KINDER than the thing it doubles and the suite was green while the button was broken: * it TYPED its scalars while YamlDotNet returns every one as a string -- the master checklist reached the button with the word 'null' in 37 of 39 reason slots, on the owner's screen; * it took the LAST of two duplicate keys while YamlDotNet raises `Duplicate key` and returns nothing -- one nested duplicate discarded a whole 255KB plant layer inside Revit on 2026-09-01, and nothing on the host could reproduce it. Both properties are the double's PRODUCT, so they are tested here rather than assumed by the files that use it. """ import os import sys import pytest sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) pytest.importorskip('yaml') from pyrevit_yaml_fake import ( # noqa: E402 DuplicateKeyError, raise_on_duplicate_keys, stringify_like_yamldotnet, strings_only_yaml_reader) def _write(tmp_path, text): path = tmp_path / 'layer.yaml' path.write_text(text, encoding='utf-8') return str(path) # ------------------------------------------------------------- duplicate keys def test_a_duplicate_key_at_the_top_level_raises(tmp_path): path = _write(tmp_path, u'a: 1\nb: 2\na: 3\n') with pytest.raises(DuplicateKeyError) as caught: strings_only_yaml_reader()(path) assert 'Duplicate key' in str(caught.value) def test_a_duplicate_key_NESTED_raises_too(tmp_path): """The shape the incident actually had. A top-level-only check would have read that file happily and thrown the layer away in production.""" path = _write(tmp_path, u'checks:\n' u' rules:\n' u' cap_label_mismatch_is_view_specific: true\n' u' other: 1\n' u' cap_label_mismatch_is_view_specific: false\n') with pytest.raises(DuplicateKeyError) as caught: strings_only_yaml_reader()(path) said = str(caught.value) assert 'cap_label_mismatch_is_view_specific' in said assert 'line 5' in said # the SECOND statement: the one to delete def test_a_duplicate_inside_a_list_item_raises(tmp_path): path = _write(tmp_path, u'items:\n - name: a\n size: 1\n name: b\n') with pytest.raises(DuplicateKeyError): strings_only_yaml_reader()(path) def test_the_same_key_in_two_different_mappings_is_fine(tmp_path): """Not a duplicate. A checker that called this one would be unusable -- every knowledge file names `note:` under a dozen different parents.""" path = _write(tmp_path, u'a:\n note: x\nb:\n note: y\n') assert strings_only_yaml_reader()(path) == {'a': {'note': 'x'}, 'b': {'note': 'y'}} def test_a_clean_file_still_reads_and_still_comes_back_as_strings(tmp_path): path = _write(tmp_path, u'n: 1.5\nflag: true\nempty: null\n') assert strings_only_yaml_reader()(path) == {'n': '1.5', 'flag': 'true', 'empty': 'null'} def test_a_document_pyyaml_cannot_parse_is_not_judged_for_duplicates(): """Stated out loud rather than left to be discovered: this detector has exactly one question, and it answers `no duplicate found` for a document it could not read at all. `tools/knowledgelint.py` is the check that does refuse those, and it is the one the landing agents run.""" raise_on_duplicate_keys(u'a:\n - [1, 2\n') # does not raise def test_the_message_leads_with_the_words_pyrevit_uses(): """The string in the message is what a person sees in Self Check and in `config_problems()`, and what they will search for.""" with pytest.raises(DuplicateKeyError) as caught: raise_on_duplicate_keys(u'a: 1\na: 2\n', path='C:/plant/k.yaml') said = str(caught.value) assert said.startswith('Duplicate key') assert 'C:/plant/k.yaml' in said # ---------------------------------------------------------------- the strings def test_every_scalar_comes_back_as_text(): """The other way this double was once kinder than production.""" assert stringify_like_yamldotnet( {'a': 1.5, 'b': True, 'c': None, 'd': [1, {'e': False}]}) == \ {'a': '1.5', 'b': 'true', 'c': 'null', 'd': ['1', {'e': 'false'}]}