mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-04 03:01:42 +08:00
统一问问微信与 Agent Hub 的查询链路 完善查询覆盖度、新鲜度和部分结果表达,避免索引滞后产生错误结论 基于会话实现真正的增量追新与历史补齐 支持后台同步、取消恢复、重启续传以及同步期间继续查询 优化知识库跨会话检索、同步状态、进度展示和侧栏布局
94 lines
3.7 KiB
TypeScript
94 lines
3.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
import type { Message } from '../../src/shared/types'
|
||
import { buildMessageGroups } from '../../src/renderer/src/components/chat/messageGrouping'
|
||
import {
|
||
normalizeJumpMessageId,
|
||
resolveMessageJumpTarget
|
||
} from '../../src/renderer/src/components/chat/messageJump'
|
||
|
||
const message = (id: string, createTime: number, content = id): Message =>
|
||
({
|
||
id,
|
||
from: 'user',
|
||
type: '普通文本',
|
||
datetime: '',
|
||
content,
|
||
isSender: false,
|
||
createTime
|
||
}) as Message
|
||
|
||
/**
|
||
* 「跳转到原聊天」的定位契约。
|
||
*
|
||
* 必须**真的**落在那一条消息上,而不是"路由切过去了"。
|
||
* 秒级时间戳在群聊里对应多条消息,所以精确 id 必须优先。
|
||
*/
|
||
describe('resolveMessageJumpTarget', () => {
|
||
it('prefers the exact stable identity over the timestamp', () => {
|
||
const messages = [
|
||
message('m1', 1_700_000_000),
|
||
message('m2', 1_700_000_000),
|
||
message('m3', 1_700_000_000)
|
||
]
|
||
const groups = buildMessageGroups(messages)
|
||
|
||
// 三条消息同一秒:只有 id 能定位到正确的那一条。
|
||
const target = resolveMessageJumpTarget(groups, 1_700_000_000, 'm3')
|
||
expect(target).toMatchObject({ messageId: 'm3', exact: true })
|
||
})
|
||
|
||
it('normalizes the synthetic local: prefix on both sides', () => {
|
||
// 归档侧存的是 `local:42`,证据侧的 messageRef 解出来是 `42` —— 必须视为同一条。
|
||
const groups = buildMessageGroups([message('local:42', 1_700_000_000)])
|
||
expect(normalizeJumpMessageId('local:42')).toBe('42')
|
||
expect(resolveMessageJumpTarget(groups, undefined, '42')).toMatchObject({
|
||
messageId: 'local:42',
|
||
exact: true
|
||
})
|
||
// 反过来也一样(证据侧带前缀、归档侧不带)。
|
||
const plain = buildMessageGroups([message('42', 1_700_000_000)])
|
||
expect(resolveMessageJumpTarget(plain, undefined, 'local:42')).toMatchObject({
|
||
messageId: '42',
|
||
exact: true
|
||
})
|
||
})
|
||
|
||
it('returns the archive-side id so the highlight comparison cannot silently mismatch', () => {
|
||
const groups = buildMessageGroups([message('local:17078', 1_700_000_000)])
|
||
const target = resolveMessageJumpTarget(groups, undefined, '17078')
|
||
// 传进去的是归一化后的 `17078`,但返回的必须是归档侧真实出现的 `local:17078`:
|
||
// MessageGroup 用 message.id 直接比对高亮。
|
||
expect(target?.messageId).toBe('local:17078')
|
||
})
|
||
|
||
it('falls back to the first message at or after the timestamp for legacy evidence', () => {
|
||
const groups = buildMessageGroups([
|
||
message('old', 1_690_000_000),
|
||
message('hit', 1_700_000_100),
|
||
message('newer', 1_700_000_200)
|
||
])
|
||
expect(resolveMessageJumpTarget(groups, 1_700_000_000, undefined)).toMatchObject({
|
||
messageId: 'hit',
|
||
exact: false
|
||
})
|
||
})
|
||
|
||
it('reports nothing to jump to when the message no longer exists', () => {
|
||
const groups = buildMessageGroups([message('m1', 1_700_000_000)])
|
||
// 目标已被删除 / 清理,且时间戳晚于所有消息 → 调用方必须走诚实降级文案。
|
||
expect(resolveMessageJumpTarget(groups, 1_900_000_000, 'gone')).toBeNull()
|
||
expect(resolveMessageJumpTarget(groups, undefined, 'gone')).toBeNull()
|
||
expect(resolveMessageJumpTarget(groups, null, null)).toBeNull()
|
||
})
|
||
|
||
it('still resolves by id when the evidence carries no usable timestamp', () => {
|
||
const groups = buildMessageGroups([message('m1', 1_700_000_000), message('m2', 1_700_000_600)])
|
||
// 没有 createTime 的证据在真实数据里确实存在(老缓存),不能因此放弃定位。
|
||
expect(resolveMessageJumpTarget(groups, undefined, 'm1')).toMatchObject({
|
||
messageId: 'm1',
|
||
exact: true,
|
||
groupIndex: 0
|
||
})
|
||
})
|
||
})
|