@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,336 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
2
- import {
3
- ComponentNotFoundError,
4
- getComponentMountPoint,
5
- InvalidBlockletError,
6
- } from "../../utils/blocklet.mjs";
7
-
8
- describe("blocklet", () => {
9
- let mockFetch;
10
- beforeEach(() => {
11
- // Mock global fetch
12
- mockFetch = spyOn(global, "fetch").mockResolvedValue({
13
- ok: true,
14
- json: () => Promise.resolve({ name: "test-repo", description: "Test repo" }),
15
- statusText: "OK",
16
- });
17
- });
18
-
19
- afterEach(() => {
20
- mockFetch?.mockRestore();
21
- });
22
-
23
- // ERROR CLASSES TESTS
24
- describe("InvalidBlockletError", () => {
25
- test("should create error with correct properties", () => {
26
- const url = "https://example.com";
27
- const status = 404;
28
- const statusText = "Not Found";
29
-
30
- const error = new InvalidBlockletError(url, status, statusText);
31
-
32
- expect(error).toBeInstanceOf(Error);
33
- expect(error.name).toBe("InvalidBlockletError");
34
- expect(error.message).toBe(
35
- 'Invalid application URL: "https://example.com". Unable to fetch configuration.',
36
- );
37
- expect(error.url).toBe(url);
38
- expect(error.status).toBe(status);
39
- expect(error.statusText).toBe(statusText);
40
- });
41
-
42
- test("should handle null status and statusText", () => {
43
- const url = "https://example.com";
44
-
45
- const error = new InvalidBlockletError(url, null, "Network error");
46
-
47
- expect(error.url).toBe(url);
48
- expect(error.status).toBeNull();
49
- expect(error.statusText).toBe("Network error");
50
- });
51
-
52
- test("should be instanceof Error", () => {
53
- const error = new InvalidBlockletError("https://example.com");
54
- expect(error instanceof Error).toBe(true);
55
- expect(error instanceof InvalidBlockletError).toBe(true);
56
- });
57
- });
58
-
59
- describe("ComponentNotFoundError", () => {
60
- test("should create error with correct properties", () => {
61
- const did = "z8ia28nJVd6UMcS4dcJf5NLhv3rLmrFCK";
62
- const appUrl = "https://example.com";
63
-
64
- const error = new ComponentNotFoundError(did, appUrl);
65
-
66
- expect(error).toBeInstanceOf(Error);
67
- expect(error.name).toBe("ComponentNotFoundError");
68
- expect(error.message).toBe(
69
- 'Your website "https://example.com" missing required component to host your docs.',
70
- );
71
- expect(error.did).toBe(did);
72
- expect(error.appUrl).toBe(appUrl);
73
- });
74
-
75
- test("should be instanceof Error", () => {
76
- const error = new ComponentNotFoundError("test-did", "https://example.com");
77
- expect(error instanceof Error).toBe(true);
78
- expect(error instanceof ComponentNotFoundError).toBe(true);
79
- });
80
- });
81
-
82
- // GETCOMPONENTMOUNTPOINT FUNCTION TESTS
83
- describe("getComponentMountPoint", () => {
84
- const testAppUrl = "https://example.com";
85
- const testDid = "z8ia28nJVd6UMcS4dcJf5NLhv3rLmrFCK";
86
- const expectedUrl = "https://example.com/__blocklet__.js?type=json";
87
-
88
- test("should return mount point for existing component", async () => {
89
- const mockConfig = {
90
- componentMountPoints: [
91
- { did: "other-did", mountPoint: "/other" },
92
- { did: testDid, mountPoint: "/api/discuss" },
93
- { did: "another-did", mountPoint: "/another" },
94
- ],
95
- };
96
-
97
- mockFetch.mockResolvedValue({
98
- ok: true,
99
- json: () => Promise.resolve(mockConfig),
100
- });
101
-
102
- const result = await getComponentMountPoint(testAppUrl, testDid);
103
-
104
- expect(result).toBe("/api/discuss");
105
- expect(mockFetch).toHaveBeenCalledWith(expectedUrl, {
106
- method: "GET",
107
- headers: { Accept: "application/json" },
108
- });
109
- });
110
-
111
- // NETWORK ERROR TESTS
112
- test("should throw InvalidBlockletError when fetch fails", async () => {
113
- mockFetch.mockRejectedValue(new Error("Network timeout"));
114
-
115
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
116
- InvalidBlockletError,
117
- );
118
-
119
- try {
120
- await getComponentMountPoint(testAppUrl, testDid);
121
- } catch (error) {
122
- expect(error.url).toBe(testAppUrl);
123
- expect(error.status).toBeNull();
124
- expect(error.statusText).toBe("Network timeout");
125
- }
126
- });
127
-
128
- test("should throw InvalidBlockletError when response is not ok", async () => {
129
- mockFetch.mockResolvedValue({
130
- ok: false,
131
- status: 404,
132
- statusText: "Not Found",
133
- });
134
-
135
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
136
- InvalidBlockletError,
137
- );
138
-
139
- try {
140
- await getComponentMountPoint(testAppUrl, testDid);
141
- } catch (error) {
142
- expect(error.url).toBe(testAppUrl);
143
- expect(error.status).toBe(404);
144
- expect(error.statusText).toBe("Not Found");
145
- }
146
- });
147
-
148
- test("should throw InvalidBlockletError when JSON parsing fails", async () => {
149
- mockFetch.mockResolvedValue({
150
- ok: true,
151
- json: () => Promise.reject(new Error("Invalid JSON")),
152
- });
153
-
154
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
155
- InvalidBlockletError,
156
- );
157
-
158
- try {
159
- await getComponentMountPoint(testAppUrl, testDid);
160
- } catch (error) {
161
- expect(error.url).toBe(testAppUrl);
162
- expect(error.status).toBeNull();
163
- expect(error.statusText).toBe("Invalid JSON response");
164
- }
165
- });
166
-
167
- // COMPONENT NOT FOUND TESTS
168
- test("should throw ComponentNotFoundError when component is not found", async () => {
169
- const mockConfig = {
170
- componentMountPoints: [
171
- { did: "other-did", mountPoint: "/other" },
172
- { did: "another-did", mountPoint: "/another" },
173
- ],
174
- };
175
-
176
- mockFetch.mockResolvedValue({
177
- ok: true,
178
- json: () => Promise.resolve(mockConfig),
179
- });
180
-
181
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
182
- ComponentNotFoundError,
183
- );
184
-
185
- try {
186
- await getComponentMountPoint(testAppUrl, testDid);
187
- } catch (error) {
188
- expect(error.did).toBe(testDid);
189
- expect(error.appUrl).toBe(testAppUrl);
190
- }
191
- });
192
-
193
- test("should throw ComponentNotFoundError when componentMountPoints is undefined", async () => {
194
- const mockConfig = {};
195
-
196
- mockFetch.mockResolvedValue({
197
- ok: true,
198
- json: () => Promise.resolve(mockConfig),
199
- });
200
-
201
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
202
- ComponentNotFoundError,
203
- );
204
- });
205
-
206
- test("should throw ComponentNotFoundError when componentMountPoints is empty", async () => {
207
- const mockConfig = {
208
- componentMountPoints: [],
209
- };
210
-
211
- mockFetch.mockResolvedValue({
212
- ok: true,
213
- json: () => Promise.resolve(mockConfig),
214
- });
215
-
216
- await expect(getComponentMountPoint(testAppUrl, testDid)).rejects.toThrow(
217
- ComponentNotFoundError,
218
- );
219
- });
220
-
221
- // EDGE CASES
222
- test("should handle component at the beginning of array", async () => {
223
- const mockConfig = {
224
- componentMountPoints: [
225
- { did: testDid, mountPoint: "/first" },
226
- { did: "other-did", mountPoint: "/other" },
227
- ],
228
- };
229
-
230
- mockFetch.mockResolvedValue({
231
- ok: true,
232
- json: () => Promise.resolve(mockConfig),
233
- });
234
-
235
- const result = await getComponentMountPoint(testAppUrl, testDid);
236
- expect(result).toBe("/first");
237
- });
238
-
239
- test("should handle component at the end of array", async () => {
240
- const mockConfig = {
241
- componentMountPoints: [
242
- { did: "other-did", mountPoint: "/other" },
243
- { did: testDid, mountPoint: "/last" },
244
- ],
245
- };
246
-
247
- mockFetch.mockResolvedValue({
248
- ok: true,
249
- json: () => Promise.resolve(mockConfig),
250
- });
251
-
252
- const result = await getComponentMountPoint(testAppUrl, testDid);
253
- expect(result).toBe("/last");
254
- });
255
-
256
- test("should handle single component", async () => {
257
- const mockConfig = {
258
- componentMountPoints: [{ did: testDid, mountPoint: "/single" }],
259
- };
260
-
261
- mockFetch.mockResolvedValue({
262
- ok: true,
263
- json: () => Promise.resolve(mockConfig),
264
- });
265
-
266
- const result = await getComponentMountPoint(testAppUrl, testDid);
267
- expect(result).toBe("/single");
268
- });
269
-
270
- test("should handle complex mount points", async () => {
271
- const mockConfig = {
272
- componentMountPoints: [{ did: testDid, mountPoint: "/api/v1/discuss-kit/endpoint" }],
273
- };
274
-
275
- mockFetch.mockResolvedValue({
276
- ok: true,
277
- json: () => Promise.resolve(mockConfig),
278
- });
279
-
280
- const result = await getComponentMountPoint(testAppUrl, testDid);
281
- expect(result).toBe("/api/v1/discuss-kit/endpoint");
282
- });
283
-
284
- test("should handle empty mount point", async () => {
285
- const mockConfig = {
286
- componentMountPoints: [{ did: testDid, mountPoint: "" }],
287
- };
288
-
289
- mockFetch.mockResolvedValue({
290
- ok: true,
291
- json: () => Promise.resolve(mockConfig),
292
- });
293
-
294
- const result = await getComponentMountPoint(testAppUrl, testDid);
295
- expect(result).toBe("");
296
- });
297
-
298
- test("should handle null/undefined mount point", async () => {
299
- const mockConfig = {
300
- componentMountPoints: [{ did: testDid, mountPoint: null }],
301
- };
302
-
303
- mockFetch.mockResolvedValue({
304
- ok: true,
305
- json: () => Promise.resolve(mockConfig),
306
- });
307
-
308
- const result = await getComponentMountPoint(testAppUrl, testDid);
309
- expect(result).toBeNull();
310
- });
311
-
312
- // NETWORK TIMEOUT AND RETRY SCENARIOS
313
- test("should handle network errors with different error types", async () => {
314
- const errorTypes = [
315
- new TypeError("Failed to fetch"),
316
- new Error("Connection refused"),
317
- new Error("Timeout"),
318
- new ReferenceError("Network error"),
319
- ];
320
-
321
- for (const error of errorTypes) {
322
- mockFetch.mockRejectedValueOnce(error);
323
-
324
- try {
325
- await getComponentMountPoint(testAppUrl, testDid);
326
- expect(true).toBe(false); // Should not reach here
327
- } catch (caughtError) {
328
- expect(caughtError).toBeInstanceOf(InvalidBlockletError);
329
- expect(caughtError.url).toBe(testAppUrl);
330
- expect(caughtError.status).toBeNull();
331
- expect(caughtError.statusText).toBe(error.message);
332
- }
333
- }
334
- });
335
- });
336
- });
@@ -1,355 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import {
3
- detectResolvableConflicts,
4
- generateConflictResolutionRules,
5
- getFilteredOptions,
6
- } from "../../utils/conflict-detector.mjs";
7
- import { processConfigFields } from "../../utils/utils.mjs";
8
-
9
- describe("conflict-detector", () => {
10
- describe("getFilteredOptions", () => {
11
- test("should filter experiencedUsers when documentPurpose is getStarted", () => {
12
- const allOptions = {
13
- completeBeginners: "Complete beginners",
14
- domainFamiliar: "Domain familiar",
15
- experiencedUsers: "Experienced users",
16
- emergencyTroubleshooting: "Emergency troubleshooting",
17
- };
18
-
19
- const currentSelections = {
20
- documentPurpose: ["getStarted"],
21
- };
22
-
23
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
24
-
25
- expect(result.filteredOptions).not.toHaveProperty("experiencedUsers");
26
- expect(result.appliedFilters).toHaveLength(1);
27
- expect(result.appliedFilters[0].removedOption).toBe("experiencedUsers");
28
- });
29
-
30
- test("should filter completeBeginners when documentPurpose is findAnswers", () => {
31
- const allOptions = {
32
- completeBeginners: "Complete beginners",
33
- domainFamiliar: "Domain familiar",
34
- experiencedUsers: "Experienced users",
35
- };
36
-
37
- const currentSelections = {
38
- documentPurpose: ["findAnswers"],
39
- };
40
-
41
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
42
-
43
- expect(result.filteredOptions).not.toHaveProperty("completeBeginners");
44
- expect(result.appliedFilters).toHaveLength(1);
45
- expect(result.appliedFilters[0].removedOption).toBe("completeBeginners");
46
- });
47
-
48
- test("should filter emergencyTroubleshooting when documentPurpose is understandSystem", () => {
49
- const allOptions = {
50
- completeBeginners: "Complete beginners",
51
- emergencyTroubleshooting: "Emergency troubleshooting",
52
- };
53
-
54
- const currentSelections = {
55
- documentPurpose: ["understandSystem"],
56
- };
57
-
58
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
59
-
60
- expect(result.filteredOptions).not.toHaveProperty("emergencyTroubleshooting");
61
- expect(result.appliedFilters).toHaveLength(1);
62
- });
63
-
64
- test("should filter experiencedUsers when targetAudienceTypes includes endUsers", () => {
65
- const allOptions = {
66
- completeBeginners: "Complete beginners",
67
- experiencedUsers: "Experienced users",
68
- };
69
-
70
- const currentSelections = {
71
- targetAudienceTypes: ["endUsers"],
72
- };
73
-
74
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
75
-
76
- expect(result.filteredOptions).not.toHaveProperty("experiencedUsers");
77
- expect(result.appliedFilters).toHaveLength(1);
78
- });
79
-
80
- test("should return original options when no conflicts", () => {
81
- const allOptions = {
82
- option1: "Option 1",
83
- option2: "Option 2",
84
- };
85
-
86
- const currentSelections = {};
87
-
88
- const result = getFilteredOptions("unknownType", currentSelections, allOptions);
89
-
90
- expect(result.filteredOptions).toEqual(allOptions);
91
- expect(result.appliedFilters).toHaveLength(0);
92
- });
93
-
94
- test("should handle object selections with value property", () => {
95
- const allOptions = {
96
- experiencedUsers: "Experienced users",
97
- domainFamiliar: "Domain familiar",
98
- };
99
-
100
- const currentSelections = {
101
- documentPurpose: [{ value: "getStarted", label: "Get Started" }],
102
- };
103
-
104
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
105
-
106
- expect(result.filteredOptions).not.toHaveProperty("experiencedUsers");
107
- expect(result.appliedFilters).toHaveLength(1);
108
- });
109
-
110
- test("should handle multiple conditions in cross-conflict rules", () => {
111
- const allOptions = {
112
- emergencyTroubleshooting: "Emergency troubleshooting",
113
- domainFamiliar: "Domain familiar",
114
- };
115
-
116
- const currentSelections = {
117
- targetAudienceTypes: ["decisionMakers"],
118
- };
119
-
120
- const result = getFilteredOptions("readerKnowledgeLevel", currentSelections, allOptions);
121
-
122
- expect(result.filteredOptions).not.toHaveProperty("emergencyTroubleshooting");
123
- expect(result.appliedFilters).toHaveLength(1);
124
- });
125
- });
126
-
127
- describe("detectResolvableConflicts", () => {
128
- test("should detect document purpose conflicts", () => {
129
- const config = {
130
- documentPurpose: ["getStarted", "findAnswers"],
131
- targetAudienceTypes: ["developers"],
132
- };
133
-
134
- const conflicts = detectResolvableConflicts(config);
135
-
136
- expect(conflicts).toHaveLength(1);
137
- expect(conflicts[0]).toMatchObject({
138
- type: "documentPurpose",
139
- items: ["getStarted", "findAnswers"],
140
- strategy: "layered_structure",
141
- description: "Quick start and API reference conflict, resolved through layered structure",
142
- });
143
- });
144
-
145
- test("should detect target audience conflicts", () => {
146
- const config = {
147
- documentPurpose: ["completeTasks"],
148
- targetAudienceTypes: ["endUsers", "developers"],
149
- };
150
-
151
- const conflicts = detectResolvableConflicts(config);
152
-
153
- expect(conflicts).toHaveLength(1);
154
- expect(conflicts[0]).toMatchObject({
155
- type: "targetAudienceTypes",
156
- items: ["endUsers", "developers"],
157
- strategy: "separate_user_paths",
158
- description: "End users and developers conflict, resolved through separate user paths",
159
- });
160
- });
161
-
162
- test("should detect multiple conflicts", () => {
163
- const config = {
164
- documentPurpose: ["getStarted", "findAnswers", "understandSystem"],
165
- targetAudienceTypes: ["endUsers", "developers"],
166
- };
167
-
168
- const conflicts = detectResolvableConflicts(config);
169
-
170
- expect(conflicts).toHaveLength(3);
171
-
172
- // Check for getStarted vs findAnswers conflict
173
- expect(
174
- conflicts.some(
175
- (c) =>
176
- c.type === "documentPurpose" &&
177
- c.items.includes("getStarted") &&
178
- c.items.includes("findAnswers"),
179
- ),
180
- ).toBe(true);
181
-
182
- // Check for getStarted vs understandSystem conflict
183
- expect(
184
- conflicts.some(
185
- (c) =>
186
- c.type === "documentPurpose" &&
187
- c.items.includes("getStarted") &&
188
- c.items.includes("understandSystem"),
189
- ),
190
- ).toBe(true);
191
-
192
- // Check for endUsers vs developers conflict
193
- expect(
194
- conflicts.some(
195
- (c) =>
196
- c.type === "targetAudienceTypes" &&
197
- c.items.includes("endUsers") &&
198
- c.items.includes("developers"),
199
- ),
200
- ).toBe(true);
201
- });
202
-
203
- test("should not detect conflicts with single selections", () => {
204
- const config = {
205
- documentPurpose: ["getStarted"],
206
- targetAudienceTypes: ["developers"],
207
- };
208
-
209
- const conflicts = detectResolvableConflicts(config);
210
-
211
- expect(conflicts).toHaveLength(0);
212
- });
213
-
214
- test("should not detect conflicts with non-conflicting combinations", () => {
215
- const config = {
216
- documentPurpose: ["completeTasks", "solveProblems"],
217
- targetAudienceTypes: ["developers", "devops"],
218
- };
219
-
220
- const conflicts = detectResolvableConflicts(config);
221
-
222
- expect(conflicts).toHaveLength(0);
223
- });
224
-
225
- test("should handle object arrays with value property", () => {
226
- const config = {
227
- documentPurpose: [
228
- { value: "getStarted", label: "Get Started" },
229
- { value: "findAnswers", label: "Find Answers" },
230
- ],
231
- };
232
-
233
- const conflicts = detectResolvableConflicts(config);
234
-
235
- expect(conflicts).toHaveLength(1);
236
- expect(conflicts[0].items).toEqual(["getStarted", "findAnswers"]);
237
- });
238
- });
239
-
240
- describe("generateConflictResolutionRules", () => {
241
- test("should generate resolution rules for conflicts", () => {
242
- const conflicts = [
243
- {
244
- type: "documentPurpose",
245
- items: ["getStarted", "findAnswers"],
246
- strategy: "layered_structure",
247
- description: "Quick start and API reference conflict, resolved through layered structure",
248
- },
249
- {
250
- type: "targetAudienceTypes",
251
- items: ["endUsers", "developers"],
252
- strategy: "separate_user_paths",
253
- description: "End users and developers conflict, resolved through separate user paths",
254
- },
255
- ];
256
-
257
- const rules = generateConflictResolutionRules(conflicts);
258
-
259
- expect(rules).toContain("=== Conflict Resolution Guidelines ===");
260
- expect(rules).toContain('Detected "getStarted" and "findAnswers" purpose conflict');
261
- expect(rules).toContain('Detected "endUsers" and "developers" audience conflict');
262
- expect(rules).toContain('Quick start section: Uses "get started" style');
263
- expect(rules).toContain('User guide path: Uses "end users" style');
264
- expect(rules).toContain("Conflict Resolution Principles:");
265
- expect(rules).toContain(
266
- "1. Meet diverse needs through intelligent structural design, not simple concatenation",
267
- );
268
- });
269
-
270
- test("should return empty string for no conflicts", () => {
271
- const conflicts = [];
272
- const rules = generateConflictResolutionRules(conflicts);
273
- expect(rules).toBe("");
274
- });
275
-
276
- test("should handle unknown strategies gracefully", () => {
277
- const conflicts = [
278
- {
279
- type: "documentPurpose",
280
- items: ["unknown1", "unknown2"],
281
- strategy: "unknown_strategy",
282
- description: "Unknown conflict",
283
- },
284
- ];
285
-
286
- const rules = generateConflictResolutionRules(conflicts);
287
-
288
- expect(rules).toContain("=== Conflict Resolution Guidelines ===");
289
- expect(rules).toContain("Conflict Resolution Principles:");
290
- // Should not contain any strategy-specific text since strategy is unknown
291
- expect(rules).not.toContain('Detected "unknown1" and "unknown2"');
292
- });
293
- });
294
-
295
- describe("processConfigFields integration", () => {
296
- test("should integrate conflict resolution into config processing", () => {
297
- const config = {
298
- documentPurpose: ["getStarted", "findAnswers"],
299
- targetAudienceTypes: ["endUsers", "developers"],
300
- readerKnowledgeLevel: "completeBeginners",
301
- documentationDepth: "balancedCoverage",
302
- };
303
-
304
- const result = processConfigFields(config);
305
-
306
- // Should detect conflicts
307
- expect(result.detectedConflicts).toBeDefined();
308
- expect(result.detectedConflicts).toHaveLength(2);
309
-
310
- // Should include conflict resolution rules in final rules
311
- expect(result.rules).toContain("=== Conflict Resolution Guidelines ===");
312
- expect(result.rules).toContain("Create layered documentation structure");
313
- expect(result.rules).toContain("Create separate user paths");
314
-
315
- // Should also include regular configuration content with enhanced format
316
- expect(result.rules).toContain("Document Purpose - Get started quickly:");
317
- expect(result.rules).toContain("Target Audience - End users (non-technical):");
318
- expect(result.rules).toContain("Target Audience - Developers integrating your product/API:");
319
- expect(result.rules).toContain("Reader Knowledge Level:");
320
- });
321
-
322
- test("should work without conflicts", () => {
323
- const config = {
324
- documentPurpose: ["completeTasks"],
325
- targetAudienceTypes: ["developers"],
326
- readerKnowledgeLevel: "domainFamiliar",
327
- };
328
-
329
- const result = processConfigFields(config);
330
-
331
- // Should not detect conflicts
332
- expect(result.detectedConflicts).toBeUndefined();
333
-
334
- // Should not include conflict resolution rules
335
- expect(result.rules).not.toContain("=== Conflict Resolution Guidelines ===");
336
-
337
- // Should still include regular configuration content with enhanced format
338
- expect(result.rules).toContain("Document Purpose - Complete specific tasks:");
339
- expect(result.rules).toContain("Target Audience - Developers integrating your product/API:");
340
- });
341
-
342
- test("should preserve target audience field processing", () => {
343
- const config = {
344
- targetAudienceTypes: ["developers", "devops"],
345
- targetAudience: "Existing audience description",
346
- };
347
-
348
- const result = processConfigFields(config);
349
-
350
- expect(result.targetAudience).toContain("Existing audience description");
351
- expect(result.targetAudience).toContain("Developers integrating your product/API");
352
- expect(result.targetAudience).toContain("DevOps / SRE / Infrastructure teams");
353
- });
354
- });
355
- });