cloudcc-cli 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/.claude/settings.json +15 -0
  2. package/.cloudcc-cache.json +17 -48
  3. package/.cursor/skills/cloudcc-cli-dev.zip +0 -0
  4. package/.cursor/skills/cloudcc-cli-usage/SKILL.md +67 -0
  5. package/README.md +22 -0
  6. package/bin/cc.js +13 -8
  7. package/bin/index.js +12 -2
  8. package/bin/mcp.js +1 -1
  9. package/build/{component-cc-test-001.common.js → component-CCPlugin1774500425584.common.js} +25 -25
  10. package/build/component-CCPlugin1774500425584.common.js.map +1 -0
  11. package/build/component-CCPlugin1774500425584.css +1 -0
  12. package/build/{component-cc-test-001.umd.js → component-CCPlugin1774500425584.umd.js} +27 -27
  13. package/build/component-CCPlugin1774500425584.umd.js.map +1 -0
  14. package/build/{component-cc-test-001.umd.min.js → component-CCPlugin1774500425584.umd.min.js} +3 -3
  15. package/build/component-CCPlugin1774500425584.umd.min.js.map +1 -0
  16. package/build/demo.html +1 -1
  17. package/{src/mcp → mcp}/tools/Class Editor Guide/handler.js +12 -4
  18. package/{src/mcp → mcp}/tools/Component Editor Guide/handler.js +15 -14
  19. package/{src/mcp → mcp}/tools/Trigger Editor Guide/handler.js +8 -2
  20. package/package.json +2 -2
  21. package/src/application/delete.js +59 -0
  22. package/src/application/doc.js +46 -0
  23. package/src/application/docs/devguide.md +173 -0
  24. package/src/application/docs/introduction.md +81 -0
  25. package/src/application/get.js +31 -5
  26. package/src/application/index.js +2 -0
  27. package/src/brief/get.js +1 -1
  28. package/src/classes/create.js +6 -1
  29. package/src/classes/delete.js +49 -0
  30. package/src/classes/detail.js +21 -7
  31. package/src/classes/doc.js +49 -472
  32. package/src/classes/docs/devguide.md +451 -0
  33. package/src/classes/get.js +9 -2
  34. package/src/classes/index.js +3 -1
  35. package/src/classes/publish.js +6 -1
  36. package/src/classes/pull.js +6 -1
  37. package/src/classes/pullList.js +6 -3
  38. package/src/config/doc.js +31 -0
  39. package/src/config/docs/devguide.md +100 -0
  40. package/src/config/index.js +5 -0
  41. package/src/customPage/create.js +109 -14
  42. package/src/customPage/delete.js +2 -2
  43. package/src/customPage/doc.js +46 -0
  44. package/src/customPage/docs/devguide.md +200 -0
  45. package/src/customPage/docs/introduction.md +224 -0
  46. package/src/customPage/get.js +1 -1
  47. package/src/customPage/index.js +1 -0
  48. package/src/customSetting/create.js +36 -0
  49. package/src/customSetting/delete.js +35 -0
  50. package/src/customSetting/deleteCustomSettingField.js +43 -0
  51. package/src/customSetting/detail.js +33 -0
  52. package/src/customSetting/doc.js +22 -179
  53. package/src/customSetting/docs/devguide.md +181 -0
  54. package/src/customSetting/docs/introduction.md +3 -0
  55. package/src/customSetting/editCustomSettingField.js +34 -0
  56. package/src/customSetting/get.js +34 -0
  57. package/src/customSetting/index.js +10 -1
  58. package/src/customSetting/modify.js +30 -0
  59. package/src/customSetting/saveCustomSettingField.js +46 -0
  60. package/src/fields/delete.js +52 -0
  61. package/src/fields/doc.js +45 -0
  62. package/src/fields/docs/devguide.md +224 -0
  63. package/src/fields/docs/introduction.md +217 -0
  64. package/src/fields/index.js +2 -0
  65. package/src/globalSelectList/create.js +51 -0
  66. package/src/globalSelectList/delete.js +56 -0
  67. package/src/globalSelectList/detail.js +45 -0
  68. package/src/globalSelectList/doc.js +52 -0
  69. package/src/globalSelectList/docs/devguide.md +212 -0
  70. package/src/globalSelectList/docs/introduction.md +82 -0
  71. package/src/globalSelectList/get.js +31 -0
  72. package/src/globalSelectList/index.js +16 -0
  73. package/src/menu/create-page.js +54 -26
  74. package/src/menu/create-script.js +67 -19
  75. package/src/menu/create.js +9 -3
  76. package/src/menu/delete.js +59 -0
  77. package/src/menu/doc.js +57 -0
  78. package/src/menu/docs/devguide.md +203 -0
  79. package/src/menu/docs/introduction.md +99 -0
  80. package/src/menu/get.js +56 -0
  81. package/src/menu/index.js +3 -0
  82. package/src/menu/validator.js +80 -0
  83. package/src/object/delete.js +51 -0
  84. package/src/object/doc.js +45 -0
  85. package/src/object/docs/devguide.md +112 -0
  86. package/src/object/docs/introduction.md +187 -0
  87. package/src/object/get.js +1 -23
  88. package/src/object/index.js +2 -0
  89. package/src/pagelayout/create.js +123 -0
  90. package/src/pagelayout/doc.js +46 -0
  91. package/src/pagelayout/docs/devguide.md +295 -0
  92. package/src/pagelayout/docs/introduction.md +44 -0
  93. package/src/pagelayout/get.js +46 -0
  94. package/src/pagelayout/index.js +9 -0
  95. package/src/plugin/detail.js +14 -6
  96. package/src/plugin/doc.js +43 -863
  97. package/src/plugin/docs/devguide.md +923 -0
  98. package/src/plugin/publish1.js +3 -3
  99. package/src/profile/create.js +108 -0
  100. package/src/profile/delete.js +59 -0
  101. package/src/profile/doc.js +46 -0
  102. package/src/profile/docs/devguide.md +332 -0
  103. package/src/profile/docs/introduction.md +123 -0
  104. package/src/profile/get.js +55 -0
  105. package/src/profile/index.js +14 -0
  106. package/src/project/doc.js +39 -372
  107. package/src/project/docs/devguide.md +359 -0
  108. package/src/project/docs/introduction.md +3 -0
  109. package/src/recordType/create.js +77 -0
  110. package/src/recordType/delete.js +52 -0
  111. package/src/recordType/doc.js +36 -0
  112. package/src/recordType/docs/devguide.md +160 -0
  113. package/src/recordType/docs/introduction.md +53 -0
  114. package/src/recordType/editInfo.js +39 -0
  115. package/src/recordType/editSave.js +47 -0
  116. package/src/recordType/get.js +1 -1
  117. package/src/recordType/getList.js +31 -0
  118. package/src/recordType/index.js +16 -3
  119. package/src/recordType/newInfo.js +39 -0
  120. package/src/recordType/validDelete.js +91 -0
  121. package/src/res.md +66 -0
  122. package/src/role/create.js +153 -0
  123. package/src/role/delete.js +59 -0
  124. package/src/role/doc.js +46 -0
  125. package/src/role/docs/devguide.md +387 -0
  126. package/src/role/docs/introduction.md +124 -0
  127. package/src/role/get.js +57 -0
  128. package/src/role/index.js +10 -0
  129. package/src/scheduleJob/delete.js +26 -0
  130. package/src/scheduleJob/detail.js +23 -0
  131. package/src/scheduleJob/doc.js +49 -0
  132. package/src/scheduleJob/docs/devguide.md +79 -0
  133. package/src/scheduleJob/docs/introduction.md +101 -0
  134. package/src/scheduleJob/get.js +26 -0
  135. package/src/scheduleJob/index.js +15 -0
  136. package/src/script/delete.js +112 -0
  137. package/src/script/doc.js +31 -245
  138. package/src/script/docs/devguide.md +290 -0
  139. package/src/script/docs/introduction.md +48 -0
  140. package/src/script/index.js +1 -0
  141. package/src/staticResource/count.js +46 -0
  142. package/src/staticResource/create.js +97 -0
  143. package/src/staticResource/delete.js +48 -0
  144. package/src/staticResource/detail.js +46 -0
  145. package/src/staticResource/doc.js +39 -0
  146. package/src/staticResource/docs/devguide.md +157 -0
  147. package/src/staticResource/docs/introduction.md +3 -0
  148. package/src/staticResource/get.js +48 -0
  149. package/src/staticResource/index.js +13 -0
  150. package/src/timer/create.js +6 -1
  151. package/src/timer/delete.js +49 -0
  152. package/src/timer/detail.js +5 -5
  153. package/src/timer/doc.js +57 -0
  154. package/src/timer/get.js +7 -1
  155. package/src/timer/index.js +4 -1
  156. package/src/timer/publish.js +6 -1
  157. package/src/timer/pull.js +6 -1
  158. package/src/timer/pullList.js +5 -3
  159. package/src/triggers/delete.js +46 -0
  160. package/src/triggers/detail.js +5 -5
  161. package/src/triggers/doc.js +49 -364
  162. package/src/triggers/docs/devguide.md +334 -0
  163. package/src/triggers/get.js +7 -3
  164. package/src/triggers/index.js +2 -4
  165. package/src/triggers/pullList.js +7 -7
  166. package/src/user/create.js +50 -0
  167. package/src/user/delete.js +59 -0
  168. package/src/user/doc.js +46 -0
  169. package/src/user/docs/devguide.md +634 -0
  170. package/src/user/docs/introduction.md +124 -0
  171. package/src/user/get.js +112 -0
  172. package/src/user/index.js +12 -0
  173. package/src/user/update.js +96 -0
  174. package/src/user/view.js +60 -0
  175. package/test/application.cli.test.js +49 -8
  176. package/test/classes.cli.test.js +14 -5
  177. package/test/customPage.cli.test.js +96 -0
  178. package/test/customSetting.cli.test.js +84 -0
  179. package/test/fields.cli.test.js +18 -3
  180. package/test/globalSelectList.cli.test.js +94 -0
  181. package/test/menu-script.cli.test.js +147 -0
  182. package/test/menu.cli.test.js +42 -5
  183. package/test/object.cli.test.js +17 -1
  184. package/test/plugin.cli.test.js +5 -3
  185. package/test/scheduleJob.cli.test.js +52 -0
  186. package/test/staticResource.cli.test.js +78 -0
  187. package/test/timer.cli.test.js +20 -7
  188. package/test/trigger.cli.test.js +13 -5
  189. package/tmp_customsetting_detail.json +1 -0
  190. package/.cursor/skills/cloudcc-cli-dev/BACKEND_CLASS.md +0 -97
  191. package/.cursor/skills/cloudcc-cli-dev/BACKEND_SCHEDULE.md +0 -78
  192. package/.cursor/skills/cloudcc-cli-dev/BACKEND_TRIGGER.md +0 -137
  193. package/.cursor/skills/cloudcc-cli-dev/CLI_CHEATSHEET.md +0 -215
  194. package/.cursor/skills/cloudcc-cli-dev/CUSTOM-SETTING-API.md +0 -241
  195. package/.cursor/skills/cloudcc-cli-dev/INSTALL_AND_BOOTSTRAP.md +0 -59
  196. package/.cursor/skills/cloudcc-cli-dev/OBJECTS_AND_FIELDS.md +0 -120
  197. package/.cursor/skills/cloudcc-cli-dev/REQUIREMENTS_BREAKDOWN.md +0 -98
  198. package/.cursor/skills/cloudcc-cli-dev/SKILL.md +0 -44
  199. package/.cursor/skills/cloudcc-cli-dev/VUE_CUSTOM_COMPONENT.md +0 -151
  200. package/build/component-cc-test-001.common.js.map +0 -1
  201. package/build/component-cc-test-001.css +0 -1
  202. package/build/component-cc-test-001.umd.js.map +0 -1
  203. package/build/component-cc-test-001.umd.min.js.map +0 -1
  204. package/classes/CCdd/CCdd.java +0 -22
  205. package/classes/CCdd/CCddTest.java +0 -11
  206. package/classes/CCdd/config.json +0 -1
  207. package/core.zip +0 -0
  208. package/plugins/cc-test-001/cc-test-001.vue +0 -32
  209. package/plugins/cc-test-001/components/HelloWorld.vue +0 -11
  210. package/plugins/cc-test-001/config.json +0 -6
  211. package/schedule/CCdd/CCdd.java +0 -11
  212. package/schedule/CCdd/config.json +0 -1
  213. package/src/approval/approve.js +0 -105
  214. package/src/approval/get.js +0 -245
  215. package/src/approval/index.js +0 -11
  216. package/src/approval/reject.js +0 -105
  217. package/src/plugin/readme.md +0 -7
  218. package/target/ccopenapi-0.0.4-classes.jar +0 -0
  219. package/target/ccopenapi-0.0.4.jar +0 -0
  220. package/target/classes/CCdd/CCdd.class +0 -0
  221. package/target/classes/CCdd/CCddTest.class +0 -0
  222. package/target/classes/CCdd/config.json +0 -1
  223. package/target/maven-archiver/pom.properties +0 -3
  224. package/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +0 -20
  225. package/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +0 -19
  226. /package/{src/mcp → mcp}/cliRunner.js +0 -0
  227. /package/{src/mcp → mcp}/index.js +0 -0
  228. /package/{src/mcp → mcp}/readme.md +0 -0
  229. /package/{src/mcp → mcp}/tools/Application Creator/handler.js +0 -0
  230. /package/{src/mcp → mcp}/tools/Approval/handler.js +0 -0
  231. /package/{src/mcp → mcp}/tools/Class Creator/handler.js +0 -0
  232. /package/{src/mcp → mcp}/tools/Class Detail Retriever/handler.js +0 -0
  233. /package/{src/mcp → mcp}/tools/Class List Retriever/handler.js +0 -0
  234. /package/{src/mcp → mcp}/tools/Class Publisher/handler.js +0 -0
  235. /package/{src/mcp → mcp}/tools/Class Puller/handler.js +0 -0
  236. /package/{src/mcp → mcp}/tools/Client Script Detail Retriever/handler.js +0 -0
  237. /package/{src/mcp → mcp}/tools/Client Script Editor Guide/handler.js +0 -0
  238. /package/{src/mcp → mcp}/tools/Client Script List Retriever/handler.js +0 -0
  239. /package/{src/mcp → mcp}/tools/Client Script Publisher/handler.js +0 -0
  240. /package/{src/mcp → mcp}/tools/Client Script Puller/handler.js +0 -0
  241. /package/{src/mcp → mcp}/tools/CloudCC Development Overview/handler.js +0 -0
  242. /package/{src/mcp → mcp}/tools/Component Creator/handler.js +0 -0
  243. /package/{src/mcp → mcp}/tools/Component Detail Retriever/handler.js +0 -0
  244. /package/{src/mcp → mcp}/tools/Component List Retriever/handler.js +0 -0
  245. /package/{src/mcp → mcp}/tools/Component Publisher/handler.js +0 -0
  246. /package/{src/mcp → mcp}/tools/Component Puller/handler.js +0 -0
  247. /package/{src/mcp → mcp}/tools/Dev Environment Creator/fetcher.js +0 -0
  248. /package/{src/mcp → mcp}/tools/Dev Environment Creator/handler.js +0 -0
  249. /package/{src/mcp → mcp}/tools/Dev Environment Validator/handler.js +0 -0
  250. /package/{src/mcp → mcp}/tools/Developer Key Setup Guide/fetcher.js +0 -0
  251. /package/{src/mcp → mcp}/tools/Developer Key Setup Guide/handler.js +0 -0
  252. /package/{src/mcp → mcp}/tools/JSP Migrator/handler.js +0 -0
  253. /package/{src/mcp → mcp}/tools/Menu Creator/handler.js +0 -0
  254. /package/{src/mcp → mcp}/tools/Object Creator/handler.js +0 -0
  255. /package/{src/mcp → mcp}/tools/Object Fields Creator/handler.js +0 -0
  256. /package/{src/mcp → mcp}/tools/Object Fields Retriever/handler.js +0 -0
  257. /package/{src/mcp → mcp}/tools/Object List Retriever/handler.js +0 -0
  258. /package/{src/mcp → mcp}/tools/Scheduled Class Creator/handler.js +0 -0
  259. /package/{src/mcp → mcp}/tools/Scheduled Class Detail Retriever/handler.js +0 -0
  260. /package/{src/mcp → mcp}/tools/Scheduled Class List Retriever/handler.js +0 -0
  261. /package/{src/mcp → mcp}/tools/Scheduled Class Publisher/handler.js +0 -0
  262. /package/{src/mcp → mcp}/tools/Scheduled Class Puller/handler.js +0 -0
  263. /package/{src/mcp → mcp}/tools/Trigger Creator/handler.js +0 -0
  264. /package/{src/mcp → mcp}/tools/Trigger Detail Retriever/handler.js +0 -0
  265. /package/{src/mcp → mcp}/tools/Trigger List Retriever/handler.js +0 -0
  266. /package/{src/mcp → mcp}/tools/Trigger Publisher/handler.js +0 -0
  267. /package/{src/mcp → mcp}/tools/Trigger Puller/handler.js +0 -0
  268. /package/{src/mcp → mcp}/tools/index.js +0 -0
  269. /package/{docs//350/207/252/345/256/232/344/271/211/347/261/273.md" → src/classes/docs/introduction.md} +0 -0
  270. /package/{docs/CloudCC/350/207/252/345/256/232/344/271/211/347/273/204/344/273/266/344/275/277/347/224/250/350/257/264/346/230/216.md" → src/plugin/docs/introduction.md} +0 -0
  271. /package/{docs/cloudcc/345/256/232/346/227/266/344/275/234/344/270/232.md" → src/timer/docs/devguide.md} +0 -0
  272. /package/{docs/cloudcc/345/256/232/346/227/266/347/261/273.md" → src/timer/docs/introduction.md} +0 -0
  273. /package/{docs//350/247/246/345/217/221/345/231/250/347/261/273.md" → src/triggers/docs/introduction.md} +0 -0
@@ -16,11 +16,12 @@ async function runCc(args) {
16
16
  return execAsync(cmd, { cwd: repoRoot });
17
17
  }
18
18
 
19
- test("字段管理流程:获取对象列表→create 字段→get 字段列表", async (t) => {
19
+ test("字段管理流程:获取对象列表→create 字段→get 字段列表→delete", async (t) => {
20
20
  let objPrefix = null;
21
21
  let objId = null;
22
22
  let objName = null;
23
23
  const fieldLabel = `AutoField_${Date.now()}`;
24
+ let fieldId = null;
24
25
 
25
26
  t.test("1) 获取对象列表(取第一个对象的 id 和 objprefix)", async () => {
26
27
  // 只取自定义对象,避免标准对象在部分环境下字段接口异常
@@ -62,8 +63,22 @@ test("字段管理流程:获取对象列表→create 字段→get 字段列表
62
63
  if (res.stdFields) assert.ok(Array.isArray(res.stdFields), "stdFields 应为数组");
63
64
  if (res.cusFields) assert.ok(Array.isArray(res.cusFields), "cusFields 应为数组");
64
65
 
65
- // 尽量校验新字段是否已出现(不强制)
66
+ // 尽量校验新字段是否已出现,并记录 id
66
67
  const allCus = Array.isArray(res.cusFields) ? res.cusFields : [];
67
- const hit = allCus.some((f) => f.fieldname === fieldLabel || f.apiname?.includes("_custom_s_field"));
68
+ const hit = allCus.find((f) => f.fieldname === fieldLabel);
69
+ if (hit && hit.id) {
70
+ fieldId = hit.id;
71
+ }
72
+ });
73
+
74
+ t.test("4) delete 删除刚创建字段", async () => {
75
+ // 个别环境字段列表刷新有延迟,找不到时跳过强校验
76
+ if (!fieldId) {
77
+ console.error("[fields-test] 未在列表中定位到新字段 id,跳过 delete");
78
+ return;
79
+ }
80
+ const { stdout, stderr } = await runCc(["delete", "fields", repoRoot, fieldId, objId]);
81
+ const out = `${stdout}\n${stderr}`.trim();
82
+ assert.match(out, /Success|成功/i, "delete fields 应输出成功信息");
68
83
  });
69
84
  });
@@ -0,0 +1,94 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const { exec } = require("node:child_process");
4
+ const { promisify } = require("node:util");
5
+ const path = require("node:path");
6
+
7
+ const execAsync = promisify(exec);
8
+ const repoRoot = path.resolve(__dirname, "..");
9
+
10
+ function quoteArg(value) {
11
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
12
+ }
13
+
14
+ async function runCc(args) {
15
+ const cmd = `npx --prefix "${repoRoot}" cc ${args.map(quoteArg).join(" ")}`;
16
+ return execAsync(cmd, { cwd: repoRoot });
17
+ }
18
+
19
+ test("全局选项列表", async (t) => {
20
+ const ts = Date.now();
21
+ const label = `TestGSL${ts}`;
22
+ const name = `test_gsl_${ts}`;
23
+ let createdId = null;
24
+
25
+ await t.test("1) 获取 doc(globalSelectList introduction / devguide)", async () => {
26
+ const intro = await runCc(["doc", "globalSelectList", "introduction"]);
27
+ assert.match(intro.stdout, /全局选项列表/);
28
+
29
+ const devguide = await runCc(["doc", "globalSelectList", "devguide"]);
30
+ assert.match(devguide.stdout, /全局选项列表/);
31
+ });
32
+
33
+ await t.test("2) 获取全局选项列表(get)", async () => {
34
+ const { stdout } = await runCc(["get", "globalSelectList", repoRoot]);
35
+ const list = JSON.parse(stdout.trim());
36
+ assert.ok(Array.isArray(list), "get globalSelectList 应返回数组");
37
+ assert.ok(list.length >= 0, "列表长度应为非负整数");
38
+ });
39
+
40
+ await t.test("3) 新建全局选项列表(create)", async () => {
41
+ const body = encodeURI(
42
+ JSON.stringify({
43
+ label,
44
+ name,
45
+ description: "cli test 自动创建",
46
+ ptext: "选项A\r\n选项B\r\n选项C",
47
+ isPicklistSorted: "0",
48
+ isFirstDefault: "1",
49
+ })
50
+ );
51
+ const { stderr } = await runCc(["create", "globalSelectList", repoRoot, body]);
52
+ assert.match(stderr, /Success|created/i, "create 应输出成功信息");
53
+
54
+ // 从列表中找到刚创建的记录,取得 id
55
+ const { stdout } = await runCc(["get", "globalSelectList", repoRoot]);
56
+ const list = JSON.parse(stdout.trim());
57
+ const found = list.find((item) => item.name === name || item.label === label);
58
+ assert.ok(found, "新建后 get 列表中应能找到该记录");
59
+ createdId = found.id;
60
+ assert.ok(createdId, "新建记录应有 id");
61
+ });
62
+
63
+ await t.test("4) 获取详情(detail)", async () => {
64
+ assert.ok(createdId, "detail 测试需要 createdId");
65
+ const { stdout } = await runCc(["detail", "globalSelectList", repoRoot, createdId]);
66
+ const result = JSON.parse(stdout.trim());
67
+
68
+ assert.ok(result.globalSelect, "detail 应返回 globalSelect 字段");
69
+ assert.equal(result.globalSelect.id, createdId, "detail.globalSelect.id 应与请求 id 一致");
70
+ assert.ok(result.globalSelect.label, "detail.globalSelect 应包含 label");
71
+ assert.ok(result.globalSelect.name, "detail.globalSelect 应包含 name");
72
+
73
+ assert.ok(Array.isArray(result.enabledList), "detail 应返回 enabledList 数组");
74
+ assert.ok(result.enabledList.length >= 3, "enabledList 应包含新建时填写的 3 个选项");
75
+
76
+ assert.ok(Array.isArray(result.disabledList), "detail 应返回 disabledList 数组");
77
+ assert.ok(Array.isArray(result.useList), "detail 应返回 useList 数组");
78
+ });
79
+
80
+ await t.test("5) 删除全局选项列表(delete)", async () => {
81
+ assert.ok(createdId, "delete 测试需要 createdId");
82
+ const { stdout, stderr } = await runCc(["delete", "globalSelectList", repoRoot, createdId]);
83
+ const out = `${stdout}\n${stderr}`.trim();
84
+ assert.match(out, /Success|deleted/i, "delete 应输出成功信息");
85
+ });
86
+
87
+ await t.test("6) 删除后 get 列表中不再包含该记录", async () => {
88
+ assert.ok(createdId, "验证删除需要 createdId");
89
+ const { stdout } = await runCc(["get", "globalSelectList", repoRoot]);
90
+ const list = JSON.parse(stdout.trim());
91
+ const found = list.find((item) => item.id === createdId);
92
+ assert.equal(found, undefined, "删除后列表中不应再包含已删除记录");
93
+ });
94
+ });
@@ -0,0 +1,147 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const path = require("node:path");
4
+ const { exec } = require("node:child_process");
5
+ const { promisify } = require("node:util");
6
+
7
+ const execAsync = promisify(exec);
8
+ const repoRoot = path.resolve(__dirname, "..");
9
+
10
+ function quoteArg(value) {
11
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
12
+ }
13
+
14
+ async function runCc(args) {
15
+ const cmd = `npx --prefix "${repoRoot}" cc ${args.map(quoteArg).join(" ")}`;
16
+ return execAsync(cmd, { cwd: repoRoot });
17
+ }
18
+
19
+ test("自定义脚本菜单管理流程:doc→创建脚本菜单→查询列表→删除", async (t) => {
20
+ const tabName = `CC测试脚本菜单_${Date.now()}`;
21
+ // pname 必须以字母开头,只能包含字母、数字、下划线
22
+ const pname = `test_script_menu_${Date.now()}`;
23
+ const functioncode = "ccc.alert('Hello from test');";
24
+ let menuId = null;
25
+
26
+ await t.test("0) 获取 doc(menu devguide 包含脚本菜单说明)", async () => {
27
+ const { stdout } = await runCc(["doc", "menu", "devguide"]);
28
+ assert.match(stdout, /脚本|script|functioncode/i, "devguide 应包含脚本菜单相关说明");
29
+ });
30
+
31
+ await t.test("1) 创建自定义脚本菜单(仅必需参数)", async () => {
32
+ const { stdout, stderr } = await runCc([
33
+ "create", "menu", "script",
34
+ repoRoot,
35
+ tabName,
36
+ pname
37
+ ]);
38
+ const out = `${stdout}\n${stderr}`.trim();
39
+ assert.match(out, /Success|成功/i, "create menu script 应输出成功信息");
40
+ assert.match(out, /console\.log\("hello"\)/i, "默认脚本内容应为 console.log(\"hello\")");
41
+ });
42
+
43
+ await t.test("2) 查询菜单列表(get menu)并匹配刚创建的脚本菜单", async () => {
44
+ const { stdout } = await runCc(["get", "menu", repoRoot]);
45
+ const list = JSON.parse(stdout.trim());
46
+ assert.ok(Array.isArray(list), "get menu 应返回数组");
47
+
48
+ // 脚本菜单可能在 scriptlist 中,也可能在合并后的列表中
49
+ const allMenus = Array.isArray(list) ? list : [];
50
+ const hit = allMenus.find((item) =>
51
+ item.tabName === tabName ||
52
+ item.tabLabel === tabName ||
53
+ item.label === tabName ||
54
+ item.name === tabName ||
55
+ item.pname === pname
56
+ );
57
+
58
+ if (!hit) {
59
+ console.error("[menu-script-test] 未在菜单列表定位到刚创建的脚本菜单,跳过删除步骤");
60
+ return;
61
+ }
62
+ menuId = hit.id;
63
+ assert.ok(menuId, "命中菜单应包含 id");
64
+ console.error(`\n[menu-script-test] 找到脚本菜单: ${hit.tabName || hit.label} (id=${menuId})`);
65
+ });
66
+
67
+ await t.test("3) 删除脚本菜单(delete menu)", async () => {
68
+ if (!menuId) {
69
+ console.error("[menu-script-test] 无 menuId,跳过 delete menu");
70
+ return;
71
+ }
72
+ const { stdout, stderr } = await runCc(["delete", "menu", repoRoot, menuId]);
73
+ const out = `${stdout}\n${stderr}`.trim();
74
+ assert.match(out, /Success|成功/i, "delete menu 应输出成功信息");
75
+ });
76
+ });
77
+
78
+ test("自定义脚本菜单完整参数测试", async (t) => {
79
+ const tabName = `CC脚本菜单完整_${Date.now()}`;
80
+ const pname = `full_test_menu_${Date.now()}`;
81
+ const functioncode = "console.log('Custom script executed'); ccc.alert('Done');";
82
+ const tabStyle = "cloudtab150";
83
+ const mobileimg = "cloudcc05";
84
+ let menuId = null;
85
+
86
+ await t.test("1) 创建带完整参数的脚本菜单", async () => {
87
+ const { stdout, stderr } = await runCc([
88
+ "create", "menu", "script",
89
+ repoRoot,
90
+ tabName,
91
+ pname,
92
+ functioncode,
93
+ tabStyle,
94
+ mobileimg
95
+ ]);
96
+ const out = `${stdout}\n${stderr}`.trim();
97
+ assert.match(out, /Success|成功/i, "带完整参数的 create menu script 应成功");
98
+ assert.match(out, /Custom script executed/, "应包含自定义脚本内容");
99
+ });
100
+
101
+ await t.test("2) 查询并清理", async () => {
102
+ const { stdout } = await runCc(["get", "menu", repoRoot]);
103
+ const list = JSON.parse(stdout.trim());
104
+ const hit = list.find((item) => item.tabName === tabName || item.pname === pname);
105
+ if (hit && hit.id) {
106
+ menuId = hit.id;
107
+ await runCc(["delete", "menu", repoRoot, menuId]);
108
+ console.error(`[menu-script-test] 已清理测试菜单: ${tabName}`);
109
+ }
110
+ });
111
+ });
112
+
113
+ test("自定义脚本菜单参数验证测试", async (t) => {
114
+ await t.test("1) 缺少 tabName 参数应返回错误", async () => {
115
+ await assert.rejects(
116
+ () => runCc(["create", "menu", "script", repoRoot]),
117
+ /Error|缺少|required/i,
118
+ "缺少必需参数时应报错"
119
+ );
120
+ });
121
+
122
+ await t.test("2) 自动生成 pname(当未提供时)", async () => {
123
+ const autoTabName = `AutoPnameTest_${Date.now()}`;
124
+ const { stdout, stderr } = await runCc([
125
+ "create", "menu", "script",
126
+ repoRoot,
127
+ autoTabName
128
+ // 不提供 pname,测试自动生成逻辑
129
+ ]);
130
+ const out = `${stdout}\n${stderr}`.trim();
131
+ // 由于 pname 是必需的,这里应该提示自动生成或报错
132
+ // 根据代码逻辑,如果不提供 pname 会尝试用 tabName 生成
133
+ console.error(`[menu-script-test] 自动生成测试输出: ${out.substring(0, 200)}`);
134
+
135
+ // 清理:查询并删除
136
+ try {
137
+ const { stdout: listOut } = await runCc(["get", "menu", repoRoot]);
138
+ const list = JSON.parse(listOut.trim());
139
+ const hit = list.find((item) => item.tabName === autoTabName);
140
+ if (hit && hit.id) {
141
+ await runCc(["delete", "menu", repoRoot, hit.id]);
142
+ }
143
+ } catch (e) {
144
+ // 忽略清理错误
145
+ }
146
+ });
147
+ });
@@ -16,11 +16,20 @@ async function runCc(args) {
16
16
  return execAsync(cmd, { cwd: repoRoot });
17
17
  }
18
18
 
19
- test("菜单管理流程:获取对象列表→create menu object", async (t) => {
19
+ test("菜单管理流程:doc→获取对象列表→create menu object", async (t) => {
20
20
  let objectId = null;
21
21
  let objectName = null;
22
+ const tabName = `CC测试菜单Tab_${Date.now()}`;
23
+ let menuId = null;
22
24
 
23
- t.test("1) 获取自定义对象列表(取第一个自定义对象 id 用于创建菜单)", async () => {
25
+ await t.test("0) 获取 doc(menu introduction / devguide)", async () => {
26
+ const intro = await runCc(["doc", "menu", "introduction"]);
27
+ assert.match(intro.stdout, /菜单/);
28
+ const dev = await runCc(["doc", "menu", "devguide"]);
29
+ assert.match(dev.stdout, /菜单/);
30
+ });
31
+
32
+ await t.test("1) 获取自定义对象列表(取第一个自定义对象 id 用于创建菜单)", async () => {
24
33
  const { stdout } = await runCc(["get", "object", repoRoot, "custom"]);
25
34
  const list = JSON.parse(stdout.trim());
26
35
  assert.ok(Array.isArray(list), "get object custom 应返回数组");
@@ -32,10 +41,38 @@ test("菜单管理流程:获取对象列表→create menu object", async (t) =
32
41
  console.error(`\n[menu-test] 目标自定义对象: ${objectName || "Unknown"} (id=${objectId})`);
33
42
  });
34
43
 
35
- t.test("2) 创建对象类型菜单(create menu object)", async () => {
44
+ await t.test("2) 创建对象类型菜单(create menu object)", async () => {
36
45
  assert.ok(objectId, "需要 objectId");
37
- await assert.doesNotReject(() =>
38
- runCc(["create", "menu", "object", repoRoot, objectId, "CC测试菜单Tab"])
46
+ const { stdout, stderr } = await runCc(["create", "menu", "object", repoRoot, objectId, tabName]);
47
+ const out = `${stdout}\n${stderr}`.trim();
48
+ assert.match(out, /Success|成功/i, "create menu object 应输出成功信息");
49
+ });
50
+
51
+ await t.test("3) 查询菜单列表(get menu)并匹配刚创建菜单", async () => {
52
+ const { stdout } = await runCc(["get", "menu", repoRoot]);
53
+ const list = JSON.parse(stdout.trim());
54
+ assert.ok(Array.isArray(list), "get menu 应返回数组");
55
+ const hit = list.find((item) =>
56
+ item.tabName === tabName ||
57
+ item.tabLabel === tabName ||
58
+ item.label === tabName ||
59
+ item.name === tabName
39
60
  );
61
+ if (!hit) {
62
+ console.error("[menu-test] 未在菜单列表定位到刚创建菜单,跳过删除步骤");
63
+ return;
64
+ }
65
+ menuId = hit.id;
66
+ assert.ok(menuId, "命中菜单应包含 id");
67
+ });
68
+
69
+ await t.test("4) 删除菜单(delete menu)", async () => {
70
+ if (!menuId) {
71
+ console.error("[menu-test] 无 menuId,跳过 delete menu");
72
+ return;
73
+ }
74
+ const { stdout, stderr } = await runCc(["delete", "menu", repoRoot, menuId]);
75
+ const out = `${stdout}\n${stderr}`.trim();
76
+ assert.match(out, /Success|成功/i, "delete menu 应输出成功信息");
40
77
  });
41
78
  });
@@ -16,10 +16,11 @@ async function runCc(args) {
16
16
  return execAsync(cmd, { cwd: repoRoot });
17
17
  }
18
18
 
19
- test("对象管理流程:get 对象列表→create 对象→get 列表校验", async (t) => {
19
+ test("对象管理流程:get 对象列表→create 对象→get 列表校验→delete", async (t) => {
20
20
  const objectLabel = `TestObj${Date.now()}`;
21
21
  const labelNeedle = "testobj";
22
22
  let createdSlugHit = false;
23
+ let createdObjId = null;
23
24
 
24
25
  t.test("1) create 创建自定义对象", async () => {
25
26
  await assert.doesNotReject(() => runCc(["create", "object", repoRoot, objectLabel]));
@@ -46,6 +47,14 @@ test("对象管理流程:get 对象列表→create 对象→get 列表校验",
46
47
  return s.includes(labelNeedle) || l.includes(labelNeedle);
47
48
  });
48
49
  assert.ok(createdSlugHit, "custom 列表应包含刚创建的自定义对象(按 testobj 关键字匹配)");
50
+
51
+ const created = list.find((o) => {
52
+ const l = `${o.label || o.objname || ""}`.toLowerCase();
53
+ return l === objectLabel.toLowerCase();
54
+ });
55
+ if (created && created.id) {
56
+ createdObjId = created.id;
57
+ }
49
58
  });
50
59
 
51
60
  t.test("4) get 获取全部对象列表(both / 默认)并校验包含新对象", async () => {
@@ -61,4 +70,11 @@ test("对象管理流程:get 对象列表→create 对象→get 列表校验",
61
70
  });
62
71
  assert.ok(found || createdSlugHit, "both 列表应包含刚创建的自定义对象");
63
72
  });
73
+
74
+ t.test("5) delete 删除刚创建对象", async () => {
75
+ assert.ok(createdObjId, "delete object 前应有 createdObjId");
76
+ const { stdout, stderr } = await runCc(["delete", "object", repoRoot, createdObjId]);
77
+ const out = `${stdout}\n${stderr}`.trim();
78
+ assert.match(out, /Success|成功/i, "delete object 应输出成功信息");
79
+ });
64
80
  });
@@ -39,9 +39,11 @@ test("组件管理流程:创建→doc→发布→拉取→详情→列表→
39
39
  assert.ok(config.component && config.component.includes(pluginName));
40
40
  });
41
41
 
42
- t.test("2) 获取 doc(plugin overview)", async () => {
43
- const { stdout } = await runCc(["doc", "plugin", "overview"]);
44
- assert.ok(stdout.length > 0, "doc plugin 应有输出");
42
+ t.test("2) 获取 doc(plugin introduction / devguide)", async () => {
43
+ const intro = await runCc(["doc", "plugin", "introduction"]);
44
+ assert.match(intro.stdout, /自定义组件/);
45
+ const dev = await runCc(["doc", "plugin", "devguide"]);
46
+ assert.match(dev.stdout, /自定义组件/);
45
47
  });
46
48
 
47
49
  t.test("3) 发布组件(publish:以输出判断成功)", async () => {
@@ -0,0 +1,52 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const path = require("node:path");
4
+ const { exec } = require("node:child_process");
5
+ const { promisify } = require("node:util");
6
+
7
+ const execAsync = promisify(exec);
8
+ const repoRoot = path.resolve(__dirname, "..");
9
+
10
+ function quoteArg(value) {
11
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
12
+ }
13
+
14
+ async function runCc(args) {
15
+ const cmd = `npx --prefix "${repoRoot}" cc ${args.map(quoteArg).join(" ")}`;
16
+ return execAsync(cmd, { cwd: repoRoot });
17
+ }
18
+
19
+ test("定时作业管理:get -> detail(可选 delete)", async (t) => {
20
+ let firstJobId = null;
21
+
22
+ t.test("1) 获取定时作业列表", async () => {
23
+ const { stdout } = await runCc(["get", "scheduleJob", repoRoot]);
24
+ const list = JSON.parse(stdout.trim() || "[]");
25
+ assert.ok(Array.isArray(list), "get scheduleJob 应返回数组");
26
+ if (list.length > 0 && list[0].id) {
27
+ firstJobId = list[0].id;
28
+ }
29
+ });
30
+
31
+ t.test("2) 获取定时作业详情(若存在 id)", async () => {
32
+ if (!firstJobId) {
33
+ console.error("[scheduleJob-test] 无可用 jobId,跳过 detail");
34
+ return;
35
+ }
36
+ await assert.doesNotReject(() => runCc(["detail", "scheduleJob", firstJobId, repoRoot]));
37
+ });
38
+
39
+ t.test("3) 删除定时作业(仅在 ENABLE_DESTRUCTIVE_TESTS=1 时执行)", async () => {
40
+ if (process.env.ENABLE_DESTRUCTIVE_TESTS !== "1") {
41
+ console.error("[scheduleJob-test] 默认跳过 delete(设置 ENABLE_DESTRUCTIVE_TESTS=1 可启用)");
42
+ return;
43
+ }
44
+ if (!firstJobId) {
45
+ console.error("[scheduleJob-test] 无可用 jobId,跳过 delete");
46
+ return;
47
+ }
48
+ const { stdout, stderr } = await runCc(["delete", "scheduleJob", firstJobId, repoRoot]);
49
+ const out = `${stdout}\n${stderr}`.trim();
50
+ assert.match(out, /Success|成功/i, "delete scheduleJob 应输出成功信息");
51
+ });
52
+ });
@@ -0,0 +1,78 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const path = require("node:path");
4
+ const { exec } = require("node:child_process");
5
+ const { promisify } = require("node:util");
6
+
7
+ const execAsync = promisify(exec);
8
+ const repoRoot = path.resolve(__dirname, "..");
9
+
10
+ function quoteArg(value) {
11
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
12
+ }
13
+
14
+ async function runCc(args) {
15
+ const cmd = `npx --prefix "${repoRoot}" cc ${args.map(quoteArg).join(" ")}`;
16
+ return execAsync(cmd, { cwd: repoRoot });
17
+ }
18
+
19
+ test("静态资源管理:get -> detail -> count(可选 delete)", async (t) => {
20
+ let firstResourceId = null;
21
+
22
+ t.test("1) 获取静态资源列表", async () => {
23
+ try {
24
+ const { stdout } = await runCc(["get", "staticResource", repoRoot]);
25
+ const list = JSON.parse(stdout.trim() || "[]");
26
+ assert.ok(Array.isArray(list), "get staticResource 应返回数组");
27
+ if (list.length > 0) {
28
+ firstResourceId = list[0].id || list[0].objid || null;
29
+ }
30
+ } catch (e) {
31
+ const msg = `${e.stderr || e.message || ""}`;
32
+ if (/404|Get Static Resource Failed/i.test(msg)) {
33
+ console.error("[staticResource-test] 当前环境未开放 staticResource 接口,跳过相关强校验");
34
+ return;
35
+ }
36
+ throw e;
37
+ }
38
+ });
39
+
40
+ t.test("2) 查询静态资源详情(若存在 id)", async () => {
41
+ if (!firstResourceId) {
42
+ console.error("[staticResource-test] 无可用 resourceId,跳过 detail");
43
+ return;
44
+ }
45
+ await assert.doesNotReject(() =>
46
+ runCc(["detail", "staticResource", repoRoot, firstResourceId])
47
+ );
48
+ });
49
+
50
+ t.test("3) 统计静态资源容量(count)", async () => {
51
+ try {
52
+ const { stdout } = await runCc(["count", "staticResource", repoRoot]);
53
+ const data = JSON.parse(stdout.trim() || "{}");
54
+ assert.equal(typeof data, "object", "count staticResource 应返回对象");
55
+ } catch (e) {
56
+ const msg = `${e.stderr || e.message || ""}`;
57
+ if (/404|Count Static Resource Failed/i.test(msg)) {
58
+ console.error("[staticResource-test] 当前环境未开放 staticResource count 接口,跳过 count 强校验");
59
+ return;
60
+ }
61
+ throw e;
62
+ }
63
+ });
64
+
65
+ t.test("4) 删除静态资源(仅在 ENABLE_DESTRUCTIVE_TESTS=1 时执行)", async () => {
66
+ if (process.env.ENABLE_DESTRUCTIVE_TESTS !== "1") {
67
+ console.error("[staticResource-test] 默认跳过 delete(设置 ENABLE_DESTRUCTIVE_TESTS=1 可启用)");
68
+ return;
69
+ }
70
+ if (!firstResourceId) {
71
+ console.error("[staticResource-test] 无可用 resourceId,跳过 delete");
72
+ return;
73
+ }
74
+ const { stdout, stderr } = await runCc(["delete", "staticResource", repoRoot, firstResourceId]);
75
+ const out = `${stdout}\n${stderr}`.trim();
76
+ assert.match(out, /Success|成功/i, "delete staticResource 应输出成功信息");
77
+ });
78
+ });
@@ -18,7 +18,7 @@ async function runCc(args) {
18
18
  return execAsync(cmd, { cwd: repoRoot });
19
19
  }
20
20
 
21
- test("定时任务管理流程:创建→发布→拉取→线上详情→列表→批量拉取前2个→清空 schedule 文件夹", async (t) => {
21
+ test("定时任务管理流程:创建→doc→发布→拉取→线上详情→列表→批量拉取→delete→清空 schedule 文件夹", async (t) => {
22
22
  const timerName = `CCTimer${Date.now()}`;
23
23
  const timerDir = path.join(scheduleRoot, timerName);
24
24
  const configPath = path.join(timerDir, "config.json");
@@ -37,14 +37,21 @@ test("定时任务管理流程:创建→发布→拉取→线上详情→列
37
37
  assert.equal(config.name, timerName);
38
38
  });
39
39
 
40
- t.test("2) 发布定时任务(publish,写回 config.id)", async () => {
40
+ t.test("2) 获取 doc(timer introduction / devguide)", async () => {
41
+ const intro = await runCc(["doc", "timer", "introduction"]);
42
+ assert.match(intro.stdout, /定时类/);
43
+ const dev = await runCc(["doc", "timer", "devguide"]);
44
+ assert.match(dev.stdout, /定时/);
45
+ });
46
+
47
+ t.test("3) 发布定时任务(publish,写回 config.id)", async () => {
41
48
  await runCc(["publish", "timer", timerName]);
42
49
  const configAfterPublish = JSON.parse(fs.readFileSync(configPath, "utf8"));
43
50
  publishedId = configAfterPublish.id || null;
44
51
  assert.ok(publishedId, "publish 后应写入 config.id");
45
52
  });
46
53
 
47
- t.test("3) 拉取定时任务(pull:覆盖 SOURCE 区域)", async () => {
54
+ t.test("4) 拉取定时任务(pull:覆盖 SOURCE 区域)", async () => {
48
55
  const localJava = fs.readFileSync(javaPath, "utf8");
49
56
  const modifiedJava = localJava.replace(
50
57
  /\/\/ @SOURCE_CONTENT_START[\s\S]*?\/\/ @SOURCE_CONTENT_END/,
@@ -57,12 +64,12 @@ test("定时任务管理流程:创建→发布→拉取→线上详情→列
57
64
  assert.ok(!javaAfterPull.includes("LOCAL_ONLY"), "pull 后应使用远端源码替换本地标记内容");
58
65
  });
59
66
 
60
- t.test("4) 查询线上定时任务详情(detail:仅使用 id)", async () => {
67
+ t.test("5) 查询线上定时任务详情(detail:仅使用 id)", async () => {
61
68
  assert.ok(publishedId, "发布后应有 publishedId");
62
69
  await assert.doesNotReject(() => runCc(["detail", "timer", "", publishedId]));
63
70
  });
64
71
 
65
- t.test("5) get 获取线上定时任务列表(取前2个 id)", async () => {
72
+ t.test("6) get 获取线上定时任务列表(取前2个 id)", async () => {
66
73
  const listQuery = encodeURI(
67
74
  JSON.stringify({
68
75
  shownum: "2000",
@@ -80,7 +87,7 @@ test("定时任务管理流程:创建→发布→拉取→线上详情→列
80
87
  assert.ok(topIds.length >= 1, "线上定时任务列表至少应包含 1 个 id");
81
88
  });
82
89
 
83
- t.test("6) 批量拉取前2个定时任务(pullList)", async () => {
90
+ t.test("7) 批量拉取前2个定时任务(pullList)", async () => {
84
91
  assert.ok(topIds.length >= 1, "pullList 需要至少 1 个线上定时任务 id");
85
92
  const beforeCount = fs.existsSync(scheduleRoot)
86
93
  ? fs.readdirSync(scheduleRoot).filter((n) => fs.statSync(path.join(scheduleRoot, n)).isDirectory()).length
@@ -96,7 +103,13 @@ test("定时任务管理流程:创建→发布→拉取→线上详情→列
96
103
  assert.ok(afterCount >= beforeCount, "pullList 之后 schedule 目录应存在/可用");
97
104
  });
98
105
 
99
- t.test("7) 清空 schedule 文件夹", async () => {
106
+ t.test("8) 删除当前创建定时类(delete timer)", async () => {
107
+ const { stdout, stderr } = await runCc(["delete", "timer", timerName, repoRoot]);
108
+ const out = `${stdout}\n${stderr}`.trim();
109
+ assert.match(out, /Success|成功/i, "delete timer 应输出成功信息");
110
+ });
111
+
112
+ t.test("9) 清空 schedule 文件夹", async () => {
100
113
  if (fs.existsSync(scheduleRoot)) {
101
114
  fs.rmSync(scheduleRoot, { recursive: true, force: true });
102
115
  }
@@ -18,7 +18,7 @@ async function runCc(args) {
18
18
  return execAsync(cmd, { cwd: repoRoot });
19
19
  }
20
20
 
21
- test("触发器管理流程:获取对象→创建→doc→发布→拉取→线上详情→列表→批量拉取前2个→清空 triggers 文件夹", async (t) => {
21
+ test("触发器管理流程:获取对象→创建→doc→发布→拉取→线上详情→列表→批量拉取→delete→清空 triggers 文件夹", async (t) => {
22
22
  let schemetableName = "Account";
23
23
  let targetObjectId = null;
24
24
  let apiname = null;
@@ -65,9 +65,11 @@ test("触发器管理流程:获取对象→创建→doc→发布→拉取→
65
65
  assert.equal(config.triggerTime, triggerTime);
66
66
  });
67
67
 
68
- t.test("3) 获取 doc(triggers overview)", async () => {
69
- const { stdout } = await runCc(["doc", "triggers", "overview"]);
70
- assert.match(stdout, /触发器|CCTrigger|编辑指南/i);
68
+ t.test("3) 获取 doc(triggers introduction / devguide)", async () => {
69
+ const intro = await runCc(["doc", "triggers", "introduction"]);
70
+ assert.match(intro.stdout, /触发器/);
71
+ const dev = await runCc(["doc", "triggers", "devguide"]);
72
+ assert.match(dev.stdout, /触发器/);
71
73
  });
72
74
 
73
75
  t.test("4) 发布触发器(publish,写回 config.id)", async () => {
@@ -135,7 +137,13 @@ test("触发器管理流程:获取对象→创建→doc→发布→拉取→
135
137
  assert.ok(afterCount >= beforeCount, "pullList 之后 triggers 目录应存在/可用");
136
138
  });
137
139
 
138
- t.test("9) 清空 triggers 文件夹", async () => {
140
+ t.test("9) 删除当前创建触发器(delete triggers", async () => {
141
+ const { stdout, stderr } = await runCc(["delete", "triggers", namePath, repoRoot]);
142
+ const out = `${stdout}\n${stderr}`.trim();
143
+ assert.match(out, /Success|成功/i, "delete triggers 应输出成功信息");
144
+ });
145
+
146
+ t.test("10) 清空 triggers 文件夹", async () => {
139
147
  if (fs.existsSync(triggersRoot)) {
140
148
  fs.rmSync(triggersRoot, { recursive: true, force: true });
141
149
  }
@@ -0,0 +1 @@
1
+ {"deletedFieldCount":0,"obj":{"schemetableName":"aa_setting_1774536485","iscustom":"1","hierarchies":true,"prefix":"aa_setting_1774536485","datatableName":"tp_cs_aa_setting_1774536485","dataType":"L","createdate":1774507700000,"remark":"","label":"aa1","accessable":"2","createbyid":"0052017BE8702F1PIi4j","tableType":"4","isDeleted":"0","id":"2026E99E6A88A6CaCVk0","snapshotVersion":-9223372036853139000,"lastmodifybyid":"0052017BE8702F1PIi4j","lastmodifydate":1774507927000,"persistenceState":4},"cusFields":[{"watermarkstatus":null,"isDeleted":"0","is_deleted":"0","casesensitive":null,"datafieldRef":null,"datafield_ref":null,"aggconditiondis":null,"relatedFields":null,"related_fields":null,"fieldState":"enable","field_state":"enable","visibleLines":null,"visible_lines":null,"aggcondition":null,"summaryfieldtype":null,"masterFormulaCode":null,"master_formula_code":null,"lookupWindowText":null,"lookup_window_text":null,"requires":null,"watermarkfield":null,"id":"ffe20262DFB3F12TFAlU","schemetableName":null,"schemetable_name":null,"lastmodifydate":1774508412000,"decimalPlaces":null,"decimal_places":null,"maskcharacter":null,"encrypttype":null,"expressionType":null,"expression_type":null,"isonly":null,"iscustom":"1","createbyid":"0052017BE8702F1PIi4j","apiname":"aa1_text_1774536916","helps":null,"createdate":1774508123000,"isTracked":null,"is_tracked":null,"schemefieldLength":"255","schemefield_length":"255","displayThousands":null,"display_thousands":null,"filterType":null,"filter_type":null,"ischeckrepeat":null,"isenableFilter":null,"isenable_filter":null,"iscover":null,"lookupObjDefaultField":null,"lookup_obj_default_field":null,"parentId":null,"parent_id":null,"iscustompicklist":null,"name":"鏂囨湰","filterCriteria":null,"filter_criteria":null,"masktype":null,"schemefieldName":"aa1_text_1774536916","schemefield_name":"aa1_text_1774536916","defaultValue":null,"default_value":null,"errorMessage":null,"error_message":null,"existenceSubfield":null,"existence_subfield":null,"hasFilter":null,"has_filter":null,"isusing":null,"renderstyle":null,"displayType":null,"display_type":null,"isrepeat":null,"managed":null,"summarizedObj":null,"summarized_obj":null,"aggregateField":null,"aggregate_field":null,"filterLogic":null,"filter_logic":null,"placeholder":null,"deletedDate":null,"deleted_date":null,"childrelationName":null,"childrelation_name":null,"remark":null,"labelName":"鏂囨湰","label_name":"鏂囨湰","lastmodifybyid":"0052017BE8702F1PIi4j","lookupObj":null,"lookup_obj":null,"schemefieldType":"S","schemefield_type":"S","schemetableId":"2026E99E6A88A6CaCVk0","schemetable_id":"2026E99E6A88A6CaCVk0","showalloptions":null,"edittype":null,"controlfieldlabel":null,"executeExpression":null,"execute_expression":null,"expression":null,"isaggfilter":null},{"watermarkstatus":null,"isDeleted":"0","is_deleted":"0","casesensitive":null,"datafieldRef":"aa1_url_1774536916","datafield_ref":"aa1_url_1774536916","aggconditiondis":null,"relatedFields":null,"related_fields":null,"fieldState":"enable","field_state":"enable","visibleLines":null,"visible_lines":null,"aggcondition":null,"summaryfieldtype":null,"masterFormulaCode":null,"master_formula_code":null,"lookupWindowText":null,"lookup_window_text":null,"requires":null,"watermarkfield":null,"id":"ffe202640673301CPXYu","schemetableName":null,"schemetable_name":null,"lastmodifydate":1774508118000,"decimalPlaces":null,"decimal_places":null,"maskcharacter":null,"encrypttype":null,"expressionType":null,"expression_type":null,"isonly":null,"iscustom":"1","createbyid":"0052017BE8702F1PIi4j","apiname":"aa1_url_1774536916","helps":null,"createdate":1774508118000,"isTracked":null,"is_tracked":null,"schemefieldLength":"255","schemefield_length":"255","displayThousands":null,"display_thousands":null,"filterType":null,"filter_type":null,"ischeckrepeat":null,"isenableFilter":null,"isenable_filter":null,"iscover":null,"lookupObjDefaultField":null,"lookup_obj_default_field":null,"parentId":null,"parent_id":null,"iscustompicklist":null,"name":"aa1_url","filterCriteria":null,"filter_criteria":null,"masktype":null,"schemefieldName":"aa1_url_1774536916","schemefield_name":"aa1_url_1774536916","defaultValue":null,"default_value":null,"errorMessage":null,"error_message":null,"existenceSubfield":null,"existence_subfield":null,"hasFilter":null,"has_filter":null,"isusing":null,"renderstyle":null,"displayType":null,"display_type":null,"isrepeat":null,"managed":null,"summarizedObj":null,"summarized_obj":null,"aggregateField":null,"aggregate_field":null,"filterLogic":null,"filter_logic":null,"placeholder":null,"deletedDate":null,"deleted_date":null,"childrelationName":null,"childrelation_name":null,"remark":null,"labelName":"aa1_url","label_name":"aa1_url","lastmodifybyid":"0052017BE8702F1PIi4j","lookupObj":null,"lookup_obj":null,"schemefieldType":"U","schemefield_type":"U","schemetableId":"2026E99E6A88A6CaCVk0","schemetable_id":"2026E99E6A88A6CaCVk0","showalloptions":null,"edittype":"_blank","controlfieldlabel":null,"executeExpression":null,"execute_expression":null,"expression":null,"isaggfilter":null}]}