-
Notifications
You must be signed in to change notification settings - Fork 54
Integration package refinements #266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 15 commits
3cb2022
6e25a90
fd25c32
464ecc6
d1ec76e
6c0a56e
6a57b4c
943fd71
efc7da2
5c77c65
ecb2c6e
3048e19
930bf09
603050d
415264b
cadb843
902d412
b373f31
5329bc4
a37a136
bcca57f
4be418a
329fefa
4e8dca3
61739f4
223a1f8
fae00e9
2d6a9eb
a4e3a25
12f9d90
995d44e
f077099
209c56d
31d5f2f
73205e0
42846ed
ba50824
8dc344c
ba92b0b
66b818c
284ab17
a21a856
54c4981
16b3366
055367a
df11807
a70cbe7
bc55f30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,5 @@ | ||
| from .basic_sample import BasicSample | ||
| from .quickstart_sample import QuickstartSample | ||
|
|
||
| __all__ = [ | ||
| "BasicSample", | ||
| "QuickstartSample", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ test: | |
| name: Test Bot | ||
| text: hi 5 | ||
| locale: en-US | ||
| - skip | ||
| - type: assertion | ||
| quantifier: one | ||
| activity: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| import pytest | ||
|
|
||
| from typing import Awaitable, Callable, Iterable | ||
|
|
||
| from aiohttp.web import Request, Response, Application, StreamResponse | ||
|
|
||
| from microsoft_agents.activity import Activity | ||
|
|
||
| from microsoft_agents.copilotstudio.client import ( | ||
| CopilotClient, | ||
| ConnectionSettings, | ||
| PowerPlatformEnvironment, | ||
| ) | ||
|
|
||
| from microsoft_agents.testing.integration.core import AiohttpRunner | ||
|
|
||
|
|
||
| def mock_mcs_handler(activity: Activity) -> Callable[[Request], Awaitable[Response]]: | ||
| """Creates a mock handler for MCS endpoint returning the given activity.""" | ||
|
|
||
| async def handler(request: Request) -> Response: | ||
| activity_data = activity.model_dump_json(exclude_unset=True) | ||
| return Response(body=activity_data) | ||
|
|
||
| return handler | ||
|
|
||
|
|
||
| def mock_mcs_handler( | ||
| activities: Iterable[Activity], | ||
| ) -> Callable[[Request], Awaitable[StreamResponse]]: | ||
| """Creates a mock handler for MCS endpoint returning SSE-formatted activity.""" | ||
|
|
||
| async def handler(request: Request) -> StreamResponse: | ||
| response = StreamResponse(status=200) | ||
| response.headers["Content-Type"] = "text/event-stream" | ||
| response.headers["x-ms-conversationid"] = "test-conv-id" | ||
| # response.headers['Content-Length'] = str(len(activity_data)) | ||
| await response.prepare(request) | ||
|
|
||
| # Proper SSE format | ||
| for activity in activities: | ||
| activity_data = activity.model_dump_json(exclude_unset=True) | ||
| await response.write(b"event: activity\n") | ||
| await response.write(f"data: {activity_data}\n\n".encode("utf-8")) | ||
|
|
||
| await response.write_eof() | ||
| return response | ||
|
|
||
| return handler | ||
|
||
|
|
||
|
|
||
| def mock_mcs_endpoint( | ||
| mocker, activities: Iterable[Activity], path: str, port: int | ||
| ) -> AiohttpRunner: | ||
| """Mock MCS responses for testing.""" | ||
|
|
||
| PowerPlatformEnvironment.get_copilot_studio_connection_url = mocker.MagicMock( | ||
| return_value=f"http://localhost:{port}{path}" | ||
| ) | ||
|
|
||
| app = Application() | ||
| app.router.add_post(path, mock_mcs_handler(activities)) | ||
|
|
||
| return AiohttpRunner(app, port=port) | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_start_conversation_and_ask_question_large_message(mocker): | ||
|
|
||
| activity = Activity( | ||
| type="message", text="*" * 1_000_000, conversation={"id": "conv-id"} | ||
| ) | ||
|
|
||
| runner = mock_mcs_endpoint(mocker, [activity], "/mcs-endpoint", port=8081) | ||
|
|
||
| async with runner: | ||
| settings = ConnectionSettings("environment-id", "agent-id") | ||
| client = CopilotClient(settings=settings, token="test-token") | ||
|
|
||
| with pytest.raises(Exception, match="Chunk too big"): | ||
| async for conv_activity in client.start_conversation(): | ||
| assert conv_activity.type == "message" | ||
|
|
||
| # with pytest.raises(Exception, match="Chunk too big"): | ||
| # async for question_activity in client.ask_question("Hello!", "conv-id"): | ||
| # assert question_activity.type == "message" | ||
|
|
||
|
|
||
| def activity_generator(activity: Activity, n: int) -> Iterable[Activity]: | ||
| for i in range(n): | ||
| yield activity | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_start_conversation_many(mocker): | ||
|
|
||
| activity = Activity(type="message", conversation={"id": "conv-id"}) | ||
| activities = activity_generator(activity, 100_000) | ||
|
|
||
| runner = mock_mcs_endpoint(mocker, activities, "/mcs-endpoint", port=8081) | ||
|
|
||
| async with runner: | ||
| settings = ConnectionSettings("environment-id", "agent-id") | ||
| client = CopilotClient(settings=settings, token="test-token") | ||
|
|
||
| for i in range(100): | ||
| # try: | ||
| async for conv_activity in client.start_conversation(): | ||
| assert conv_activity.type == "message" | ||
| # except Exception as e: | ||
| # assert str(e) == "Chunk too big" | ||
|
|
||
| # with pytest.raises(Exception, match="Chunk too big"): | ||
| # async for question_activity in client.ask_question("Hello!", "conv-id"): | ||
| # assert question_activity.type == "message" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ | |
|
|
||
| from .assertions import ( | ||
| ModelAssertion, | ||
| Selector, | ||
| ModelSelector, | ||
| AssertionQuantifier, | ||
| assert_model, | ||
| assert_field, | ||
|
|
@@ -31,6 +31,8 @@ | |
| DataDrivenTest, | ||
| ) | ||
|
|
||
| from .cli import cli | ||
|
||
|
|
||
| __all__ = [ | ||
| "SDKConfig", | ||
| "generate_token", | ||
|
|
@@ -45,7 +47,7 @@ | |
| "populate_activity", | ||
| "get_host_and_port", | ||
| "ModelAssertion", | ||
| "Selector", | ||
| "ModelSelector", | ||
| "AssertionQuantifier", | ||
| "assert_model", | ||
| "assert_field", | ||
|
|
@@ -56,4 +58,5 @@ | |
| "FieldAssertionType", | ||
| "ddt", | ||
| "DataDrivenTest", | ||
| "cli", | ||
|
||
| ] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate function definition. The function
mock_mcs_handleris defined twice with different signatures (lines 19-26 and 28-45), which will cause the second definition to override the first. The second definition is the one actually used on line 60. Consider renaming one of them or removing the unused first definition.