"""验证码生成与编解码测试。""" import pytest from authbot import captcha def test_generate_basic_properties(): for _ in range(50): cap = captcha.generate(4) assert len(cap.options) == 4 assert len(set(cap.options)) == 4 # 选项互不重复 assert cap.answer in cap.options assert all(v >= 0 for v in cap.options) # 运算式与答案自洽 expected = cap.a + cap.b if cap.op == "+" else cap.a - cap.b if cap.op == "-" else cap.a * cap.b assert expected == cap.answer assert cap.op in ("+", "-", "×") def test_generate_option_count_variants(): for n in (2, 3, 5): cap = captcha.generate(n) assert len(cap.options) == n assert len(set(cap.options)) == n def test_token_unique_per_captcha(): tokens = {captcha.generate().token for _ in range(100)} assert len(tokens) == 100 def test_parse_button_data_roundtrip(): token, value = "abc123", 42 encoded = captcha.encode_button_data(token, value) assert captcha.parse_button_data(encoded) == (token, value) @pytest.mark.parametrize( "data", ["", "v|", "v|abc", "v|abc|x", "hello|abc|1", "cmd|abc|1", "v|abc|1|2"], ) def test_parse_button_data_rejects_invalid(data): assert captcha.parse_button_data(data) is None def test_keyboard_structure(): cap = captcha.generate(4) kb = cap.keyboard() rows = kb["content"]["rows"] assert len(rows) == 2 # 每行 2 个按钮 flat = [btn for row in rows for btn in row["buttons"]] assert len(flat) == 4 labels = {btn["render_data"]["label"] for btn in flat} assert labels == {str(v) for v in cap.options} for btn in flat: token, value = captcha.parse_button_data(btn["action"]["data"]) assert token == cap.token assert value in cap.options assert btn["action"]["type"] == 1 # 回调按钮 def test_markdown_templates(): cap = captcha.generate(4) welcome = captcha.welcome_markdown(cap, 10) assert "10 分钟" in welcome assert cap.question in welcome retry = captcha.retry_markdown(cap) assert cap.question in retry assert "换一题" in retry