@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.
- package/CHANGELOG.md +25 -0
- package/agents/clear/choose-contents.mjs +14 -1
- package/agents/clear/clear-media-description.mjs +129 -0
- package/agents/clear/index.yaml +3 -1
- package/agents/evaluate/code-snippet.mjs +28 -24
- package/agents/evaluate/document-structure.yaml +0 -4
- package/agents/evaluate/document.yaml +1 -5
- package/agents/generate/index.yaml +1 -0
- package/agents/init/index.mjs +10 -0
- package/agents/media/batch-generate-media-description.yaml +44 -0
- package/agents/media/generate-media-description.yaml +47 -0
- package/agents/media/load-media-description.mjs +238 -0
- package/agents/publish/index.yaml +4 -0
- package/agents/publish/publish-docs.mjs +77 -5
- package/agents/publish/translate-meta.mjs +103 -0
- package/agents/update/generate-document.yaml +30 -28
- package/agents/update/index.yaml +1 -0
- package/agents/update/update-document-detail.yaml +3 -1
- package/agents/utils/load-sources.mjs +103 -53
- package/agents/utils/update-branding.mjs +69 -0
- package/aigne.yaml +6 -0
- package/assets/report-template/report.html +34 -34
- package/package.json +17 -2
- package/prompts/common/document/role-and-personality.md +3 -1
- package/prompts/detail/d2-diagram/guide.md +7 -1
- package/prompts/detail/d2-diagram/user-prompt.md +3 -0
- package/prompts/detail/generate/system-prompt.md +6 -7
- package/prompts/detail/generate/user-prompt.md +12 -3
- package/prompts/detail/update/user-prompt.md +0 -2
- package/prompts/evaluate/document-structure.md +6 -7
- package/prompts/evaluate/document.md +16 -25
- package/prompts/media/media-description/system-prompt.md +35 -0
- package/prompts/media/media-description/user-prompt.md +8 -0
- package/prompts/structure/update/user-prompt.md +0 -4
- package/utils/constants/index.mjs +0 -107
- package/utils/file-utils.mjs +86 -0
- package/utils/markdown-checker.mjs +0 -20
- package/utils/request.mjs +7 -0
- package/utils/upload-files.mjs +231 -0
- package/utils/utils.mjs +11 -1
- package/.aigne/doc-smith/config.yaml +0 -77
- package/.aigne/doc-smith/history.yaml +0 -37
- package/.aigne/doc-smith/output/structure-plan.json +0 -162
- package/.aigne/doc-smith/preferences.yml +0 -97
- package/.aigne/doc-smith/upload-cache.yaml +0 -1893
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
- package/.github/workflows/ci.yml +0 -54
- package/.github/workflows/create-release-pr.yaml +0 -21
- package/.github/workflows/publish-docs.yml +0 -65
- package/.github/workflows/release.yml +0 -49
- package/.github/workflows/reviewer.yml +0 -54
- package/.release-please-manifest.json +0 -3
- package/RELEASE.md +0 -9
- package/assets/screenshots/doc-complete-setup.png +0 -0
- package/assets/screenshots/doc-generate-docs.png +0 -0
- package/assets/screenshots/doc-generate.png +0 -0
- package/assets/screenshots/doc-generated-successfully.png +0 -0
- package/assets/screenshots/doc-publish.png +0 -0
- package/assets/screenshots/doc-regenerate.png +0 -0
- package/assets/screenshots/doc-translate-langs.png +0 -0
- package/assets/screenshots/doc-translate.png +0 -0
- package/assets/screenshots/doc-update.png +0 -0
- package/biome.json +0 -73
- package/codecov.yml +0 -15
- package/docs/_sidebar.md +0 -15
- package/docs/configuration-initial-setup.ja.md +0 -179
- package/docs/configuration-initial-setup.md +0 -179
- package/docs/configuration-initial-setup.zh-TW.md +0 -179
- package/docs/configuration-initial-setup.zh.md +0 -179
- package/docs/configuration-managing-preferences.ja.md +0 -100
- package/docs/configuration-managing-preferences.md +0 -100
- package/docs/configuration-managing-preferences.zh-TW.md +0 -100
- package/docs/configuration-managing-preferences.zh.md +0 -100
- package/docs/configuration.ja.md +0 -96
- package/docs/configuration.md +0 -96
- package/docs/configuration.zh-TW.md +0 -96
- package/docs/configuration.zh.md +0 -96
- package/docs/getting-started.ja.md +0 -88
- package/docs/getting-started.md +0 -88
- package/docs/getting-started.zh-TW.md +0 -88
- package/docs/getting-started.zh.md +0 -88
- package/docs/guides-cleaning-up.ja.md +0 -51
- package/docs/guides-cleaning-up.md +0 -51
- package/docs/guides-cleaning-up.zh-TW.md +0 -51
- package/docs/guides-cleaning-up.zh.md +0 -51
- package/docs/guides-evaluating-documents.ja.md +0 -66
- package/docs/guides-evaluating-documents.md +0 -66
- package/docs/guides-evaluating-documents.zh-TW.md +0 -66
- package/docs/guides-evaluating-documents.zh.md +0 -66
- package/docs/guides-generating-documentation.ja.md +0 -151
- package/docs/guides-generating-documentation.md +0 -151
- package/docs/guides-generating-documentation.zh-TW.md +0 -151
- package/docs/guides-generating-documentation.zh.md +0 -151
- package/docs/guides-interactive-chat.ja.md +0 -85
- package/docs/guides-interactive-chat.md +0 -85
- package/docs/guides-interactive-chat.zh-TW.md +0 -85
- package/docs/guides-interactive-chat.zh.md +0 -85
- package/docs/guides-managing-history.ja.md +0 -48
- package/docs/guides-managing-history.md +0 -48
- package/docs/guides-managing-history.zh-TW.md +0 -48
- package/docs/guides-managing-history.zh.md +0 -48
- package/docs/guides-publishing-your-docs.ja.md +0 -78
- package/docs/guides-publishing-your-docs.md +0 -78
- package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
- package/docs/guides-publishing-your-docs.zh.md +0 -78
- package/docs/guides-translating-documentation.ja.md +0 -95
- package/docs/guides-translating-documentation.md +0 -95
- package/docs/guides-translating-documentation.zh-TW.md +0 -95
- package/docs/guides-translating-documentation.zh.md +0 -95
- package/docs/guides-updating-documentation.ja.md +0 -77
- package/docs/guides-updating-documentation.md +0 -77
- package/docs/guides-updating-documentation.zh-TW.md +0 -77
- package/docs/guides-updating-documentation.zh.md +0 -77
- package/docs/guides.ja.md +0 -32
- package/docs/guides.md +0 -32
- package/docs/guides.zh-TW.md +0 -32
- package/docs/guides.zh.md +0 -32
- package/docs/overview.ja.md +0 -61
- package/docs/overview.md +0 -61
- package/docs/overview.zh-TW.md +0 -61
- package/docs/overview.zh.md +0 -61
- package/docs/release-notes.ja.md +0 -255
- package/docs/release-notes.md +0 -255
- package/docs/release-notes.zh-TW.md +0 -255
- package/docs/release-notes.zh.md +0 -255
- package/media.md +0 -19
- package/prompts/common/afs/afs-tools-usage.md +0 -5
- package/prompts/common/afs/use-afs-instruction.md +0 -1
- package/release-please-config.json +0 -14
- package/tests/agents/chat/chat.test.mjs +0 -46
- package/tests/agents/clear/choose-contents.test.mjs +0 -284
- package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
- package/tests/agents/clear/clear-document-config.test.mjs +0 -167
- package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
- package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
- package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
- package/tests/agents/evaluate/fixtures/api-services.md +0 -87
- package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
- package/tests/agents/evaluate/generate-report.test.mjs +0 -312
- package/tests/agents/generate/check-document-structure.test.mjs +0 -45
- package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
- package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
- package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
- package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
- package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
- package/tests/agents/generate/generate-structure.test.mjs +0 -45
- package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
- package/tests/agents/history/view.test.mjs +0 -97
- package/tests/agents/init/init.test.mjs +0 -1657
- package/tests/agents/prefs/prefs.test.mjs +0 -431
- package/tests/agents/publish/publish-docs.test.mjs +0 -787
- package/tests/agents/translate/choose-language.test.mjs +0 -311
- package/tests/agents/translate/translate-document.test.mjs +0 -51
- package/tests/agents/update/check-document.test.mjs +0 -463
- package/tests/agents/update/check-update-is-single.test.mjs +0 -300
- package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
- package/tests/agents/update/generate-document.test.mjs +0 -51
- package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
- package/tests/agents/update/user-review-document.test.mjs +0 -582
- package/tests/agents/utils/action-success.test.mjs +0 -54
- package/tests/agents/utils/check-detail-result.test.mjs +0 -743
- package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
- package/tests/agents/utils/choose-docs.test.mjs +0 -406
- package/tests/agents/utils/exit.test.mjs +0 -70
- package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
- package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
- package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
- package/tests/agents/utils/format-document-structure.test.mjs +0 -364
- package/tests/agents/utils/fs.test.mjs +0 -267
- package/tests/agents/utils/load-sources.test.mjs +0 -1470
- package/tests/agents/utils/save-docs.test.mjs +0 -109
- package/tests/agents/utils/save-output.test.mjs +0 -315
- package/tests/agents/utils/save-single-doc.test.mjs +0 -364
- package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
- package/tests/utils/auth-utils.test.mjs +0 -596
- package/tests/utils/blocklet.test.mjs +0 -336
- package/tests/utils/conflict-detector.test.mjs +0 -355
- package/tests/utils/constants.test.mjs +0 -295
- package/tests/utils/d2-utils.test.mjs +0 -437
- package/tests/utils/deploy.test.mjs +0 -399
- package/tests/utils/docs-finder-utils.test.mjs +0 -650
- package/tests/utils/file-utils.test.mjs +0 -521
- package/tests/utils/history-utils.test.mjs +0 -206
- package/tests/utils/kroki-utils.test.mjs +0 -646
- package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
- package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
- package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
- package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
- package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
- package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
- package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
- package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
- package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
- package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
- package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
- package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
- package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
- package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
- package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
- package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
- package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
- package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
- package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
- package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
- package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
- package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
- package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
- package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
- package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
- package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
- package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
- package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
- package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
- package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
- package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
- package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
- package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
- package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
- package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
- package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
- package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
- package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
- package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
- package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
- package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
- package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
- package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
- package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
- package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
- package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
- package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
- package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
- package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
- package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
- package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
- package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
- package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
- package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
- package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
- package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
- package/tests/utils/linter/index.test.mjs +0 -440
- package/tests/utils/linter/scan-results.mjs +0 -42
- package/tests/utils/load-config.test.mjs +0 -141
- package/tests/utils/markdown/index.test.mjs +0 -478
- package/tests/utils/mermaid-validator.test.mjs +0 -541
- package/tests/utils/mock-chat-model.mjs +0 -12
- package/tests/utils/preferences-utils.test.mjs +0 -465
- package/tests/utils/save-value-to-config.test.mjs +0 -483
- package/tests/utils/utils.test.mjs +0 -941
|
@@ -1,476 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
-
import moveDocument from "../../../../agents/generate/document-structure-tools/move-document.mjs";
|
|
3
|
-
|
|
4
|
-
describe("move-document", () => {
|
|
5
|
-
let consoleSpy;
|
|
6
|
-
let baseDocumentStructure;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
consoleSpy = spyOn(console, "log").mockImplementation(() => {});
|
|
10
|
-
baseDocumentStructure = [
|
|
11
|
-
{
|
|
12
|
-
title: "Getting Started",
|
|
13
|
-
description: "Introduction to the project",
|
|
14
|
-
path: "/getting-started",
|
|
15
|
-
parentId: null,
|
|
16
|
-
sourceIds: ["intro.md"],
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
title: "API Reference",
|
|
20
|
-
description: "Complete API documentation",
|
|
21
|
-
path: "/api",
|
|
22
|
-
parentId: null,
|
|
23
|
-
sourceIds: ["api.js"],
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
title: "Authentication",
|
|
27
|
-
description: "How to authenticate with the API",
|
|
28
|
-
path: "/api/auth",
|
|
29
|
-
parentId: "/api",
|
|
30
|
-
sourceIds: ["auth.js", "security.md"],
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
title: "Rate Limiting",
|
|
34
|
-
description: "API rate limiting documentation",
|
|
35
|
-
path: "/api/rate-limiting",
|
|
36
|
-
parentId: "/api",
|
|
37
|
-
sourceIds: ["rate-limit.js"],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
title: "OAuth",
|
|
41
|
-
description: "OAuth authentication flow",
|
|
42
|
-
path: "/api/auth/oauth",
|
|
43
|
-
parentId: "/api/auth",
|
|
44
|
-
sourceIds: ["oauth.js"],
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
title: "Tutorials",
|
|
48
|
-
description: "Step-by-step tutorials",
|
|
49
|
-
path: "/tutorials",
|
|
50
|
-
parentId: null,
|
|
51
|
-
sourceIds: ["tutorials.md"],
|
|
52
|
-
},
|
|
53
|
-
];
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
afterEach(() => {
|
|
57
|
-
consoleSpy?.mockRestore();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// SUCCESSFUL MOVE TESTS
|
|
61
|
-
test("should move document to different parent successfully", async () => {
|
|
62
|
-
const result = await moveDocument({
|
|
63
|
-
documentStructure: baseDocumentStructure,
|
|
64
|
-
path: "/api/rate-limiting",
|
|
65
|
-
newParentId: "/tutorials",
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
expect(result.documentStructure).toHaveLength(6);
|
|
69
|
-
expect(result.updatedDocument).toEqual({
|
|
70
|
-
title: "Rate Limiting",
|
|
71
|
-
description: "API rate limiting documentation",
|
|
72
|
-
path: "/api/rate-limiting",
|
|
73
|
-
parentId: "/tutorials",
|
|
74
|
-
sourceIds: ["rate-limit.js"],
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
expect(result.originalDocument).toEqual({
|
|
78
|
-
title: "Rate Limiting",
|
|
79
|
-
description: "API rate limiting documentation",
|
|
80
|
-
path: "/api/rate-limiting",
|
|
81
|
-
parentId: "/api",
|
|
82
|
-
sourceIds: ["rate-limit.js"],
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Verify the document was actually updated in the structure
|
|
86
|
-
const updatedDoc = result.documentStructure.find((doc) => doc.path === "/api/rate-limiting");
|
|
87
|
-
expect(updatedDoc.parentId).toBe("/tutorials");
|
|
88
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("should move document to top level (null parent)", async () => {
|
|
92
|
-
const result = await moveDocument({
|
|
93
|
-
documentStructure: baseDocumentStructure,
|
|
94
|
-
path: "/api/auth",
|
|
95
|
-
newParentId: null,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
expect(result.updatedDocument.parentId).toBeNull();
|
|
99
|
-
expect(result.originalDocument.parentId).toBe("/api");
|
|
100
|
-
|
|
101
|
-
const updatedDoc = result.documentStructure.find((doc) => doc.path === "/api/auth");
|
|
102
|
-
expect(updatedDoc.parentId).toBeNull();
|
|
103
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("should handle undefined newParentId as null", async () => {
|
|
107
|
-
const result = await moveDocument({
|
|
108
|
-
documentStructure: baseDocumentStructure,
|
|
109
|
-
path: "/api/auth",
|
|
110
|
-
newParentId: undefined,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
expect(result.updatedDocument.parentId).toBeNull();
|
|
114
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test("should handle empty string newParentId as null", async () => {
|
|
118
|
-
const result = await moveDocument({
|
|
119
|
-
documentStructure: baseDocumentStructure,
|
|
120
|
-
path: "/api/rate-limiting",
|
|
121
|
-
newParentId: "",
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(result.updatedDocument.parentId).toBeNull();
|
|
125
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("should handle string 'null' newParentId but keep it as string", async () => {
|
|
129
|
-
const result = await moveDocument({
|
|
130
|
-
documentStructure: baseDocumentStructure,
|
|
131
|
-
path: "/api/auth/oauth",
|
|
132
|
-
newParentId: "null",
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
expect(result.updatedDocument.parentId).toBe("null");
|
|
136
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("should move deeply nested document", async () => {
|
|
140
|
-
const result = await moveDocument({
|
|
141
|
-
documentStructure: baseDocumentStructure,
|
|
142
|
-
path: "/api/auth/oauth",
|
|
143
|
-
newParentId: "/getting-started",
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
expect(result.updatedDocument.parentId).toBe("/getting-started");
|
|
147
|
-
expect(result.originalDocument.parentId).toBe("/api/auth");
|
|
148
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// VALIDATION ERROR TESTS
|
|
152
|
-
test("should return error when path is missing", async () => {
|
|
153
|
-
const result = await moveDocument({
|
|
154
|
-
documentStructure: baseDocumentStructure,
|
|
155
|
-
newParentId: "/tutorials",
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
159
|
-
expect(result.originalDocument).toBeUndefined();
|
|
160
|
-
expect(result.updatedDocument).toBeUndefined();
|
|
161
|
-
expect(consoleSpy).toHaveBeenCalledWith("⚠️ Cannot move document: path: Required");
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test("should return error when path is empty string", async () => {
|
|
165
|
-
const result = await moveDocument({
|
|
166
|
-
documentStructure: baseDocumentStructure,
|
|
167
|
-
path: "",
|
|
168
|
-
newParentId: "/tutorials",
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
172
|
-
expect(consoleSpy).toHaveBeenCalledWith("⚠️ Cannot move document: path: Path is required");
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("should return error when document does not exist", async () => {
|
|
176
|
-
const result = await moveDocument({
|
|
177
|
-
documentStructure: baseDocumentStructure,
|
|
178
|
-
path: "/nonexistent-document",
|
|
179
|
-
newParentId: "/tutorials",
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
183
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
184
|
-
"⚠️ Cannot move document: Document '/nonexistent-document' does not exist. Please select an existing document to move.",
|
|
185
|
-
);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
test("should return error when new parent does not exist", async () => {
|
|
189
|
-
const result = await moveDocument({
|
|
190
|
-
documentStructure: baseDocumentStructure,
|
|
191
|
-
path: "/api/rate-limiting",
|
|
192
|
-
newParentId: "/nonexistent-parent",
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
196
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
197
|
-
"⚠️ Cannot move document: Target parent document '/nonexistent-parent' does not exist. Please select an existing parent document.",
|
|
198
|
-
);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// CIRCULAR DEPENDENCY TESTS
|
|
202
|
-
test("should prevent moving document under its own child", async () => {
|
|
203
|
-
const result = await moveDocument({
|
|
204
|
-
documentStructure: baseDocumentStructure,
|
|
205
|
-
path: "/api",
|
|
206
|
-
newParentId: "/api/auth",
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
210
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
211
|
-
"⚠️ Cannot move document: Moving '/api' under '/api/auth' would create an invalid hierarchy. Please select a parent that is not nested under the document being moved.",
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test("should prevent moving document under its grandchild", async () => {
|
|
216
|
-
const result = await moveDocument({
|
|
217
|
-
documentStructure: baseDocumentStructure,
|
|
218
|
-
path: "/api",
|
|
219
|
-
newParentId: "/api/auth/oauth",
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
expect(result.documentStructure).toEqual(baseDocumentStructure);
|
|
223
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
224
|
-
"⚠️ Cannot move document: Moving '/api' under '/api/auth/oauth' would create an invalid hierarchy. Please select a parent that is not nested under the document being moved.",
|
|
225
|
-
);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
test("should allow moving document to same parent (no change)", async () => {
|
|
229
|
-
const result = await moveDocument({
|
|
230
|
-
documentStructure: baseDocumentStructure,
|
|
231
|
-
path: "/api/auth",
|
|
232
|
-
newParentId: "/api/auth",
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
// The move-document logic doesn't prevent self-assignment, it just does the operation
|
|
236
|
-
expect(result.updatedDocument.parentId).toBe("/api/auth");
|
|
237
|
-
expect(result.originalDocument.parentId).toBe("/api");
|
|
238
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test("should allow moving to sibling or unrelated documents", async () => {
|
|
242
|
-
// Move from /api/auth to /tutorials (siblings under different parents)
|
|
243
|
-
const result = await moveDocument({
|
|
244
|
-
documentStructure: baseDocumentStructure,
|
|
245
|
-
path: "/api/auth",
|
|
246
|
-
newParentId: "/tutorials",
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
expect(result.updatedDocument.parentId).toBe("/tutorials");
|
|
250
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
test("should handle complex circular dependency scenarios", async () => {
|
|
254
|
-
const complexStructure = [
|
|
255
|
-
...baseDocumentStructure,
|
|
256
|
-
{
|
|
257
|
-
title: "OAuth Scopes",
|
|
258
|
-
description: "OAuth scope documentation",
|
|
259
|
-
path: "/api/auth/oauth/scopes",
|
|
260
|
-
parentId: "/api/auth/oauth",
|
|
261
|
-
sourceIds: ["scopes.md"],
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
title: "JWT Tokens",
|
|
265
|
-
description: "JWT token handling",
|
|
266
|
-
path: "/api/auth/oauth/jwt",
|
|
267
|
-
parentId: "/api/auth/oauth",
|
|
268
|
-
sourceIds: ["jwt.js"],
|
|
269
|
-
},
|
|
270
|
-
];
|
|
271
|
-
|
|
272
|
-
// Try to move /api under its great-grandchild
|
|
273
|
-
const result = await moveDocument({
|
|
274
|
-
documentStructure: complexStructure,
|
|
275
|
-
path: "/api",
|
|
276
|
-
newParentId: "/api/auth/oauth/scopes",
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
expect(result.documentStructure).toEqual(complexStructure);
|
|
280
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
281
|
-
"⚠️ Cannot move document: Moving '/api' under '/api/auth/oauth/scopes' would create an invalid hierarchy. Please select a parent that is not nested under the document being moved.",
|
|
282
|
-
);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// EDGE CASES
|
|
286
|
-
test("should handle moving to same parent (no-op)", async () => {
|
|
287
|
-
const result = await moveDocument({
|
|
288
|
-
documentStructure: baseDocumentStructure,
|
|
289
|
-
path: "/api/auth",
|
|
290
|
-
newParentId: "/api",
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// Should still work, even though it's essentially a no-op
|
|
294
|
-
expect(result.updatedDocument.parentId).toBe("/api");
|
|
295
|
-
expect(result.originalDocument.parentId).toBe("/api");
|
|
296
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test("should handle moving top-level document to become child", async () => {
|
|
300
|
-
const result = await moveDocument({
|
|
301
|
-
documentStructure: baseDocumentStructure,
|
|
302
|
-
path: "/getting-started",
|
|
303
|
-
newParentId: "/tutorials",
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
expect(result.originalDocument.parentId).toBeNull();
|
|
307
|
-
expect(result.updatedDocument.parentId).toBe("/tutorials");
|
|
308
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
test("should preserve all other document properties", async () => {
|
|
312
|
-
const result = await moveDocument({
|
|
313
|
-
documentStructure: baseDocumentStructure,
|
|
314
|
-
path: "/api/rate-limiting",
|
|
315
|
-
newParentId: "/tutorials",
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
const originalDoc = baseDocumentStructure.find((doc) => doc.path === "/api/rate-limiting");
|
|
319
|
-
const updatedDoc = result.updatedDocument;
|
|
320
|
-
|
|
321
|
-
expect(updatedDoc.title).toBe(originalDoc.title);
|
|
322
|
-
expect(updatedDoc.description).toBe(originalDoc.description);
|
|
323
|
-
expect(updatedDoc.path).toBe(originalDoc.path);
|
|
324
|
-
expect(updatedDoc.sourceIds).toEqual(originalDoc.sourceIds);
|
|
325
|
-
// Only parentId should change
|
|
326
|
-
expect(updatedDoc.parentId).not.toBe(originalDoc.parentId);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
test("should handle empty documentation structure", async () => {
|
|
330
|
-
const result = await moveDocument({
|
|
331
|
-
documentStructure: [],
|
|
332
|
-
path: "/any-path",
|
|
333
|
-
newParentId: "/any-parent",
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
expect(result.documentStructure).toEqual([]);
|
|
337
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
338
|
-
"⚠️ Cannot move document: Document '/any-path' does not exist. Please select an existing document to move.",
|
|
339
|
-
);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
test("should handle single documentation structure", async () => {
|
|
343
|
-
const singleDocStructure = [
|
|
344
|
-
{
|
|
345
|
-
title: "Only Document",
|
|
346
|
-
description: "The only document",
|
|
347
|
-
path: "/only",
|
|
348
|
-
parentId: null,
|
|
349
|
-
sourceIds: ["only.md"],
|
|
350
|
-
},
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
const result = await moveDocument({
|
|
354
|
-
documentStructure: singleDocStructure,
|
|
355
|
-
path: "/only",
|
|
356
|
-
newParentId: "/nonexistent",
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
expect(result.documentStructure).toEqual(singleDocStructure);
|
|
360
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
361
|
-
"⚠️ Cannot move document: Target parent document '/nonexistent' does not exist. Please select an existing parent document.",
|
|
362
|
-
);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
// DATA INTEGRITY TESTS
|
|
366
|
-
test("should not modify original documentation structure", async () => {
|
|
367
|
-
const originalStructure = [...baseDocumentStructure];
|
|
368
|
-
|
|
369
|
-
await moveDocument({
|
|
370
|
-
documentStructure: baseDocumentStructure,
|
|
371
|
-
path: "/api/rate-limiting",
|
|
372
|
-
newParentId: "/tutorials",
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
expect(baseDocumentStructure).toEqual(originalStructure);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
test("should update only the specified document", async () => {
|
|
379
|
-
const result = await moveDocument({
|
|
380
|
-
documentStructure: baseDocumentStructure,
|
|
381
|
-
path: "/api/rate-limiting",
|
|
382
|
-
newParentId: "/tutorials",
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// Count how many documents have changed
|
|
386
|
-
let changedCount = 0;
|
|
387
|
-
for (let i = 0; i < baseDocumentStructure.length; i++) {
|
|
388
|
-
if (
|
|
389
|
-
JSON.stringify(baseDocumentStructure[i]) !== JSON.stringify(result.documentStructure[i])
|
|
390
|
-
) {
|
|
391
|
-
changedCount++;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
expect(changedCount).toBe(1);
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
test("should preserve document order in array", async () => {
|
|
399
|
-
const result = await moveDocument({
|
|
400
|
-
documentStructure: baseDocumentStructure,
|
|
401
|
-
path: "/api/auth",
|
|
402
|
-
newParentId: "/tutorials",
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
// Verify all documents are in the same positions except the moved one
|
|
406
|
-
for (let i = 0; i < baseDocumentStructure.length; i++) {
|
|
407
|
-
if (baseDocumentStructure[i].path === "/api/auth") {
|
|
408
|
-
// This is the moved document, check everything except parentId
|
|
409
|
-
const original = baseDocumentStructure[i];
|
|
410
|
-
const updated = result.documentStructure[i];
|
|
411
|
-
expect(updated.title).toBe(original.title);
|
|
412
|
-
expect(updated.description).toBe(original.description);
|
|
413
|
-
expect(updated.path).toBe(original.path);
|
|
414
|
-
expect(updated.sourceIds).toEqual(original.sourceIds);
|
|
415
|
-
expect(updated.parentId).toBe("/tutorials");
|
|
416
|
-
} else {
|
|
417
|
-
// Other documents should be unchanged
|
|
418
|
-
expect(result.documentStructure[i]).toEqual(baseDocumentStructure[i]);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
// RETURN VALUE TESTS
|
|
424
|
-
test("should return complete original and updated document information", async () => {
|
|
425
|
-
const result = await moveDocument({
|
|
426
|
-
documentStructure: baseDocumentStructure,
|
|
427
|
-
path: "/api/rate-limiting",
|
|
428
|
-
newParentId: "/tutorials",
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
expect(result.originalDocument).toEqual({
|
|
432
|
-
title: "Rate Limiting",
|
|
433
|
-
description: "API rate limiting documentation",
|
|
434
|
-
path: "/api/rate-limiting",
|
|
435
|
-
parentId: "/api",
|
|
436
|
-
sourceIds: ["rate-limit.js"],
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
expect(result.updatedDocument).toEqual({
|
|
440
|
-
title: "Rate Limiting",
|
|
441
|
-
description: "API rate limiting documentation",
|
|
442
|
-
path: "/api/rate-limiting",
|
|
443
|
-
parentId: "/tutorials",
|
|
444
|
-
sourceIds: ["rate-limit.js"],
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
// Verify both have all required properties
|
|
448
|
-
["title", "description", "path", "parentId", "sourceIds"].forEach((prop) => {
|
|
449
|
-
expect(result.originalDocument).toHaveProperty(prop);
|
|
450
|
-
expect(result.updatedDocument).toHaveProperty(prop);
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
test("should handle special characters in paths", async () => {
|
|
455
|
-
const specialStructure = [
|
|
456
|
-
...baseDocumentStructure,
|
|
457
|
-
{
|
|
458
|
-
title: "Special Document",
|
|
459
|
-
description: "Document with special characters",
|
|
460
|
-
path: "/api/special-chars_and.numbers123",
|
|
461
|
-
parentId: "/api",
|
|
462
|
-
sourceIds: ["special.md"],
|
|
463
|
-
},
|
|
464
|
-
];
|
|
465
|
-
|
|
466
|
-
const result = await moveDocument({
|
|
467
|
-
documentStructure: specialStructure,
|
|
468
|
-
path: "/api/special-chars_and.numbers123",
|
|
469
|
-
newParentId: "/tutorials",
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
expect(result.updatedDocument.path).toBe("/api/special-chars_and.numbers123");
|
|
473
|
-
expect(result.updatedDocument.parentId).toBe("/tutorials");
|
|
474
|
-
expect(consoleSpy).not.toHaveBeenCalled();
|
|
475
|
-
});
|
|
476
|
-
});
|