首页
/ Strapi 测试应用共享模板 tests/app-template:E2E 与 CLI 双测试体系的统一基座及其工作原理

Strapi 测试应用共享模板 tests/app-template:E2E 与 CLI 双测试体系的统一基座及其工作原理

2026-09-06 14:16:05作者:龚格成

Strapi 仓库中 tests/app-template 目录是一个被 E2E(Playwright 浏览器)与 CLI(Jest 命令行)两套测试体系共同复用的“测试应用模板”,为所有测试提供一个内容类型、组件与配置完全一致的基线应用。读完本文,你将理解该模板的目录构成与配置含义、统一测试运行器如何基于它批量生成 test-app-* 应用(yalc 链接、SQLite 覆盖、端口分配与 Git 基线),以及模板变更后的清理与重建操作规范,从而能独立维护或排查 Strapi 的端到端与 CLI 测试环境。

一、Shared Test App Template 的定位

根据 tests/app-template/README.md 的官方说明,该模板的核心定位有三点:

  • 它是一个共享模板应用,同时被 e2e(Playwright)cli(Jest) 两套测试体系使用;
  • 它提供了一个一致的基线应用,预置了固定的内容类型(content types)、组件(components)与配置(configurations),保证测试可重复、可对比;
  • 模板位于 tests/app-template,由统一测试运行器 tests/scripts/run-tests.js 在生成测试应用时自动消费,两类测试共享同一套应用定义,从而确保测试行为的一致性。

从模板自身的 package.json 可以确认其身份:包名为 @strapi/e2e-test-app、版本 0.1.0private: true,脚本仅包含 strapi build / strapi develop / strapi start / strapi 四个基础命令,依赖固定为 @strapi/strapi@strapi/plugin-users-permissions(均为 latest)、better-sqlite3@12.8.0 以及 react@18.3.1react-dom@18.3.1react-router-dom@6.30.4styled-components@6.4.1,并要求 node >=20.0.0 <=26.x.x

二、模板的目录结构与内容构成

2.1 config/:预置的应用配置

模板 config/ 目录包含七份配置文件,是保证两个测试体系行为一致的关键:

文件 作用要点
config/database.js 通过 DATABASE_CLIENT 切换 mysql / postgres / sqlite,默认 sqlite,文件位于 .tmp/data.dbuseNullAsDefault: true
config/server.js 默认 HOST=0.0.0.0PORT=1337,支持 APP_KEYS 与 webhook 关系填充开关
config/admin.js ADMIN_JWT_SECRET、API Token 盐值,并启用 preview 功能——除 api::product.product 外返回 https://strapi.io/preview/... 占位地址,服务于 preview 相关测试
config/features.js 读取 BETA_MEDIA_LIBRARY 环境变量开启 future.betaMediaLibrary,用于特性开关(feature flag)测试
config/api.js API 路由与响应结构相关配置
config/middlewares.js 中间件挂载配置
config/plugins.js 插件配置

其中 config/admin.js 值得注意:secrets.encryptionKey 硬编码为 'example-key'flagsnpspromoteEEdocLinks 均默认 true——这类取值只服务测试环境,生产项目不应照搬。

2.2 src/api/:预置内容类型矩阵

模板在 src/api/ 下预置了覆盖面很广的 API,按测试关注点可分为几组(均为 tests/app-template/src/api/ 下的相对子目录):

  • 基础 CRUD 与关系articleauthorcategorycatdogmatchproductshopteamupcoming-matchhomepagecountry
  • 关系专项relation-labrelation-target,配合 src/components 中的 match/player.json 等组件,覆盖多对多/自引用关系场景;
  • 内容类型形态single-type-localizedsingle-type-non-localsingle-type-unpublished,分别验证单例类型在本地化、非本地化、草稿/发布(unpublished)三种形态下的表现;
  • 约束与状态unique(唯一约束)、conditioncomplex
  • 测试控制面config 目录提供控制器/路由/服务与 utils/resync-super-admin-after-import.js 等辅助逻辑,供测试用例主动操控应用状态。

