ZITADEL 功能型 UI 端到端测试实战:用 Nx + Cypress 驱动 Management Console 用户旅程验证 📅 发布时间:2026/9/14 8:47:06 👁 浏览次数: ZITADEL 功能型 UI 端到端测试实战用 Nx Cypress 驱动 Management Console 用户旅程验证【免费下载链接】zitadelZITADEL - Identity infrastructure, simplified for you.项目地址: https://gitcode.com/GitHub_Trending/zi/zitadel本篇基于 ZITADEL 仓库中 tests/functional-ui/AGENTS.md 的官方 Agent 指南展开介绍如何在这个 Nx monorepo 中运行针对 Management Console管理控制台的 Cypress 端到端测试。读完后你能掌握五个已验证的 Nx 目标打开交互式 Runner、跑测试套件、单独起测试库、单独起测试 API、停止测试基建的完整用法以及底层编排细节——临时 Postgres、API 构建启动链路、系统令牌签发机制和测试辅助层的实现原理从而能够在本地可靠地复现与调试 Console 用户旅程测试。一、functional-ui 测试的定位tests/functional-ui 目录承载的是基于 Cypress 的端到端测试聚焦于 Management Console 的用户流程user journeys其运行前提是一个“正在运行的 ZITADEL API”——即测试不是对着静态页面跑而是对着一个完整的 Zitadel 后端内嵌 Console 静态资源进行真实交互验证。指南中特别强调了两条工作流约束Workflow Notes它是 Console 的主要测试路径由于zitadel/console项目本身没有定义 Nx 的test目标functional-ui 套件就是验证 Console 用户旅程的第一也是目前唯一的E2E 测试通道强依赖 API 的构建/运行编排这些测试依赖 API 的 build/run 编排在没有同步更新本套件的前提下应避免改动 API 的启动假设startup assumptions。这一点从 tests/functional-ui/project.json 的依赖声明可以得到印证run-api目标声明了dependsOn: [zitadel/api:build]test目标则同时依赖run-db、run-api与zitadel/api:build且implicitDependencies指向了zitadel/api和zitadel/console两个项目。二、已验证的 Nx 目标速查指南中列出了五个已经过验证Verified的 Nx 目标这是复现整个测试环境的核心操作面目标命令作用打开交互式 Cypress Runnerpnpm nx run zitadel/functional-ui:open启动 Cypress Test Runner 交互界面便于逐个调试用例运行测试套件pnpm nx run zitadel/functional-ui:test完整跑一次 functional UIConsole测试仅启动测试数据库pnpm nx run zitadel/functional-ui:run-db启动一个本地临时ephemeralPostgres仅启动测试 APIpnpm nx run zitadel/functional-ui:run-api构建并运行内嵌 Management Console 的 Zitadel API停止测试基建pnpm nx run zitadel/functional-ui:stop停掉测试用的本地 Postgrestest目标支持通过参数指定浏览器例如--browser electron指南指出electron浏览器应当始终可用Cypress 内置。编排细节各目标到底做了什么结合 tests/functional-ui/project.json 的源码可以看清每个目标背后的实际动作run-db执行nx run zitadel/devcontainer:compose up --force-recreate --renew-anon-volumes db-functional-ui即借助 devcontainer 项目的 compose 编排强制重建并刷新匿名卷拉起一个仅服务于 functional-ui 的临时 Postgres 容器。run-api先依赖zitadel/api:build编译 Go 后端二进制再执行nx run zitadel/api:prod:test-functional-ui --excludeTaskDependencies。标记为continuous: true作为长驻进程运行。open声明依赖zitadel/console:dev、run-db、run-api即同时拉起 Console 开发服务、数据库与 API 后再打开交互式 Cypress Runner。test以nx:run-commands顺序执行三条命令cypress install——确保 Cypress 二进制就位wait-on --verbose --interval 2000 --simultaneous 1 --timeout 30m ${CYPRESS_BACKEND_URL}/debug/ready——每 2 秒轮询一次 API 的 ready 端点最长等待 30 分钟确保后端完全就绪后再跑浏览器DISPLAY cypress run——以无显示环境CI 风格执行测试。该目标开启cache: true其缓存输入除了默认项外还显式纳入了 API 构建产物.artifacts/bin/*/*/zitadel.local——即 API 二进制一变测试缓存即失效重跑。stop执行nx run zitadel/devcontainer:compose down --volumes db-functional-ui带卷清理地拆除临时 Postgres。API 是如何被拉起来的apps/api/project.json 显示prod目标通过nx:run-commands启动二进制./.artifacts/bin/$(go env GOOS)/$(go env GOARCH)/${ZITADEL_BINARY:-zitadel.local} \ start-from-init --config ${API_CONFIG_FILE} --steps ${API_CONFIG_FILE} \ --masterkey MasterkeyNeedsToHave32Characters其中test-functional-ui配置configuration把API_CONFIG_FILE指向 apps/api/test-functional-ui.yaml。也就是说functional-ui 测试用的是start-from-init子命令加一份专用 YAML——“init start”一步完成数据库从这份配置里现场初始化。三、测试环境配置test-functional-ui.yaml 解读apps/api/test-functional-ui.yaml 是为 UI 端到端测试专门准备的 API 配置关键项如下数据库Database.postgres指向库名zitadel应用账号zitadel/zitadel、管理账号postgres/postgresSSL 均设为disable并配置AwaitInitialConn: 5m、MaxOpenConns: 15、MaxIdleConns: 10。注释说明该配置可通过/etc/hosts条目复用到 Docker 之外的 Zitadel 进程提升了环境复用性。TLSEnabled: false测试环境走明文 HTTP与默认baseUrl的http://前缀对应。QuotasAccess.Enabled: true且Debounce.MinFrequency: 0s、MaxBulkSize: 0——配额功能在测试中是开启且即时生效的。这解释了测试辅助层为何需要显式清理配额见下文context()。SystemAPIUsers声明了一个名为cypress的系统 API 用户KeyData是一段 Base64 编码的 RSA 公钥-----BEGIN PUBLIC KEY-----...。这正是 Cypress 侧签发系统令牌的验签公钥两端由此配对见下一节。DefaultInstanceMfaInitSkipLifetime: 0、Features.LoginV2.Required: false——为测试流程移除 MFA 等强制项的干扰。四、Cypress 配置baseUrl、系统令牌与 Webhook 桩tests/functional-ui/cypress.config.ts 是整个测试基建的枢纽值得逐项理解环境变量与默认值变量默认值说明CYPRESS_BASE_URLhttp://localhost:8083/ui/consoleConsole 页面入口CYPRESS_BACKEND_URL由 baseUrl 去掉/ui/console后缀推导API 后端地址CYPRESS_WEBHOOK_HANDLER_PORT8900内置 Webhook 接收桩端口CYPRESS_WEBHOOK_HANDLER_HOSTlocalhostWebhook 桩监听主机CYPRESS_ORGANIZATIONzitadel测试组织标识其他关键参数defaultCommandTimeout: 10000、pageLoadTimeout: 180000页面加载最长 3 分钟适配冷启动、video: true、测试报告输出到cypress/resultsHTML JSON、trashAssetsBeforeRuns: false保留历史产物便于回溯。系统令牌system token的签发链路这是理解本套件鉴权模型的关键。setupNodeEvents中注册了若干cy.tasksystemToken()使用配置中内置的 RSA 私钥以RS256算法现场签发一个 JWTclaims 为isscypress、subcypress、aud${CYPRESS_BACKEND_URL}、exp设为约 999 年后。由于 test-functional-ui.yaml 中SystemAPIUsers声明了与私钥配对的cypress公钥该令牌即被 Zitadel 识别为合法的系统 API 令牌可访问/system/v1。safetoken({key, token})/loadtoken({key})一个跨 spec 的令牌内存缓存Map避免同一会话重复登录。Webhook 事件桩startWebhookEventHandler()在 Node 侧启动一个 HTTP 服务默认 8900 端口把收到的每个 Webhook 请求的 payload 与响应状态码记录到webhookEvents数组resetWebhookEvents()、handledWebhookEvents()、failWebhookEvents(count)三个任务允许测试用例读取事件、并让前 N 个请求故意返回 500——用于验证通知/Webhook 投递与失败重试行为。测试辅助层supportsupport/api/apiauth.ts 封装了两条鉴权路径apiAuth()以 IAM Admin 用户密码登录Password1!返回一组版本化 API 基地址/management/v1、/admin/v1、/auth/v1、/oidc/v1、/saml/v2、/v2/features等供 UI 之外的直接 API 断言使用systemAuth()通过cy.task(systemToken)获取系统令牌封装/system/v1调用。custom 命令层 进一步提供了cy.context()依次完成systemAuth()→instanceUnderTest()→ 清除AuthenticatedRequests与ExecutionSeconds两类配额呼应 YAML 中 Quotas 的开启→apiAuth()最终返回{ system, api, instanceId }三元组让每个 spec 在统一的“干净上下文”中执行。注意 support/api/instances.ts 中instanceUnderTest会断言“API 上恰好只有一个 instance”——这与start-from-init全新初始化的环境假设严格匹配也是“不要改动 API 启动假设”这条工作流约束的具体落点。此外还有shouldNotExist()等待某选择器元素数归零用于验证删除后的 UI 状态、shouldConfirmSuccess()断言.data-e2e-success出现且.data-e2e-failure不存在等通用断言命令。cypress/support/api/下还按领域拆分了orgs.ts、projects.ts、members.ts、grants.ts、policies.ts、oidc-settings.ts、smtp.ts、sms.ts、search.ts等 helper覆盖组织、项目、成员、授权、策略与外部服务的预置操作。五、测试覆盖面从 tests/functional-ui/cypress/e2e 目录结构看spec 按 Console 功能域组织organization/organizations.cy.ts、projects/projects.cy.ts、permissions/permissions.cy.ts——组织、项目与权限管理humans/humans.cy.ts、machines/machines.cy.ts——人类用户与机器用户Service Account 一类身份管理applications/applications.cy.ts——应用管理instance/settings/notifications.cy.ts、secret-generator.cy.ts与settings/login-policy.cy.ts、password-complexity.cy.ts、oidc-settings.cy.ts、features.cy.ts、private-labeling.cy.ts、external-links-settings.cy.ts——实例级设置events/events.cy.ts、i18n/api.cy.ts——事件审计与国际化。结合 tests/functional-ui/package.json套件依赖cypress ^15.14.2、cypress-wait-until自定义等待、jsonwebtoken配合 Node 侧签 token与uuid生成测试数据标识。六、实操步骤与注意事项一次完整的功能型 UI 测试流程可以归纳为在仓库根目录确认 pnpm 依赖已安装工作区根package.json定义了 Nx workspacepnpm nx run zitadel/functional-ui:test或交互调试时...:open——该命令会自动拉起临时 Postgres、构建并启动内嵌 Console 的 Zitadel API、等待${CYPRESS_BACKEND_URL}/debug/ready就绪后再跑 Cypress测试完成后执行pnpm nx run zitadel/functional-ui:stop清理临时数据库。需要注意的适用前提与限制测试环境默认 HTTPTLS 关闭、localhost 地址与固定端口Console 8083、Webhook 桩 8900如自定义端口需通过CYPRESS_BASE_URL、CYPRESS_WEBHOOK_HANDLER_PORT等环境变量传入instanceUnderTest要求“API 上恰好一个实例”依赖start-from-init的全新初始化语义若更换启动方式必须同步更新本套件AGENTS.md 的明确警告浏览器选择通过test目标参数传入如--browser electronelectron始终可用由于 Console 项目自身无 Nxtest目标任何针对 Console 用户旅程的回归验证都应走本套件。小结tests/functional-ui是 ZITADEL 仓库中验证 Management Console 用户旅程的主通道以 AGENTS.md 的五个已验证 Nx 目标为操作入口以 project.json 的依赖编排、test-functional-ui.yaml 的全新初始化配置、cypress.config.ts 的系统令牌与 Webhook 桩机制为底层支撑构成了一条从临时数据库到浏览器断言的完整、可复现的端到端测试链路。理解这条链路也就掌握了在本地复现、调试和扩展 ZITADEL Console 功能测试所需的全部关键事实。【免费下载链接】zitadelZITADEL - Identity infrastructure, simplified for you.项目地址: https://gitcode.com/GitHub_Trending/zi/zitadel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考