From 641c61dc198f04b341be713f8e3fcd6c288e5c7e Mon Sep 17 00:00:00 2001 From: Matysh Date: Mon, 27 Jul 2026 13:02:10 +0300 Subject: [PATCH] test: the files-migrate test now sets the integration up like its neighbours the new CR-2/CR-3 test sent WS commands without a config entry, so the handlers were not registered and CI reported success=False --- tests_backend/test_ha_websocket.py | 61 ++++++++++++++++++------------ 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/tests_backend/test_ha_websocket.py b/tests_backend/test_ha_websocket.py index 9850084..f170404 100644 --- a/tests_backend/test_ha_websocket.py +++ b/tests_backend/test_ha_websocket.py @@ -127,40 +127,53 @@ async def test_admin_check_fails_closed(hass, hass_ws_client): assert wsapi._check_write(hass, _AdminConn()) is True -async def test_files_migrate_copies_and_reports_mapping(hass, hass_ws_client, tmp_path): +async def test_files_migrate_copies_and_reports_mapping( + hass: HomeAssistant, hass_ws_client: WebSocketGenerator +) -> None: """review CR-2/CR-3: migrate COPIES, never overwrites, and reports the mapping.""" import os + from custom_components.houseplan.const import FILES_DIR - base = os.path.join(hass.config.path(FILES_DIR)) + await _setup(hass) + client = await hass_ws_client(hass) + + base = hass.config.path(FILES_DIR) src = os.path.join(base, "old1") dst = os.path.join(base, "new1") - await hass.async_add_executor_job(lambda: os.makedirs(src, exist_ok=True)) - await hass.async_add_executor_job(lambda: os.makedirs(dst, exist_ok=True)) - await hass.async_add_executor_job( - lambda: open(os.path.join(src, "m.pdf"), "wb").write(b"SOURCE") - ) - # коллизия: в целевой папке уже есть ДРУГОЙ файл с тем же именем - await hass.async_add_executor_job( - lambda: open(os.path.join(dst, "m.pdf"), "wb").write(b"OTHER") - ) - client = await hass_ws_client(hass) - await client.send_json({"id": 1, "type": "houseplan/files/migrate", - "from_id": "old1", "to_id": "new1"}) + def _prepare() -> None: + os.makedirs(src, exist_ok=True) + os.makedirs(dst, exist_ok=True) + with open(os.path.join(src, "m.pdf"), "wb") as fh: + fh.write(b"SOURCE") + # a DIFFERENT file already owns the name in the destination + with open(os.path.join(dst, "m.pdf"), "wb") as fh: + fh.write(b"OTHER") + + await hass.async_add_executor_job(_prepare) + + await client.send_json_auto_id( + {"type": "houseplan/files/migrate", "from_id": "old1", "to_id": "new1"} + ) resp = await client.receive_json() - assert resp["success"] + assert resp["success"], resp mapping = resp["result"]["mapping"] - assert mapping["m.pdf"] != "m.pdf" # переименован, а не перезаписан - # источник ещё на месте (копия, не перенос) и чужой файл не тронут - assert await hass.async_add_executor_job(lambda: os.path.isfile(os.path.join(src, "m.pdf"))) - assert await hass.async_add_executor_job( - lambda: open(os.path.join(dst, "m.pdf"), "rb").read()) == b"OTHER" - assert await hass.async_add_executor_job( - lambda: open(os.path.join(dst, mapping["m.pdf"]), "rb").read()) == b"SOURCE" + assert mapping["m.pdf"] != "m.pdf" # renamed instead of overwriting - # cleanup удаляет исходную папку — вызывается только после успешного сохранения - await client.send_json({"id": 2, "type": "houseplan/files/cleanup", "marker_id": "old1"}) + def _read_all() -> tuple[bool, bytes, bytes]: + with open(os.path.join(dst, "m.pdf"), "rb") as fh: + other = fh.read() + with open(os.path.join(dst, mapping["m.pdf"]), "rb") as fh: + copied = fh.read() + return os.path.isfile(os.path.join(src, "m.pdf")), other, copied + + src_kept, other, copied = await hass.async_add_executor_job(_read_all) + assert src_kept, "migrate must COPY, not move (review CR-2)" + assert other == b"OTHER" and copied == b"SOURCE" + + # cleanup runs only after the config is safely committed + await client.send_json_auto_id({"type": "houseplan/files/cleanup", "marker_id": "old1"}) resp2 = await client.receive_json() assert resp2["success"] and resp2["result"]["removed"] is True assert not await hass.async_add_executor_job(lambda: os.path.isdir(src))