Skip to content

Commit 1a84d4d

Browse files
committed
fix tests
1 parent 27cdfef commit 1a84d4d

File tree

1 file changed

+43
-162
lines changed

1 file changed

+43
-162
lines changed

packages/apps/tests/test_token_manager.py

Lines changed: 43 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
Licensed under the MIT License.
44
"""
55

6-
from unittest.mock import AsyncMock, MagicMock, patch
6+
from unittest.mock import MagicMock, patch
77

88
import pytest
99
from microsoft.teams.api import ClientCredentials, JsonWebToken
1010
from microsoft.teams.apps.token_manager import TokenManager
11-
from microsoft.teams.common import Client
1211

1312
# Valid JWT-like token for testing (format: header.payload.signature)
1413
VALID_TEST_TOKEN = (
@@ -23,204 +22,86 @@ class TestTokenManager:
2322

2423
@pytest.mark.asyncio
2524
async def test_get_bot_token_success(self):
26-
"""Test successful bot token refresh, caching, and expiration refresh."""
27-
# First token response
28-
mock_token_response1 = MagicMock()
29-
mock_token_response1.access_token = VALID_TEST_TOKEN
30-
31-
# Second token response for expired token
32-
mock_token_response2 = MagicMock()
33-
mock_token_response2.access_token = (
34-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
35-
"eyJzdWIiOiI5ODc2NTQzMjEwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
36-
"Twzj7LKlhYUUe2GFRME4WOZdWq2TdayZhWjhBr1r5X4"
37-
)
38-
39-
# Third token response for force refresh
40-
mock_token_response3 = MagicMock()
41-
mock_token_response3.access_token = (
42-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
43-
"eyJzdWIiOiIxMTExMTExMTExIiwibmFtZSI6IkZvcmNlIFJlZnJlc2giLCJpYXQiOjE1MTYyMzkwMjJ9."
44-
"dQw4w9WgXcQ"
45-
)
46-
25+
"""Test successful bot token retrieval using MSAL."""
4726
mock_credentials = ClientCredentials(
4827
client_id="test-client-id",
4928
client_secret="test-client-secret",
5029
tenant_id="test-tenant-id",
5130
)
5231

53-
# Mock the BotTokenClient
54-
mock_bot_token_client = MagicMock()
55-
mock_bot_token_client.get = AsyncMock(
56-
side_effect=[mock_token_response1, mock_token_response2, mock_token_response3]
57-
)
32+
# Mock MSAL ConfidentialClientApplication
33+
mock_msal_app = MagicMock()
34+
mock_msal_app.acquire_token_for_client = MagicMock(return_value={"access_token": VALID_TEST_TOKEN})
5835

59-
mock_http_client = MagicMock(spec=Client)
60-
mock_http_client.clone = MagicMock(return_value=mock_http_client)
36+
with patch("microsoft.teams.apps.token_manager.ConfidentialClientApplication", return_value=mock_msal_app):
37+
manager = TokenManager(credentials=mock_credentials)
6138

62-
with patch("microsoft.teams.apps.token_manager.BotTokenClient", return_value=mock_bot_token_client):
63-
manager = TokenManager(
64-
credentials=mock_credentials,
65-
)
66-
67-
# First call
68-
token1 = await manager.get_bot_token()
69-
assert token1 is not None
70-
assert isinstance(token1, JsonWebToken)
71-
mock_bot_token_client.get.assert_called_once()
72-
73-
# Second call should use cache (mock should still only be called once)
74-
token2 = await manager.get_bot_token()
75-
assert token2 == token1
76-
mock_bot_token_client.get.assert_called_once() # Still only called once due to caching
39+
token = await manager.get_bot_token()
7740

78-
# Mock the token as expired
79-
token1.is_expired = MagicMock(return_value=True)
41+
assert token is not None
42+
assert isinstance(token, JsonWebToken)
43+
assert str(token) == VALID_TEST_TOKEN
8044

81-
# Third call should refresh because token is expired
82-
token3 = await manager.get_bot_token()
83-
assert token3 is not None
84-
assert token3 != token1 # New token
85-
assert mock_bot_token_client.get.call_count == 2
45+
# Verify MSAL was called with correct scope
46+
mock_msal_app.acquire_token_for_client.assert_called_once_with(["https://api.botframework.com/.default"])
8647

8748
@pytest.mark.asyncio
8849
async def test_get_bot_token_no_credentials(self):
89-
"""Test refreshing bot token with no credentials returns None."""
90-
mock_http_client = MagicMock(spec=Client)
91-
mock_http_client.clone = MagicMock(return_value=mock_http_client)
92-
93-
with patch("microsoft.teams.apps.token_manager.BotTokenClient"):
94-
manager = TokenManager(
95-
credentials=None,
96-
)
97-
98-
token = await manager.get_bot_token()
99-
assert token is None
50+
"""Test getting bot token with no credentials returns None."""
51+
manager = TokenManager(credentials=None)
52+
token = await manager.get_bot_token()
53+
assert token is None
10054

10155
@pytest.mark.asyncio
10256
async def test_get_graph_token_default(self):
103-
"""Test getting default graph token with caching and expiration refresh."""
104-
# First token response
105-
mock_token_response1 = MagicMock()
106-
mock_token_response1.access_token = VALID_TEST_TOKEN
107-
108-
# Second token response for expired token
109-
mock_token_response2 = MagicMock()
110-
mock_token_response2.access_token = (
111-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
112-
"eyJzdWIiOiI5ODc2NTQzMjEwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
113-
"Twzj7LKlhYUUe2GFRME4WOZdWq2TdayZhWjhBr1r5X4"
114-
)
115-
57+
"""Test getting default graph token using MSAL."""
11658
mock_credentials = ClientCredentials(
11759
client_id="test-client-id",
11860
client_secret="test-client-secret",
11961
tenant_id="default-tenant-id",
12062
)
12163

122-
# Mock the BotTokenClient
123-
mock_bot_token_client = MagicMock()
124-
mock_bot_token_client.get_graph = AsyncMock(side_effect=[mock_token_response1, mock_token_response2])
125-
126-
mock_http_client = MagicMock(spec=Client)
127-
mock_http_client.clone = MagicMock(return_value=mock_http_client)
128-
129-
with patch("microsoft.teams.apps.token_manager.BotTokenClient", return_value=mock_bot_token_client):
130-
manager = TokenManager(
131-
credentials=mock_credentials,
132-
)
133-
134-
token1 = await manager.get_graph_token()
64+
# Mock MSAL ConfidentialClientApplication
65+
mock_msal_app = MagicMock()
66+
mock_msal_app.acquire_token_for_client = MagicMock(return_value={"access_token": VALID_TEST_TOKEN})
13567

136-
assert token1 is not None
137-
assert isinstance(token1, JsonWebToken)
68+
with patch("microsoft.teams.apps.token_manager.ConfidentialClientApplication", return_value=mock_msal_app):
69+
manager = TokenManager(credentials=mock_credentials)
13870

139-
# Verify it's cached
140-
token2 = await manager.get_graph_token()
141-
assert token2 == token1
142-
mock_bot_token_client.get_graph.assert_called_once()
71+
token = await manager.get_graph_token()
14372

144-
# Mock the token as expired
145-
token1.is_expired = MagicMock(return_value=True)
73+
assert token is not None
74+
assert isinstance(token, JsonWebToken)
75+
assert str(token) == VALID_TEST_TOKEN
14676

147-
# Third call should refresh because token is expired
148-
token3 = await manager.get_graph_token()
149-
assert token3 is not None
150-
assert token3 != token1 # New token
151-
assert mock_bot_token_client.get_graph.call_count == 2
77+
# Verify MSAL was called with correct scope
78+
mock_msal_app.acquire_token_for_client.assert_called_once_with(["https://graph.microsoft.com/.default"])
15279

15380
@pytest.mark.asyncio
15481
async def test_get_graph_token_with_tenant(self):
155-
"""Test getting tenant-specific graph token."""
156-
mock_token_response = MagicMock()
157-
mock_token_response.access_token = VALID_TEST_TOKEN
158-
82+
"""Test getting tenant-specific graph token using MSAL."""
15983
original_credentials = ClientCredentials(
16084
client_id="test-client-id",
16185
client_secret="test-client-secret",
16286
tenant_id="original-tenant-id",
16387
)
16488

165-
# Mock the BotTokenClient
166-
mock_bot_token_client = MagicMock()
167-
mock_bot_token_client.get_graph = AsyncMock(return_value=mock_token_response)
168-
169-
mock_http_client = MagicMock(spec=Client)
170-
mock_http_client.clone = MagicMock(return_value=mock_http_client)
89+
# Mock MSAL ConfidentialClientApplication
90+
mock_msal_app = MagicMock()
91+
mock_msal_app.acquire_token_for_client = MagicMock(return_value={"access_token": VALID_TEST_TOKEN})
17192

172-
with patch("microsoft.teams.apps.token_manager.BotTokenClient", return_value=mock_bot_token_client):
173-
manager = TokenManager(
174-
credentials=original_credentials,
175-
)
93+
with patch(
94+
"microsoft.teams.apps.token_manager.ConfidentialClientApplication", return_value=mock_msal_app
95+
) as mock_msal_class:
96+
manager = TokenManager(credentials=original_credentials)
17697

17798
token = await manager.get_graph_token("different-tenant-id")
17899

179100
assert token is not None
180-
mock_bot_token_client.get_graph.assert_called_once()
181-
182-
# Verify tenant-specific credentials were created
183-
call_args = mock_bot_token_client.get_graph.call_args
184-
passed_credentials = call_args[0][0]
185-
assert isinstance(passed_credentials, ClientCredentials)
186-
assert passed_credentials.tenant_id == "different-tenant-id"
187-
188-
@pytest.mark.asyncio
189-
async def test_graph_token_force_refresh(self):
190-
"""Test force refreshing graph token even when not expired."""
191-
mock_token_response1 = MagicMock()
192-
mock_token_response1.access_token = VALID_TEST_TOKEN
193-
194-
mock_token_response2 = MagicMock()
195-
mock_token_response2.access_token = (
196-
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
197-
"eyJzdWIiOiIxMTExMTExMTExIiwibmFtZSI6IkZvcmNlIFJlZnJlc2giLCJpYXQiOjE1MTYyMzkwMjJ9."
198-
"dQw4w9WgXcQ"
199-
)
200-
201-
mock_credentials = ClientCredentials(
202-
client_id="test-client-id",
203-
client_secret="test-client-secret",
204-
tenant_id="test-tenant-id",
205-
)
206-
207-
mock_bot_token_client = MagicMock()
208-
mock_bot_token_client.get_graph = AsyncMock(side_effect=[mock_token_response1, mock_token_response2])
209-
210-
mock_http_client = MagicMock(spec=Client)
211-
mock_http_client.clone = MagicMock(return_value=mock_http_client)
212-
213-
with patch("microsoft.teams.apps.token_manager.BotTokenClient", return_value=mock_bot_token_client):
214-
manager = TokenManager(
215-
credentials=mock_credentials,
216-
)
217-
218-
# First call
219-
token1 = await manager.get_graph_token()
220-
assert token1 is not None
221-
mock_bot_token_client.get_graph.assert_called_once()
101+
assert isinstance(token, JsonWebToken)
222102

223-
# Second call should use cache
224-
token2 = await manager.get_graph_token()
225-
assert token2 == token1
226-
mock_bot_token_client.get_graph.assert_called_once() # Still only called once
103+
# Verify MSAL app was created with different tenant ID
104+
# The manager caches MSAL clients, so we check the call to the class constructor
105+
calls = mock_msal_class.call_args_list
106+
# Should have been called with different-tenant-id
107+
assert any("different-tenant-id" in str(call) for call in calls)

0 commit comments

Comments
 (0)