1515import aiohttp
1616import orjson
1717import pytest
18+ from aiofiles import os as aos
1819from PIL import Image
1920
2021from tests .conftest import (
3132 TEST_VIDEO_EXISTS ,
3233 TEST_VIEWPORT_EXISTS ,
3334 MockDatetime ,
35+ async_read_bytes ,
36+ async_write_bytes ,
37+ async_write_text ,
3438 compare_objs ,
3539 get_time ,
3640 validate_video_file ,
@@ -1093,7 +1097,7 @@ async def test_get_package_camera_snapshot_args(protect_client: ProtectApiClient
10931097@patch ("uiprotect.api.datetime" , MockDatetime )
10941098@patch ("uiprotect.api.time.time" , get_time )
10951099@pytest .mark .asyncio ()
1096- async def test_get_camera_video (protect_client : ProtectApiClient , now , tmp_binary_file ):
1100+ async def test_get_camera_video (protect_client : ProtectApiClient , now , tmp_path : Path ):
10971101 camera = next (iter (protect_client .bootstrap .cameras .values ()))
10981102 start = now - timedelta (seconds = CONSTANTS ["camera_video_length" ])
10991103
@@ -1111,10 +1115,11 @@ async def test_get_camera_video(protect_client: ProtectApiClient, now, tmp_binar
11111115 raise_exception = False ,
11121116 )
11131117
1114- tmp_binary_file .write (data )
1115- tmp_binary_file .close ()
1116-
1117- validate_video_file (tmp_binary_file .name , CONSTANTS ["camera_video_length" ])
1118+ out_path = tmp_path / "video.mp4"
1119+ await async_write_bytes (out_path , data )
1120+ await asyncio .to_thread (
1121+ validate_video_file , out_path , CONSTANTS ["camera_video_length" ]
1122+ )
11181123
11191124
11201125@pytest .mark .asyncio ()
@@ -1738,7 +1743,7 @@ async def test_load_session_rejects_missing_csrf_token(tmp_path: Path) -> None:
17381743 }
17391744
17401745 config_file = tmp_path / "unifi_protect.json"
1741- config_file . write_bytes ( orjson .dumps (config ))
1746+ await async_write_bytes ( config_file , orjson .dumps (config ))
17421747
17431748 # Try to load the session
17441749 cookie = await client ._read_auth_config ()
@@ -1775,7 +1780,7 @@ async def test_load_session_accepts_valid_csrf_token(tmp_path: Path) -> None:
17751780 }
17761781
17771782 config_file = tmp_path / "unifi_protect.json"
1778- config_file . write_bytes ( orjson .dumps (config ))
1783+ await async_write_bytes ( config_file , orjson .dumps (config ))
17791784
17801785 # Try to load the session
17811786 cookie = await client ._read_auth_config ()
@@ -1815,7 +1820,7 @@ async def test_load_session_with_invalid_token(tmp_path: Path) -> None:
18151820 }
18161821
18171822 config_file = tmp_path / "unifi_protect.json"
1818- config_file . write_bytes ( orjson .dumps (config ))
1823+ await async_write_bytes ( config_file , orjson .dumps (config ))
18191824
18201825 # Load the session
18211826 cookie = await client ._read_auth_config ()
@@ -1861,7 +1866,7 @@ async def test_load_session_with_token_two_segments(tmp_path: Path) -> None:
18611866 }
18621867
18631868 config_file = tmp_path / "unifi_protect.json"
1864- config_file . write_bytes ( orjson .dumps (config ))
1869+ await async_write_bytes ( config_file , orjson .dumps (config ))
18651870
18661871 # Load the session
18671872 cookie = await client ._read_auth_config ()
@@ -1899,7 +1904,7 @@ async def test_invalid_token_triggers_reauthentication(
18991904 }
19001905
19011906 config_file = tmp_path / "unifi_protect.json"
1902- config_file . write_bytes ( orjson .dumps (invalid_config ))
1907+ await async_write_bytes ( config_file , orjson .dumps (invalid_config ))
19031908
19041909 # Setup mock for authentication
19051910 mock_auth_response = AsyncMock ()
@@ -1929,7 +1934,7 @@ async def test_invalid_token_triggers_reauthentication(
19291934 assert client ._is_authenticated is True
19301935
19311936 # Verify the session file was updated with the new valid token
1932- updated_config = orjson .loads (config_file . read_bytes ( ))
1937+ updated_config = orjson .loads (await async_read_bytes ( config_file ))
19331938 session_data = updated_config ["sessions" ][session_hash ]
19341939 assert session_data ["csrf" ] == "new-csrf-token-12345"
19351940 # The new token should be a valid JWT format (3 segments)
@@ -1968,12 +1973,12 @@ async def test_clear_session_removes_specific_session(tmp_path: Path) -> None:
19681973 }
19691974
19701975 config_file = tmp_path / "unifi_protect.json"
1971- config_file . write_bytes ( orjson .dumps (config ))
1976+ await async_write_bytes ( config_file , orjson .dumps (config ))
19721977
19731978 await client .clear_session ()
19741979
19751980 # File should still exist with the other session intact
1976- updated_config = orjson .loads (config_file . read_bytes ( ))
1981+ updated_config = orjson .loads (await async_read_bytes ( config_file ))
19771982 assert session_hash not in updated_config ["sessions" ]
19781983 assert "other_session_hash" in updated_config ["sessions" ]
19791984 assert client ._is_authenticated is False
@@ -2013,11 +2018,11 @@ async def test_clear_all_sessions_removes_file(
20132018 }
20142019
20152020 config_file = tmp_path / "unifi_protect.json"
2016- config_file . write_bytes ( orjson .dumps (config ))
2021+ await async_write_bytes ( config_file , orjson .dumps (config ))
20172022
20182023 await client .clear_all_sessions ()
20192024
2020- assert not config_file . exists ()
2025+ assert not await aos . path . exists (config_file )
20212026 assert client ._is_authenticated is False
20222027 assert client ._last_token_cookie is None
20232028 assert client ._last_token_cookie_decode is None
@@ -2041,13 +2046,13 @@ async def test_clear_methods_do_nothing_when_sessions_disabled(
20412046 )
20422047
20432048 config_file = tmp_path / "unifi_protect.json"
2044- config_file . write_bytes ( orjson .dumps ({"sessions" : {}}))
2049+ await async_write_bytes ( config_file , orjson .dumps ({"sessions" : {}}))
20452050
20462051 await getattr (client , clear_method )()
20472052
20482053 # File should still exist since sessions are disabled
2049- assert config_file . exists ()
2050- config = orjson .loads (config_file . read_bytes ( ))
2054+ assert await aos . path . exists (config_file )
2055+ config = orjson .loads (await async_read_bytes ( config_file ))
20512056 assert config == {"sessions" : {}}
20522057
20532058
@@ -2066,13 +2071,13 @@ async def test_clear_session_with_invalid_config_file(tmp_path: Path) -> None:
20662071
20672072 # Create a config file with invalid JSON
20682073 config_file = tmp_path / "unifi_protect.json"
2069- config_file . write_text ( "invalid json content {{{" )
2074+ await async_write_text ( config_file , "invalid json content {{{" )
20702075
20712076 # Call clear_session - should handle the exception gracefully
20722077 await client .clear_session ()
20732078
20742079 # File should still exist
2075- assert config_file . exists ()
2080+ assert await aos . path . exists (config_file )
20762081
20772082
20782083@pytest .mark .asyncio ()
@@ -2099,7 +2104,7 @@ async def test_clear_methods_handle_missing_file(
20992104
21002105 # No file should exist and no error should be raised
21012106 config_file = tmp_path / "unifi_protect.json"
2102- assert not config_file . exists ()
2107+ assert not await aos . path . exists (config_file )
21032108 # Client state should NOT be reset since no file was found
21042109 assert client ._is_authenticated is True
21052110 assert client ._last_token_cookie == "some_token" # noqa: S105
@@ -2133,12 +2138,12 @@ async def test_clear_session_when_session_not_in_config(tmp_path: Path) -> None:
21332138 }
21342139
21352140 config_file = tmp_path / "unifi_protect.json"
2136- config_file . write_bytes ( orjson .dumps (config ))
2141+ await async_write_bytes ( config_file , orjson .dumps (config ))
21372142
21382143 await client .clear_session ()
21392144
21402145 # File should still have the original session
2141- updated_config = orjson .loads (config_file . read_bytes ( ))
2146+ updated_config = orjson .loads (await async_read_bytes ( config_file ))
21422147 assert "different_hash" in updated_config ["sessions" ]
21432148 # Client state should NOT be reset since no session was actually removed
21442149 assert client ._is_authenticated is True
@@ -2166,7 +2171,7 @@ async def test_clear_all_sessions_handles_file_disappearing(
21662171
21672172 # Create config file so path.exists() check passes
21682173 config_file = tmp_path / "unifi_protect.json"
2169- config_file . write_bytes ( orjson .dumps ({"sessions" : {}}))
2174+ await async_write_bytes ( config_file , orjson .dumps ({"sessions" : {}}))
21702175
21712176 # Mock aos.remove to raise FileNotFoundError (race condition simulation)
21722177 mock_remove .side_effect = FileNotFoundError (
@@ -2217,9 +2222,9 @@ async def test_authenticate_with_session_storage(
22172222
22182223 # Verify session was saved to file
22192224 config_file = tmp_path / "unifi_protect.json"
2220- assert config_file . exists ()
2225+ assert await aos . path . exists (config_file )
22212226
2222- config = orjson .loads (config_file . read_bytes ( ))
2227+ config = orjson .loads (await async_read_bytes ( config_file ))
22232228 assert "sessions" in config
22242229 sessions = config ["sessions" ]
22252230 assert len (sessions ) == 1
0 commit comments