Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma strängvärde byggs med konkatenering i stället för att matcha mönstret.
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest'
|
|
import { sendFeedback } from '../feedback-client'
|
|
|
|
/**
|
|
* The thumbs shipped wired to nothing: they lit up and the vote died in
|
|
* component state. These pin the contract the button now depends on, in
|
|
* particular that a failed send reports false, because the pressed state is
|
|
* set from this return value and must never claim a report that never arrived.
|
|
*/
|
|
|
|
describe('sendFeedback', () => {
|
|
it('posts the vote to the feedback endpoint', async () => {
|
|
const fetchImpl = vi.fn().mockResolvedValue({ ok: true })
|
|
|
|
const ok = await sendFeedback({
|
|
conversationId: 'c1',
|
|
sentiment: 'negative',
|
|
messageIndex: 3,
|
|
fetchImpl: fetchImpl as unknown as typeof fetch,
|
|
})
|
|
|
|
expect(ok).toBe(true)
|
|
const [url, init] = fetchImpl.mock.calls[0]!
|
|
expect(url).toBe('/api/agent/feedback')
|
|
expect(init.method).toBe('POST')
|
|
expect(JSON.parse(init.body)).toEqual({
|
|
conversation_id: 'c1',
|
|
sentiment: 'negative',
|
|
message_index: 3,
|
|
})
|
|
})
|
|
|
|
it('omits the message index rather than sending null for it', async () => {
|
|
// The route validates message_index as an integer when present; sending
|
|
// null would fail validation and lose the vote for no reason.
|
|
const fetchImpl = vi.fn().mockResolvedValue({ ok: true })
|
|
await sendFeedback({
|
|
conversationId: 'c1',
|
|
sentiment: 'positive',
|
|
fetchImpl: fetchImpl as unknown as typeof fetch,
|
|
})
|
|
expect(JSON.parse(fetchImpl.mock.calls[0]![1].body)).toEqual({
|
|
conversation_id: 'c1',
|
|
sentiment: 'positive',
|
|
})
|
|
})
|
|
|
|
it('reports failure for a non-2xx instead of assuming it landed', async () => {
|
|
const fetchImpl = vi.fn().mockResolvedValue({ ok: false, status: 404 })
|
|
expect(
|
|
await sendFeedback({
|
|
conversationId: 'c1',
|
|
sentiment: 'positive',
|
|
fetchImpl: fetchImpl as unknown as typeof fetch,
|
|
}),
|
|
).toBe(false)
|
|
})
|
|
|
|
it('reports failure instead of throwing when the request dies', async () => {
|
|
// Offline, or the request cut off by a navigation. An unhandled rejection
|
|
// here would surface as an error in the middle of reading an answer.
|
|
const fetchImpl = vi.fn().mockRejectedValue(new TypeError('Failed to fetch'))
|
|
await expect(
|
|
sendFeedback({
|
|
conversationId: 'c1',
|
|
sentiment: 'negative',
|
|
fetchImpl: fetchImpl as unknown as typeof fetch,
|
|
}),
|
|
).resolves.toBe(false)
|
|
})
|
|
})
|