@aigne/doc-smith 0.8.12-beta.7 → 0.8.12-beta.9

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 (284) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/agents/clear/choose-contents.mjs +14 -1
  3. package/agents/clear/clear-media-description.mjs +129 -0
  4. package/agents/clear/index.yaml +3 -1
  5. package/agents/evaluate/code-snippet.mjs +28 -24
  6. package/agents/evaluate/document-structure.yaml +0 -4
  7. package/agents/evaluate/document.yaml +1 -5
  8. package/agents/generate/index.yaml +1 -0
  9. package/agents/init/index.mjs +10 -0
  10. package/agents/media/batch-generate-media-description.yaml +44 -0
  11. package/agents/media/generate-media-description.yaml +47 -0
  12. package/agents/media/load-media-description.mjs +238 -0
  13. package/agents/publish/index.yaml +4 -0
  14. package/agents/publish/publish-docs.mjs +77 -5
  15. package/agents/publish/translate-meta.mjs +103 -0
  16. package/agents/update/generate-document.yaml +30 -28
  17. package/agents/update/index.yaml +1 -0
  18. package/agents/update/update-document-detail.yaml +3 -1
  19. package/agents/utils/load-sources.mjs +103 -53
  20. package/agents/utils/update-branding.mjs +69 -0
  21. package/aigne.yaml +6 -0
  22. package/assets/report-template/report.html +34 -34
  23. package/package.json +17 -2
  24. package/prompts/common/document/role-and-personality.md +3 -1
  25. package/prompts/detail/d2-diagram/guide.md +7 -1
  26. package/prompts/detail/d2-diagram/user-prompt.md +3 -0
  27. package/prompts/detail/generate/system-prompt.md +6 -7
  28. package/prompts/detail/generate/user-prompt.md +12 -3
  29. package/prompts/detail/update/user-prompt.md +0 -2
  30. package/prompts/evaluate/document-structure.md +6 -7
  31. package/prompts/evaluate/document.md +16 -25
  32. package/prompts/media/media-description/system-prompt.md +35 -0
  33. package/prompts/media/media-description/user-prompt.md +8 -0
  34. package/prompts/structure/update/user-prompt.md +0 -4
  35. package/utils/constants/index.mjs +0 -107
  36. package/utils/file-utils.mjs +86 -0
  37. package/utils/markdown-checker.mjs +0 -20
  38. package/utils/request.mjs +7 -0
  39. package/utils/upload-files.mjs +231 -0
  40. package/utils/utils.mjs +11 -1
  41. package/.aigne/doc-smith/config.yaml +0 -77
  42. package/.aigne/doc-smith/history.yaml +0 -37
  43. package/.aigne/doc-smith/output/structure-plan.json +0 -162
  44. package/.aigne/doc-smith/preferences.yml +0 -97
  45. package/.aigne/doc-smith/upload-cache.yaml +0 -1893
  46. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  47. package/.github/workflows/ci.yml +0 -54
  48. package/.github/workflows/create-release-pr.yaml +0 -21
  49. package/.github/workflows/publish-docs.yml +0 -65
  50. package/.github/workflows/release.yml +0 -49
  51. package/.github/workflows/reviewer.yml +0 -54
  52. package/.release-please-manifest.json +0 -3
  53. package/RELEASE.md +0 -9
  54. package/assets/screenshots/doc-complete-setup.png +0 -0
  55. package/assets/screenshots/doc-generate-docs.png +0 -0
  56. package/assets/screenshots/doc-generate.png +0 -0
  57. package/assets/screenshots/doc-generated-successfully.png +0 -0
  58. package/assets/screenshots/doc-publish.png +0 -0
  59. package/assets/screenshots/doc-regenerate.png +0 -0
  60. package/assets/screenshots/doc-translate-langs.png +0 -0
  61. package/assets/screenshots/doc-translate.png +0 -0
  62. package/assets/screenshots/doc-update.png +0 -0
  63. package/biome.json +0 -73
  64. package/codecov.yml +0 -15
  65. package/docs/_sidebar.md +0 -15
  66. package/docs/configuration-initial-setup.ja.md +0 -179
  67. package/docs/configuration-initial-setup.md +0 -179
  68. package/docs/configuration-initial-setup.zh-TW.md +0 -179
  69. package/docs/configuration-initial-setup.zh.md +0 -179
  70. package/docs/configuration-managing-preferences.ja.md +0 -100
  71. package/docs/configuration-managing-preferences.md +0 -100
  72. package/docs/configuration-managing-preferences.zh-TW.md +0 -100
  73. package/docs/configuration-managing-preferences.zh.md +0 -100
  74. package/docs/configuration.ja.md +0 -96
  75. package/docs/configuration.md +0 -96
  76. package/docs/configuration.zh-TW.md +0 -96
  77. package/docs/configuration.zh.md +0 -96
  78. package/docs/getting-started.ja.md +0 -88
  79. package/docs/getting-started.md +0 -88
  80. package/docs/getting-started.zh-TW.md +0 -88
  81. package/docs/getting-started.zh.md +0 -88
  82. package/docs/guides-cleaning-up.ja.md +0 -51
  83. package/docs/guides-cleaning-up.md +0 -51
  84. package/docs/guides-cleaning-up.zh-TW.md +0 -51
  85. package/docs/guides-cleaning-up.zh.md +0 -51
  86. package/docs/guides-evaluating-documents.ja.md +0 -66
  87. package/docs/guides-evaluating-documents.md +0 -66
  88. package/docs/guides-evaluating-documents.zh-TW.md +0 -66
  89. package/docs/guides-evaluating-documents.zh.md +0 -66
  90. package/docs/guides-generating-documentation.ja.md +0 -151
  91. package/docs/guides-generating-documentation.md +0 -151
  92. package/docs/guides-generating-documentation.zh-TW.md +0 -151
  93. package/docs/guides-generating-documentation.zh.md +0 -151
  94. package/docs/guides-interactive-chat.ja.md +0 -85
  95. package/docs/guides-interactive-chat.md +0 -85
  96. package/docs/guides-interactive-chat.zh-TW.md +0 -85
  97. package/docs/guides-interactive-chat.zh.md +0 -85
  98. package/docs/guides-managing-history.ja.md +0 -48
  99. package/docs/guides-managing-history.md +0 -48
  100. package/docs/guides-managing-history.zh-TW.md +0 -48
  101. package/docs/guides-managing-history.zh.md +0 -48
  102. package/docs/guides-publishing-your-docs.ja.md +0 -78
  103. package/docs/guides-publishing-your-docs.md +0 -78
  104. package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
  105. package/docs/guides-publishing-your-docs.zh.md +0 -78
  106. package/docs/guides-translating-documentation.ja.md +0 -95
  107. package/docs/guides-translating-documentation.md +0 -95
  108. package/docs/guides-translating-documentation.zh-TW.md +0 -95
  109. package/docs/guides-translating-documentation.zh.md +0 -95
  110. package/docs/guides-updating-documentation.ja.md +0 -77
  111. package/docs/guides-updating-documentation.md +0 -77
  112. package/docs/guides-updating-documentation.zh-TW.md +0 -77
  113. package/docs/guides-updating-documentation.zh.md +0 -77
  114. package/docs/guides.ja.md +0 -32
  115. package/docs/guides.md +0 -32
  116. package/docs/guides.zh-TW.md +0 -32
  117. package/docs/guides.zh.md +0 -32
  118. package/docs/overview.ja.md +0 -61
  119. package/docs/overview.md +0 -61
  120. package/docs/overview.zh-TW.md +0 -61
  121. package/docs/overview.zh.md +0 -61
  122. package/docs/release-notes.ja.md +0 -255
  123. package/docs/release-notes.md +0 -255
  124. package/docs/release-notes.zh-TW.md +0 -255
  125. package/docs/release-notes.zh.md +0 -255
  126. package/media.md +0 -19
  127. package/prompts/common/afs/afs-tools-usage.md +0 -5
  128. package/prompts/common/afs/use-afs-instruction.md +0 -1
  129. package/release-please-config.json +0 -14
  130. package/tests/agents/chat/chat.test.mjs +0 -46
  131. package/tests/agents/clear/choose-contents.test.mjs +0 -284
  132. package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
  133. package/tests/agents/clear/clear-document-config.test.mjs +0 -167
  134. package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
  135. package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
  136. package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
  137. package/tests/agents/evaluate/fixtures/api-services.md +0 -87
  138. package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
  139. package/tests/agents/evaluate/generate-report.test.mjs +0 -312
  140. package/tests/agents/generate/check-document-structure.test.mjs +0 -45
  141. package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
  142. package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
  143. package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
  144. package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
  145. package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
  146. package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
  147. package/tests/agents/generate/generate-structure.test.mjs +0 -45
  148. package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
  149. package/tests/agents/history/view.test.mjs +0 -97
  150. package/tests/agents/init/init.test.mjs +0 -1657
  151. package/tests/agents/prefs/prefs.test.mjs +0 -431
  152. package/tests/agents/publish/publish-docs.test.mjs +0 -787
  153. package/tests/agents/translate/choose-language.test.mjs +0 -311
  154. package/tests/agents/translate/translate-document.test.mjs +0 -51
  155. package/tests/agents/update/check-document.test.mjs +0 -463
  156. package/tests/agents/update/check-update-is-single.test.mjs +0 -300
  157. package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
  158. package/tests/agents/update/generate-document.test.mjs +0 -51
  159. package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
  160. package/tests/agents/update/user-review-document.test.mjs +0 -582
  161. package/tests/agents/utils/action-success.test.mjs +0 -54
  162. package/tests/agents/utils/check-detail-result.test.mjs +0 -743
  163. package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
  164. package/tests/agents/utils/choose-docs.test.mjs +0 -406
  165. package/tests/agents/utils/exit.test.mjs +0 -70
  166. package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
  167. package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
  168. package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
  169. package/tests/agents/utils/format-document-structure.test.mjs +0 -364
  170. package/tests/agents/utils/fs.test.mjs +0 -267
  171. package/tests/agents/utils/load-sources.test.mjs +0 -1470
  172. package/tests/agents/utils/save-docs.test.mjs +0 -109
  173. package/tests/agents/utils/save-output.test.mjs +0 -315
  174. package/tests/agents/utils/save-single-doc.test.mjs +0 -364
  175. package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
  176. package/tests/utils/auth-utils.test.mjs +0 -596
  177. package/tests/utils/blocklet.test.mjs +0 -336
  178. package/tests/utils/conflict-detector.test.mjs +0 -355
  179. package/tests/utils/constants.test.mjs +0 -295
  180. package/tests/utils/d2-utils.test.mjs +0 -437
  181. package/tests/utils/deploy.test.mjs +0 -399
  182. package/tests/utils/docs-finder-utils.test.mjs +0 -650
  183. package/tests/utils/file-utils.test.mjs +0 -521
  184. package/tests/utils/history-utils.test.mjs +0 -206
  185. package/tests/utils/kroki-utils.test.mjs +0 -646
  186. package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
  187. package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
  188. package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
  189. package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
  190. package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
  191. package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
  192. package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
  193. package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
  194. package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
  195. package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
  196. package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
  197. package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
  198. package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
  199. package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
  200. package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
  201. package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
  202. package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
  203. package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
  204. package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
  205. package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
  206. package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
  207. package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
  208. package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
  209. package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
  210. package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
  211. package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
  212. package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
  213. package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
  214. package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
  215. package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
  216. package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
  217. package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
  218. package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
  219. package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
  220. package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
  221. package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
  222. package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
  223. package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
  224. package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
  225. package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
  226. package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
  227. package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
  228. package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
  229. package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
  230. package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
  231. package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
  232. package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
  233. package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
  234. package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
  235. package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
  236. package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
  237. package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
  238. package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
  239. package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
  240. package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
  241. package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
  242. package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
  243. package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
  244. package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
  245. package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
  246. package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
  247. package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
  248. package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
  249. package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
  250. package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
  251. package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
  252. package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
  253. package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
  254. package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
  255. package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
  256. package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
  257. package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
  258. package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
  259. package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
  260. package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
  261. package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
  262. package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
  263. package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
  264. package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
  265. package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
  266. package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
  267. package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
  268. package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
  269. package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
  270. package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
  271. package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
  272. package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
  273. package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
  274. package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
  275. package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
  276. package/tests/utils/linter/index.test.mjs +0 -440
  277. package/tests/utils/linter/scan-results.mjs +0 -42
  278. package/tests/utils/load-config.test.mjs +0 -141
  279. package/tests/utils/markdown/index.test.mjs +0 -478
  280. package/tests/utils/mermaid-validator.test.mjs +0 -541
  281. package/tests/utils/mock-chat-model.mjs +0 -12
  282. package/tests/utils/preferences-utils.test.mjs +0 -465
  283. package/tests/utils/save-value-to-config.test.mjs +0 -483
  284. package/tests/utils/utils.test.mjs +0 -941