模板还附带若干 documentation/1.0.0/*.json 文档定义(如 article、homepage、product、shop、team、unique),用于 documentation 插件相关断言。

2.3 src/components/ 与 template/ 子目录

组件定义位于 src/components,包括 component-category/match/player.jsonmeta/seo.jsonpage-blocks/(hero-image、content-and-image、product-carousel)以及 product/variations.jsonunique/

此外仓库中还存在一个 tests/app-template/template/ 子目录,内含 src/api/(category、complex、config、single-type-localized/non-local/unpublished)以及 constants.jsindex.js。从源码结构看,它是一套精简的辅助副本,README 未对其作专门说明;template.json(内容仅为 {"package": {"private": true}})则约束生成应用的包元信息。

2.4 应用入口的测试友好初始化

模板的 src/index.jsbootstrap 阶段做了三件事:

module.exports = {
  register(/* { strapi } */) {},
  async bootstrap({ strapi }) {
    strapi.service('api::config.config').rateLimitEnable(false);
    strapi.service('api::config.config').adminAutoOpenEnable(false);
    await createTestTransferToken(strapi);
  },
};

即:关闭速率限制与 admin 自动打开行为(避免测试中限流干扰),并通过 src/create-transfer-token.js 预生成测试用 transfer token,供 data transfer / import 类用例直接使用。

三、两套测试体系如何消费该模板

3.1 统一运行器 tests/scripts/run-tests.js

README 指出模板“由统一测试运行器自动使用”,该运行器即 tests/scripts/run-tests.js,其 yargs 命令定义可归纳为:

选项 别名 说明
--type <e2e|cli> -t 必填,决定运行 e2e 还是 cli 测试,并决定 tests/<type>/tests 下的 domain 目录与 test-apps/<type> 应用目录
--concurrency <n> -c 并发数量;e2e 表示并发测试应用数,cli 表示并发 domain 数,默认等于 domain 总数
--domains <...> -d 指定要运行的 domain(子套件),默认全部
--setup -f 强制重建测试应用(对应 README 中的 “--setup flag to force regeneration”)
--updateSnapshot -u 透传 -u 给 Jest 更新快照
clean 子命令 --type 清理 test-apps/<type> 下所有测试应用

顶层 package.json 中的脚本即通过两个薄包装器调用该运行器:tests/scripts/run-e2e-tests.jstests/scripts/run-cli-tests.js 分别向 run-tests.js 注入 --type e2e / --type cli。根 package.json 中可用的测试命令包括:

yarn test:e2e            # node tests/scripts/run-e2e-tests.js
yarn test:e2e:ce         # cross-env STRAPI_E2E_EDITION=ce
yarn test:e2e:ee         # cross-env STRAPI_E2E_EDITION=ee
yarn test:e2e:clean      # clean 子命令,type=e2e
yarn test:cli            # node tests/scripts/run-cli-tests.js
yarn test:cli:clean
yarn test:cli:debug      # --debug
yarn test:cli:update     # -u
yarn test:clean          # 依次执行 api/e2e/cli 三类 clean

3.2 生成流程:从模板到 test-app-N

真正“吃模板”的逻辑在 tests/utils/runners/shared-setup.jssetupTestApps--setup 被指定或现有应用数量不足时触发,完整流程为:

  1. 发布工作区包到 yalc 存储:运行器先调用 scripts/yalc-publish.jspublishYalc),确保测试应用链接的是当前仓库源码而非 npm 发布版本;

  2. 清理旧应用:对 test-apps/<type> 下已有的应用逐个执行 tests/helpers/test-app.js 中的 cleanTestApprimraf 删除目录);

  3. 生成新应用generateTestApptests/app-template/package.json 对应目录为 template 调用 create-strapi-appcreateStrapi,scope 关键参数包括:

    • database:强制覆盖为 sqlite,filename: './.tmp/data.db'useNullAsDefault: true(覆盖模板自身的 config/database.js 默认值,使每个测试应用自带独立数据库文件);
    • template: path.resolve('tests/app-template')link: true(生成后清空 yarn.lock 并执行 scripts/yalc-link.js 链接工作区包);
    • packageManager: 'yarn'runApp: falsegitInit: falseinstallDependencies: falsestrapiVersionpackages/core/strapi 的版本号。

    这与 CLI 侧 packages/cli/create-strapi-app/src/index.ts 支持的 --template <template> / --template-branch / --template-path 选项相对应——测试流程本质上就是“用本地目录作为模板执行一次 create-strapi”。

  4. 环境变量修正:读取生成应用的 .env 并移除 PORT=1337 行,因为 e2e 会按应用序号动态分配端口;

  5. features 配置手工注入setupTestEnvironment(仅 e2e 传入)把模板的 config/features.js 原样写入生成应用的 config/features.js。源码注释说明了原因:“a template does not allow the config folder”,即模板机制不允许随模板携带 config/ 目录,因此 BETA_MEDIA_LIBRARY 等特性开关只能生成后手工补写;

  6. e2e 的 Git 基线commitE2eBaseline 为 e2e 专属,对每个生成应用执行 git init + git add -A + 提交(提交信息 e2e test app baseline,作者固定为 Strapi CLI <test@strapi.io>)。后续测试间的 resetFiles 仅通过 git reset --hard + git clean -fd 回到该基线,实现每个用例间的文件级隔离。

