Something went wrong. Try again.
A Python client for Microsoft Teams' consumer chat API
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139import pytestfrom fake_http import FakeResponse, FakeSession
from teamsy.auth import TeamsAuthErrorfrom teamsy.device_code import ( DeviceCodeDeclined, DeviceCodeExpired, DeviceCodeInfo, poll_device_code, start_device_code,)
@pytest.fixture(autouse=True)def no_real_sleep(monkeypatch): async def fake_sleep(_delay): pass
monkeypatch.setattr("teamsy.device_code.asyncio.sleep", fake_sleep) monkeypatch.setattr("teamsy.executor.asyncio.sleep", fake_sleep)
@pytest.mark.asyncioasync def test_start_device_code_parses_response(): session = FakeSession( [ FakeResponse( 200, { "device_code": "dc", "user_code": "ABCD1234", "verification_uri": "https://microsoft.com/devicelogin", "interval": 5, "expires_in": 900, }, ) ] ) info = await start_device_code(session) assert info.user_code == "ABCD1234" assert info.verification_uri == "https://microsoft.com/devicelogin" assert info.interval == 5
@pytest.mark.asyncioasync def test_start_device_code_falls_back_to_verification_url_key(): # The legacy v1 device-code endpoint uses "verification_url", not # "verification_uri". session = FakeSession( [ FakeResponse( 200, { "device_code": "dc", "user_code": "ABCD1234", "verification_url": "https://microsoft.com/devicelogin", }, ) ] ) info = await start_device_code(session) assert info.verification_uri == "https://microsoft.com/devicelogin"
@pytest.mark.asyncioasync def test_start_device_code_raises_on_missing_fields(): session = FakeSession([FakeResponse(200, {"device_code": "dc"})]) with pytest.raises(TeamsAuthError): await start_device_code(session)
def _info(**overrides) -> DeviceCodeInfo: defaults = { "device_code": "dc", "user_code": "ABCD1234", "verification_uri": "https://microsoft.com/devicelogin", "interval": 5, "expires_in": 900, } defaults.update(overrides) return DeviceCodeInfo(**defaults)
@pytest.mark.asyncioasync def test_poll_device_code_succeeds_after_pending(): session = FakeSession( [ FakeResponse(200, {"error": "authorization_pending"}), FakeResponse( 200, { "access_token": "access-1", "refresh_token": "refresh-1", "expires_in": 3600, }, ), ] ) refresh_token = await poll_device_code(session, _info()) assert refresh_token == "refresh-1"
@pytest.mark.asyncioasync def test_poll_device_code_raises_missing_refresh_token(): session = FakeSession([FakeResponse(200, {"access_token": "access-1"})]) with pytest.raises(TeamsAuthError): await poll_device_code(session, _info())
@pytest.mark.asyncioasync def test_poll_device_code_declined(): session = FakeSession([FakeResponse(200, {"error": "authorization_declined"})]) with pytest.raises(DeviceCodeDeclined): await poll_device_code(session, _info())
@pytest.mark.asyncioasync def test_poll_device_code_server_side_expiry(): session = FakeSession([FakeResponse(200, {"error": "expired_token"})]) with pytest.raises(DeviceCodeExpired): await poll_device_code(session, _info())
@pytest.mark.asyncioasync def test_poll_device_code_local_deadline_expiry(): # expires_in=0 means the deadline (time.monotonic() + expires_in) is # already in the past by the time the first sleep would return. session = FakeSession([]) # no request should even be made with pytest.raises(DeviceCodeExpired): await poll_device_code(session, _info(expires_in=0))
@pytest.mark.asyncioasync def test_poll_device_code_unknown_error_raises_generic(): session = FakeSession([FakeResponse(200, {"error": "something_else"})]) with pytest.raises(TeamsAuthError) as exc_info: await poll_device_code(session, _info()) assert not isinstance(exc_info.value, (DeviceCodeDeclined, DeviceCodeExpired))