import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test" import { z } from "zod" import { QuestionTool } from "../../src/tool/question" import * as QuestionModule from "../../src/question" const ctx = { sessionID: "test-session", messageID: "test-message", callID: "test-call", agent: "test-agent", abort: AbortSignal.any([]), metadata: () => {}, ask: async () => {}, } describe("tool.question", () => { let askSpy: any beforeEach(() => { askSpy = spyOn(QuestionModule.Question, "ask").mockImplementation(async () => { return [] }) }) afterEach(() => { askSpy.mockRestore() }) test("should successfully execute with valid question parameters", async () => { const tool = await QuestionTool.init() const questions = [ { question: "What is your favorite color?", header: "Color", options: [ { label: "Red", description: "The color of passion" }, { label: "Blue", description: "The color of sky" }, ], multiple: false, }, ] askSpy.mockResolvedValueOnce([["Red"]]) const result = await tool.execute({ questions }, ctx) expect(askSpy).toHaveBeenCalledTimes(1) expect(result.title).toBe("Asked 1 question") }) test("should now pass with a header longer than 12 but less than 30 chars", async () => { const tool = await QuestionTool.init() const questions = [ { question: "What is your favorite animal?", header: "This Header is Over 12", options: [{ label: "Dog", description: "Man's best friend" }], }, ] askSpy.mockResolvedValueOnce([["Dog"]]) const result = await tool.execute({ questions }, ctx) expect(result.output).toContain(`"What is your favorite animal?"="Dog"`) }) test("should throw an Error for header exceeding 30 characters", async () => { const tool = await QuestionTool.init() const questions = [ { question: "What is your favorite animal?", header: "This Header is Definitely More Than Thirty Characters Long", options: [{ label: "Dog", description: "Man's best friend" }], }, ] try { await tool.execute({ questions }, ctx) // If it reaches here, the test should fail expect(true).toBe(false) } catch (e: any) { expect(e).toBeInstanceOf(Error) expect(e.cause).toBeInstanceOf(z.ZodError) } }) test("should throw an Error for label exceeding 30 characters", async () => { const tool = await QuestionTool.init() const questions = [ { question: "A question with a very long label", header: "Long Label", options: [ { label: "This is a very, very, very long label that will exceed the limit", description: "A description" }, ], }, ] try { await tool.execute({ questions }, ctx) // If it reaches here, the test should fail expect(true).toBe(false) } catch (e: any) { expect(e).toBeInstanceOf(Error) expect(e.cause).toBeInstanceOf(z.ZodError) } }) })