@@ -1,483 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
- import * as fs from "node:fs";
3
- import { existsSync } from "node:fs";
4
- import fsPromisesDefault, * as fsPromises from "node:fs/promises";
5
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
- import { dirname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
-
9
- import { DOC_SMITH_DIR } from "../../utils/constants/index.mjs";
10
- import { saveValueToConfig } from "../../utils/utils.mjs";
11
-
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
-
15
- // Test directory for isolated testing
16
- const TEST_DIR = join(__dirname, "temp-config-test");
17
- const TEST_CONFIG_DIR = join(TEST_DIR, DOC_SMITH_DIR);
18
- const TEST_CONFIG_PATH = join(TEST_CONFIG_DIR, "config.yaml");
19
-
20
- // Store original working directory
21
- let originalCwd;
22
-
23
- // Setup and teardown helpers
24
- async function setupTestDir() {
25
- // Save original working directory
26
- originalCwd = process.cwd();
27
-
28
- if (existsSync(TEST_DIR)) {
29
- await rm(TEST_DIR, { recursive: true, force: true });
30
- }
31
- await mkdir(TEST_DIR, { recursive: true });
32
-
33
- // Change to test directory for the duration of tests
34
- process.chdir(TEST_DIR);
35
- }
36
-
37
- async function teardownTestDir() {
38
- // Change back to original directory
39
- process.chdir(originalCwd);
40
-
41
- if (existsSync(TEST_DIR)) {
42
- await rm(TEST_DIR, { recursive: true, force: true });
43
- }
44
- }
45
-
46
- async function readConfigFile() {
47
- if (!existsSync(TEST_CONFIG_PATH)) {
48
- return "";
49
- }
50
- return await readFile(TEST_CONFIG_PATH, "utf8");
51
- }
52
-
53
- async function createInitialConfig(content) {
54
- await mkdir(TEST_CONFIG_DIR, { recursive: true });
55
- await writeFile(TEST_CONFIG_PATH, content, "utf8");
56
- }
57
-
58
- // Test suite
59
- describe("save-value-to-config", () => {
60
- let restoreFunctions = [];
61
-
62
- beforeEach(async () => {
63
- await setupTestDir();
64
-
65
- // Restore any existing mocks that might interfere with our file operations
66
- // This is crucial when running alongside other test files like utils.test.mjs
67
- restoreFunctions = [];
68
-
69
- // Restore fs sync mocks if they exist
70
- if (typeof fs.existsSync.mockRestore === "function") {
71
- fs.existsSync.mockRestore();
72
- restoreFunctions.push(() => spyOn(fs, "existsSync").mockReturnValue(true));
73
- }
74
- if (typeof fs.mkdirSync.mockRestore === "function") {
75
- fs.mkdirSync.mockRestore();
76
- restoreFunctions.push(() => spyOn(fs, "mkdirSync").mockImplementation(() => {}));
77
- }
78
-
79
- // Restore fs async mocks if they exist
80
- if (typeof fsPromises.writeFile.mockRestore === "function") {
81
- fsPromises.writeFile.mockRestore();
82
- restoreFunctions.push(() => spyOn(fsPromises, "writeFile").mockResolvedValue());
83
- }
84
- if (typeof fsPromises.mkdir.mockRestore === "function") {
85
- fsPromises.mkdir.mockRestore();
86
- restoreFunctions.push(() => spyOn(fsPromises, "mkdir").mockResolvedValue());
87
- }
88
- if (typeof fsPromises.readFile.mockRestore === "function") {
89
- fsPromises.readFile.mockRestore();
90
- restoreFunctions.push(() => spyOn(fsPromises, "readFile").mockResolvedValue("test content"));
91
- }
92
-
93
- // Restore default import mocks if they exist
94
- if (typeof fsPromisesDefault.writeFile.mockRestore === "function") {
95
- fsPromisesDefault.writeFile.mockRestore();
96
- restoreFunctions.push(() => spyOn(fsPromisesDefault, "writeFile").mockResolvedValue());
97
- }
98
- if (typeof fsPromisesDefault.mkdir.mockRestore === "function") {
99
- fsPromisesDefault.mkdir.mockRestore();
100
- restoreFunctions.push(() => spyOn(fsPromisesDefault, "mkdir").mockResolvedValue());
101
- }
102
- });
103
-
104
- afterEach(async () => {
105
- await teardownTestDir();
106
-
107
- // Restore the original mocks that other tests might depend on
108
- restoreFunctions.forEach((restoreFn) => {
109
- try {
110
- restoreFn();
111
- } catch {
112
- // Ignore errors when restoring mocks
113
- }
114
- });
115
- });
116
-
117
- test("Save string value to empty file", async () => {
118
- await saveValueToConfig("projectName", "test-project");
119
- const content = await readConfigFile();
120
-
121
- expect(content).toContain("projectName: test-project");
122
- });
123
-
124
- test("Save string value with comment to empty file", async () => {
125
- await saveValueToConfig("projectDesc", "A test project", "Project description");
126
- const content = await readConfigFile();
127
-
128
- expect(content).toContain("# Project description");
129
- expect(content).toContain("projectDesc: A test project");
130
- });
131
-
132
- test("Save array value to empty file", async () => {
133
- await saveValueToConfig("translateLanguages", ["zh", "ja", "ko"]);
134
- const content = await readConfigFile();
135
-
136
- expect(content).toContain("translateLanguages:");
137
- expect(content).toContain(" - zh");
138
- expect(content).toContain(" - ja");
139
- expect(content).toContain(" - ko");
140
- });
141
-
142
- test("Save empty array", async () => {
143
- await saveValueToConfig("emptyArray", []);
144
- const content = await readConfigFile();
145
-
146
- expect(content).toContain("emptyArray: []");
147
- });
148
-
149
- test("Save array with comment", async () => {
150
- await saveValueToConfig("sourcePaths", ["./src", "./lib"], "Source code paths");
151
- const content = await readConfigFile();
152
-
153
- expect(content).toContain("# Source code paths");
154
- expect(content).toContain("sourcePaths:");
155
- expect(content).toContain(" - ./src");
156
- expect(content).toContain(" - ./lib");
157
- });
158
-
159
- test("Update existing string value", async () => {
160
- await createInitialConfig('projectName: "old-project"\nversion: "1.0.0"');
161
-
162
- await saveValueToConfig("projectName", "new-project");
163
- const content = await readConfigFile();
164
-
165
- expect(content).toContain("projectName: new-project");
166
- expect(content).toContain('version: "1.0.0"');
167
- expect(content).not.toContain("old-project");
168
- });
169
-
170
- test("Update existing array value", async () => {
171
- await createInitialConfig(`translateLanguages:
172
- - en
173
- - fr
174
- version: "1.0.0"`);
175
-
176
- await saveValueToConfig("translateLanguages", ["zh", "ja"]);
177
- const content = await readConfigFile();
178
-
179
- expect(content).toContain("translateLanguages:");
180
- expect(content).toContain(" - zh");
181
- expect(content).toContain(" - ja");
182
- expect(content).not.toContain(" - en");
183
- expect(content).not.toContain(" - fr");
184
- expect(content).toContain('version: "1.0.0"');
185
- });
186
-
187
- test("Update array to empty array", async () => {
188
- await createInitialConfig(`translateLanguages:
189
- - en
190
- - fr
191
- version: "1.0.0"`);
192
-
193
- await saveValueToConfig("translateLanguages", []);
194
- const content = await readConfigFile();
195
-
196
- expect(content).toContain("translateLanguages: []");
197
- expect(content).not.toContain(" - en");
198
- expect(content).toContain('version: "1.0.0"');
199
- });
200
-
201
- test("Update empty array to populated array", async () => {
202
- await createInitialConfig(`translateLanguages: []
203
- version: "1.0.0"`);
204
-
205
- await saveValueToConfig("translateLanguages", ["zh", "ja"]);
206
- const content = await readConfigFile();
207
-
208
- expect(content).toContain("translateLanguages:");
209
- expect(content).toContain(" - zh");
210
- expect(content).toContain(" - ja");
211
- expect(content).not.toContain("translateLanguages: []");
212
- expect(content).toContain('version: "1.0.0"');
213
- });
214
-
215
- test("Add comment to existing value without comment", async () => {
216
- await createInitialConfig('projectName: "test-project"\nversion: "1.0.0"');
217
-
218
- await saveValueToConfig("projectName", "updated-project", "Updated project name");
219
- const content = await readConfigFile();
220
-
221
- expect(content).toContain("# Updated project name");
222
- expect(content).toContain("projectName: updated-project");
223
- });
224
-
225
- test("Update value that already has comment", async () => {
226
- await createInitialConfig(`# Project information
227
- projectName: "old-project"
228
- version: "1.0.0"`);
229
-
230
- await saveValueToConfig("projectName", "new-project", "Updated project info");
231
- const content = await readConfigFile();
232
-
233
- expect(content).toContain("# Project information");
234
- expect(content).toContain("projectName: new-project");
235
- expect(content).not.toContain("# Updated project info");
236
- });
237
-
238
- test("Complex array with various items", async () => {
239
- const complexArray = ["./src/components", "./lib/utils", "./modules/auth"];
240
- await saveValueToConfig("sourcePaths", complexArray, "All source paths");
241
- const content = await readConfigFile();
242
-
243
- expect(content).toContain("# All source paths");
244
- expect(content).toContain("sourcePaths:");
245
- expect(content).toContain(" - ./src/components");
246
- expect(content).toContain(" - ./lib/utils");
247
- expect(content).toContain(" - ./modules/auth");
248
- });
249
-
250
- test("Mixed content preservation", async () => {
251
- await createInitialConfig(`# Project configuration
252
- projectName: "original-project"
253
- translateLanguages:
254
- - en
255
- - fr
256
- # Other settings
257
- version: "1.0.0"
258
- locale: en`);
259
-
260
- await saveValueToConfig("translateLanguages", ["zh", "ja", "ko"], "Updated languages");
261
- const content = await readConfigFile();
262
-
263
- expect(content).toContain("# Project configuration");
264
- expect(content).toContain('projectName: "original-project"');
265
- expect(content).toContain("# Updated languages");
266
- expect(content).toContain("translateLanguages:");
267
- expect(content).toContain(" - zh");
268
- expect(content).toContain(" - ja");
269
- expect(content).toContain(" - ko");
270
- expect(content).toContain("# Other settings");
271
- expect(content).toContain('version: "1.0.0"');
272
- expect(content).toContain("locale: en");
273
- expect(content).not.toContain(" - en");
274
- expect(content).not.toContain(" - fr");
275
- });
276
-
277
- test("Array in middle of file", async () => {
278
- await createInitialConfig(`projectName: "test-project"
279
- translateLanguages:
280
- - en
281
- - fr
282
- locale: en
283
- version: "1.0.0"`);
284
-
285
- await saveValueToConfig("translateLanguages", ["zh"]);
286
- const content = await readConfigFile();
287
-
288
- expect(content).toContain('projectName: "test-project"');
289
- expect(content).toContain("translateLanguages:");
290
- expect(content).toContain(" - zh");
291
- expect(content).toContain("locale: en");
292
- expect(content).toContain('version: "1.0.0"');
293
- expect(content).not.toContain(" - en");
294
- expect(content).not.toContain(" - fr");
295
- });
296
-
297
- test("Handle undefined values", async () => {
298
- const initialContent = 'projectName: "test-project"';
299
- await createInitialConfig(initialContent);
300
-
301
- await saveValueToConfig("undefinedKey", undefined);
302
- const content = await readConfigFile();
303
-
304
- expect(content).toBe(initialContent);
305
- });
306
-
307
- // Edge cases and special character tests
308
- describe("Special characters and edge cases", () => {
309
- test("Save string with double quotes", async () => {
310
- await saveValueToConfig("projectDesc", 'My "awesome" project with quotes');
311
- const content = await readConfigFile();
312
-
313
- // Should be properly escaped
314
- expect(content).toContain('My "awesome" project with quotes');
315
- // Verify YAML is valid by checking structure
316
- expect(content).toContain("projectDesc:");
317
- });
318
-
319
- test("Save string with single quotes", async () => {
320
- await saveValueToConfig("projectName", "It's a 'great' project");
321
- const content = await readConfigFile();
322
-
323
- expect(content).toContain("It's a 'great' project");
324
- expect(content).toContain("projectName:");
325
- });
326
-
327
- test("Save string with colons and special YAML characters", async () => {
328
- await saveValueToConfig(
329
- "rule",
330
- "Use proper formatting: semicolons; colons: and pipes | symbols",
331
- );
332
- const content = await readConfigFile();
333
-
334
- expect(content).toContain("Use proper formatting: semicolons; colons: and pipes | symbols");
335
- expect(content).toContain("rule:");
336
- });
337
-
338
- test("Save multiline string with newlines", async () => {
339
- const multilineValue =
340
- "Line 1: First line\nLine 2: Second line\nLine 3: Third line with: special characters";
341
- await saveValueToConfig("multilineRule", multilineValue);
342
- const content = await readConfigFile();
343
-
344
- expect(content).toContain("Line 1: First line");
345
- expect(content).toContain("Line 2: Second line");
346
- expect(content).toContain("Line 3: Third line with: special characters");
347
- });
348
-
349
- test("Save string with Chinese characters and symbols", async () => {
350
- await saveValueToConfig(
351
- "chineseProject",
352
- '中文项目:包含特殊符号!@#¥%…()—— quotes"and" colons:',
353
- );
354
- const content = await readConfigFile();
355
-
356
- expect(content).toContain('中文项目:包含特殊符号!@#¥%…()—— quotes"and" colons:');
357
- expect(content).toContain("chineseProject:");
358
- });
359
-
360
- test("Save string with emoji and Unicode", async () => {
361
- await saveValueToConfig(
362
- "emojiProject",
363
- "🚀 Project with emoji: 🔥 hot features 💯 and symbols ⭐ ✨ 🎉",
364
- );
365
- const content = await readConfigFile();
366
-
367
- expect(content).toContain("🚀 Project with emoji: 🔥 hot features 💯 and symbols ⭐ ✨ 🎉");
368
- expect(content).toContain("emojiProject:");
369
- });
370
-
371
- test("Save array with special character items", async () => {
372
- const specialPaths = [
373
- "./src: main source",
374
- "./lib/utils: helper functions",
375
- "./docs-中文/guide",
376
- "./path with spaces/file",
377
- "./symbols@#$%/directory",
378
- './quotes"and"colons:/path',
379
- ];
380
- await saveValueToConfig("specialPaths", specialPaths);
381
- const content = await readConfigFile();
382
-
383
- expect(content).toContain("specialPaths:");
384
- specialPaths.forEach((path) => {
385
- expect(content).toContain(path);
386
- });
387
- });
388
-
389
- test("Save array with multiline items", async () => {
390
- const multilineArray = [
391
- "Item 1:\nWith newline content",
392
- "Item 2: Simple item",
393
- "Item 3:\nMultiple\nLines\nWith: colons and | pipes",
394
- ];
395
- await saveValueToConfig("multilineArray", multilineArray);
396
- const content = await readConfigFile();
397
-
398
- expect(content).toContain("multilineArray:");
399
- expect(content).toContain("Item 1:");
400
- expect(content).toContain("With newline content");
401
- expect(content).toContain("Item 3:");
402
- expect(content).toContain("With: colons and | pipes");
403
- });
404
-
405
- test("Update existing value containing special characters", async () => {
406
- await createInitialConfig('projectName: "old: project with | pipes"\nversion: "1.0.0"');
407
-
408
- await saveValueToConfig("projectName", 'new: project with "quotes" and | pipes: updated');
409
- const content = await readConfigFile();
410
-
411
- expect(content).toContain('new: project with "quotes" and | pipes: updated');
412
- expect(content).toContain('version: "1.0.0"');
413
- expect(content).not.toContain("old: project");
414
- });
415
-
416
- test("Save very long string with special characters", async () => {
417
- const longString =
418
- "A very long project description that contains many special characters: colons, semicolons; quotes \"like this\", single quotes 'like this', pipes | symbols, Chinese characters 中文内容:包含各种符号!@#¥%…()——, emojis 🚀🔥💯⭐✨🎉, and newlines\nSecond line with more content\nThird line: even more special content with all sorts of symbols @#$%^&*()_+-=[]{}|\\;':./?,<>~`";
419
- await saveValueToConfig("veryLongDesc", longString);
420
- const content = await readConfigFile();
421
-
422
- expect(content).toContain("veryLongDesc:");
423
- expect(content).toContain("A very long project description");
424
- expect(content).toContain("中文内容:包含各种符号");
425
- expect(content).toContain("🚀🔥💯⭐✨🎉");
426
- expect(content).toContain("Second line with more content");
427
- });
428
-
429
- test("Save empty string", async () => {
430
- await saveValueToConfig("emptyString", "");
431
- const content = await readConfigFile();
432
-
433
- expect(content).toContain('emptyString: ""');
434
- });
435
-
436
- test("Save string that looks like YAML syntax", async () => {
437
- await saveValueToConfig("yamlLikeString", "key: value\nother: - item1\n- item2: subvalue");
438
- const content = await readConfigFile();
439
-
440
- expect(content).toContain("yamlLikeString:");
441
- expect(content).toContain("key: value");
442
- expect(content).toContain("other: - item1");
443
- expect(content).toContain("- item2: subvalue");
444
- });
445
-
446
- test("Complex mixed scenario with multiple special character values", async () => {
447
- // Create initial config with some special content
448
- await createInitialConfig(`# Project configuration
449
- # with special comments: and symbols
450
- projectName: "original: project"
451
- locale: zh`);
452
-
453
- // Update with various special character content
454
- await saveValueToConfig("projectDesc", 'Updated description: with "quotes" and | pipes');
455
- await saveValueToConfig("specialArray", [
456
- "path: with colons",
457
- "中文路径/文件",
458
- "emoji 🔥 path",
459
- ]);
460
- await saveValueToConfig(
461
- "multilineContent",
462
- "Line 1: content\nLine 2: more content\nLine 3: final content",
463
- );
464
-
465
- const content = await readConfigFile();
466
-
467
- // Check all content is preserved
468
- expect(content).toContain("# Project configuration");
469
- expect(content).toContain("# with special comments: and symbols");
470
- expect(content).toContain('projectName: "original: project"');
471
- expect(content).toContain("locale: zh");
472
- expect(content).toContain('Updated description: with "quotes" and | pipes');
473
- expect(content).toContain("specialArray:");
474
- expect(content).toContain("path: with colons");
475
- expect(content).toContain("中文路径/文件");
476
- expect(content).toContain("emoji 🔥 path");
477
- expect(content).toContain("multilineContent:");
478
- expect(content).toContain("Line 1: content");
479
- expect(content).toContain("Line 2: more content");
480
- expect(content).toContain("Line 3: final content");
481
- });
482
- });
483
- });