fe9b749154
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
"""微信登录 M1 测试:bind_ticket 令牌、wechat-login(openid 命中/未命中)、
|
|
bind-phone(建号/占用/令牌过期)。
|
|
|
|
沿用 tests/test_auth.py 风格:HTTP 走 client fixture;微信 code→openid 用 monkeypatch
|
|
拦掉(conftest 里 WECHAT_APP_ID/SECRET 是 dummy,不真连微信);短信走 SMS_MOCK(任意 6 位通过)。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from app.core import security
|
|
from app.integrations import wxpay
|
|
|
|
|
|
def _fake_userinfo(openid: str, nickname: str | None = "微信昵称", avatar: str | None = "http://x/a.png"):
|
|
"""返回一个可传给 monkeypatch 的假 code_to_userinfo(忽略 code,固定返回给定 openid)。"""
|
|
def _f(code: str) -> dict:
|
|
return {"openid": openid, "nickname": nickname, "avatar_url": avatar, "raw": {}}
|
|
return _f
|
|
|
|
|
|
# ===== Task 1: bind_ticket 令牌 =====
|
|
|
|
def test_bind_ticket_roundtrip() -> None:
|
|
token = security.create_bind_ticket(openid="oid1", wechat_nickname="昵", wechat_avatar_url="http://a")
|
|
claims = security.decode_bind_ticket(token)
|
|
assert claims["openid"] == "oid1"
|
|
assert claims["wnk"] == "昵"
|
|
assert claims["wav"] == "http://a"
|
|
|
|
|
|
def test_bind_ticket_wrong_type_rejected() -> None:
|
|
# 用 access token 冒充 bind_ticket → TokenError(typ 不匹配)
|
|
access, _ = security.create_token(user_id=1, token_type="access")
|
|
with pytest.raises(security.TokenError):
|
|
security.decode_bind_ticket(access)
|
|
|
|
|
|
def test_bind_ticket_expired_rejected(monkeypatch) -> None:
|
|
monkeypatch.setattr(security.settings, "WECHAT_BIND_TICKET_EXPIRE_MINUTES", -1)
|
|
token = security.create_bind_ticket(openid="oid", wechat_nickname=None, wechat_avatar_url=None)
|
|
with pytest.raises(security.TokenError):
|
|
security.decode_bind_ticket(token)
|
|
|
|
|
|
# ===== Task 2: wechat-login =====
|
|
|
|
def test_wechat_login_new_openid_returns_bind_ticket(client, monkeypatch) -> None:
|
|
monkeypatch.setattr(wxpay, "code_to_userinfo", _fake_userinfo("openid_new_1", "小明", "http://x/m.png"))
|
|
r = client.post("/api/v1/auth/wechat-login", json={"code": "wxcode1", "device_id": "devA"})
|
|
assert r.status_code == 200, r.text
|
|
body = r.json()
|
|
assert body["status"] == "need_bind_phone"
|
|
assert body["bind_ticket"]
|
|
assert body["wechat_nickname"] == "小明"
|
|
assert body["wechat_avatar_url"] == "http://x/m.png"
|
|
assert body["token"] is None
|
|
|
|
|
|
def test_wechat_login_invalid_code_returns_400(client, monkeypatch) -> None:
|
|
def _raise(code: str) -> dict:
|
|
raise ValueError("微信授权失败: invalid code")
|
|
monkeypatch.setattr(wxpay, "code_to_userinfo", _raise)
|
|
r = client.post("/api/v1/auth/wechat-login", json={"code": "bad", "device_id": "devA"})
|
|
assert r.status_code == 400, r.text
|