3.3 e2e 分支:Playwright 应用矩阵

tests/scripts/run-tests.js 的 e2e 分支中:

  • 需要生成的应用数为 min(选中 domain 数, concurrency),应用路径为 test-apps/e2e/test-app-<i>
  • 应用按 domain 分块(chunk),每块内并发启动,第 j 个应用固定占用端口 8000 + j
  • 为每个应用动态写出 playwright.config.js(将 PORT 以数字字面量写入 process.env.PORT),配置本体由 playwright.base.config.jscreateConfig 生成,report 文件命名为 playwright-<domain>-<port>.xml

应用名匹配规则在 getCurrentTestApps 中体现:仅识别 test-apps/<type> 下符合 /^test-app-\d+$/ 的目录,从而排除 test-results 等非应用目录。

3.4 cli 分支:Jest domain 编排

cli 分支的差异在于按 domain 配置文件编排:loadDomainConfigs 读取 tests/cli/tests/<domain> 的配置,calculateTestAppsRequired 决定所需应用数;某些 domain 可声明 testApps: 0(例如 create-strapi-app 一类“脚手架到临时目录”的套件,不需要占用 test-apps 下的常驻应用)。每个 domain 使用仓库根 jest.config.cli.js 作为 Jest 配置,-u 时自动追加快照更新参数;批次内任一套件失败会以 N tests failed 终止整个批次。

此外 tests/helpers/test-app.js 中的 runTestApp 展示了测试应用的真实启动方式:yarn strapi buildyarn strapi start,并注入 STRAPI_DISABLE_EE(未提供 STRAPI_LICENSE 时置为 !process.env.STRAPI_LICENSE)与 JWT_SECRET: 'aSecret',保证 CI 环境的可复现性。

四、更新模板的标准操作

README 的 “Updating the Template” 一节给出模板变更后的两步规范,其背后的代码依据是:模板内容被烘焙进已生成的 test-app-*,模板更新不会自动反映到现存应用。

  1. 清理已有测试应用

    yarn test:e2e:clean   # 或 yarn test:cli:clean
    

    对应运行器 clean 子命令,遍历并 rimraftest-apps/<type> 下所有 test-app-* 目录(见 tests/scripts/run-tests.jsclean 命令的 handler)。

  2. 重新生成

    yarn test:e2e          # 或 yarn test:cli
    yarn test:e2e -f       # 使用 --setup / -f 强制重建,即使应用数量已足够
    

    不传 --setup 时,setupTestApps 检测到应用数量满足要求会直接跳过生成并打印提示:“Skipping setting up test apps, use --setup to force the setup process”。

需要牢记的一致性约束:由于 e2e 与 cli 共用该模板,任何对内容类型、组件或配置的改动都会同时影响两套测试体系,提交前应尽量在本地用 yarn test:clean && yarn test:e2e(或对应 cli 命令)完整验证。

五、验证路径速查

关注点 仓库内入口
模板定义 tests/app-template/(config/、src/api/、src/components/、package.json、template.json)
统一运行器与 CLI 参数 tests/scripts/run-tests.js
应用生成/清理核心逻辑 tests/utils/runners/shared-setup.jstests/helpers/test-app.js
模板机制(--template 等) packages/cli/create-strapi-app/src/index.ts
e2e 入口与 edition 开关 tests/scripts/run-e2e-tests.jstests/utils/e2e-edition.ts
Playwright 基础配置 playwright.base.config.js
CLI Jest 配置 jest.config.cli.js

六、小结

tests/app-template 是 Strapi 测试体系的“单一事实来源”:它以一整套预置的内容类型矩阵、组件与配置,保证 Playwright 端到端测试与 Jest CLI 测试运行在完全相同的基线应用之上;tests/scripts/run-tests.js 配合 tests/utils/runners/shared-setup.js 负责“模板 → yalc 链接 + sqlite 覆盖 + features 注入 + Git 基线 → 端口分配”的完整生成链路。理解并遵循其“先 clean、后 --setup 重建”的更新流程,是维护该模板时避免环境漂移的关键。

登录后查看全文
热门项目推荐
相关项目推荐