question.test.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test"
  2. import { z } from "zod"
  3. import { QuestionTool } from "../../src/tool/question"
  4. import * as QuestionModule from "../../src/question"
  5. import { SessionID, MessageID } from "../../src/session/schema"
  6. const ctx = {
  7. sessionID: SessionID.make("ses_test-session"),
  8. messageID: MessageID.make("test-message"),
  9. callID: "test-call",
  10. agent: "test-agent",
  11. abort: AbortSignal.any([]),
  12. messages: [],
  13. metadata: () => {},
  14. ask: async () => {},
  15. }
  16. describe("tool.question", () => {
  17. let askSpy: any
  18. beforeEach(() => {
  19. askSpy = spyOn(QuestionModule.Question, "ask").mockImplementation(async () => {
  20. return []
  21. })
  22. })
  23. afterEach(() => {
  24. askSpy.mockRestore()
  25. })
  26. test("should successfully execute with valid question parameters", async () => {
  27. const tool = await QuestionTool.init()
  28. const questions = [
  29. {
  30. question: "What is your favorite color?",
  31. header: "Color",
  32. options: [
  33. { label: "Red", description: "The color of passion" },
  34. { label: "Blue", description: "The color of sky" },
  35. ],
  36. multiple: false,
  37. },
  38. ]
  39. askSpy.mockResolvedValueOnce([["Red"]])
  40. const result = await tool.execute({ questions }, ctx)
  41. expect(askSpy).toHaveBeenCalledTimes(1)
  42. expect(result.title).toBe("Asked 1 question")
  43. })
  44. test("should now pass with a header longer than 12 but less than 30 chars", async () => {
  45. const tool = await QuestionTool.init()
  46. const questions = [
  47. {
  48. question: "What is your favorite animal?",
  49. header: "This Header is Over 12",
  50. options: [{ label: "Dog", description: "Man's best friend" }],
  51. },
  52. ]
  53. askSpy.mockResolvedValueOnce([["Dog"]])
  54. const result = await tool.execute({ questions }, ctx)
  55. expect(result.output).toContain(`"What is your favorite animal?"="Dog"`)
  56. })
  57. // intentionally removed the zod validation due to tool call errors, hoping prompting is gonna be good enough
  58. // test("should throw an Error for header exceeding 30 characters", async () => {
  59. // const tool = await QuestionTool.init()
  60. // const questions = [
  61. // {
  62. // question: "What is your favorite animal?",
  63. // header: "This Header is Definitely More Than Thirty Characters Long",
  64. // options: [{ label: "Dog", description: "Man's best friend" }],
  65. // },
  66. // ]
  67. // try {
  68. // await tool.execute({ questions }, ctx)
  69. // // If it reaches here, the test should fail
  70. // expect(true).toBe(false)
  71. // } catch (e: any) {
  72. // expect(e).toBeInstanceOf(Error)
  73. // expect(e.cause).toBeInstanceOf(z.ZodError)
  74. // }
  75. // })
  76. // test("should throw an Error for label exceeding 30 characters", async () => {
  77. // const tool = await QuestionTool.init()
  78. // const questions = [
  79. // {
  80. // question: "A question with a very long label",
  81. // header: "Long Label",
  82. // options: [
  83. // { label: "This is a very, very, very long label that will exceed the limit", description: "A description" },
  84. // ],
  85. // },
  86. // ]
  87. // try {
  88. // await tool.execute({ questions }, ctx)
  89. // // If it reaches here, the test should fail
  90. // expect(true).toBe(false)
  91. // } catch (e: any) {
  92. // expect(e).toBeInstanceOf(Error)
  93. // expect(e.cause).toBeInstanceOf(z.ZodError)
  94. // }
  95. // })
  96. })