Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 134 additions & 96 deletions tests/interactions/inline/test_inline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,53 @@ local h = require("tests.helpers")
local new_set = MiniTest.new_set
local T = MiniTest.new_set()

local inline
local child = MiniTest.new_child_neovim()

T["Inline"] = new_set({
hooks = {
pre_case = function()
inline = h.setup_inline({
adapters = {
http = {
fake_adapter = { name = "fake_adapter" },
h.child_start(child)
child.lua([[
h = require('tests.helpers')
config = require("tests.config")

-- Setup inline in child process
inline = h.setup_inline({
adapters = {
http = {
fake_adapter = { name = "fake_adapter" },
},
},
},
})
})
]])
end,
post_case = function()
child.lua([[inline = nil]])
end,
post_case = function() end,
post_once = child.stop,
},
})

T["Inline"]["can parse json output correctly"] = function()
local json = inline:parse_output([[{
local json_str = [[{
"code": "function test() end",
"placement": "add"
}]])
}]]

local json = child.lua([[return inline:parse_output(...)]], { json_str })
h.eq("function test() end", json.code)
h.eq("add", json.placement)
end

T["Inline"]["can parse markdown output correctly"] = function()
local json = inline:parse_output([[```json
local markdown_str = [[```json
{
"code": "function test() end",
"placement": "add"
}
```]])
```]]

local json = child.lua([[return inline:parse_output(...)]], { markdown_str })
h.eq("function test() end", json.code)
h.eq("add", json.placement)
end
Expand All @@ -49,7 +61,7 @@ T["Inline"]["can parse Ollama output correctly"] = function()
.. ' "placement": "before"\n'
.. "}"

local json = inline:parse_output(ollama_response_str)
local json = child.lua_get([[inline:parse_output(...)]], { ollama_response_str })
local expected_code_block = [[


Expand All @@ -64,152 +76,176 @@ end

T["Inline"]["handles different placements"] = function()
-- Test 'add' placement
inline:place("add")
h.eq(inline.classification.pos, {
line = inline.buffer_context.end_line + 1,
child.lua([[inline:place("add")]])
local pos = child.lua([[return inline.classification.pos]])
local buffer_context = child.lua([[return inline.buffer_context]])
h.eq(pos, {
line = buffer_context.end_line + 1,
col = 0,
bufnr = inline.buffer_context.bufnr,
bufnr = buffer_context.bufnr,
})

-- Test 'replace' placement
inline:place("replace")
h.eq(inline.classification.pos, {
line = inline.buffer_context.start_line,
col = inline.buffer_context.start_col,
bufnr = inline.buffer_context.bufnr,
child.lua([[inline:place("replace")]])
pos = child.lua([[return inline.classification.pos]])
buffer_context = child.lua([[return inline.buffer_context]])
h.eq(pos, {
line = buffer_context.start_line,
col = buffer_context.start_col,
bufnr = buffer_context.bufnr,
})

-- Test 'before' placement
inline:place("before")
h.eq(inline.classification.pos, {
line = inline.buffer_context.start_line - 1,
col = math.max(0, inline.buffer_context.start_col - 1),
bufnr = inline.buffer_context.bufnr,
child.lua([[inline:place("before")]])
pos = child.lua([[return inline.classification.pos]])
buffer_context = child.lua([[return inline.buffer_context]])
h.eq(pos, {
line = buffer_context.start_line - 1,
col = math.max(0, buffer_context.start_col - 1),
bufnr = buffer_context.bufnr,
})
end

T["Inline"]["forms correct prompts"] = function()
local prompts = {
{
role = "user",
content = "test prompt",
opts = { contains_code = true },
},
}
child.lua([[
local prompts = {
{
role = "user",
content = "test prompt",
opts = { contains_code = true },
},
}

inline.prompts = prompts
inline.buffer_context.is_visual = true
inline.buffer_context.lines = { "local x = 1" }
inline.prompts = prompts
inline.buffer_context.is_visual = true
inline.buffer_context.lines = { "local x = 1" }

inline:prompt("Hello World")
inline:prompt("Hello World")
]])

h.eq(#inline.prompts, 4)
local prompts = child.lua([[return inline.prompts]])
h.eq(#prompts, 4)
-- System prompt
h.expect_starts_with("You are a knowledgeable", inline.prompts[1].content)
h.expect_starts_with("You are a knowledgeable", prompts[1].content)
-- Visual selection
h.eq(
"For context, this is the code that I've visually selected in the buffer, which is relevant to my prompt:\n<code>\n```lua\nlocal x = 1\n```\n</code>",
inline.prompts[3].content
prompts[3].content
)
-- User prompt
h.eq("<prompt>Hello World</prompt>", inline.prompts[#inline.prompts].content)
h.eq("<prompt>Hello World</prompt>", prompts[#prompts].content)
end

T["Inline"]["generates correct prompt structure"] = function()
local submitted_prompts = {}

-- Mock the submit function
function inline:submit(prompts)
submitted_prompts = prompts
end
child.lua([[
-- Mock the submit function
_G.submitted_prompts = {}
function inline:submit(prompts)
_G.submitted_prompts = prompts
end

inline:prompt("Test prompt")
inline:prompt("Test prompt")
]])

local submitted_prompts = child.lua([[return _G.submitted_prompts]])
h.eq(#submitted_prompts, 2) -- Should be a system prompt and the user prompt
h.eq(submitted_prompts[1].role, "system")
h.eq(submitted_prompts[2].role, "user")
h.eq(submitted_prompts[2].content, "<prompt>Test prompt</prompt>")
end

T["Inline"]["the first word can be an adapter"] = function()
-- Mock the submit function
local submitted_prompts = {}
function inline:submit(prompts)
submitted_prompts = prompts
end
child.lua([[
-- Mock the submit function
_G.submitted_prompts = {}
function inline:submit(prompts)
_G.submitted_prompts = prompts
end
]])

-- Adapter is the default
h.eq(inline.adapter.name, "test_adapter")
h.eq(child.lua([[return inline.adapter.name]]), "test_adapter")

inline:prompt("fake_adapter print hello world")
child.lua([[inline:prompt("fake_adapter print hello world")]])

-- Adapter has been changed
h.eq("fake_adapter", inline.adapter.name)
h.eq("fake_adapter", child.lua([[return inline.adapter.name]]))

-- Adapter is removed from the prompt
local submitted_prompts = child.lua([[return _G.submitted_prompts]])
h.eq(submitted_prompts[2].content, "<prompt>print hello world</prompt>")
end

T["Inline"]["can be called from the action palette"] = function()
local prompt = {
name = "test",
strategy = "inline",
prompts = {
{
role = "user",
content = "Action Palette test",
child.lua([[
local prompt = {
name = "test",
strategy = "inline",
prompts = {
{
role = "user",
content = "Action Palette test",
},
},
},
}
}

local interaction = require("codecompanion.interactions").new({
buffer_context = inline.buffer_context,
selected = prompt,
})
interaction:start("inline")
local interaction = require("codecompanion.interactions").new({
buffer_context = inline.buffer_context,
selected = prompt,
})
interaction:start("inline")

_G.test_interaction = interaction
]])

-- System prompt is added
h.eq(2, #interaction.called.prompts)
h.eq(2, child.lua([[return #_G.test_interaction.called.prompts]]))

-- User prompt is added
h.eq("Action Palette test", interaction.called.prompts[2].content)
h.eq("Action Palette test", child.lua([[return _G.test_interaction.called.prompts[2].content]]))
end

T["Inline"]["integration"] = function()
-- Mock the submit function
local submitted_prompts = {}
function inline:submit(prompts)
submitted_prompts = prompts
end
child.lua([[
-- Mock the submit function
_G.submitted_prompts = {}
function inline:submit(prompts)
_G.submitted_prompts = prompts
end

inline:prompt("#{foo} can you print hello world?")
inline:prompt("#{foo} can you print hello world?")
]])

local submitted_prompts = child.lua([[return _G.submitted_prompts]])
h.eq("The output from foo variable", submitted_prompts[2].content)
h.eq("<prompt>can you print hello world?</prompt>", submitted_prompts[3].content)
end

T["Inline"]["can parse adapter syntax"] = function()
local submitted_prompts = {}
function inline:submit(prompts)
submitted_prompts = prompts
end

-- Mock the buffer variable to return predictable content
local original_buffer_variable = require("codecompanion.config").interactions.inline.variables.buffer
require("codecompanion.config").interactions.inline.variables.buffer = {
callback = function()
return "mocked buffer content"
end,
description = "Mock buffer for testing",
}
child.lua([[
_G.submitted_prompts = {}
function inline:submit(prompts)
_G.submitted_prompts = prompts
end

-- Mock the buffer variable to return predictable content
_G.original_buffer_variable = require("codecompanion.config").interactions.inline.variables.buffer
require("codecompanion.config").interactions.inline.variables.buffer = {
callback = function()
return "mocked buffer content"
end,
description = "Mock buffer for testing",
}
]])

-- Default adapter
h.eq(inline.adapter.name, "test_adapter")
h.eq(child.lua([[return inline.adapter.name]]), "test_adapter")

inline:prompt("adapter=fake_adapter #{buffer} print hello world")
h.eq("fake_adapter", inline.adapter.name)
child.lua([[inline:prompt("adapter=fake_adapter #{buffer} print hello world")]])
h.eq("fake_adapter", child.lua([[return inline.adapter.name]]))

-- Should be system + buffer content + user prompt
local submitted_prompts = child.lua([[return _G.submitted_prompts]])
h.eq(3, #submitted_prompts)

h.eq("mocked buffer content", submitted_prompts[2].content)
Expand All @@ -218,7 +254,9 @@ T["Inline"]["can parse adapter syntax"] = function()
h.eq("<prompt>print hello world</prompt>", submitted_prompts[#submitted_prompts].content)

-- Restore original buffer variable
require("codecompanion.config").interactions.inline.variables.buffer = original_buffer_variable
child.lua([[
require("codecompanion.config").interactions.inline.variables.buffer = _G.original_buffer_variable
]])
end

return T