Skip to content

Commit

Permalink
[BUILD-254] fix: Handle deck updates response with empty notes correc…
Browse files Browse the repository at this point in the history
…tly (#927)

* fix: Handle deck updates response with empty notes correctly

* Add test

* Fix exception handling handling for client tests
  • Loading branch information
RisingOrange authored Mar 25, 2024
1 parent c1e2967 commit 3c22eca
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 12 deletions.
3 changes: 3 additions & 0 deletions ankihub/ankihub_client/ankihub_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,9 @@ def get_deck_updates(
if should_cancel and should_cancel():
return None

if not chunk.notes:
continue

if chunk.from_csv:
# The CSV contains all notes, so we assign instead of extending
notes_data_from_csv = chunk.notes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
interactions:
- request:
body: '{"username": "test1", "password": "asdf"}'
headers:
Accept:
- application/json; version=18.0
Content-Length:
- '41'
Content-Type:
- application/json
method: POST
uri: http://localhost:8000/api/login/
response:
body:
string: '{"expiry":"2024-04-20T11:14:04.085095Z","token":"dcb750c2d67a26450bea083c7ca0e7cbb70f0aece0eda87cfd0993583e51d3bd"}'
headers:
Allow:
- POST, OPTIONS
Content-Language:
- en
Content-Length:
- '115'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Sat, 23 Mar 2024 11:14:04 GMT
Referrer-Policy:
- same-origin
Server:
- WSGIServer/0.2 CPython/3.8.17
Server-Timing:
- TimerPanel_utime;dur=299.5340000000226;desc="User CPU time", TimerPanel_stime;dur=2.427000000000845;desc="System
CPU time", TimerPanel_total;dur=301.96100000002343;desc="Total CPU time",
TimerPanel_total_time;dur=219.2665290003788;desc="Elapsed time", SQLPanel_sql_time;dur=8.263236000857432;desc="SQL
16 queries", CachePanel_total_time;dur=0;desc="Cache 0 Calls"
Set-Cookie:
- csrftoken=GEJ14GLNrCpTovniHl5vOIipFded4604; expires=Sat, 22 Mar 2025 11:14:04
GMT; HttpOnly; Max-Age=31449600; Path=/; SameSite=Lax
- sessionid=zxmvjngepkvsttkrziapyu09k2nl0ffi; expires=Sat, 30 Mar 2024 11:14:04
GMT; HttpOnly; Max-Age=604800; Path=/; SameSite=Lax
Vary:
- Accept, Cookie, Accept-Language, origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
djdt-store-id:
- ff681edc37564104bbfe37c99a4d6410
status:
code: 200
message: OK
version: 1
51 changes: 39 additions & 12 deletions tests/client/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Callable, Generator, List, cast
from typing import Callable, Generator, List, Optional, cast
from unittest.mock import Mock

import pytest
Expand Down Expand Up @@ -253,7 +253,7 @@ def remove_db_dump() -> Generator:
elif result.returncode == 1 and "No such container" in result.stderr:
# Nothing to do
pass
elif "Container" in result.stderr and "is not running" in result.stderr:
elif "container" in result.stderr.lower() and "is not running" in result.stderr:
# Container is not running, nothing to do
pass
elif "docker: command not found" in result.stderr:
Expand Down Expand Up @@ -1008,39 +1008,66 @@ def test_get_deck_updates_with_external_notes_url(
assert deck_updates.notes == [note1_from_json, note2_from_csv]
assert deck_updates.latest_update == latest_update

@pytest.mark.vcr()
def test_get_empty_deck_updates(
self, authorized_client_for_user_test1: AnkiHubClient, mocker: MockerFixture
):
client = authorized_client_for_user_test1

# Mock responses from deck updates endpoint
response = self._deck_updates_response_mock_with_json_notes(
notes=[],
latest_update=None,
)

mocker.patch(
"ankihub.ankihub_client.ankihub_client.AnkiHubClient._send_request",
return_value=response,
)

# Assert that the deck updates are as expected.
deck_updates = client.get_deck_updates(ID_OF_DECK_OF_USER_TEST1, since=None)
assert deck_updates.notes == []
assert deck_updates.latest_update is None

def _deck_updates_response_mock_with_json_notes(
self, notes: List[NoteInfo], latest_update: datetime
self, notes: List[NoteInfo], latest_update: Optional[datetime]
) -> Mock:
result = Mock()
note_dicts = [note.to_dict() for note in notes]
notes_encoded = gzip.compress(json.dumps(note_dicts).encode("utf-8"))
notes_encoded = base64.b85encode(notes_encoded)
latest_update_str = datetime.strftime(
latest_update, ANKIHUB_DATETIME_FORMAT_STR
)
result.json = lambda: {
"external_notes_url": None,
"next": None,
"notes": notes_encoded,
"latest_update": latest_update_str,
"latest_update": datetime.strftime(
latest_update, ANKIHUB_DATETIME_FORMAT_STR
)
if latest_update
else None,
"protected_fields": {},
"protected_tags": [],
}
result.status_code = 200
return result

def _deck_updates_response_mock_with_csv_notes(
self, notes: List[NoteInfo], latest_update: datetime, mocker: MockerFixture
self,
notes: List[NoteInfo],
latest_update: Optional[datetime],
mocker: MockerFixture,
) -> Mock:
result = Mock()
latest_update_str = datetime.strftime(
latest_update, ANKIHUB_DATETIME_FORMAT_STR
)
result.json = lambda: {
"external_notes_url": "test_url",
"next": None,
"notes": None,
"latest_update": latest_update_str,
"latest_update": datetime.strftime(
latest_update, ANKIHUB_DATETIME_FORMAT_STR
)
if latest_update
else None,
"protected_fields": {},
"protected_tags": [],
}
Expand Down

0 comments on commit 3c22eca

Please sign in to comment.