🐛 fix(vscode): 按种类筛选后仍能展开匹配块的完整主体,接口改叫路由

This commit is contained in:
cruldra committed 2026-10-08 17:35:07 +08:00
1 parent 3abc87dbef
commit 6723c1dcc3
5 files changed
+152 -16

No files matched your search

@@ -2,7 +2,15 @@ import type { BlockTreeState } from './BlockTree'
import type { BlockView, KindBadge } from './types'
import { renderToStaticMarkup } from 'react-dom/server'
import { describe, expect, it, vi } from 'vitest'
import { fileAttributes } from '../../../src/codeReader/attributes'
import { toBlockViews } from '../../../src/codeReader/blockView'
import { createPythonAdapter } from '../../../src/codeReader/languages/python'
import { fastapiRule } from '../../../src/codeReader/rules/fastapi'
import { WASM_DIR, withBlocks } from '../../../src/codeReader/testSupport'
import { pythonZhTranslator } from '../../../src/codeReader/translators/pythonZh'
import { BlockLevel } from './BlockTree'
import { applyFilter } from './filter'
import { FilterBar } from './FilterBar'
import { collapsedIds } from './viewState'
// 高亮的上下文所在的模块、编辑框都连着和 VS Code 收发消息的那一套,渲染成 HTML 用不着
@@ -77,6 +85,62 @@ function render(folds: Record<string, boolean>): string {
return renderToStaticMarkup(<BlockLevel blocks={[CARD]} tree={state(collapsedIds([CARD], folds))} />)
}
describe('路由筛选后展开函数体', () => {
it('真实 FastAPI 路由保留 if 和 return 子块,收起时有箭头,展开后显示完整主体及请求响应,菜单和标签统一叫路由', async () => {
const source = [
'from fastapi import APIRouter',
'router = APIRouter()',
'@router.put("/account")',
'async def put_miniprogram_account(enabled: bool):',
' if enabled:',
' return "enabled-body"',
' return "disabled-body"',
'def unrelated():',
' return "unrelated-body"',
].join('\n')
const language = createPythonAdapter(WASM_DIR)
const blocks = await withBlocks(language, 'python', source, parsed => toBlockViews(
parsed,
{ source, language, markers: [] },
pythonZhTranslator,
{ rules: [fastapiRule], report: (message) => { throw new Error(message) } },
))
const route = blocks.find(block => block.kind === 'fastapi.route')!
expect(route.children.map(block => block.kind)).toEqual(['if', 'return'])
expect(route.children[0].children.map(block => block.kind)).toEqual(['return'])
const attributes = fileAttributes(blocks, pythonZhTranslator.attributeNames)
const excluded = { kind: attributes.find(attribute => attribute.id === 'kind')!.values.map(value => value.id).filter(kind => kind !== 'fastapi.route') }
const filtered = applyFilter(blocks, excluded, new Set())
const tree = { ...state(collapsedIds(blocks, {})), ...filtered }
const closed = renderToStaticMarkup(<BlockLevel blocks={blocks} tree={tree} />)
expect(closed).toContain('aria-label="展开子块"')
expect(closed).not.toContain('enabled-body')
const opened = renderToStaticMarkup(<BlockLevel blocks={blocks} tree={{ ...tree, collapsed: new Set() }} />)
expect(opened).toContain('enabled-body')
expect(opened).toContain('disabled-body')
expect(opened).not.toContain('unrelated-body')
expect(opened).toContain('请求')
expect(opened).toContain('响应')
expect(route.badge?.label).toBe('路由')
expect(route.concepts.find(concept => concept.id === 'fastapi.route')?.label).toBe('路由')
const bar = renderToStaticMarkup(
<FilterBar
attributes={attributes}
excluded={excluded}
view={filtered}
highlight={undefined}
onChange={() => {}}
onMoveOccurrence={() => {}}
translators={[]}
translatorId="zh"
onSelectTranslator={() => {}}
/>,
)
expect(bar).toContain('种类:路由')
expect(bar).not.toContain('接口')
})
})
describe('挂在卡片子行上的子块', () => {
it('默认不画,子行的名称是展开它的按钮;卡片收着时留下的子块不画', () => {
const html = render({})