Newer
Older
navi-1 / webclient / tests / unit / components / messages / toolCardRenderers.test.js
// @vitest-environment jsdom
import { beforeEach, describe, expect, it } from 'vitest'
import { mount } from '@vue/test-utils'

import { setLocale } from '@/i18n/index.js'
import ToolCard from '@/components/messages/ToolCard.vue'

function card(overrides = {}) {
  return {
    id: 'tool_1',
    name: 'filesystem_read',
    args: { action: 'read', path: '/tmp/x.txt' },
    result: '',
    success: true,
    pending: false,
    startedAt: Date.now(),
    isSubagent: false,
    steps: [],
    ...overrides,
  }
}

function mountCard(overrides) {
  // The card body is mounted lazily on the first open; these tests inspect
  // what the renderers produce, so the card starts open.
  return mount(ToolCard, { props: { tool: card(overrides), defaultOpen: true } })
}

beforeEach(() => {
  setLocale('en')
})

describe('ToolCard — file-tool renderers beat the markdown heuristic', () => {
  it('renders a read result with the numbered header plaque', () => {
    // The "|" in the header used to make looksLikeMarkdown() claim the result.
    const wrapper = mountCard({
      result: '[/tmp/x.txt  |  2 lines  |  12 B]\n1: alpha\n2: beta',
    })

    expect(wrapper.find('.read-header').exists()).toBe(true)
    expect(wrapper.findAll('.read-num')).toHaveLength(2)
    // The dedicated renderer wins: no markdown paragraph around the header.
    expect(wrapper.find('.tool-result p').exists()).toBe(false)

    wrapper.unmount()
  })

  it('renders a numbered diff with add/remove colouring', () => {
    // A numbered diff starts with "- 1│ …", which looks like a markdown list.
    const wrapper = mountCard({
      args: { action: 'diff', path: '/tmp/x.txt', other: '/tmp/y.txt' },
      result: '--- a/x.txt\n+++ b/x.txt\n@@ -1 +1 @@\n- 1│ beta\n+ 1│ BETA',
    })

    expect(wrapper.findAll('.diff-del').length).toBeGreaterThan(0)
    expect(wrapper.findAll('.diff-add').length).toBeGreaterThan(0)

    wrapper.unmount()
  })

  it('renders file_ai edit results as a diff', () => {
    const wrapper = mountCard({
      name: 'file_ai',
      args: { action: 'edit', path: '/tmp/x.txt', instruction: 'replace' },
      result: '@@ -1 +1 @@\n- 1│ alpha\n+ 1│ OMEGA',
    })

    expect(wrapper.findAll('.diff-add').length).toBeGreaterThan(0)

    wrapper.unmount()
  })

  it('still renders markdown for tools without a dedicated renderer', () => {
    const wrapper = mountCard({
      name: 'terminal',
      args: { action: 'run' },
      result: '**bold** output',
    })

    expect(wrapper.find('.tool-result strong').exists()).toBe(true)

    wrapper.unmount()
  })
})