57 lines
2.8 KiB
TypeScript
57 lines
2.8 KiB
TypeScript
// 被移出项目/项目关闭后的发送拒绝:403 `conversation: not-project-member` 走专用文案,
|
|
// 其他失败保持通用文案(见 src/store.ts sendMessage 的 catch 分支)。
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { api } from '../src/api'
|
|
import { store } from '../src/store'
|
|
import type { Conversation, Message } from '../src/contracts'
|
|
|
|
const REMOVED_TOAST = '无法继续发送:你已不在该项目中或项目已关闭;历史对话仍可查看'
|
|
const REMOVED_DELIVERY_ERROR = '无法发送:你已不在该项目中或项目已关闭,内容已保留'
|
|
const GENERIC_DELIVERY_ERROR = '发送未成功,内容已保留;可修改后重试或移除'
|
|
|
|
function detail(id: string) {
|
|
return {
|
|
conversation: { id, projectId: 'p', title: id, createdAt: '', updatedAt: '' } as Conversation,
|
|
messages: [] as Message[], runs: [], activeHitl: [], lastSeq: 0, resumeSeq: 0,
|
|
}
|
|
}
|
|
class FakeEventSource {
|
|
onopen = null
|
|
onerror = null
|
|
onmessage = null
|
|
addEventListener() {}
|
|
close() {}
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
vi.stubGlobal('EventSource', FakeEventSource)
|
|
vi.spyOn(api, 'conversationDetail').mockImplementation(async id => detail(id))
|
|
vi.spyOn(api, 'getPlan').mockResolvedValue(null)
|
|
vi.spyOn(api, 'getTodos').mockResolvedValue(null)
|
|
vi.spyOn(api, 'listCards').mockResolvedValue([])
|
|
vi.spyOn(api, 'listTasks').mockResolvedValue([])
|
|
vi.spyOn(api, 'listArtifacts').mockResolvedValue([])
|
|
vi.spyOn(api, 'surfaceList').mockResolvedValue([])
|
|
vi.spyOn(api, 'projectSurfaces').mockResolvedValue([])
|
|
vi.spyOn(api, 'listProjectCards').mockResolvedValue([])
|
|
await store.openProject('p')
|
|
await store.openConversation('a')
|
|
})
|
|
afterEach(() => { vi.useRealTimers(); vi.restoreAllMocks(); vi.unstubAllGlobals() })
|
|
|
|
describe('sendMessage rejection copy', () => {
|
|
it('keeps the message in the outbox with the removed-member copy on 403 not-project-member', async () => {
|
|
vi.spyOn(api, 'sendMessage').mockRejectedValue(new Error('403: conversation: not-project-member'))
|
|
expect(await store.sendMessage('这条还要继续吗', [], 'kept-id')).toBe('rejected')
|
|
expect(store.getState().outbox[0]).toMatchObject({ id: 'kept-id', text: '这条还要继续吗', attachmentIds: [] })
|
|
expect(store.getState().outbox[0].deliveryError).toBe(REMOVED_DELIVERY_ERROR)
|
|
expect(store.getState().toast).toBe(REMOVED_TOAST)
|
|
})
|
|
|
|
it('keeps the generic copy for any other send failure', async () => {
|
|
vi.spyOn(api, 'sendMessage').mockRejectedValue(new Error('500: upstream down'))
|
|
expect(await store.sendMessage('这条还要继续吗', [], 'kept-id')).toBe('rejected')
|
|
expect(store.getState().outbox[0].deliveryError).toBe(GENERIC_DELIVERY_ERROR)
|
|
expect(store.getState().toast).toContain('发送失败:')
|
|
})
|
|
}) |