# -*- coding: utf-8 -*- from unittest.mock import MagicMock import pytest def test_ensure_logged_in_dispatches_password_auto(monkeypatch): from service.rpa_helpers import auth_flows monkeypatch.setattr(auth_flows, "_is_already_logged_in", lambda p, a: False) monkeypatch.setattr(auth_flows, "_poll_until", lambda *a, **k: True) loc = MagicMock() page = MagicMock() page.url = "http://example.com" page.locator.return_value.first = loc account = {"auth_strategy": "password_auto", "login_id": "u", "url": "http://x"} r = auth_flows.ensure_logged_in(page, account, credentials={"plaintext": "pw"}) assert r.ok is True page.goto.assert_called() assert loc.type.call_count >= 2 loc.click.assert_called() def test_ensure_logged_in_dispatches_qr_code_manual(monkeypatch): from service.rpa_helpers import auth_flows monkeypatch.setattr(auth_flows, "_is_already_logged_in", lambda p, a: True) page = MagicMock() account = {"auth_strategy": "qr_code_manual", "url": "http://x"} r = auth_flows.ensure_logged_in(page, account) assert r.ok is True def test_ensure_logged_in_client_certificate_raises(): from service.rpa_helpers.auth_flows import AuthStrategyError, ensure_logged_in page = MagicMock() account = {"auth_strategy": "client_certificate"} with pytest.raises(AuthStrategyError) as ei: ensure_logged_in(page, account) assert ei.value.code == "ERR_AUTH_STRATEGY_NOT_AUTOMATABLE" def test_ensure_logged_in_api_token_no_op(): from service.rpa_helpers.auth_flows import ensure_logged_in page = MagicMock() account = {"auth_strategy": "api_token"} r = ensure_logged_in(page, account) assert r.ok is True page.goto.assert_not_called() def test_ensure_logged_in_missing_credentials(): from service.rpa_helpers.auth_flows import AuthStrategyError, ensure_logged_in page = MagicMock() account = {"auth_strategy": "password_auto", "login_id": "u"} with pytest.raises(AuthStrategyError) as ei: ensure_logged_in(page, account, credentials=None) assert ei.value.code == "ERR_CREDENTIAL_MISSING" def test_ensure_logged_in_unknown_strategy(): from service.rpa_helpers.auth_flows import AuthStrategyError, ensure_logged_in page = MagicMock() account = {"auth_strategy": "bogus"} with pytest.raises(AuthStrategyError) as ei: ensure_logged_in(page, account) assert ei.value.code == "ERR_AUTH_STRATEGY_NOT_SUPPORTED" def test_ensure_logged_in_no_strategy(): from service.rpa_helpers.auth_flows import AuthStrategyError, ensure_logged_in page = MagicMock() account = {"auth_strategy": ""} with pytest.raises(AuthStrategyError) as ei: ensure_logged_in(page, account) assert ei.value.code == "ERR_AUTH_STRATEGY_NOT_SUPPORTED" def test_device_bound_fingerprint_mismatch(monkeypatch): from service.rpa_helpers.auth_flows import AuthStrategyError, ensure_logged_in monkeypatch.setattr( "service.rpa_helpers.auth_flows._current_machine_fingerprint", lambda: "right_fp", ) page = MagicMock() account = { "auth_strategy": "device_bound", "device_fingerprint": "wrong_fp", "login_id": "u", "url": "http://x", } with pytest.raises(AuthStrategyError) as ei: ensure_logged_in(page, account, credentials={"plaintext": "pw"}) assert ei.value.code == "ERR_DEVICE_FINGERPRINT_MISMATCH" def test_is_already_logged_in_default_false(): from service.rpa_helpers.auth_flows import _is_already_logged_in p = MagicMock() p.url = "about:blank" assert _is_already_logged_in(p, {}) is False p.url = "https://www.douyin.com" assert _is_already_logged_in(p, {}) is False p.url = "https://www.douyin.com/user/abc" assert _is_already_logged_in( p, {"extra_json": {"logged_in_url_pattern": r"/user/"}}, ) is True loc_first = MagicMock() loc_first.is_visible.return_value = True loc = MagicMock() loc.first = loc_first p2 = MagicMock() p2.url = "https://example.com/home" p2.locator.return_value = loc assert _is_already_logged_in( p2, {"extra_json": {"logged_in_selector": "#avatar"}}, ) is True p2.locator.assert_called_with("#avatar") def test_qr_code_manual_default_no_hooks(): from service.rpa_helpers.auth_flows import ensure_logged_in qr_first = MagicMock() qr_first.wait_for.side_effect = TimeoutError("mock qr timeout") qr_loc = MagicMock() qr_loc.first = qr_first page = MagicMock() page.url = "about:blank" page.locator.return_value = qr_loc account = {"auth_strategy": "qr_code_manual", "url": "http://login.example"} r = ensure_logged_in(page, account) page.goto.assert_called_once_with( "http://login.example", wait_until="domcontentloaded", timeout=60000, ) qr_first.wait_for.assert_called_once() assert r.ok is False assert r.message == "qr code not found"