@aigne/doc-smith 0.8.12-beta.8 → 0.8.12

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 (264) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/agents/publish/index.yaml +4 -0
  3. package/agents/publish/publish-docs.mjs +77 -5
  4. package/agents/publish/translate-meta.mjs +103 -0
  5. package/agents/update/generate-document.yaml +30 -28
  6. package/agents/update/update-document-detail.yaml +3 -1
  7. package/agents/utils/update-branding.mjs +69 -0
  8. package/package.json +16 -2
  9. package/prompts/common/document/role-and-personality.md +3 -1
  10. package/prompts/detail/d2-diagram/guide.md +7 -1
  11. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  12. package/prompts/detail/generate/system-prompt.md +6 -7
  13. package/prompts/detail/generate/user-prompt.md +12 -3
  14. package/prompts/detail/update/user-prompt.md +0 -2
  15. package/prompts/structure/update/user-prompt.md +0 -4
  16. package/utils/file-utils.mjs +69 -24
  17. package/utils/markdown-checker.mjs +0 -20
  18. package/utils/request.mjs +7 -0
  19. package/utils/upload-files.mjs +231 -0
  20. package/utils/utils.mjs +11 -1
  21. package/.aigne/doc-smith/config.yaml +0 -77
  22. package/.aigne/doc-smith/history.yaml +0 -37
  23. package/.aigne/doc-smith/media-description.yaml +0 -91
  24. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  25. package/.aigne/doc-smith/preferences.yml +0 -97
  26. package/.aigne/doc-smith/upload-cache.yaml +0 -1830
  27. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  28. package/.github/workflows/ci.yml +0 -54
  29. package/.github/workflows/create-release-pr.yaml +0 -21
  30. package/.github/workflows/publish-docs.yml +0 -65
  31. package/.github/workflows/release.yml +0 -49
  32. package/.github/workflows/reviewer.yml +0 -54
  33. package/.release-please-manifest.json +0 -3
  34. package/RELEASE.md +0 -9
  35. package/assets/screenshots/doc-complete-setup.png +0 -0
  36. package/assets/screenshots/doc-generate-docs.png +0 -0
  37. package/assets/screenshots/doc-generate.png +0 -0
  38. package/assets/screenshots/doc-generated-successfully.png +0 -0
  39. package/assets/screenshots/doc-publish.png +0 -0
  40. package/assets/screenshots/doc-regenerate.png +0 -0
  41. package/assets/screenshots/doc-translate-langs.png +0 -0
  42. package/assets/screenshots/doc-translate.png +0 -0
  43. package/assets/screenshots/doc-update.png +0 -0
  44. package/biome.json +0 -73
  45. package/codecov.yml +0 -15
  46. package/docs/_sidebar.md +0 -15
  47. package/docs/configuration-initial-setup.ja.md +0 -179
  48. package/docs/configuration-initial-setup.md +0 -198
  49. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  50. package/docs/configuration-initial-setup.zh.md +0 -179
  51. package/docs/configuration-managing-preferences.ja.md +0 -100
  52. package/docs/configuration-managing-preferences.md +0 -100
  53. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  54. package/docs/configuration-managing-preferences.zh.md +0 -100
  55. package/docs/configuration.ja.md +0 -69
  56. package/docs/configuration.md +0 -69
  57. package/docs/configuration.zh-TW.md +0 -69
  58. package/docs/configuration.zh.md +0 -69
  59. package/docs/getting-started.ja.md +0 -107
  60. package/docs/getting-started.md +0 -107
  61. package/docs/getting-started.zh-TW.md +0 -107
  62. package/docs/getting-started.zh.md +0 -107
  63. package/docs/guides-cleaning-up.ja.md +0 -51
  64. package/docs/guides-cleaning-up.md +0 -52
  65. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  66. package/docs/guides-cleaning-up.zh.md +0 -51
  67. package/docs/guides-evaluating-documents.ja.md +0 -66
  68. package/docs/guides-evaluating-documents.md +0 -107
  69. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  70. package/docs/guides-evaluating-documents.zh.md +0 -66
  71. package/docs/guides-generating-documentation.ja.md +0 -151
  72. package/docs/guides-generating-documentation.md +0 -89
  73. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  74. package/docs/guides-generating-documentation.zh.md +0 -151
  75. package/docs/guides-interactive-chat.ja.md +0 -85
  76. package/docs/guides-interactive-chat.md +0 -93
  77. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  78. package/docs/guides-interactive-chat.zh.md +0 -85
  79. package/docs/guides-managing-history.ja.md +0 -48
  80. package/docs/guides-managing-history.md +0 -53
  81. package/docs/guides-managing-history.zh-TW.md +0 -48
  82. package/docs/guides-managing-history.zh.md +0 -48
  83. package/docs/guides-publishing-your-docs.ja.md +0 -78
  84. package/docs/guides-publishing-your-docs.md +0 -83
  85. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  86. package/docs/guides-publishing-your-docs.zh.md +0 -78
  87. package/docs/guides-translating-documentation.ja.md +0 -95
  88. package/docs/guides-translating-documentation.md +0 -100
  89. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  90. package/docs/guides-translating-documentation.zh.md +0 -95
  91. package/docs/guides-updating-documentation.ja.md +0 -77
  92. package/docs/guides-updating-documentation.md +0 -79
  93. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  94. package/docs/guides-updating-documentation.zh.md +0 -77
  95. package/docs/guides.ja.md +0 -32
  96. package/docs/guides.md +0 -32
  97. package/docs/guides.zh-TW.md +0 -32
  98. package/docs/guides.zh.md +0 -32
  99. package/docs/overview.ja.md +0 -61
  100. package/docs/overview.md +0 -61
  101. package/docs/overview.zh-TW.md +0 -61
  102. package/docs/overview.zh.md +0 -61
  103. package/docs/release-notes.ja.md +0 -255
  104. package/docs/release-notes.md +0 -288
  105. package/docs/release-notes.zh-TW.md +0 -255
  106. package/docs/release-notes.zh.md +0 -255
  107. package/prompts/common/afs/afs-tools-usage.md +0 -5
  108. package/prompts/common/afs/use-afs-instruction.md +0 -1
  109. package/release-please-config.json +0 -14
  110. package/tests/agents/chat/chat.test.mjs +0 -46
  111. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  112. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  113. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  114. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  115. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  116. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  117. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  118. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  119. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  120. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  121. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  122. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  123. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  124. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  125. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  126. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  127. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  128. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  129. package/tests/agents/history/view.test.mjs +0 -97
  130. package/tests/agents/init/init.test.mjs +0 -1657
  131. package/tests/agents/prefs/prefs.test.mjs +0 -431
  132. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  133. package/tests/agents/translate/choose-language.test.mjs +0 -311
  134. package/tests/agents/translate/translate-document.test.mjs +0 -51
  135. package/tests/agents/update/check-document.test.mjs +0 -463
  136. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  137. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  138. package/tests/agents/update/generate-document.test.mjs +0 -51
  139. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  140. package/tests/agents/update/user-review-document.test.mjs +0 -582
  141. package/tests/agents/utils/action-success.test.mjs +0 -54
  142. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  143. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  144. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  145. package/tests/agents/utils/exit.test.mjs +0 -70
  146. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  147. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  148. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  149. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  150. package/tests/agents/utils/fs.test.mjs +0 -267
  151. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  152. package/tests/agents/utils/save-docs.test.mjs +0 -109
  153. package/tests/agents/utils/save-output.test.mjs +0 -315
  154. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  155. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  156. package/tests/utils/auth-utils.test.mjs +0 -596
  157. package/tests/utils/blocklet.test.mjs +0 -336
  158. package/tests/utils/conflict-detector.test.mjs +0 -355
  159. package/tests/utils/constants.test.mjs +0 -295
  160. package/tests/utils/d2-utils.test.mjs +0 -437
  161. package/tests/utils/deploy.test.mjs +0 -399
  162. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  163. package/tests/utils/file-utils.test.mjs +0 -521
  164. package/tests/utils/history-utils.test.mjs +0 -206
  165. package/tests/utils/kroki-utils.test.mjs +0 -646
  166. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  167. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  168. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  169. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  170. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  171. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  172. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  173. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  174. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  175. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  176. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  177. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  178. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  179. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  180. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  181. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  182. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  183. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  184. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  185. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  186. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  187. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  188. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  189. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  190. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  191. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  192. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  193. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  194. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  195. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  196. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  197. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  198. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  199. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  200. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  201. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  202. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  203. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  204. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  205. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  206. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  207. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  208. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  209. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  210. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  211. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  212. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  213. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  214. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  215. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  216. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  217. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  218. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  219. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  220. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  221. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  222. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  223. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  224. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  225. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  226. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  227. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  228. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  229. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  230. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  231. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  232. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  233. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  234. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  235. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  236. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  237. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  238. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  239. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  240. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  241. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  242. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  243. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  244. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  245. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  246. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  247. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  248. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  249. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  250. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  251. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  252. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  253. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  254. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  255. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  256. package/tests/utils/linter/index.test.mjs +0 -440
  257. package/tests/utils/linter/scan-results.mjs +0 -42
  258. package/tests/utils/load-config.test.mjs +0 -141
  259. package/tests/utils/markdown/index.test.mjs +0 -478
  260. package/tests/utils/mermaid-validator.test.mjs +0 -541
  261. package/tests/utils/mock-chat-model.mjs +0 -12
  262. package/tests/utils/preferences-utils.test.mjs +0 -465
  263. package/tests/utils/save-value-to-config.test.mjs +0 -483
  264. package/tests/utils/utils.test.mjs +0 -941
