Skip to content

Commit ebfa7cf

Browse files
committed
[Stage 3/3] Add integration tests for nested sub-agent questions
Add comprehensive test coverage for recursive descendant question collection: - Test grandchild questions appear in list - Test questions from multiple nesting levels - Test deep hierarchy (4 levels) - Test session parent-child relationships These tests verify the fix for issue anomalyco#7654 works correctly across various nesting scenarios and edge cases.
1 parent 407dbe8 commit ebfa7cf

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import { test, expect } from "bun:test"
2+
import { Question } from "../../src/question"
3+
import { Session } from "../../src/session"
4+
import { Instance } from "../../src/project/instance"
5+
import { tmpdir } from "../fixture/fixture"
6+
7+
test("nested sessions - grandchild question appears in list", async () => {
8+
await using tmp = await tmpdir({ git: true })
9+
await Instance.provide({
10+
directory: tmp.path,
11+
fn: async () => {
12+
// Create root session
13+
const root = await Session.create({})
14+
15+
// Create child session
16+
const child = await Session.create({ parentID: root.id })
17+
18+
// Create grandchild session
19+
const grandchild = await Session.create({ parentID: child.id })
20+
21+
// Ask a question from the grandchild session
22+
const questions = [
23+
{
24+
question: "What would you like to do?",
25+
header: "Grandchild Action",
26+
options: [
27+
{ label: "Option A", description: "First option from grandchild" },
28+
{ label: "Option B", description: "Second option from grandchild" },
29+
],
30+
},
31+
]
32+
33+
Question.ask({
34+
sessionID: grandchild.id,
35+
questions,
36+
})
37+
38+
// Verify the question appears in the list
39+
const pending = await Question.list()
40+
expect(pending.length).toBe(1)
41+
expect(pending[0].sessionID).toBe(grandchild.id)
42+
expect(pending[0].questions).toEqual(questions)
43+
44+
// Cleanup
45+
await Session.remove(grandchild.id)
46+
await Session.remove(child.id)
47+
await Session.remove(root.id)
48+
},
49+
})
50+
})
51+
52+
test("nested sessions - questions from multiple levels", async () => {
53+
await using tmp = await tmpdir({ git: true })
54+
await Instance.provide({
55+
directory: tmp.path,
56+
fn: async () => {
57+
// Create session hierarchy: root -> child -> grandchild
58+
const root = await Session.create({})
59+
const child = await Session.create({ parentID: root.id })
60+
const grandchild = await Session.create({ parentID: child.id })
61+
62+
// Ask question from root
63+
const rootQuestions = [
64+
{
65+
question: "Root question?",
66+
header: "Root",
67+
options: [{ label: "Root A", description: "Root option" }],
68+
},
69+
]
70+
71+
Question.ask({
72+
sessionID: root.id,
73+
questions: rootQuestions,
74+
})
75+
76+
// Ask question from child
77+
const childQuestions = [
78+
{
79+
question: "Child question?",
80+
header: "Child",
81+
options: [{ label: "Child A", description: "Child option" }],
82+
},
83+
]
84+
85+
Question.ask({
86+
sessionID: child.id,
87+
questions: childQuestions,
88+
})
89+
90+
// Ask question from grandchild
91+
const grandchildQuestions = [
92+
{
93+
question: "Grandchild question?",
94+
header: "Grandchild",
95+
options: [{ label: "Grandchild A", description: "Grandchild option" }],
96+
},
97+
]
98+
99+
Question.ask({
100+
sessionID: grandchild.id,
101+
questions: grandchildQuestions,
102+
})
103+
104+
// Verify all questions appear in the list
105+
const pending = await Question.list()
106+
expect(pending.length).toBe(3)
107+
108+
// Verify each session has its question
109+
const rootPending = pending.find((p) => p.sessionID === root.id)
110+
expect(rootPending).toBeDefined()
111+
expect(rootPending?.questions).toEqual(rootQuestions)
112+
113+
const childPending = pending.find((p) => p.sessionID === child.id)
114+
expect(childPending).toBeDefined()
115+
expect(childPending?.questions).toEqual(childQuestions)
116+
117+
const grandchildPending = pending.find((p) => p.sessionID === grandchild.id)
118+
expect(grandchildPending).toBeDefined()
119+
expect(grandchildPending?.questions).toEqual(grandchildQuestions)
120+
121+
// Cleanup - reply to questions first to remove them from pending
122+
await Question.reply({
123+
requestID: rootPending!.id,
124+
answers: [["Root A"]],
125+
})
126+
127+
await Question.reply({
128+
requestID: childPending!.id,
129+
answers: [["Child A"]],
130+
})
131+
132+
await Question.reply({
133+
requestID: grandchildPending!.id,
134+
answers: [["Grandchild A"]],
135+
})
136+
137+
await Session.remove(grandchild.id)
138+
await Session.remove(child.id)
139+
await Session.remove(root.id)
140+
},
141+
})
142+
})
143+
144+
test("nested sessions - deep hierarchy (4 levels)", async () => {
145+
await using tmp = await tmpdir({ git: true })
146+
await Instance.provide({
147+
directory: tmp.path,
148+
fn: async () => {
149+
// Create deep hierarchy: root -> child -> grandchild -> great-grandchild
150+
const root = await Session.create({})
151+
const child = await Session.create({ parentID: root.id })
152+
const grandchild = await Session.create({ parentID: child.id })
153+
const greatGrandchild = await Session.create({ parentID: grandchild.id })
154+
155+
// Ask question from the deepest level
156+
const questions = [
157+
{
158+
question: "Question from great-grandchild?",
159+
header: "Deep Question",
160+
options: [{ label: "Deep Option", description: "From 4th level" }],
161+
},
162+
]
163+
164+
Question.ask({
165+
sessionID: greatGrandchild.id,
166+
questions,
167+
})
168+
169+
// Verify the question appears in the list
170+
const pending = await Question.list()
171+
expect(pending.length).toBe(1)
172+
expect(pending[0].sessionID).toBe(greatGrandchild.id)
173+
expect(pending[0].questions).toEqual(questions)
174+
175+
// Cleanup
176+
await Question.reply({
177+
requestID: pending[0].id,
178+
answers: [["Deep Option"]],
179+
})
180+
181+
await Session.remove(greatGrandchild.id)
182+
await Session.remove(grandchild.id)
183+
await Session.remove(child.id)
184+
await Session.remove(root.id)
185+
},
186+
})
187+
})
188+
189+
test("nested sessions - verify session parent-child relationships", async () => {
190+
await using tmp = await tmpdir({ git: true })
191+
await Instance.provide({
192+
directory: tmp.path,
193+
fn: async () => {
194+
// Create session hierarchy
195+
const root = await Session.create({})
196+
const child = await Session.create({ parentID: root.id })
197+
const grandchild = await Session.create({ parentID: child.id })
198+
199+
// Verify the parent-child relationships are set correctly
200+
const rootInfo = await Session.get(root.id)
201+
expect(rootInfo.parentID).toBeUndefined()
202+
203+
const childInfo = await Session.get(child.id)
204+
expect(childInfo.parentID).toBe(root.id)
205+
206+
const grandchildInfo = await Session.get(grandchild.id)
207+
expect(grandchildInfo.parentID).toBe(child.id)
208+
209+
// Cleanup
210+
await Session.remove(grandchild.id)
211+
await Session.remove(child.id)
212+
await Session.remove(root.id)
213+
},
214+
})
215+
})

0 commit comments

Comments
 (0)