initial ai assistance
This commit is contained in:
1 parent
1af9ec3172
commit
2e0bf1e88e
24 files changed
+1293
-60
No files matched your search
@@ -0,0 +1,58 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { cleanReply, rewriteMessages } from '../src/ai/rewrite'
|
||||
|
||||
const generate = vi.fn()
|
||||
vi.mock('../src/ai/engine', () => ({
|
||||
aiSupported: () => true,
|
||||
getEngine: async () => ({ generate }),
|
||||
}))
|
||||
const { RewriteButton } = await import('../src/ai/RewriteButton')
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
generate.mockReset()
|
||||
})
|
||||
|
||||
describe('rewrite prompts', () => {
|
||||
it('carries the task, text, format and length limit', () => {
|
||||
const m = rewriteMessages('shorten', 'Hello world', { 'x-editor': 'markdown', maxLength: 50 }, 'Intro')
|
||||
expect(m[0].content).toContain('Markdown')
|
||||
expect(m[0].content).toContain('50 characters')
|
||||
expect(m[1].content).toContain('Field: Intro')
|
||||
expect(m[1].content).toContain('Hello world')
|
||||
})
|
||||
it('strips fences/quotes and enforces maxLength', () => {
|
||||
expect(cleanReply('```\nHi there\n```', {})).toBe('Hi there')
|
||||
expect(cleanReply('"Hi there"', {})).toBe('Hi there')
|
||||
expect(cleanReply('abcdefghij', { maxLength: 4 })).toBe('abcd')
|
||||
})
|
||||
})
|
||||
|
||||
describe('RewriteButton', () => {
|
||||
it('only writes after Accept', async () => {
|
||||
generate.mockResolvedValue('Better text')
|
||||
const onAccept = vi.fn()
|
||||
render(<RewriteButton schema={{}} value="Bad txt" onAccept={onAccept} />)
|
||||
fireEvent.change(screen.getByLabelText('Rewrite with AI'), { target: { value: 'fix' } })
|
||||
await screen.findByLabelText('AI suggestion')
|
||||
expect(onAccept).not.toHaveBeenCalled()
|
||||
fireEvent.click(screen.getByText('Accept'))
|
||||
expect(onAccept).toHaveBeenCalledWith('Better text')
|
||||
})
|
||||
it('Reject leaves the value alone', async () => {
|
||||
generate.mockResolvedValue('Other')
|
||||
const onAccept = vi.fn()
|
||||
render(<RewriteButton schema={{}} value="x" onAccept={onAccept} />)
|
||||
fireEvent.change(screen.getByLabelText('Rewrite with AI'), { target: { value: 'improve' } })
|
||||
fireEvent.click(await screen.findByText('Reject'))
|
||||
expect(onAccept).not.toHaveBeenCalled()
|
||||
await waitFor(() => screen.getByLabelText('Rewrite with AI'))
|
||||
})
|
||||
it('surfaces engine errors', async () => {
|
||||
generate.mockRejectedValue(new Error('boom'))
|
||||
render(<RewriteButton schema={{}} value="x" onAccept={() => {}} />)
|
||||
fireEvent.change(screen.getByLabelText('Rewrite with AI'), { target: { value: 'improve' } })
|
||||
expect((await screen.findByRole('alert')).textContent).toBe('boom')
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user