ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LikeC4 E2E 测试实战:DrawIO 导出、静态站点导航与 CLI 覆盖的设计原则和落地方法

LikeC4 E2E 测试实战:DrawIO 导出、静态站点导航与 CLI 覆盖的设计原则和落地方法 LikeC4 E2E 测试实战DrawIO 导出、静态站点导航与 CLI 覆盖的设计原则和落地方法【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4LikeC4 仓库的e2e/目录承载了整个项目的端到端测试层E2E-COVERAGE.md 是其中一份聚焦“DrawIO 集成与导出”这条链路的覆盖度档案它记录了三条核心场景Playground 的 DrawIO 导出、静态站点视图导航、文档站冒烟测试与 CLIexport drawio命令已实现的 E2E 场景并逐条对照源码阐述了背后的 DRY/SOLID/KISS/YAGNI 设计决策。读完本文你将掌握这套 E2E 测试矩阵的组织方式、每个 spec 的关键断言与共享选择器/超时体系以及如何按文档中的命令在不同配置下运行这些测试。E2E 测试矩阵的整体布局从源码结构看LikeC4 的 E2E 测试分为两套运行器各自有明确的文件边界运行器配置文件测试位置覆盖对象Playwright主配置playwright.config.tstests/ 目录静态站点likec4 buildpreview的视图导航、快照对比等Playwrightplayground 配置playwright.playground.config.ts仅tests/drawio-playground.spec.tsPlayground 应用的 DrawIO 上下文菜单与下载Vitestvitest.config.tssrc/ 下的*.spec.ts与*.test-d.tslikec4CLI 命令的行为验证导出 DrawIO、模型、视图等三个关键配置文件的取舍可以直接从源码确认主配置 playwright.config.ts 的testDir指向tests/并通过testIgnore显式排除了drawio-playground.spec.ts、docs-smoke.spec.ts和mcp-render-app.spec.ts注释说明 DrawIO playground 与 MCP App 测试只走各自的专用配置而文档站冒烟测试需要 Astro 文档服务不适合与likec4 start的图预览服务混跑。该配置的webServer执行pnpm build-and-preview端口 62001即“先构建再预览”的静态站点路径并启用了retries: isCI ? 1 : 0、forbidOnly: isCI、CI 下的github报告器等典型 CI 加固项。Playground 配置 playwright.playground.config.ts 通过testMatch: **/drawio-playground.spec.ts只匹配单个 specbaseURL指向http://localhost:5174其webServer用pnpm --filter likec4/playground dev -- --port 5174在本地拉起开发服务器单测超时放宽到 60 秒。Vitest 配置 vitest.config.ts 收集src/**.spec.ts和src/**.test-d.ts类型测试文件并开启typecheck因此 CLI 行为测试与类型层断言在同一个运行器内完成。这个布局对应了 E2E-COVERAGE.md 中“Homogeneity同构性”一节强调的约定Playwright specs 统一使用test.describetest()/test.beforeEachVitest CLI specs 统一使用test与zx的$执行器选择器与 URL 在适用时与 bootstrap 生成的快照测试共享避免同一概念在多处各写一份。共享基建选择器与超时的单一事实来源helpers/selectors.ts 是 Playwright 侧共享选择器的集中定义文件头注释明确其目的是“避免 drawio-playground 与 static-navigation 两个 spec 之间重复”export const CANVAS_SELECTOR .react-flow.initialized export const EDITOR_SELECTOR .monaco-editor export const MENU_SELECTOR [rolemenu], .mantine-Menu-dropdown export function canvas(page: Page): Locator { return page.locator(CANVAS_SELECTOR).first() } export function editor(page: Page): Locator { return page.locator(EDITOR_SELECTOR).first() }两个设计点值得注意initialized状态类作为图表就绪信号canvas()定位的是.react-flow.initialized即 React Flow 画布完成初始化后才被视为“可见”。这与 bootstrap 生成的快照测试中page.waitForSelector(.react-flow.initialized)的等待逻辑一致见 bootstrap.mjs属于跨配置共享的等待约定。MENU_SELECTOR同时覆盖 ARIA 与 Mantine 两类菜单[rolemenu], .mantine-Menu-dropdown的并集写法让画布右键菜单和 Monaco 编辑器右键菜单两者渲染路径不同但共用同一菜单选择器都能被同一个 helper 命中——drawio-playground.spec.ts 中专门用注释解释了这一点。helpers/timeouts.ts 则是所有超时的单一调优点从源码看共 8 个常量TIMEOUT_CANVAS 15_000、TIMEOUT_DIAGRAM 45_000、TIMEOUT_MENU 5_000、TIMEOUT_DOWNLOAD 15_000、TIMEOUT_DOWNLOAD_ALL 20_000、TIMEOUT_EDITOR 10_000、TIMEOUT_EDITOR_MENU 3_000、TIMEOUT_PAGE 10_000。把“下载全部视图”的超时20s设置得高于“下载单个视图”15s与 Export all 需要遍历多张视图的实际耗时相符这也呼应了覆盖度文档中“no magic numbers不要魔法数字”的原则——每个等待时长都有名字的语义。已实现场景一Playground 中的 DrawIO 集成tests/drawio-playground.spec.ts 是 E2E-COVERAGE.md “Implemented scenarios”清单中前五项的载体覆盖度文档对它的要点与源码逐条对应场景与断言工作区加载后图表可见beforeEach导航到教程工作区/w/tutorial/等待 URL 匹配/w\/tutorial\//、尽力等待networkidle失败则吞掉不阻断再用TIMEOUT_DIAGRAM等待画布选择器测试体本身只断言expect(canvas(page)).toBeVisible()。画布右键菜单展示 DrawIO 项右键点击画布固定坐标{ x: 200, y: 200 }常量RIGHT_CLICK_CANVAS随后断言菜单中同时出现DrawIO精确匹配、Export to DrawIO与Export all。Export to DrawIO 触发下载且内容有效这是断言最重的一条——下载文件名必须匹配/^.\.drawio$/随后显式断言download.path()非空文档中所谓“explicit assertion of download path, fail-fast, no silent branch”即不依赖可选链静默跳过再读取文件内容并断言包含mxfile且长度大于 200 字节确保下载到的是真实的 DrawIO XML 而非空文件。Export all 触发.drawio下载复用同一下载触发 helper仅验证文件名后缀因为整工作区导出的完整内容校验由 CLI 侧场景负责见下文避免重复。Monaco 编辑器右键菜单也含 Export to DrawIO先断言编辑器可见TIMEOUT_EDITOR在固定坐标{ x: 100, y: 50 }常量EDITOR_CLICK_POSITION先左键聚焦、再右键等待编辑器上下文菜单出现并断言其中含Export to DrawIOTIMEOUT_EDITOR_MENU。关键 helper 的设计openDrawioContextMenu(page)只负责“右键 返回菜单 Locator”triggerDrawioDownload(page, menuItemLabel, downloadTimeout)则体现了一个典型的先订阅事件再触发操作的时序模式async function triggerDrawioDownload( page: Page, menuItemLabel: Export to DrawIO | Export all, downloadTimeout: number, ): PromiseDownload { const downloadPromise page.waitForEvent(download, { timeout: downloadTimeout }) const menu await openDrawioContextMenu(page) await expect(menu).toBeVisible({ timeout: TIMEOUT_MENU }) await menu.getByText(menuItemLabel, { exact: false }).click() return downloadPromise }downloadPromise在点击菜单项之前就创建消除了“先点击、后监听事件”可能丢事件的竞态菜单项标签用联合类型Export to DrawIO | Export all而非自由字符串把 UI 上的合法菜单项约束到了类型层面。这正是覆盖度文档提到的“helpers with single responsibility”和“no duplication in download flows”两个下载测试共用同一条触发路径。已实现场景二静态站点的视图间导航tests/static-navigation.spec.ts 验证likec4静态站点在多个视图 URL 之间切换时图表能正确渲染。它有三个值得注意的细节URL 形状与 bootstrap 共享viewUrl()生成/project/{project}/export/{viewId}/?padding22形式的地址。这个形状并非随手写的——bootstrap.mjs 为每个已计算视图自动生成 Playwright 快照测试时使用的正是同一条 URL?padding22静态导航测试因此与 31 张已入库的基准截图见 tests/screenshots跑在同一套路由约定上。单一等待点gotoViewAndAssertDiagram内部只做一次expect(canvas(page)).toBeVisible({ timeout: TIMEOUT_CANVAS })没有额外的waitForLoadState或waitForSelector——覆盖度文档称之为“single wait point for the diagram”减少多重等待叠加导致的伪失败。遍历固定视图集合测试依次访问index、cloud、amazon三个视图来自 bootstrap 校验的e2e项目见 bootstrap.mjs 中对工作区项目清单[e2e, export-config, export-disabled, issue-2282]的断言在一个测试内完成“导航切换 图表更新”的完整语义。从源码结构看该 spec 依赖 bootstrap 先运行以生成e2e项目的工作区快照与路由数据这与 E2E-COVERAGE.md “How to run”一节中“includesstatic-navigation.spec.tsafter bootstrap”的说明一致。已实现场景三文档站冒烟测试tests/docs-smoke.spec.ts 是面向 Astro/Starlight 文档站的三个独立短测试每个测试只验证“页面能加载 有一个标志性内容”首页标题匹配/LikeC4/i且存在名为 LikeC4 的链接/tooling/drawio/页标题匹配Draw.io页面出现 export/Draw.io 相关正文/tooling/cli/页出现CLI或command line字样。三个页面 URL 以DOCS_HOME、DOCS_TOOLING_DRAWIO、DOCS_TOOLING_CLI常量集中在文件头部等待统一使用TIMEOUT_PAGE10s测试之间无共享状态——这正是覆盖度文档中“short, independent tests”的具体形态任何一个页面坏了都能独立定位不会因为上一个断言失败而连坐。覆盖度文档在运行说明中写的是pnpm test:docs配合playwright.docs.config.ts、端口 4321。需要注意从当前仓库状态看e2e/package.json 暴露的脚本为test、test:playground、test:mcp-app、typecheck、bootstrap等尚未包含test:docs脚本e2e/目录下也不存在playwright.docs.config.ts文件而主配置通过testIgnore将docs-smoke.spec.ts排除在主运行之外。可以推断文档站冒烟测试目前处于“spec 已就绪、专用配置待接入”的状态运行前应以仓库脚本的实际内容为准。已实现场景四CLIexport drawio的行为验证Playwright 无法覆盖命令行行为这部分由 Vitest 承载。src/likec4-cli-export-drawio.spec.ts 用zx的$执行器直接跑likec4CLI覆盖度文档对它的三点评价都能在源码中验证1. 命名谓词isDrawioFilefunction isDrawioFile(entry: { isFile: () boolean; name: string }): boolean { return entry.isFile() entry.name.endsWith(.drawio) }把“是不是我们关心的产物”抽成有名字的布尔函数readdirSync(...).filter(isDrawioFile)的读法与业务意图一致。2. 确定性文件顺序两个导出测试都执行entries.filter(isDrawioFile).sort((a, b) a.name.localeCompare(b.name))后再读取第一个文件——覆盖度文档中“deterministic file order (sort by name) before reading the first”指的就是这个细节不排序时“第一个.drawio文件”取决于文件系统返回顺序跨平台可能不同断言就会变得不稳定。3. 显式断言与失败路径主测试在likec4的项目根e2e/src/likec4项目 id 为e2e来自 src/likec4/likec4.config.ts下执行likec4 export drawio . -o outDir --project e2e随后断言产物含mxfile且长度大于 200另有一条--profile leanix --uncompressed测试额外断言内容含bridgeManagedtrue且匹配/likec4Id/验证 LeanIX 桥接风格在导出中生效空工作区测试用--project指向一个空目录接受“退出码 1”或“退出码 0 但 stderr 含no LikeC4 sources found”两种失败形态源码注释解释了这是 CI 中打包版 CLI 的已知偏差并预留了“quirk 修复后收紧为只接受 exitCode 1”的演进方向——E2E 断言如何与 CI 现实妥协这里给出了一个具体范例。从源码结构看当前e2e/src/下还包含likec4-cli-bridge.spec.ts、likec4-model.spec.ts、likec4-views.spec.ts等兄弟 spec 及对应的*.test-d.ts类型测试文件说明 Vitest 侧的 CLI 覆盖面已从单一 DrawIO 导出扩展到桥接、模型与视图多个领域覆盖度文档中提及的likec4-cli-build.spec.ts在当前文件列表中已不存在相关构建行为验证应当已并入上述 spec 体系。设计原则如何落到代码E2E-COVERAGE.md 开头一节把 DRY、SOLID、KISS、YAGNI 逐 spec 对号入座结合源码可以归纳出四条可复用的模式常量上移、helper 单一职责drawio-playground、static-navigation、docs-smokeTUTORIAL_PATH、RIGHT_CLICK_CANVAS、VIEW_IDS、DOCS_*等全部声明在文件顶部canvas(page)、editor(page)、gotoViewAndAssertDiagram(page, viewId)这类小函数各自只做一件事测试体读起来接近伪代码。单一等待点static-navigation一个导航动作只配一个断言等待避免“等待风暴”。命名谓词 确定性排序cli-export-drawio把过滤条件与顺序假设显式化消除对文件系统行为与字符串字面量的隐式依赖。失败路径也要测cli-export-drawio 的空工作区测试CLI 的“必须失败”场景同样有 E2E 级验证且对 CI 已知偏差留了注释化的收紧计划。文档最后还提到一次“integrity全局一致性扫描”ExportDrawioParams、isSourceFile、ROUNDTRIP_IGNORED_DIRS等导出侧类型、OnDrawioExportError、CollectViewModelsOptions等 Playground 侧类型、以及applyLoggerConfig与Page类型等均在 CLI/Playground/E2E 各层被检查过一致性。这提示维护者E2E 层改动选择器、URL 或导出文件名约定时需要同步检查各包中共享的类型与常量而不是只改测试。如何运行这些测试以下命令均来自 E2E-COVERAGE.md “How to run”一节并与 e2e/package.json 的脚本定义核对一致# 前置安装依赖CI 场景下依赖以本地 tarball 形式引入见 package.json 中的 file:../packages/*/package.tgz pnpm install # PlaywrightplaygroundDrawIO 菜单、下载等场景 cd e2e pnpm test:playground # Playwright主配置静态站点导航 bootstrap 生成的视图快照 cd e2e pnpm bootstrap # 生成 e2e 项目数据与快照 spec cd e2e pnpm test # VitestCLI 行为测试含 export drawio同时跑类型检查 cd e2e pnpm typecheck运行前提与限制bootstrap 先于主 Playwright 测试pnpm bootstrapbootstrap.mjs会执行likec4 codegen生成 React 组件与模型文件校验工作区项目清单并为e2e与issue-2282两个项目的每个视图生成tests/*-gen.spec.ts快照测试。主配置下的导航与快照测试都依赖这一步。端口与服务器由 webServer 配置托管主配置自动拉起pnpm build-and-previewlikec4 build -o ./dist ./src likec4 preview端口 62001playground 配置自动拉起 5174 端口的 dev server且本地运行时reuseExistingServer: !isCI——本地已手动起服务可以直接复用。截图基准已入库tests/screenshots按chromium-linux/chromium-darwin两个平台目录存放了 31 张基准 PNGsnapshotPathTemplate将其固定为{testDir}/__screenshots__/{projectName}-{platform}/{arg}{ext}更新基线用pnpm test:update-screenshots且主配置将像素差异容忍度设为maxDiffPixelRatio: 0.01以吸收 CI 上字体/布局的微小抖动。浏览器当前配置只跑 ChromiumDesktop Chrome HiDPI设备描述本地首次运行前可执行pnpm install:chromium确保浏览器可用。覆盖度现状小结对照 E2E-COVERAGE.md 的清单全部列出的场景均已勾选完成Playground 的 DrawIO 菜单/可见性/单视图导出/全量导出/编辑器菜单五项CLI 的export drawio产出mxfile一项以及“Pending (optional)”中的静态站点导航与文档站冒烟两项也都已实现。从当前仓库状态看仍有两处与代码存在待对齐的落差文档站冒烟对应的专用配置与test:docs脚本尚未在 e2e/package.json 中出现文档提到的likec4-cli-build.spec.ts已不在 e2e/src 的 spec 列表中。这两点可以作为后续维护该测试矩阵时的优先核对项除此之外文档中列出的每条设计原则与运行命令都能在上述源码文件里找到一一对应的实现证据。【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表