完善设备端体验与微信校验支持
This commit is contained in:
@@ -96,6 +96,91 @@ async def test_start_card_bind_rejects_family_member_who_is_not_owner(monkeypatc
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_card_groups_groups_cards_by_visible_device(monkeypatch):
|
||||
service = BindingService()
|
||||
db_session = FakeSession()
|
||||
|
||||
async def fake_get_session():
|
||||
return db_session
|
||||
|
||||
async def fake_list_card_groups_by_user(self, user_id):
|
||||
assert user_id == 99
|
||||
return [
|
||||
{
|
||||
"device_id": "TalkingQ_device001",
|
||||
"child_id": 7,
|
||||
"child_name": "孩子一",
|
||||
"bound_at": datetime(2026, 6, 8, 10, 0, 0),
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": None,
|
||||
"card_status": 1,
|
||||
"card_updated_at": datetime(2026, 6, 8, 10, 1, 0),
|
||||
},
|
||||
{
|
||||
"device_id": "TalkingQ_device001",
|
||||
"child_id": 7,
|
||||
"child_name": "孩子一",
|
||||
"bound_at": datetime(2026, 6, 8, 10, 0, 0),
|
||||
"card_id": 10,
|
||||
"card_uuid": "CARD_UUID_B",
|
||||
"card_name": "备用卡",
|
||||
"card_status": 1,
|
||||
"card_updated_at": datetime(2026, 6, 8, 10, 0, 30),
|
||||
},
|
||||
{
|
||||
"device_id": "TalkingQ_device002",
|
||||
"child_id": None,
|
||||
"child_name": None,
|
||||
"bound_at": datetime(2026, 6, 8, 9, 0, 0),
|
||||
"card_id": None,
|
||||
"card_uuid": None,
|
||||
"card_name": None,
|
||||
"card_status": None,
|
||||
"card_updated_at": None,
|
||||
},
|
||||
]
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.list_card_groups_by_user", fake_list_card_groups_by_user)
|
||||
|
||||
groups = await service.list_card_groups(user_id=99)
|
||||
|
||||
assert groups == [
|
||||
{
|
||||
"device_id": "TalkingQ_device001",
|
||||
"child_id": 7,
|
||||
"child_name": "孩子一",
|
||||
"bound_at": datetime(2026, 6, 8, 10, 0, 0),
|
||||
"cards": [
|
||||
{
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": None,
|
||||
"status": 1,
|
||||
"updated_at": datetime(2026, 6, 8, 10, 1, 0),
|
||||
},
|
||||
{
|
||||
"card_id": 10,
|
||||
"card_uuid": "CARD_UUID_B",
|
||||
"card_name": "备用卡",
|
||||
"status": 1,
|
||||
"updated_at": datetime(2026, 6, 8, 10, 0, 30),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"device_id": "TalkingQ_device002",
|
||||
"child_id": None,
|
||||
"child_name": None,
|
||||
"bound_at": datetime(2026, 6, 8, 9, 0, 0),
|
||||
"cards": [],
|
||||
},
|
||||
]
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_finalize_nfc_bind_expires_late_card_without_binding(monkeypatch):
|
||||
service = BindingService()
|
||||
@@ -311,3 +396,137 @@ async def test_finalize_nfc_bind_adds_card_without_rebinding_device(monkeypatch)
|
||||
assert db_session.commits == 1
|
||||
assert db_session.rollbacks == 0
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_card_name_allows_device_owner(monkeypatch):
|
||||
service = BindingService()
|
||||
db_session = FakeSession()
|
||||
updated_cards = []
|
||||
|
||||
async def fake_get_session():
|
||||
return db_session
|
||||
|
||||
async def fake_get_visible_card_by_id(self, card_id, user_id):
|
||||
assert card_id == 11
|
||||
assert user_id == 99
|
||||
return {
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": None,
|
||||
"card_status": 1,
|
||||
"card_updated_at": datetime(2026, 6, 8, 10, 1, 0),
|
||||
"device_id": "TalkingQ_device001",
|
||||
"owner_user_id": 99,
|
||||
}
|
||||
|
||||
async def fake_update_card_name(self, card_id, card_name):
|
||||
updated_cards.append((card_id, card_name))
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.get_visible_card_by_id", fake_get_visible_card_by_id)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.update_card_name", fake_update_card_name)
|
||||
|
||||
result = await service.update_card_name(card_id=11, card_name=" 奶奶的卡 ", user_id=99)
|
||||
|
||||
assert result == {
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": "奶奶的卡",
|
||||
"status": 1,
|
||||
"updated_at": datetime(2026, 6, 8, 10, 1, 0),
|
||||
}
|
||||
assert updated_cards == [(11, "奶奶的卡")]
|
||||
assert db_session.commits == 1
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_card_name_rejects_family_member(monkeypatch):
|
||||
service = BindingService()
|
||||
db_session = FakeSession()
|
||||
updated_cards = []
|
||||
|
||||
async def fake_get_session():
|
||||
return db_session
|
||||
|
||||
async def fake_get_visible_card_by_id(self, card_id, user_id):
|
||||
assert card_id == 11
|
||||
assert user_id == 88
|
||||
return {
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": None,
|
||||
"card_status": 1,
|
||||
"card_updated_at": datetime(2026, 6, 8, 10, 1, 0),
|
||||
"device_id": "TalkingQ_device001",
|
||||
"owner_user_id": 99,
|
||||
}
|
||||
|
||||
async def fake_update_card_name(self, card_id, card_name):
|
||||
updated_cards.append((card_id, card_name))
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.get_visible_card_by_id", fake_get_visible_card_by_id)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.update_card_name", fake_update_card_name)
|
||||
|
||||
with pytest.raises(BindingError, match="only the device owner can rename cards"):
|
||||
await service.update_card_name(card_id=11, card_name="备用卡", user_id=88)
|
||||
|
||||
assert updated_cards == []
|
||||
assert db_session.commits == 0
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_card_name_allows_clearing_name(monkeypatch):
|
||||
service = BindingService()
|
||||
db_session = FakeSession()
|
||||
updated_cards = []
|
||||
|
||||
async def fake_get_session():
|
||||
return db_session
|
||||
|
||||
async def fake_get_visible_card_by_id(self, card_id, user_id):
|
||||
assert card_id == 11
|
||||
assert user_id == 99
|
||||
return {
|
||||
"card_id": 11,
|
||||
"card_uuid": "CARD_UUID_A",
|
||||
"card_name": "备用卡",
|
||||
"card_status": 1,
|
||||
"card_updated_at": None,
|
||||
"device_id": "TalkingQ_device001",
|
||||
"owner_user_id": 99,
|
||||
}
|
||||
|
||||
async def fake_update_card_name(self, card_id, card_name):
|
||||
updated_cards.append((card_id, card_name))
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.get_visible_card_by_id", fake_get_visible_card_by_id)
|
||||
monkeypatch.setattr("banban.service.binding.BindingDAO.update_card_name", fake_update_card_name)
|
||||
|
||||
result = await service.update_card_name(card_id=11, card_name=" ", user_id=99)
|
||||
|
||||
assert result["card_name"] is None
|
||||
assert updated_cards == [(11, None)]
|
||||
assert db_session.commits == 1
|
||||
assert db_session.closed is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_card_name_rejects_too_long_name(monkeypatch):
|
||||
service = BindingService()
|
||||
db_session = FakeSession()
|
||||
|
||||
async def fake_get_session():
|
||||
return db_session
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
|
||||
with pytest.raises(BindingError, match="64 characters or fewer"):
|
||||
await service.update_card_name(card_id=11, card_name="卡" * 65, user_id=99)
|
||||
|
||||
assert db_session.commits == 0
|
||||
assert db_session.closed is False
|
||||
|
||||
Reference in New Issue
Block a user