@@ -179,7 +179,9 @@ async def test_agents_get_backup_does_not_throw_on_not_found(
179179 mock_client : MagicMock ,
180180) -> None :
181181 """Test agent get backup does not throw on a backup not found."""
182- mock_client .list_objects_v2 .return_value = {"Contents" : []}
182+ mock_client .get_paginator .return_value .paginate .return_value .__aiter__ .return_value = [
183+ {"Contents" : []}
184+ ]
183185
184186 client = await hass_ws_client (hass )
185187 await client .send_json_auto_id ({"type" : "backup/details" , "backup_id" : "random" })
@@ -202,18 +204,20 @@ async def test_agents_list_backups_with_corrupted_metadata(
202204 agent = IDriveE2BackupAgent (hass , mock_config_entry )
203205
204206 # Set up mock responses for both valid and corrupted metadata files
205- mock_client .list_objects_v2 .return_value = {
206- "Contents" : [
207- {
208- "Key" : "valid_backup.metadata.json" ,
209- "LastModified" : "2023-01-01T00:00:00+00:00" ,
210- },
211- {
212- "Key" : "corrupted_backup.metadata.json" ,
213- "LastModified" : "2023-01-01T00:00:00+00:00" ,
214- },
215- ]
216- }
207+ mock_client .get_paginator .return_value .paginate .return_value .__aiter__ .return_value = [
208+ {
209+ "Contents" : [
210+ {
211+ "Key" : "valid_backup.metadata.json" ,
212+ "LastModified" : "2023-01-01T00:00:00+00:00" ,
213+ },
214+ {
215+ "Key" : "corrupted_backup.metadata.json" ,
216+ "LastModified" : "2023-01-01T00:00:00+00:00" ,
217+ },
218+ ]
219+ }
220+ ]
217221
218222 # Mock responses for get_object calls
219223 valid_metadata = json .dumps (agent_backup .as_dict ())
@@ -270,7 +274,9 @@ async def test_agents_delete_not_throwing_on_not_found(
270274 mock_client : MagicMock ,
271275) -> None :
272276 """Test agent delete backup does not throw on a backup not found."""
273- mock_client .list_objects_v2 .return_value = {"Contents" : []}
277+ mock_client .get_paginator .return_value .paginate .return_value .__aiter__ .return_value = [
278+ {"Contents" : []}
279+ ]
274280
275281 client = await hass_ws_client (hass )
276282
@@ -284,7 +290,7 @@ async def test_agents_delete_not_throwing_on_not_found(
284290
285291 assert response ["success" ]
286292 assert response ["result" ] == {"agent_errors" : {}}
287- assert mock_client .delete_object .call_count == 0
293+ assert mock_client .delete_objects .call_count == 0
288294
289295
290296async def test_agents_upload (
@@ -490,28 +496,35 @@ async def test_cache_expiration(
490496 metadata_content = json .dumps (agent_backup .as_dict ())
491497 mock_body = AsyncMock ()
492498 mock_body .read .return_value = metadata_content .encode ()
493- mock_client .list_objects_v2 .return_value = {
494- "Contents" : [
495- {"Key" : "test.metadata.json" , "LastModified" : "2023-01-01T00:00:00+00:00" }
496- ]
497- }
499+ mock_client .get_paginator .return_value .paginate .return_value .__aiter__ .return_value = [
500+ {
501+ "Contents" : [
502+ {
503+ "Key" : "test.metadata.json" ,
504+ "LastModified" : "2023-01-01T00:00:00+00:00" ,
505+ }
506+ ]
507+ }
508+ ]
509+
510+ mock_client .get_object .return_value = {"Body" : mock_body }
498511
499512 # First call should query IDrive e2
500513 await agent .async_list_backups ()
501- assert mock_client .list_objects_v2 .call_count == 1
514+ assert mock_client .get_paginator .call_count == 1
502515 assert mock_client .get_object .call_count == 1
503516
504517 # Second call should use cache
505518 await agent .async_list_backups ()
506- assert mock_client .list_objects_v2 .call_count == 1
519+ assert mock_client .get_paginator .call_count == 1
507520 assert mock_client .get_object .call_count == 1
508521
509522 # Set cache to expire
510523 agent ._cache_expiration = time () - 1
511524
512525 # Third call should query IDrive e2 again
513526 await agent .async_list_backups ()
514- assert mock_client .list_objects_v2 .call_count == 2
527+ assert mock_client .get_paginator .call_count == 2
515528 assert mock_client .get_object .call_count == 2
516529
517530
@@ -526,3 +539,88 @@ async def test_listeners_get_cleaned_up(hass: HomeAssistant) -> None:
526539 remove_listener ()
527540
528541 assert DATA_BACKUP_AGENT_LISTENERS not in hass .data
542+
543+
544+ async def test_list_backups_with_pagination (
545+ hass : HomeAssistant ,
546+ mock_config_entry : MockConfigEntry ,
547+ ) -> None :
548+ """Test listing backups when paginating through multiple pages."""
549+ # Create agent
550+ agent = IDriveE2BackupAgent (hass , mock_config_entry )
551+
552+ # Create two different backups
553+ backup1 = AgentBackup (
554+ backup_id = "backup1" ,
555+ date = "2023-01-01T00:00:00+00:00" ,
556+ addons = [],
557+ database_included = False ,
558+ extra_metadata = {},
559+ folders = [],
560+ homeassistant_included = False ,
561+ homeassistant_version = None ,
562+ name = "Backup 1" ,
563+ protected = False ,
564+ size = 0 ,
565+ )
566+ backup2 = AgentBackup (
567+ backup_id = "backup2" ,
568+ date = "2023-01-02T00:00:00+00:00" ,
569+ addons = [],
570+ database_included = False ,
571+ extra_metadata = {},
572+ folders = [],
573+ homeassistant_included = False ,
574+ homeassistant_version = None ,
575+ name = "Backup 2" ,
576+ protected = False ,
577+ size = 0 ,
578+ )
579+
580+ # Setup two pages of results
581+ page1 = {
582+ "Contents" : [
583+ {
584+ "Key" : "backup1.metadata.json" ,
585+ "LastModified" : "2023-01-01T00:00:00+00:00" ,
586+ },
587+ {"Key" : "backup1.tar" , "LastModified" : "2023-01-01T00:00:00+00:00" },
588+ ]
589+ }
590+ page2 = {
591+ "Contents" : [
592+ {
593+ "Key" : "backup2.metadata.json" ,
594+ "LastModified" : "2023-01-02T00:00:00+00:00" ,
595+ },
596+ {"Key" : "backup2.tar" , "LastModified" : "2023-01-02T00:00:00+00:00" },
597+ ]
598+ }
599+
600+ # Setup mock client
601+ mock_client = mock_config_entry .runtime_data
602+ mock_client .get_paginator .return_value .paginate .return_value .__aiter__ .return_value = [
603+ page1 ,
604+ page2 ,
605+ ]
606+
607+ # Mock get_object responses based on the key
608+ async def mock_get_object (** kwargs ):
609+ """Mock get_object with different responses based on the key."""
610+ key = kwargs .get ("Key" , "" )
611+ if "backup1" in key :
612+ mock_body = AsyncMock ()
613+ mock_body .read .return_value = json .dumps (backup1 .as_dict ()).encode ()
614+ return {"Body" : mock_body }
615+ # backup2
616+ mock_body = AsyncMock ()
617+ mock_body .read .return_value = json .dumps (backup2 .as_dict ()).encode ()
618+ return {"Body" : mock_body }
619+
620+ mock_client .get_object .side_effect = mock_get_object
621+
622+ # List backups and verify we got both
623+ backups = await agent .async_list_backups ()
624+ assert len (backups ) == 2
625+ backup_ids = {backup .backup_id for backup in backups }
626+ assert backup_ids == {"backup1" , "backup2" }
0 commit comments