Files
Agent-System-Frontend/src/rdmAuditTree.test.ts
weichen ad503c9535 Complete recursive audit tree navigation
Why: Review found unsupported node detail calls, discarded child pages, shallow trace selection, stale detail responses, invalid operation filters, and missing audit identity.

Evidence: 35 frontend test files with 285 tests pass; production build, knip baseline, and diff check pass.

Impact: Both trees paginate recursively, trace selection covers every depth, and audit rows preserve valid operation, object, and source semantics.

Refs: rdm-two-trees-latest-templates
2026-10-15 06:19:33 +00:00

43 lines
2.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { collectRecursiveTree, isTreeItemInspectable, mergeTreePage, type AuditTreePage } from './rdmAuditTree'
describe('RDM audit tree traversal', () => {
it('keeps child cursors and appends later pages', () => {
const first: AuditTreePage = {
items: [{ kind: 'paragraph', id: 'p-1', title: '一' }],
nextCursor: 'next', hasMore: true, truncated: false,
}
const second: AuditTreePage = {
items: [{ kind: 'paragraph', id: 'p-2', title: '二' }],
hasMore: false, truncated: false,
}
expect(mergeTreePage(first, second)).toEqual({
items: [...first.items, ...second.items],
hasMore: false,
truncated: false,
})
})
it('collects every page and every server-reported depth for trace selection', async () => {
const pages = new Map<string, AuditTreePage>([
['|', { items: [{ kind: 'doc', id: 'doc-1', title: '文档', hasChildren: true }], nextCursor: 'root-2', hasMore: true, truncated: false }],
['|root-2', { items: [{ kind: 'doc', id: 'doc-2', title: '文档二', hasChildren: false }], hasMore: false, truncated: false }],
['doc-1|', { items: [{ kind: 'section', id: 'dn-sec', title: '模板章', templateBlockId: 'tpl.sec', hasChildren: true }], nextCursor: 'child-2', hasMore: true, truncated: false }],
['doc-1|child-2', { items: [{ kind: 'section', id: 'sec-2', title: '正文', hasChildren: false }], hasMore: false, truncated: false }],
['dn-sec|', { items: [{ kind: 'paragraph', id: 'p-deep', title: '深层内容', hasChildren: false }], hasMore: false, truncated: false }],
])
const items = await collectRecursiveTree(async (parent, cursor) => {
const page = pages.get(`${parent}|${cursor}`)
if (!page) throw new Error(`unexpected page ${parent}|${cursor}`)
return page
})
expect(items.map(item => item.id)).toEqual(['doc-1', 'doc-2', 'dn-sec', 'sec-2', 'p-deep'])
})
it('only requests object details for legacy sections supported by the server', () => {
expect(isTreeItemInspectable({ kind: 'section', id: 'sec-2', title: '正文', templateBlockId: '' })).toBe(true)
expect(isTreeItemInspectable({ kind: 'section', id: 'dn-sec', title: '模板章', templateBlockId: 'tpl.sec' })).toBe(false)
expect(isTreeItemInspectable({ kind: 'paragraph', id: 'p-1', title: '内容' })).toBe(false)
})
})