[{"data":1,"prerenderedAt":1186},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fv2\u002Fmodules\u002Ftests":3},{"id":4,"title":5,"body":6,"description":1178,"extension":1179,"meta":1180,"navigation":120,"path":1182,"seo":1183,"stem":1184,"__hash__":1185},"docs\u002Fdocs\u002Fv2\u002Fmodules\u002Ftests\u002Findex.md","tests\u002F",{"type":7,"value":8,"toc":1170},"minimark",[9,13,29,74,79,86,289,293,300,451,454,458,461,655,658,662,669,901,905,908,1127,1131,1134,1166],[10,11,5],"h1",{"id":12},"tests",[14,15,16,17,20,21,24,25,28],"p",{},"Put test files in ",[18,19,5],"code",{},". Same runner as agent tests — ",[18,22,23],{},"bun:test",", with the ",[18,26,27],{},"Axon()","\nharness available as a global. The difference: you are not testing the module in\nisolation. Modules have no standalone runtime. You boot a parent agent with the module\nloaded and test the contribution surface — what tools appeared, what prompts render,\nhow hooks behave.",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-bash shiki shiki-themes dark-plus","tests\u002F\n├── hooks.test.ts\n├── prompts.test.ts\n└── tools.test.ts\n","bash","",[18,37,38,47,57,65],{"__ignoreMap":35},[39,40,43],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sCudf","tests\u002F\n",[39,48,50,53],{"class":41,"line":49},2,[39,51,52],{"class":45},"├──",[39,54,56],{"class":55},"sKc5r"," hooks.test.ts\n",[39,58,60,62],{"class":41,"line":59},3,[39,61,52],{"class":45},[39,63,64],{"class":55}," prompts.test.ts\n",[39,66,68,71],{"class":41,"line":67},4,[39,69,70],{"class":45},"└──",[39,72,73],{"class":55}," tools.test.ts\n",[75,76,78],"h2",{"id":77},"the-harness","The harness",[14,80,81,82,85],{},"Run tests from inside an agent that has your module installed. The harness boots that\nagent's full runtime — your module's ",[18,83,84],{},"setup()"," runs, its tools are registered, its\nprompts are available.",[30,87,91],{"className":88,"code":89,"language":90,"meta":35,"style":35},"language-ts shiki shiki-themes dark-plus","import { Mock } from \"@arcforge\u002Fengines\u002Fmock\"\n\ndescribe(\"discord module\", () => {\n    it(\"registers the discord tool namespace\", async () => {\n        const runtime = await Axon({\n            blueprint: { config: { engine: Mock() } },\n        })\n\n        expect(runtime.axon.tools.discord).toBeDefined()\n\n        await runtime.shutdown()\n    })\n})\n","ts",[18,92,93,116,122,143,166,188,210,216,221,257,262,277,283],{"__ignoreMap":35},[39,94,95,99,103,107,110,113],{"class":41,"line":42},[39,96,98],{"class":97},"sYbnZ","import",[39,100,102],{"class":101},"sTNBD"," { ",[39,104,106],{"class":105},"s3F5K","Mock",[39,108,109],{"class":101}," } ",[39,111,112],{"class":97},"from",[39,114,115],{"class":55}," \"@arcforge\u002Fengines\u002Fmock\"\n",[39,117,118],{"class":41,"line":49},[39,119,121],{"emptyLinePlaceholder":120},true,"\n",[39,123,124,127,130,133,136,140],{"class":41,"line":59},[39,125,126],{"class":45},"describe",[39,128,129],{"class":101},"(",[39,131,132],{"class":55},"\"discord module\"",[39,134,135],{"class":101},", () ",[39,137,139],{"class":138},"scz_3","=>",[39,141,142],{"class":101}," {\n",[39,144,145,148,150,153,156,159,162,164],{"class":41,"line":67},[39,146,147],{"class":45},"    it",[39,149,129],{"class":101},[39,151,152],{"class":55},"\"registers the discord tool namespace\"",[39,154,155],{"class":101},", ",[39,157,158],{"class":138},"async",[39,160,161],{"class":101}," () ",[39,163,139],{"class":138},[39,165,142],{"class":101},[39,167,169,172,176,179,182,185],{"class":41,"line":168},5,[39,170,171],{"class":138},"        const",[39,173,175],{"class":174},"s9McN"," runtime",[39,177,178],{"class":101}," = ",[39,180,181],{"class":97},"await",[39,183,184],{"class":45}," Axon",[39,186,187],{"class":101},"({\n",[39,189,191,194,196,199,201,204,207],{"class":41,"line":190},6,[39,192,193],{"class":105},"            blueprint:",[39,195,102],{"class":101},[39,197,198],{"class":105},"config:",[39,200,102],{"class":101},[39,202,203],{"class":105},"engine:",[39,205,206],{"class":45}," Mock",[39,208,209],{"class":101},"() } },\n",[39,211,213],{"class":41,"line":212},7,[39,214,215],{"class":101},"        })\n",[39,217,219],{"class":41,"line":218},8,[39,220,121],{"emptyLinePlaceholder":120},[39,222,224,227,229,232,235,238,240,243,245,248,251,254],{"class":41,"line":223},9,[39,225,226],{"class":45},"        expect",[39,228,129],{"class":101},[39,230,231],{"class":105},"runtime",[39,233,234],{"class":101},".",[39,236,237],{"class":105},"axon",[39,239,234],{"class":101},[39,241,242],{"class":105},"tools",[39,244,234],{"class":101},[39,246,247],{"class":105},"discord",[39,249,250],{"class":101},").",[39,252,253],{"class":45},"toBeDefined",[39,255,256],{"class":101},"()\n",[39,258,260],{"class":41,"line":259},10,[39,261,121],{"emptyLinePlaceholder":120},[39,263,265,268,270,272,275],{"class":41,"line":264},11,[39,266,267],{"class":97},"        await",[39,269,175],{"class":105},[39,271,234],{"class":101},[39,273,274],{"class":45},"shutdown",[39,276,256],{"class":101},[39,278,280],{"class":41,"line":279},12,[39,281,282],{"class":101},"    })\n",[39,284,286],{"class":41,"line":285},13,[39,287,288],{"class":101},"})\n",[75,290,292],{"id":291},"testing-the-tool-surface","Testing the tool surface",[14,294,295,296,299],{},"Verify that the tools your module declares are present and callable. Call them directly\nvia ",[18,297,298],{},"runtime.axon.tools.*"," — no agent loop involved, just the function.",[30,301,303],{"className":88,"code":302,"language":90,"meta":35,"style":35},"it(\"queue returns empty state when nothing is playing\", async () => {\n    const runtime = await Axon({ blueprint: { config: { engine: Mock() } } })\n\n    const state = await runtime.axon.tools.discord.queue(guildId)\n    expect(state).toEqual({ current: null, upcoming: [] })\n\n    await runtime.shutdown()\n})\n",[18,304,305,325,357,361,399,430,434,447],{"__ignoreMap":35},[39,306,307,310,312,315,317,319,321,323],{"class":41,"line":42},[39,308,309],{"class":45},"it",[39,311,129],{"class":101},[39,313,314],{"class":55},"\"queue returns empty state when nothing is playing\"",[39,316,155],{"class":101},[39,318,158],{"class":138},[39,320,161],{"class":101},[39,322,139],{"class":138},[39,324,142],{"class":101},[39,326,327,330,332,334,336,338,341,344,346,348,350,352,354],{"class":41,"line":49},[39,328,329],{"class":138},"    const",[39,331,175],{"class":174},[39,333,178],{"class":101},[39,335,181],{"class":97},[39,337,184],{"class":45},[39,339,340],{"class":101},"({ ",[39,342,343],{"class":105},"blueprint:",[39,345,102],{"class":101},[39,347,198],{"class":105},[39,349,102],{"class":101},[39,351,203],{"class":105},[39,353,206],{"class":45},[39,355,356],{"class":101},"() } } })\n",[39,358,359],{"class":41,"line":59},[39,360,121],{"emptyLinePlaceholder":120},[39,362,363,365,368,370,372,374,376,378,380,382,384,386,388,391,393,396],{"class":41,"line":67},[39,364,329],{"class":138},[39,366,367],{"class":174}," state",[39,369,178],{"class":101},[39,371,181],{"class":97},[39,373,175],{"class":105},[39,375,234],{"class":101},[39,377,237],{"class":105},[39,379,234],{"class":101},[39,381,242],{"class":105},[39,383,234],{"class":101},[39,385,247],{"class":105},[39,387,234],{"class":101},[39,389,390],{"class":45},"queue",[39,392,129],{"class":101},[39,394,395],{"class":105},"guildId",[39,397,398],{"class":101},")\n",[39,400,401,404,406,409,411,414,416,419,422,424,427],{"class":41,"line":168},[39,402,403],{"class":45},"    expect",[39,405,129],{"class":101},[39,407,408],{"class":105},"state",[39,410,250],{"class":101},[39,412,413],{"class":45},"toEqual",[39,415,340],{"class":101},[39,417,418],{"class":105},"current:",[39,420,421],{"class":138}," null",[39,423,155],{"class":101},[39,425,426],{"class":105},"upcoming:",[39,428,429],{"class":101}," [] })\n",[39,431,432],{"class":41,"line":190},[39,433,121],{"emptyLinePlaceholder":120},[39,435,436,439,441,443,445],{"class":41,"line":212},[39,437,438],{"class":97},"    await",[39,440,175],{"class":105},[39,442,234],{"class":101},[39,444,274],{"class":45},[39,446,256],{"class":101},[39,448,449],{"class":41,"line":218},[39,450,288],{"class":101},[14,452,453],{},"Tools that depend on external connections (Discord client, databases, IMAP) will throw\nin test environments where those services aren't present. Test the logic you control —\nstate management, return shapes, guard conditions — not the external service.",[75,455,457],{"id":456},"testing-prompts","Testing prompts",[14,459,460],{},"Render the prompts your module contributes and assert on their content. This catches\ntemplate regressions — broken variable interpolation, missing sections, stale copy.",[30,462,464],{"className":88,"code":463,"language":90,"meta":35,"style":35},"it(\"renders the discord prompt with required props\", async () => {\n    const runtime = await Axon({ blueprint: { config: { engine: Mock() } } })\n\n    const prompt = await runtime.axon.prompt(\"discord\", {\n        content: \"hello\",\n        username: \"cody\",\n        channelId: \"123\",\n    })\n\n    expect(prompt.content).toContain(\"cody\")\n    expect(prompt.content).toContain(\"hello\")\n\n    await runtime.shutdown()\n})\n",[18,465,466,485,513,517,547,558,568,578,582,586,611,634,638,650],{"__ignoreMap":35},[39,467,468,470,472,475,477,479,481,483],{"class":41,"line":42},[39,469,309],{"class":45},[39,471,129],{"class":101},[39,473,474],{"class":55},"\"renders the discord prompt with required props\"",[39,476,155],{"class":101},[39,478,158],{"class":138},[39,480,161],{"class":101},[39,482,139],{"class":138},[39,484,142],{"class":101},[39,486,487,489,491,493,495,497,499,501,503,505,507,509,511],{"class":41,"line":49},[39,488,329],{"class":138},[39,490,175],{"class":174},[39,492,178],{"class":101},[39,494,181],{"class":97},[39,496,184],{"class":45},[39,498,340],{"class":101},[39,500,343],{"class":105},[39,502,102],{"class":101},[39,504,198],{"class":105},[39,506,102],{"class":101},[39,508,203],{"class":105},[39,510,206],{"class":45},[39,512,356],{"class":101},[39,514,515],{"class":41,"line":59},[39,516,121],{"emptyLinePlaceholder":120},[39,518,519,521,524,526,528,530,532,534,536,539,541,544],{"class":41,"line":67},[39,520,329],{"class":138},[39,522,523],{"class":174}," prompt",[39,525,178],{"class":101},[39,527,181],{"class":97},[39,529,175],{"class":105},[39,531,234],{"class":101},[39,533,237],{"class":105},[39,535,234],{"class":101},[39,537,538],{"class":45},"prompt",[39,540,129],{"class":101},[39,542,543],{"class":55},"\"discord\"",[39,545,546],{"class":101},", {\n",[39,548,549,552,555],{"class":41,"line":168},[39,550,551],{"class":105},"        content:",[39,553,554],{"class":55}," \"hello\"",[39,556,557],{"class":101},",\n",[39,559,560,563,566],{"class":41,"line":190},[39,561,562],{"class":105},"        username:",[39,564,565],{"class":55}," \"cody\"",[39,567,557],{"class":101},[39,569,570,573,576],{"class":41,"line":212},[39,571,572],{"class":105},"        channelId:",[39,574,575],{"class":55}," \"123\"",[39,577,557],{"class":101},[39,579,580],{"class":41,"line":218},[39,581,282],{"class":101},[39,583,584],{"class":41,"line":223},[39,585,121],{"emptyLinePlaceholder":120},[39,587,588,590,592,594,596,599,601,604,606,609],{"class":41,"line":259},[39,589,403],{"class":45},[39,591,129],{"class":101},[39,593,538],{"class":105},[39,595,234],{"class":101},[39,597,598],{"class":105},"content",[39,600,250],{"class":101},[39,602,603],{"class":45},"toContain",[39,605,129],{"class":101},[39,607,608],{"class":55},"\"cody\"",[39,610,398],{"class":101},[39,612,613,615,617,619,621,623,625,627,629,632],{"class":41,"line":264},[39,614,403],{"class":45},[39,616,129],{"class":101},[39,618,538],{"class":105},[39,620,234],{"class":101},[39,622,598],{"class":105},[39,624,250],{"class":101},[39,626,603],{"class":45},[39,628,129],{"class":101},[39,630,631],{"class":55},"\"hello\"",[39,633,398],{"class":101},[39,635,636],{"class":41,"line":279},[39,637,121],{"emptyLinePlaceholder":120},[39,639,640,642,644,646,648],{"class":41,"line":285},[39,641,438],{"class":97},[39,643,175],{"class":105},[39,645,234],{"class":101},[39,647,274],{"class":45},[39,649,256],{"class":101},[39,651,653],{"class":41,"line":652},14,[39,654,288],{"class":101},[14,656,657],{},"Test the dynamic cases — prompts that branch on data. If your prompt surfaces\nnow-playing state conditionally, assert it appears when the data is present and\ndoesn't when it isn't.",[75,659,661],{"id":660},"testing-hooks","Testing hooks",[14,663,664,665,668],{},"Your module emits hooks — fire them directly via ",[18,666,667],{},"callHook()"," and assert on the\noutcome. This is how you test the full path: hook fires, agent processes it, callback\nreceives a reply.",[30,670,672],{"className":88,"code":671,"language":90,"meta":35,"style":35},"it(\"fires a reply when a message hook is triggered\", async () => {\n    const runtime = await Axon({\n        blueprint: { config: { engine: Mock({ \"\": \"hey cody\" }) } },\n    })\n\n    let replied: string | null = null\n    await runtime.axon.hooks.callHook(\"discord:message.received\", {\n        content: \"hello barry\",\n        username: \"cody\",\n        reply: async (text: string) => { replied = text },\n    })\n\n    expect(replied).toBe(\"hey cody\")\n\n    await runtime.shutdown()\n})\n",[18,673,674,693,707,736,740,744,770,797,806,814,851,855,859,879,883,896],{"__ignoreMap":35},[39,675,676,678,680,683,685,687,689,691],{"class":41,"line":42},[39,677,309],{"class":45},[39,679,129],{"class":101},[39,681,682],{"class":55},"\"fires a reply when a message hook is triggered\"",[39,684,155],{"class":101},[39,686,158],{"class":138},[39,688,161],{"class":101},[39,690,139],{"class":138},[39,692,142],{"class":101},[39,694,695,697,699,701,703,705],{"class":41,"line":49},[39,696,329],{"class":138},[39,698,175],{"class":174},[39,700,178],{"class":101},[39,702,181],{"class":97},[39,704,184],{"class":45},[39,706,187],{"class":101},[39,708,709,712,714,716,718,720,722,724,727,730,733],{"class":41,"line":59},[39,710,711],{"class":105},"        blueprint:",[39,713,102],{"class":101},[39,715,198],{"class":105},[39,717,102],{"class":101},[39,719,203],{"class":105},[39,721,206],{"class":45},[39,723,340],{"class":101},[39,725,726],{"class":55},"\"\"",[39,728,729],{"class":105},":",[39,731,732],{"class":55}," \"hey cody\"",[39,734,735],{"class":101}," }) } },\n",[39,737,738],{"class":41,"line":67},[39,739,282],{"class":101},[39,741,742],{"class":41,"line":168},[39,743,121],{"emptyLinePlaceholder":120},[39,745,746,749,752,755,759,762,765,767],{"class":41,"line":190},[39,747,748],{"class":138},"    let",[39,750,751],{"class":105}," replied",[39,753,754],{"class":101},": ",[39,756,758],{"class":757},"sNl3T","string",[39,760,761],{"class":101}," | ",[39,763,764],{"class":757},"null",[39,766,178],{"class":101},[39,768,769],{"class":138},"null\n",[39,771,772,774,776,778,780,782,785,787,790,792,795],{"class":41,"line":212},[39,773,438],{"class":97},[39,775,175],{"class":105},[39,777,234],{"class":101},[39,779,237],{"class":105},[39,781,234],{"class":101},[39,783,784],{"class":105},"hooks",[39,786,234],{"class":101},[39,788,789],{"class":45},"callHook",[39,791,129],{"class":101},[39,793,794],{"class":55},"\"discord:message.received\"",[39,796,546],{"class":101},[39,798,799,801,804],{"class":41,"line":218},[39,800,551],{"class":105},[39,802,803],{"class":55}," \"hello barry\"",[39,805,557],{"class":101},[39,807,808,810,812],{"class":41,"line":223},[39,809,562],{"class":105},[39,811,565],{"class":55},[39,813,557],{"class":101},[39,815,816,819,821,824,827,830,832,834,837,839,841,844,846,848],{"class":41,"line":259},[39,817,818],{"class":45},"        reply",[39,820,729],{"class":105},[39,822,823],{"class":138}," async",[39,825,826],{"class":101}," (",[39,828,829],{"class":105},"text",[39,831,754],{"class":101},[39,833,758],{"class":757},[39,835,836],{"class":101},") ",[39,838,139],{"class":138},[39,840,102],{"class":101},[39,842,843],{"class":105},"replied",[39,845,178],{"class":101},[39,847,829],{"class":105},[39,849,850],{"class":101}," },\n",[39,852,853],{"class":41,"line":264},[39,854,282],{"class":101},[39,856,857],{"class":41,"line":279},[39,858,121],{"emptyLinePlaceholder":120},[39,860,861,863,865,867,869,872,874,877],{"class":41,"line":285},[39,862,403],{"class":45},[39,864,129],{"class":101},[39,866,843],{"class":105},[39,868,250],{"class":101},[39,870,871],{"class":45},"toBe",[39,873,129],{"class":101},[39,875,876],{"class":55},"\"hey cody\"",[39,878,398],{"class":101},[39,880,881],{"class":41,"line":652},[39,882,121],{"emptyLinePlaceholder":120},[39,884,886,888,890,892,894],{"class":41,"line":885},15,[39,887,438],{"class":97},[39,889,175],{"class":105},[39,891,234],{"class":101},[39,893,274],{"class":45},[39,895,256],{"class":101},[39,897,899],{"class":41,"line":898},16,[39,900,288],{"class":101},[75,902,904],{"id":903},"testing-tool-calls-through-the-loop","Testing tool calls through the loop",[14,906,907],{},"When the agent should respond to a message by calling one of your module's tools,\nscript the model with a sequence — one step per loop tick. The tool genuinely executes\nin the capsule; the second tick sees its result and speaks.",[30,909,911],{"className":88,"code":910,"language":90,"meta":35,"style":35},"import { Mock, run } from \"@arcforge\u002Fengines\u002Fmock\"\n\nit(\"agent calls play tool when asked\", async () => {\n    const runtime = await Axon({\n        blueprint: {\n            config: {\n                engine: Mock({\n                    \"play something\": [\n                        run(`discord.play(\"track\", userId, guildId)`),\n                        \"Now playing.\",\n                    ],\n                }),\n            },\n        },\n    })\n\n    const result = await runtime.axon.request(\"play something\")\n    expect(result.text).toBe(\"Now playing.\")\n\n    await runtime.shutdown()\n})\n",[18,912,913,932,936,955,969,975,982,991,1001,1014,1021,1026,1031,1036,1041,1045,1049,1079,1104,1109,1122],{"__ignoreMap":35},[39,914,915,917,919,921,923,926,928,930],{"class":41,"line":42},[39,916,98],{"class":97},[39,918,102],{"class":101},[39,920,106],{"class":105},[39,922,155],{"class":101},[39,924,925],{"class":105},"run",[39,927,109],{"class":101},[39,929,112],{"class":97},[39,931,115],{"class":55},[39,933,934],{"class":41,"line":49},[39,935,121],{"emptyLinePlaceholder":120},[39,937,938,940,942,945,947,949,951,953],{"class":41,"line":59},[39,939,309],{"class":45},[39,941,129],{"class":101},[39,943,944],{"class":55},"\"agent calls play tool when asked\"",[39,946,155],{"class":101},[39,948,158],{"class":138},[39,950,161],{"class":101},[39,952,139],{"class":138},[39,954,142],{"class":101},[39,956,957,959,961,963,965,967],{"class":41,"line":67},[39,958,329],{"class":138},[39,960,175],{"class":174},[39,962,178],{"class":101},[39,964,181],{"class":97},[39,966,184],{"class":45},[39,968,187],{"class":101},[39,970,971,973],{"class":41,"line":168},[39,972,711],{"class":105},[39,974,142],{"class":101},[39,976,977,980],{"class":41,"line":190},[39,978,979],{"class":105},"            config:",[39,981,142],{"class":101},[39,983,984,987,989],{"class":41,"line":212},[39,985,986],{"class":105},"                engine:",[39,988,206],{"class":45},[39,990,187],{"class":101},[39,992,993,996,998],{"class":41,"line":218},[39,994,995],{"class":55},"                    \"play something\"",[39,997,729],{"class":105},[39,999,1000],{"class":101}," [\n",[39,1002,1003,1006,1008,1011],{"class":41,"line":223},[39,1004,1005],{"class":45},"                        run",[39,1007,129],{"class":101},[39,1009,1010],{"class":55},"`discord.play(\"track\", userId, guildId)`",[39,1012,1013],{"class":101},"),\n",[39,1015,1016,1019],{"class":41,"line":259},[39,1017,1018],{"class":55},"                        \"Now playing.\"",[39,1020,557],{"class":101},[39,1022,1023],{"class":41,"line":264},[39,1024,1025],{"class":101},"                    ],\n",[39,1027,1028],{"class":41,"line":279},[39,1029,1030],{"class":101},"                }),\n",[39,1032,1033],{"class":41,"line":285},[39,1034,1035],{"class":101},"            },\n",[39,1037,1038],{"class":41,"line":652},[39,1039,1040],{"class":101},"        },\n",[39,1042,1043],{"class":41,"line":885},[39,1044,282],{"class":101},[39,1046,1047],{"class":41,"line":898},[39,1048,121],{"emptyLinePlaceholder":120},[39,1050,1052,1054,1057,1059,1061,1063,1065,1067,1069,1072,1074,1077],{"class":41,"line":1051},17,[39,1053,329],{"class":138},[39,1055,1056],{"class":174}," result",[39,1058,178],{"class":101},[39,1060,181],{"class":97},[39,1062,175],{"class":105},[39,1064,234],{"class":101},[39,1066,237],{"class":105},[39,1068,234],{"class":101},[39,1070,1071],{"class":45},"request",[39,1073,129],{"class":101},[39,1075,1076],{"class":55},"\"play something\"",[39,1078,398],{"class":101},[39,1080,1082,1084,1086,1089,1091,1093,1095,1097,1099,1102],{"class":41,"line":1081},18,[39,1083,403],{"class":45},[39,1085,129],{"class":101},[39,1087,1088],{"class":105},"result",[39,1090,234],{"class":101},[39,1092,829],{"class":105},[39,1094,250],{"class":101},[39,1096,871],{"class":45},[39,1098,129],{"class":101},[39,1100,1101],{"class":55},"\"Now playing.\"",[39,1103,398],{"class":101},[39,1105,1107],{"class":41,"line":1106},19,[39,1108,121],{"emptyLinePlaceholder":120},[39,1110,1112,1114,1116,1118,1120],{"class":41,"line":1111},20,[39,1113,438],{"class":97},[39,1115,175],{"class":105},[39,1117,234],{"class":101},[39,1119,274],{"class":45},[39,1121,256],{"class":101},[39,1123,1125],{"class":41,"line":1124},21,[39,1126,288],{"class":101},[75,1128,1130],{"id":1129},"running-tests","Running tests",[14,1132,1133],{},"Run from inside the agent directory that has your module installed:",[30,1135,1137],{"className":32,"code":1136,"language":34,"meta":35,"style":35},"bun test\nbun test tests\u002Fhooks.test.ts\nbun test --watch\n",[18,1138,1139,1147,1157],{"__ignoreMap":35},[39,1140,1141,1144],{"class":41,"line":42},[39,1142,1143],{"class":45},"bun",[39,1145,1146],{"class":55}," test\n",[39,1148,1149,1151,1154],{"class":41,"line":49},[39,1150,1143],{"class":45},[39,1152,1153],{"class":55}," test",[39,1155,1156],{"class":55}," tests\u002Fhooks.test.ts\n",[39,1158,1159,1161,1163],{"class":41,"line":59},[39,1160,1143],{"class":45},[39,1162,1153],{"class":55},[39,1164,1165],{"class":138}," --watch\n",[1167,1168,1169],"style",{},"html pre.shiki code .sCudf, html code.shiki .sCudf{--shiki-default:#DCDCAA}html pre.shiki code .sKc5r, html code.shiki .sKc5r{--shiki-default:#CE9178}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sYbnZ, html code.shiki .sYbnZ{--shiki-default:#C586C0}html pre.shiki code .sTNBD, html code.shiki .sTNBD{--shiki-default:#D4D4D4}html pre.shiki code .s3F5K, html code.shiki .s3F5K{--shiki-default:#9CDCFE}html pre.shiki code .scz_3, html code.shiki .scz_3{--shiki-default:#569CD6}html pre.shiki code .s9McN, html code.shiki .s9McN{--shiki-default:#4FC1FF}html pre.shiki code .sNl3T, html code.shiki .sNl3T{--shiki-default:#4EC9B0}",{"title":35,"searchDepth":49,"depth":49,"links":1171},[1172,1173,1174,1175,1176,1177],{"id":77,"depth":49,"text":78},{"id":291,"depth":49,"text":292},{"id":456,"depth":49,"text":457},{"id":660,"depth":49,"text":661},{"id":903,"depth":49,"text":904},{"id":1129,"depth":49,"text":1130},"Put test files in tests\u002F. Same runner as agent tests — bun:test, with the Axon()\nharness available as a global. The difference: you are not testing the module in\nisolation. Modules have no standalone runtime. You boot a parent agent with the module\nloaded and test the contribution surface — what tools appeared, what prompts render,\nhow hooks behave.","md",{"icon":1181},"vscode-icons:folder-type-test","\u002Fdocs\u002Fv2\u002Fmodules\u002Ftests",{"title":5,"description":1178},"docs\u002Fv2\u002Fmodules\u002Ftests\u002Findex","x7cH-2FCvfp8nZVXdlYH2XE6Nr5GQOe5oMAiBaHLUO8",1785671806694]