@@ -1,463 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
2
- import * as fsPromises from "node:fs/promises";
3
- import * as aigneCore from "@aigne/core";
4
- import checkDocument from "../../../agents/update/check-document.mjs";
5
- import * as checkDetailResultModule from "../../../agents/utils/check-detail-result.mjs";
6
-
7
- describe("check-document", () => {
8
- let mockOptions;
9
-
10
- // Spies for external dependencies
11
- let teamAgentFromSpy;
12
-
13
- // Spies for internal utils and fs operations
14
- let checkDetailResultSpy;
15
- let consoleSpy;
16
- let accessSpy;
17
- let readFileSpy;
18
-
19
- beforeEach(() => {
20
- // Set up spy for external dependencies
21
- teamAgentFromSpy = spyOn(aigneCore.TeamAgent, "from").mockReturnValue({ mockTeamAgent: true });
22
-
23
- mockOptions = {
24
- context: {
25
- agents: {
26
- handleDocumentUpdate: { mockAgent: true },
27
- },
28
- invoke: mock(async () => ({ mockResult: true })),
29
- },
30
- };
31
-
32
- // Set up spies for internal utils
33
- checkDetailResultSpy = spyOn(checkDetailResultModule, "default").mockResolvedValue({
34
- isApproved: true,
35
- detailFeedback: "",
36
- });
37
- consoleSpy = spyOn(console, "log").mockImplementation(() => {});
38
-
39
- // Use spyOn for fs operations instead of module mocking
40
- accessSpy = spyOn(fsPromises, "access").mockResolvedValue(undefined);
41
- readFileSpy = spyOn(fsPromises, "readFile").mockResolvedValue("# Test Content\n\nSome content");
42
-
43
- // Clear context mock call history
44
- mockOptions.context.invoke.mockClear();
45
- });
46
-
47
- afterEach(() => {
48
- // Restore all spies
49
- teamAgentFromSpy?.mockRestore();
50
- checkDetailResultSpy?.mockRestore();
51
- consoleSpy?.mockRestore();
52
- accessSpy?.mockRestore();
53
- readFileSpy?.mockRestore();
54
- });
55
-
56
- // FILE EXISTENCE TESTS
57
- test("should return early when file exists and no changes detected", async () => {
58
- // File exists, no changes
59
- accessSpy.mockResolvedValue();
60
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
61
-
62
- const result = await checkDocument(
63
- {
64
- path: "/getting-started",
65
- docsDir: "./docs",
66
- sourceIds: ["file1.js"],
67
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
68
- documentStructure: [{ path: "/getting-started" }],
69
- modifiedFiles: [],
70
- },
71
- mockOptions,
72
- );
73
-
74
- expect(result.detailGenerated).toBe(true);
75
- expect(mockOptions.context.invoke).not.toHaveBeenCalled();
76
- });
77
-
78
- test("should generate when file does not exist", async () => {
79
- // File doesn't exist
80
- accessSpy.mockRejectedValue(new Error("File not found"));
81
-
82
- const result = await checkDocument(
83
- {
84
- path: "/getting-started",
85
- docsDir: "./docs",
86
- sourceIds: ["file1.js"],
87
- },
88
- mockOptions,
89
- );
90
-
91
- expect(mockOptions.context.invoke).toHaveBeenCalled();
92
- expect(result.path).toBe("/getting-started");
93
- });
94
-
95
- // SOURCE IDS CHANGE TESTS
96
- test("should regenerate when sourceIds have changed", async () => {
97
- accessSpy.mockResolvedValue();
98
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
99
-
100
- await checkDocument(
101
- {
102
- path: "/getting-started",
103
- docsDir: "./docs",
104
- sourceIds: ["file1.js", "file2.js"], // Different from original
105
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
106
- documentStructure: [{ path: "/getting-started" }],
107
- },
108
- mockOptions,
109
- );
110
-
111
- expect(mockOptions.context.invoke).toHaveBeenCalled();
112
- });
113
-
114
- test("should regenerate when sourceIds count changed", async () => {
115
- accessSpy.mockResolvedValue();
116
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
117
-
118
- await checkDocument(
119
- {
120
- path: "/getting-started",
121
- docsDir: "./docs",
122
- sourceIds: ["file1.js", "file2.js", "file3.js"], // More files
123
- originalDocumentStructure: [
124
- { path: "/getting-started", sourceIds: ["file1.js", "file2.js"] },
125
- ],
126
- documentStructure: [{ path: "/getting-started" }],
127
- },
128
- mockOptions,
129
- );
130
-
131
- expect(mockOptions.context.invoke).toHaveBeenCalled();
132
- });
133
-
134
- test("should not regenerate when sourceIds are same (different order)", async () => {
135
- accessSpy.mockResolvedValue();
136
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
137
-
138
- const result = await checkDocument(
139
- {
140
- path: "/getting-started",
141
- docsDir: "./docs",
142
- sourceIds: ["file2.js", "file1.js"], // Same files, different order
143
- originalDocumentStructure: [
144
- { path: "/getting-started", sourceIds: ["file1.js", "file2.js"] },
145
- ],
146
- documentStructure: [{ path: "/getting-started" }],
147
- modifiedFiles: [],
148
- },
149
- mockOptions,
150
- );
151
-
152
- expect(result.detailGenerated).toBe(true);
153
- expect(mockOptions.context.invoke).not.toHaveBeenCalled();
154
- });
155
-
156
- test("should handle missing originalDocumentStructure gracefully", async () => {
157
- accessSpy.mockResolvedValue();
158
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
159
-
160
- const result = await checkDocument(
161
- {
162
- path: "/getting-started",
163
- docsDir: "./docs",
164
- sourceIds: ["file1.js"],
165
- originalDocumentStructure: null,
166
- documentStructure: [{ path: "/getting-started" }],
167
- modifiedFiles: [],
168
- },
169
- mockOptions,
170
- );
171
-
172
- expect(result.detailGenerated).toBe(true);
173
- expect(mockOptions.context.invoke).not.toHaveBeenCalled();
174
- });
175
-
176
- test("should handle missing original node in documentation structure", async () => {
177
- accessSpy.mockResolvedValue();
178
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
179
-
180
- const result = await checkDocument(
181
- {
182
- path: "/getting-started",
183
- docsDir: "./docs",
184
- sourceIds: ["file1.js"],
185
- originalDocumentStructure: [{ path: "/different-path", sourceIds: ["file1.js"] }],
186
- documentStructure: [{ path: "/getting-started" }],
187
- modifiedFiles: [],
188
- },
189
- mockOptions,
190
- );
191
-
192
- expect(result.detailGenerated).toBe(true);
193
- expect(mockOptions.context.invoke).not.toHaveBeenCalled();
194
- });
195
-
196
- // SOURCE FILES CHANGE TESTS - These tests are now obsolete as modifiedFiles checking has been removed
197
- // The check-document function now only checks for sourceIds changes and content validation
198
-
199
- // CONTENT VALIDATION TESTS
200
- test("should regenerate when content validation fails", async () => {
201
- accessSpy.mockResolvedValue();
202
- readFileSpy.mockResolvedValue("# Test Content");
203
- checkDetailResultSpy.mockResolvedValue({
204
- isApproved: false,
205
- detailFeedback: "Content needs improvement",
206
- });
207
-
208
- await checkDocument(
209
- {
210
- path: "/getting-started",
211
- docsDir: "./docs",
212
- sourceIds: ["file1.js"],
213
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
214
- documentStructure: [{ path: "/getting-started" }],
215
- modifiedFiles: [],
216
- },
217
- mockOptions,
218
- );
219
-
220
- expect(checkDetailResultSpy).toHaveBeenCalledWith({
221
- documentStructure: [{ path: "/getting-started" }],
222
- reviewContent: "# Test Content",
223
- docsDir: "./docs",
224
- });
225
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
226
- { mockTeamAgent: true },
227
- expect.objectContaining({
228
- detailFeedback: "Content needs improvement",
229
- }),
230
- );
231
- });
232
-
233
- test("should not validate content when file doesn't exist", async () => {
234
- accessSpy.mockRejectedValue(new Error("File not found"));
235
-
236
- await checkDocument(
237
- {
238
- path: "/getting-started",
239
- docsDir: "./docs",
240
- documentStructure: [{ path: "/getting-started" }],
241
- },
242
- mockOptions,
243
- );
244
-
245
- expect(checkDetailResultSpy).not.toHaveBeenCalled();
246
- });
247
-
248
- test("should not validate content when no documentStructure provided", async () => {
249
- accessSpy.mockResolvedValue();
250
- readFileSpy.mockResolvedValue("# Test Content");
251
-
252
- const result = await checkDocument(
253
- {
254
- path: "/getting-started",
255
- docsDir: "./docs",
256
- sourceIds: ["file1.js"],
257
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
258
- documentStructure: null,
259
- modifiedFiles: [],
260
- },
261
- mockOptions,
262
- );
263
-
264
- expect(checkDetailResultSpy).not.toHaveBeenCalled();
265
- expect(result.detailGenerated).toBe(true);
266
- });
267
-
268
- // FORCE REGENERATE TESTS
269
- test("should regenerate when forceRegenerate is true", async () => {
270
- accessSpy.mockResolvedValue();
271
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
272
-
273
- await checkDocument(
274
- {
275
- path: "/getting-started",
276
- docsDir: "./docs",
277
- sourceIds: ["file1.js"],
278
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
279
- documentStructure: [{ path: "/getting-started" }],
280
- modifiedFiles: [],
281
- forceRegenerate: true,
282
- },
283
- mockOptions,
284
- );
285
-
286
- expect(mockOptions.context.invoke).toHaveBeenCalled();
287
- });
288
-
289
- // TEAM AGENT TESTS
290
- test("should create team agent with correct configuration", async () => {
291
- accessSpy.mockRejectedValue(new Error("File not found"));
292
-
293
- await checkDocument(
294
- {
295
- path: "/getting-started",
296
- docsDir: "./docs",
297
- },
298
- mockOptions,
299
- );
300
-
301
- expect(teamAgentFromSpy).toHaveBeenCalledWith({
302
- name: "generateDocument",
303
- skills: [{ mockAgent: true }],
304
- });
305
- });
306
-
307
- test("should invoke team agent with correct parameters", async () => {
308
- accessSpy.mockRejectedValue(new Error("File not found"));
309
-
310
- await checkDocument(
311
- {
312
- path: "/getting-started",
313
- docsDir: "./docs",
314
- sourceIds: ["file1.js"],
315
- originalDocumentStructure: [{ path: "/getting-started" }],
316
- documentStructure: [{ path: "/getting-started" }],
317
- customParam: "test",
318
- },
319
- mockOptions,
320
- );
321
-
322
- expect(mockOptions.context.invoke).toHaveBeenCalledWith(
323
- { mockTeamAgent: true },
324
- expect.objectContaining({
325
- path: "/getting-started",
326
- docsDir: "./docs",
327
- sourceIds: ["file1.js"],
328
- originalDocumentStructure: [{ path: "/getting-started" }],
329
- documentStructure: [{ path: "/getting-started" }],
330
- customParam: "test",
331
- detailFeedback: "",
332
- }),
333
- );
334
- });
335
-
336
- // PATH PROCESSING TESTS
337
- test("should handle root path correctly", async () => {
338
- accessSpy.mockRejectedValue(new Error("File not found"));
339
-
340
- await checkDocument(
341
- {
342
- path: "/",
343
- docsDir: "./docs",
344
- },
345
- mockOptions,
346
- );
347
-
348
- // Root path "/" -> flatName "" -> fileFullName ".md"
349
- expect(accessSpy).toHaveBeenCalledWith(expect.stringMatching(/\.md$/));
350
- });
351
-
352
- test("should handle nested path correctly", async () => {
353
- accessSpy.mockRejectedValue(new Error("File not found"));
354
-
355
- await checkDocument(
356
- {
357
- path: "/api/users/create",
358
- docsDir: "./docs",
359
- locale: "en",
360
- },
361
- mockOptions,
362
- );
363
-
364
- // "/api/users/create" -> flatName "api-users-create" -> fileFullName "api-users-create.md"
365
- // The access function is called with a full path that includes docsDir
366
- expect(accessSpy).toHaveBeenCalled();
367
- const callArg = accessSpy.mock.calls[0][0];
368
- expect(callArg).toMatch(/api-users-create\.md$/);
369
- });
370
-
371
- // RESULT STRUCTURE TESTS
372
- test("should return correct result structure when regenerating", async () => {
373
- accessSpy.mockRejectedValue(new Error("File not found"));
374
- mockOptions.context.invoke.mockResolvedValue({ generatedContent: "test" });
375
-
376
- const result = await checkDocument(
377
- {
378
- path: "/getting-started",
379
- docsDir: "./docs",
380
- customParam: "test",
381
- },
382
- mockOptions,
383
- );
384
-
385
- expect(result).toEqual({
386
- path: "/getting-started",
387
- docsDir: "./docs",
388
- customParam: "test",
389
- result: { generatedContent: "test" },
390
- });
391
- });
392
-
393
- test("should return correct result structure when not regenerating", async () => {
394
- accessSpy.mockResolvedValue();
395
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
396
-
397
- const result = await checkDocument(
398
- {
399
- path: "/getting-started",
400
- docsDir: "./docs",
401
- sourceIds: ["file1.js"],
402
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
403
- documentStructure: [{ path: "/getting-started" }],
404
- modifiedFiles: [],
405
- customParam: "test",
406
- },
407
- mockOptions,
408
- );
409
-
410
- expect(result).toEqual({
411
- path: "/getting-started",
412
- docsDir: "./docs",
413
- customParam: "test",
414
- detailGenerated: true,
415
- });
416
- });
417
-
418
- // EDGE CASES
419
- test("should handle file read errors gracefully", async () => {
420
- accessSpy.mockResolvedValue();
421
- readFileSpy.mockRejectedValue(new Error("Read error"));
422
-
423
- // When file read fails, content validation is skipped, and since file exists
424
- // but can't be read properly, no early return occurs, so regeneration happens
425
- const result = await checkDocument(
426
- {
427
- path: "/getting-started",
428
- docsDir: "./docs",
429
- sourceIds: ["file1.js"],
430
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: ["file1.js"] }],
431
- documentStructure: [{ path: "/getting-started" }],
432
- modifiedFiles: [],
433
- },
434
- mockOptions,
435
- );
436
-
437
- // When file read fails, no content validation happens, and since no early return
438
- // condition is met, the function should proceed to regeneration
439
- expect(result.result).toBeDefined();
440
- expect(mockOptions.context.invoke).toHaveBeenCalled();
441
- expect(checkDetailResultSpy).not.toHaveBeenCalled();
442
- });
443
-
444
- test("should handle empty sourceIds arrays", async () => {
445
- accessSpy.mockResolvedValue();
446
- checkDetailResultSpy.mockResolvedValue({ isApproved: true });
447
-
448
- const result = await checkDocument(
449
- {
450
- path: "/getting-started",
451
- docsDir: "./docs",
452
- sourceIds: [],
453
- originalDocumentStructure: [{ path: "/getting-started", sourceIds: [] }],
454
- documentStructure: [{ path: "/getting-started" }],
455
- modifiedFiles: [],
456
- },
457
- mockOptions,
458
- );
459
-
460
- expect(result.detailGenerated).toBe(true);
461
- expect(mockOptions.context.invoke).not.toHaveBeenCalled();
462
- });
463
- });