Repository: home-assistant/core
File: tests/util/test_file.py (Python)

Code before:
        write_utf8_file(test_file, '{"some":"data"}', False)

    assert not os.path.exists(test_file)

    assert "File replacement cleanup failed" not in caplog.text


def test_write_utf8_file_fails_at_rename_and_remove(
    tmpdir: py.path.local, caplog: pytest.LogCaptureFixture
) -> None:
    """Test that if rename and remove both fail, we log the failed cleanup."""
    test_dir = tmpdir.mkdir("files")
    test_file = Path(test_dir / "test.json")

    with (
        pytest.raises(WriteError),
        patch("homeassistant.util.file.os.remove", side_effect=OSError),
        patch("homeassistant.util.file.os.replace", side_effect=OSError),
    ):
        write_utf8_file(test_file, '{"some":"data"}', False)

    assert "File replacement cleanup failed" in caplog.text


@pytest.mark.parametrize("func", [write_utf8_file, write_utf8_file_atomic])
def test_write_utf8_file_with_non_ascii_content(tmpdir: py.path.local, func) -> None:
    """Test files with non-ASCII content can be written even when locale is ASCII."""
    test_dir = tmpdir.mkdir("files")
    test_file = Path(test_dir / "test.json")
    non_ascii_data = '{"name":"自动化","emoji":"🏠"}'

    with patch("locale.getpreferredencoding", return_value="ascii"):
        func(test_file, non_ascii_data, False)

    with open(test_file, encoding="utf-8") as fh:
        assert fh.read() == non_ascii_data


def test_write_utf8_file_atomic_fails(tmpdir: py.path.local) -> None:
    """Test OSError from write_utf8_file_atomic is rethrown as WriteError."""
    test_dir = tmpdir.mkdir("files")
    test_file = Path(test_dir / "test.json")

    with (
        pytest.raises(WriteError),
        patch("homeassistant.util.file.AtomicWriter.open", side_effect=OSError),
    ):
        write_utf8_file_atomic(test_file, '{"some":"data"}', False)

    assert not os.path.exists(test_file)


Review comment (suggestion):
Please use the `tmp_path` fixture instead.

https://docs.pytest.org/en/stable/how-to/tmp_path.html

```suggestion
def test_write_utf8_file_with_non_ascii_content(tmp_path: Path, func) -> None:
```

Code after:
        write_utf8_file(test_file, '{"some":"data"}', False)

    assert not os.path.exists(test_file)

    assert "File replacement cleanup failed" not in caplog.text


def test_write_utf8_file_fails_at_rename_and_remove(
    tmpdir: py.path.local, caplog: pytest.LogCaptureFixture
) -> None:
    """Test that if rename and remove both fail, we log the failed cleanup."""
    test_dir = tmpdir.mkdir("files")
    test_file = Path(test_dir / "test.json")

    with (
        pytest.raises(WriteError),
        patch("homeassistant.util.file.os.remove", side_effect=OSError),
        patch("homeassistant.util.file.os.replace", side_effect=OSError),
    ):
        write_utf8_file(test_file, '{"some":"data"}', False)

    assert "File replacement cleanup failed" in caplog.text


@pytest.mark.parametrize("func", [write_utf8_file, write_utf8_file_atomic])
def test_write_utf8_file_with_non_ascii_content(tmp_path: Path, func) -> None:
    """Test files with non-ASCII content can be written even when locale is ASCII."""
    test_file = tmp_path / "test.json"
    non_ascii_data = '{"name":"自动化","emoji":"🏠"}'

    with patch("locale.getpreferredencoding", return_value="ascii"):
        func(test_file, non_ascii_data, False)

    file_text = test_file.read_text(encoding="utf-8")
    assert file_text == non_ascii_data


def test_write_utf8_file_atomic_fails(tmpdir: py.path.local) -> None:
    """Test OSError from write_utf8_file_atomic is rethrown as WriteError."""
    test_dir = tmpdir.mkdir("files")
    test_file = Path(test_dir / "test.json")

    with (
        pytest.raises(WriteError),
        patch("homeassistant.util.file.AtomicWriter.open", side_effect=OSError),
    ):
        write_utf8_file_atomic(test_file, '{"some":"data"}', False)

    assert not os.path.exists(test_file)