test(07-01): add failing tests for ZhihuLogin QR code login

TDD RED phase - tests expect ZhihuLogin class that doesn't exist yet:

- test_login_page_access: verify correct login URL
- test_qrcode_screenshot: verify QR code capture and save
- test_cookie_detection_with_z_c0: verify login detection
- test_cookie_detection_without_z_c0: verify no login when missing z_c0
- test_cookie_extraction: verify cookie string format
- test_login_timeout: verify timeout after 60s polling
- test_result_model_success: verify success result model
- test_result_model_failure: verify failure result model

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 17:50:26 +08:00
parent 19c377ef65
commit fb9bc2d1ed
+147
View File
@@ -0,0 +1,147 @@
"""Tests for ZhihuLogin QR code login functionality
Tests the core login flow:
1. Access login page
2. Capture QR code screenshot
3. Poll for login cookie (z_c0)
4. Extract cookie string on success
5. Handle timeout
"""
import pytest
from unittest.mock import MagicMock, patch, AsyncMock
from pathlib import Path
class TestZhihuLogin:
"""Test suite for ZhihuLogin class."""
def test_login_page_access(self, mock_browser):
"""Test that login page is accessed with correct URL."""
from kb_workflow.auth import ZhihuLogin
login = ZhihuLogin(intermediate_path="/tmp/test")
login.browser = mock_browser
# Simulate calling goto
login.browser.goto("https://www.zhihu.com/signin")
# Verify goto was called with correct URL
mock_browser.goto.assert_called_once_with("https://www.zhihu.com/signin")
def test_qrcode_screenshot(self, mock_browser, mock_canvas, intermediate_path):
"""Test QR code screenshot is captured and saved correctly."""
from kb_workflow.auth import ZhihuLogin
login = ZhihuLogin(intermediate_path=intermediate_path)
login.browser = mock_browser
# Mock the canvas screenshot
mock_browser.query_selector.return_value = mock_canvas
mock_canvas.screenshot.return_value = b"fake_png_bytes"
# Call _save_qrcode_image
screenshot_bytes = b"fake_png_bytes"
qrcode_path = login._save_qrcode_image(screenshot_bytes)
# Verify file was created
assert qrcode_path.exists()
assert qrcode_path.suffix == ".png"
assert "zhihu_qrcode" in qrcode_path.name
def test_cookie_detection_with_z_c0(self, mock_browser, sample_cookies):
"""Test that login is detected when z_c0 cookie exists."""
from kb_workflow.auth import ZhihuLogin
login = ZhihuLogin(intermediate_path="/tmp/test")
login.browser = mock_browser
# Mock cookies to include z_c0
mock_browser.context.cookies.return_value = sample_cookies
# Check login cookie
is_logged_in = login.check_login_cookie()
assert is_logged_in is True
def test_cookie_detection_without_z_c0(self, mock_browser, sample_cookies_no_login):
"""Test that login is NOT detected when z_c0 cookie is missing."""
from kb_workflow.auth import ZhihuLogin
login = ZhihuLogin(intermediate_path="/tmp/test")
login.browser = mock_browser
# Mock cookies without z_c0
mock_browser.context.cookies.return_value = sample_cookies_no_login
# Check login cookie
is_logged_in = login.check_login_cookie()
assert is_logged_in is False
def test_cookie_extraction(self, mock_browser, sample_cookies):
"""Test cookie string extraction after successful login."""
from kb_workflow.auth import ZhihuLogin
login = ZhihuLogin(intermediate_path="/tmp/test")
login.browser = mock_browser
# Mock cookies
mock_browser.context.cookies.return_value = sample_cookies
# Get cookie string
cookie_str = login.get_cookies_str()
# Verify format: "name1=value1; name2=value2"
assert "z_c0=test_z_c0_value" in cookie_str
assert "_xsrf=test_xsrf_value" in cookie_str
assert ";" in cookie_str
def test_login_timeout(self, mock_browser, sample_cookies_no_login):
"""Test that TimeoutError is raised after 60 seconds of polling."""
from kb_workflow.auth import ZhihuLogin
from tenacity import RetryError
login = ZhihuLogin(intermediate_path="/tmp/test", timeout=2) # Short timeout for test
login.browser = mock_browser
# Mock cookies to always return no login
mock_browser.context.cookies.return_value = sample_cookies_no_login
# Should raise RetryError (wrapped by tenacity) or TimeoutError
with pytest.raises((TimeoutError, RetryError)):
login._wait_for_login()
class TestZhihuLoginResult:
"""Test suite for ZhihuLoginResult model."""
def test_result_model_success(self):
"""Test ZhihuLoginResult model with successful login."""
from kb_workflow.auth import ZhihuLoginResult
result = ZhihuLoginResult(
success=True,
cookie_str="z_c0=abc123; _xsrf=xyz789",
qrcode_path=Path("/tmp/qrcode.png"),
error_message=None
)
assert result.success is True
assert "z_c0" in result.cookie_str
assert result.error_message is None
def test_result_model_failure(self):
"""Test ZhihuLoginResult model with failed login."""
from kb_workflow.auth import ZhihuLoginResult
result = ZhihuLoginResult(
success=False,
cookie_str="",
qrcode_path=Path("/tmp/qrcode.png"),
error_message="Login timeout after 60 seconds"
)
assert result.success is False
assert result.cookie_str == ""
assert "timeout" in result.error_message.lower()