Files
IOT_SIM/web/src/designer/document.test.ts
T
xuyueandClaude Opus 5.5 ea5a25af06 窗体设计器:工具箱、拖放、属性与事件窗口,读写 VS 格式的 Designer.cs
- Designer.cs 在浏览器端解析为语句列表,未改动的语句保留原文:
  教材 25 个参考窗体和全部示例读入再写出逐字节不变
- 编辑操作:添加 / 删除 / 移动 / 改名控件、属性、事件、列表项;
  布局语句增删规则与 VS 一致(对全部现有文件执行无变化)
- 双击控件或事件:绑定事件并在窗体代码末尾插入处理方法,跳到代码
- 预览复用运行时的 ControlView,设计时与运行时外观一致
- 修正:窗体属性 this.ClientSize = new Size(...) 被误认成创建控件;
  示例 Designer.cs 的块头注释改为 VS 的 "// " 格式
- 测试:73 个(读写往返、布局规则、编辑操作、插入事件处理方法)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 11:11:48 +08:00

42 lines
1.7 KiB
TypeScript

/// <reference types="bun" />
import { describe, expect, test } from 'bun:test'
import { existsSync } from 'node:fs'
import { resolve } from 'node:path'
import { generateDesigner, parseDesigner } from './document'
const ROOT = resolve(import.meta.dir, '../../..')
// 教材配套的参考工程不在仓库里(版权),本机有时才测
const REFERENCE_DIR = resolve(ROOT, 'docs/物联网编程与应用配套/物联网编程与应用')
async function designerFiles(dir: string) {
const files: string[] = []
for await (const path of new Bun.Glob('**/*.Designer.cs').scan({ cwd: dir })) {
if (path.includes('/obj/') || path.includes('/Properties/')) continue
files.push(resolve(dir, path))
}
return files.sort()
}
describe('读入 Designer.cs 再原样写出,内容逐字节不变', async () => {
const files = [
...(await designerFiles(resolve(ROOT, 'samples'))),
...(existsSync(REFERENCE_DIR) ? await designerFiles(REFERENCE_DIR) : []),
]
for (const file of files) {
test(file.replace(`${ROOT}/`, ''), async () => {
const text = await Bun.file(file).text()
expect(generateDesigner(parseDesigner(text))).toBe(text)
})
}
})
test('窗体属性 this.ClientSize = new Size(...) 不会被当成创建控件', async () => {
const text = await Bun.file(resolve(ROOT, 'samples/p2-t2-模拟量采集/frm_analog.Designer.cs')).text()
const doc = parseDesigner(text)
const creates = doc.prologue.filter((s) => s.kind === 'create').map((s) => (s.kind === 'create' ? s.name : ''))
expect(creates).not.toContain('ClientSize')
expect(creates).not.toContain('AutoScaleDimensions')
const formProps = doc.blocks.at(-1)!.stmts.flatMap((s) => (s.kind === 'prop' ? [s.path] : []))
expect(formProps).toContain('ClientSize')
})