Skip to content

Commit 181d599

Browse files
committed
Improve SDK E2E test assertions
- stream-chunks: Fix vacuous timeSpread >= 0 assertion, make content assertions unconditional - concurrent-streams: Replace object identity check with proper content validation - subagent-streaming: Require subagent events instead of silently skipping assertions - max-agent-steps: Add finish event assertion and new maxAgentSteps=1 test case
1 parent 261a36b commit 181d599

File tree

2 files changed

+60
-24
lines changed

2 files changed

+60
-24
lines changed

sdk/e2e/streaming/concurrent-streams.e2e.test.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('Streaming: Concurrent Streams', () => {
3232
const collector1 = new EventCollector()
3333
const collector2 = new EventCollector()
3434

35-
// Run two prompts concurrently
35+
// Run two prompts concurrently with distinctive keywords
3636
const [result1, result2] = await Promise.all([
3737
client.run({
3838
agent: DEFAULT_AGENT,
@@ -58,9 +58,17 @@ describe('Streaming: Concurrent Streams', () => {
5858
expect(collector2.hasEventType('start')).toBe(true)
5959
expect(collector2.hasEventType('finish')).toBe(true)
6060

61-
// Event counts should be independent
62-
expect(collector1.events.length).toBeGreaterThan(0)
63-
expect(collector2.events.length).toBeGreaterThan(0)
61+
// Verify streams contain expected content and aren't mixed
62+
const text1 = collector1.getFullStreamText().toUpperCase()
63+
const text2 = collector2.getFullStreamText().toUpperCase()
64+
65+
// Each stream should contain its expected keyword
66+
expect(text1).toContain('ALPHA')
67+
expect(text2).toContain('BETA')
68+
69+
// Streams should NOT contain the other stream's keyword (no mixing)
70+
expect(text1).not.toContain('BETA')
71+
expect(text2).not.toContain('ALPHA')
6472
},
6573
DEFAULT_TIMEOUT * 2,
6674
)
@@ -123,10 +131,26 @@ describe('Streaming: Concurrent Streams', () => {
123131
}),
124132
])
125133

126-
// Each collector should have independent chunks
127-
// The chunks shouldn't be identical (different prompts)
128-
// Note: We can't guarantee exact output, but they should be independent
129-
expect(collector1.streamChunks).not.toBe(collector2.streamChunks)
134+
// Each collector should have independent chunks with different content
135+
// Verify both collectors received content
136+
expect(collector1.streamChunks.length).toBeGreaterThan(0)
137+
expect(collector2.streamChunks.length).toBeGreaterThan(0)
138+
139+
// Get the full text from each stream
140+
const text1 = collector1.getFullStreamText().toUpperCase()
141+
const text2 = collector2.getFullStreamText().toUpperCase()
142+
143+
// Both should have content
144+
expect(text1.length).toBeGreaterThan(0)
145+
expect(text2.length).toBeGreaterThan(0)
146+
147+
// Verify each stream contains its expected keyword
148+
expect(text1).toContain('FIRST')
149+
expect(text2).toContain('SECOND')
150+
151+
// Verify streams are NOT mixed - each should only have its own content
152+
expect(text1).not.toContain('SECOND')
153+
expect(text2).not.toContain('FIRST')
130154
},
131155
DEFAULT_TIMEOUT * 2,
132156
)

sdk/e2e/streaming/subagent-streaming.e2e.test.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,20 @@ describe('Streaming: Subagent Streaming', () => {
3939
const subagentStarts = collector.getEventsByType('subagent_start')
4040
const subagentFinishes = collector.getEventsByType('subagent_finish')
4141

42-
// If subagents were spawned, starts and finishes should match
43-
if (subagentStarts.length > 0) {
44-
// Each started subagent should have a finish
45-
for (const start of subagentStarts) {
46-
const matchingFinish = subagentFinishes.find(
47-
(f) => f.agentId === start.agentId,
48-
)
49-
// Subagent should eventually finish (or the run ends)
50-
expect(start.agentId).toBeDefined()
51-
expect(start.agentType).toBeDefined()
52-
expect(start.displayName).toBeDefined()
53-
}
42+
// The prompt should trigger file search which spawns a subagent
43+
// If no subagents were spawned, the test isn't validating what we intend
44+
expect(subagentStarts.length).toBeGreaterThan(0)
45+
46+
// Each started subagent should have a finish
47+
for (const start of subagentStarts) {
48+
const matchingFinish = subagentFinishes.find(
49+
(f) => f.agentId === start.agentId,
50+
)
51+
// Subagent should eventually finish
52+
expect(matchingFinish).toBeDefined()
53+
expect(start.agentId).toBeDefined()
54+
expect(start.agentType).toBeDefined()
55+
expect(start.displayName).toBeDefined()
5456
}
5557
},
5658
DEFAULT_TIMEOUT * 2,
@@ -72,6 +74,9 @@ describe('Streaming: Subagent Streaming', () => {
7274

7375
const subagentStarts = collector.getEventsByType('subagent_start')
7476

77+
// Ensure we actually got subagent events to validate
78+
expect(subagentStarts.length).toBeGreaterThan(0)
79+
7580
for (const event of subagentStarts) {
7681
// Required fields
7782
expect(typeof event.agentId).toBe('string')
@@ -105,22 +110,26 @@ describe('Streaming: Subagent Streaming', () => {
105110
cwd: process.cwd(),
106111
})
107112

113+
// Verify we got subagent events (prompt should trigger file exploration)
114+
const subagentStarts = collector.getEventsByType('subagent_start')
115+
expect(subagentStarts.length).toBeGreaterThan(0)
116+
108117
// Check for subagent chunks in stream
109118
const subagentChunks = collector.streamChunks.filter(
110119
(c): c is Extract<typeof c, { type: 'subagent_chunk' }> =>
111120
typeof c !== 'string' && c.type === 'subagent_chunk',
112121
)
113122

114-
// If there are subagent events, there might be subagent chunks
115-
const subagentStarts = collector.getEventsByType('subagent_start')
116-
if (subagentStarts.length > 0 && subagentChunks.length > 0) {
117-
// Verify chunk structure
123+
// If there are subagent chunks, verify their structure
124+
if (subagentChunks.length > 0) {
118125
for (const chunk of subagentChunks) {
119126
expect(chunk.agentId).toBeDefined()
120127
expect(chunk.agentType).toBeDefined()
121128
expect(typeof chunk.chunk).toBe('string')
122129
}
123130
}
131+
// Note: Subagent chunks may not always be present even with subagent events
132+
// (e.g., if the subagent completes very quickly without streaming)
124133
},
125134
DEFAULT_TIMEOUT * 2,
126135
)
@@ -140,6 +149,9 @@ describe('Streaming: Subagent Streaming', () => {
140149

141150
const subagentStarts = collector.getEventsByType('subagent_start')
142151

152+
// Ensure we got subagent events to validate uniqueness
153+
expect(subagentStarts.length).toBeGreaterThan(0)
154+
143155
// Check for duplicates by agentId
144156
const agentIds = subagentStarts.map((s) => s.agentId)
145157
const uniqueIds = new Set(agentIds)

0 commit comments

Comments
 (0)