Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions dotnet/test/SessionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public async Task Should_Pass_Streaming_Option_To_Session_Creation()
}

[Fact]
public async Task Should_SessionEvt_Subscribed()
public async Task Should_Receive_Session_Events()
{
var session = await Client.CreateSessionAsync();
var receivedEvents = new List<SessionEvent>();
Expand All @@ -303,7 +303,7 @@ public async Task Should_SessionEvt_Subscribed()
});

// Send a message to trigger events
await session.SendAsync(new MessageOptions { Prompt = "Hello!" });
await session.SendAsync(new MessageOptions { Prompt = "What is 100+200?" });

// Wait for session to become idle (indicating message processing is complete)
var completed = await Task.WhenAny(idleReceived.Task, Task.Delay(TimeSpan.FromSeconds(60)));
Expand All @@ -315,6 +315,11 @@ public async Task Should_SessionEvt_Subscribed()
Assert.Contains(receivedEvents, evt => evt is AssistantMessageEvent);
Assert.Contains(receivedEvents, evt => evt is SessionIdleEvent);

// Verify the assistant response contains the expected answer
var assistantMessage = await TestHelper.GetFinalAssistantMessageAsync(session);
Assert.NotNull(assistantMessage);
Assert.Contains("300", assistantMessage!.Data.Content);

await session.DisposeAsync();
}
}
73 changes: 73 additions & 0 deletions go/e2e/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,79 @@ func TestSession(t *testing.T) {
t.Errorf("Expected assistant message to contain '2', got %v", assistantMessage.Data.Content)
}
})

t.Run("should receive session events", func(t *testing.T) {
ctx.ConfigureForTest(t)

session, err := client.CreateSession(nil)
if err != nil {
t.Fatalf("Failed to create session: %v", err)
}

var receivedEvents []copilot.SessionEvent
idle := make(chan bool)

session.On(func(event copilot.SessionEvent) {
receivedEvents = append(receivedEvents, event)
if event.Type == "session.idle" {
select {
case idle <- true:
default:
}
}
})

// Send a message to trigger events
_, err = session.Send(copilot.MessageOptions{Prompt: "What is 100+200?"})
if err != nil {
t.Fatalf("Failed to send message: %v", err)
}

// Wait for session to become idle
select {
case <-idle:
case <-time.After(60 * time.Second):
t.Fatal("Timed out waiting for session.idle")
}

// Should have received multiple events
if len(receivedEvents) == 0 {
t.Error("Expected to receive events, got none")
}

hasUserMessage := false
hasAssistantMessage := false
hasSessionIdle := false
for _, evt := range receivedEvents {
switch evt.Type {
case "user.message":
hasUserMessage = true
case "assistant.message":
hasAssistantMessage = true
case "session.idle":
hasSessionIdle = true
}
}

if !hasUserMessage {
t.Error("Expected to receive user.message event")
}
if !hasAssistantMessage {
t.Error("Expected to receive assistant.message event")
}
if !hasSessionIdle {
t.Error("Expected to receive session.idle event")
}

// Verify the assistant response contains the expected answer
assistantMessage, err := testharness.GetFinalAssistantMessage(session, 60*time.Second)
if err != nil {
t.Fatalf("Failed to get assistant message: %v", err)
}
if assistantMessage.Data.Content == nil || !strings.Contains(*assistantMessage.Data.Content, "300") {
t.Errorf("Expected assistant message to contain '300', got %v", assistantMessage.Data.Content)
}
})
}

func getSystemMessage(exchange testharness.ParsedHttpExchange) string {
Expand Down
32 changes: 32 additions & 0 deletions nodejs/test/e2e/session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,38 @@ describe("Sessions", async () => {
const assistantMessage = await getFinalAssistantMessage(session);
expect(assistantMessage.data.content).toContain("2");
});

it("should receive session events", async () => {
const session = await client.createSession();
const receivedEvents: Array<{ type: string }> = [];
let idleResolve: () => void;
const idlePromise = new Promise<void>((resolve) => {
idleResolve = resolve;
});

session.on((event) => {
receivedEvents.push(event);
if (event.type === "session.idle") {
idleResolve();
}
});

// Send a message to trigger events
await session.send({ prompt: "What is 100+200?" });

// Wait for session to become idle
await Promise.race([idlePromise, new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), 60000))]);

// Should have received multiple events
expect(receivedEvents.length).toBeGreaterThan(0);
expect(receivedEvents.some((e) => e.type === "user.message")).toBe(true);
expect(receivedEvents.some((e) => e.type === "assistant.message")).toBe(true);
expect(receivedEvents.some((e) => e.type === "session.idle")).toBe(true);

// Verify the assistant response contains the expected answer
const assistantMessage = await getFinalAssistantMessage(session);
expect(assistantMessage.data.content).toContain("300");
});
});

function getSystemMessage(exchange: ParsedHttpExchange): string | undefined {
Expand Down
34 changes: 34 additions & 0 deletions python/e2e/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,40 @@ async def test_should_pass_streaming_option_to_session_creation(self, ctx: E2ETe
assistant_message = await get_final_assistant_message(session)
assert "2" in assistant_message.data.content

async def test_should_receive_session_events(self, ctx: E2ETestContext):
import asyncio

session = await ctx.client.create_session()
received_events = []
idle_event = asyncio.Event()

def on_event(event):
received_events.append(event)
if event.type.value == "session.idle":
idle_event.set()

session.on(on_event)

# Send a message to trigger events
await session.send({"prompt": "What is 100+200?"})

# Wait for session to become idle
try:
await asyncio.wait_for(idle_event.wait(), timeout=60)
except asyncio.TimeoutError:
pytest.fail("Timed out waiting for session.idle")

# Should have received multiple events
assert len(received_events) > 0
event_types = [e.type.value for e in received_events]
assert "user.message" in event_types
assert "assistant.message" in event_types
assert "session.idle" in event_types

# Verify the assistant response contains the expected answer
assistant_message = await get_final_assistant_message(session)
assert "300" in assistant_message.data.content


def _get_system_message(exchange: dict) -> str:
messages = exchange.get("request", {}).get("messages", [])
Expand Down
10 changes: 10 additions & 0 deletions test/snapshots/session/should_receive_session_events.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
models:
- claude-sonnet-4.5
conversations:
- messages:
- role: system
content: ${system}
- role: user
content: What is 100+200?
- role: assistant
content: 100 + 200 = 300
Loading