diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65508a6..0bf0278 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,10 +14,10 @@ jobs: python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b2d572b..a4f94ad 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,10 +21,10 @@ jobs: id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - name: Set up Python 3.11 - uses: actions/setup-python@v6 + uses: actions/setup-python@v5 with: python-version: "3.11" diff --git a/tests/test_diff.py b/tests/test_diff.py index a5a096c..79ea278 100644 --- a/tests/test_diff.py +++ b/tests/test_diff.py @@ -105,6 +105,24 @@ def test_three_envs(self): assert results["prod"].count == 1 +class TestChangeStr: + """Tests for Change.__str__().""" + + def test_str_added(self): + c = Change(key="port", change_type=ChangeType.ADDED, new_value=8080, env="prod") + expected = "[+] port = 8080 (env: prod)" + assert str(c) == expected + + def test_str_removed(self): + c = Change(key="port", change_type=ChangeType.REMOVED, old_value=8080, env="dev") + expected = "[-] port (was 8080) (env: dev)" + assert str(c) == expected + + def test_str_changed(self): + c = Change(key="host", change_type=ChangeType.CHANGED, old_value="localhost", new_value="prod.example.com", env="prod") + assert str(c) == "[~] host: 'localhost' \u2192 'prod.example.com' (env: prod)" + + class TestDiffResultHelpers: def test_by_type(self): changes = [ diff --git a/tests/test_loader.py b/tests/test_loader.py index 9bab060..70114a8 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -85,6 +85,60 @@ def test_ignores_comments(self): assert "This is a comment" not in result +class TestLoadUnsupported: + """Tests for fallback behaviour with unknown file extensions.""" + + def test_fallback_yaml_content_in_cfg(self): + """Files with .cfg containing valid YAML should be parsed via fallback.""" + content = yaml.dump({"key": "value", "nested": {"inner": 42}}) + with tempfile.NamedTemporaryFile(suffix=".cfg", mode="w", delete=False) as f: + f.write(content) + f.flush() + result = load_file(f.name) + os.unlink(f.name) + assert result["key"] == "value" + assert result["nested.inner"] == 42 + + def test_fallback_yaml_as_json(self): + """Files with unknown ext containing valid JSON should be parsed via fallback.""" + content = json.dumps({"host": "localhost", "port": 8080}) + with tempfile.NamedTemporaryFile(suffix=".cnf", mode="w", delete=False) as f: + f.write(content) + f.flush() + result = load_file(f.name) + os.unlink(f.name) + assert result["host"] == "localhost" + assert result["port"] == 8080 + + def test_unsupported_format_fallback_to_dotenv(self): + """Files with unknown extension and no structured content fall through to .env parser and returns a dict.""" + with tempfile.NamedTemporaryFile(suffix=".xyz", mode="w", delete=False) as f: + f.write("not a config") + f.flush() + result = load_file(f.name) + os.unlink(f.name) + assert isinstance(result, dict) + + def test_unsupported_format_empty_result(self): + """Garbage content with unknown extension returns empty dict via .env fallback.""" + with tempfile.NamedTemporaryFile(suffix=".xyz", mode="w", delete=False) as f: + f.write("!!!garbage!!!") + f.flush() + result = load_file(f.name) + os.unlink(f.name) + assert result == {} + + def test_yaml_non_dict_raises(self): + """YAML containing a list (not a mapping) should raise ValueError.""" + content = yaml.dump(["item1", "item2"]) + with tempfile.NamedTemporaryFile(suffix=".yaml", mode="w", delete=False) as f: + f.write(content) + f.flush() + with pytest.raises(ValueError, match="YAML file must contain a mapping"): + load_file(f.name) + os.unlink(f.name) + + class TestFlattenNested: def test_flatten(self): data = {"a": {"b": {"c": 1}, "d": 2}, "e": 3}