@aigne/doc-smith 0.8.12-beta.3 → 0.8.12-beta.5
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/.aigne/doc-smith/config.yaml +9 -6
- package/.aigne/doc-smith/output/structure-plan.json +123 -109
- package/.aigne/doc-smith/upload-cache.yaml +48 -0
- package/.github/workflows/publish-docs.yml +4 -7
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +20 -0
- package/agents/clear/choose-contents.mjs +22 -5
- package/agents/clear/clear-auth-tokens.mjs +2 -4
- package/agents/clear/clear-deployment-config.mjs +49 -0
- package/agents/clear/clear-document-config.mjs +2 -5
- package/agents/clear/clear-document-structure.mjs +2 -6
- package/agents/clear/clear-generated-docs.mjs +0 -1
- package/agents/generate/check-need-generate-structure.mjs +15 -60
- package/agents/generate/document-structure-tools/generate-sub-structure.mjs +131 -0
- package/agents/generate/generate-structure-without-tools.yaml +65 -0
- package/agents/generate/generate-structure.yaml +7 -1
- package/agents/generate/index.yaml +0 -3
- package/agents/generate/update-document-structure.yaml +3 -0
- package/agents/generate/user-review-document-structure.mjs +7 -5
- package/agents/init/index.mjs +15 -15
- package/agents/publish/publish-docs.mjs +130 -111
- package/agents/translate/index.yaml +1 -1
- package/agents/update/batch-generate-document.yaml +1 -1
- package/agents/update/batch-update-document.yaml +1 -1
- package/agents/update/check-document.mjs +4 -19
- package/agents/update/user-review-document.mjs +4 -3
- package/agents/utils/load-sources.mjs +54 -151
- package/agents/utils/transform-detail-datasources.mjs +14 -18
- package/aigne.yaml +2 -0
- package/biome.json +1 -1
- package/docs/_sidebar.md +13 -15
- package/docs/configuration-initial-setup.ja.md +179 -0
- package/docs/configuration-initial-setup.md +179 -0
- package/docs/configuration-initial-setup.zh-TW.md +179 -0
- package/docs/configuration-initial-setup.zh.md +179 -0
- package/docs/configuration-managing-preferences.ja.md +100 -0
- package/docs/configuration-managing-preferences.md +100 -0
- package/docs/configuration-managing-preferences.zh-TW.md +100 -0
- package/docs/configuration-managing-preferences.zh.md +100 -0
- package/docs/configuration.ja.md +68 -184
- package/docs/configuration.md +62 -178
- package/docs/configuration.zh-TW.md +70 -186
- package/docs/configuration.zh.md +67 -183
- package/docs/getting-started.ja.md +46 -78
- package/docs/getting-started.md +46 -78
- package/docs/getting-started.zh-TW.md +47 -79
- package/docs/getting-started.zh.md +47 -79
- package/docs/guides-cleaning-up.ja.md +50 -0
- package/docs/guides-cleaning-up.md +50 -0
- package/docs/guides-cleaning-up.zh-TW.md +50 -0
- package/docs/guides-cleaning-up.zh.md +50 -0
- package/docs/guides-evaluating-documents.ja.md +66 -0
- package/docs/guides-evaluating-documents.md +66 -0
- package/docs/guides-evaluating-documents.zh-TW.md +66 -0
- package/docs/guides-evaluating-documents.zh.md +66 -0
- package/docs/guides-generating-documentation.ja.md +149 -0
- package/docs/guides-generating-documentation.md +149 -0
- package/docs/guides-generating-documentation.zh-TW.md +149 -0
- package/docs/guides-generating-documentation.zh.md +149 -0
- package/docs/guides-interactive-chat.ja.md +85 -0
- package/docs/guides-interactive-chat.md +85 -0
- package/docs/guides-interactive-chat.zh-TW.md +85 -0
- package/docs/guides-interactive-chat.zh.md +85 -0
- package/docs/guides-managing-history.ja.md +51 -0
- package/docs/guides-managing-history.md +51 -0
- package/docs/guides-managing-history.zh-TW.md +51 -0
- package/docs/guides-managing-history.zh.md +51 -0
- package/docs/guides-publishing-your-docs.ja.md +78 -0
- package/docs/guides-publishing-your-docs.md +78 -0
- package/docs/guides-publishing-your-docs.zh-TW.md +78 -0
- package/docs/guides-publishing-your-docs.zh.md +78 -0
- package/docs/guides-translating-documentation.ja.md +95 -0
- package/docs/guides-translating-documentation.md +95 -0
- package/docs/guides-translating-documentation.zh-TW.md +95 -0
- package/docs/guides-translating-documentation.zh.md +95 -0
- package/docs/guides-updating-documentation.ja.md +77 -0
- package/docs/guides-updating-documentation.md +77 -0
- package/docs/guides-updating-documentation.zh-TW.md +77 -0
- package/docs/guides-updating-documentation.zh.md +77 -0
- package/docs/guides.ja.md +32 -0
- package/docs/guides.md +32 -0
- package/docs/guides.zh-TW.md +32 -0
- package/docs/guides.zh.md +32 -0
- package/docs/overview.ja.md +39 -60
- package/docs/overview.md +39 -60
- package/docs/overview.zh-TW.md +39 -60
- package/docs/overview.zh.md +39 -60
- package/docs/release-notes.ja.md +255 -0
- package/docs/release-notes.md +255 -0
- package/docs/release-notes.zh-TW.md +255 -0
- package/docs/release-notes.zh.md +255 -0
- package/package.json +4 -2
- package/prompts/common/document/content-rules-core.md +1 -0
- package/prompts/common/document-structure/document-structure-rules.md +8 -9
- package/prompts/common/document-structure/output-constraints.md +1 -1
- package/prompts/structure/document-rules.md +8 -2
- package/prompts/structure/generate/system-prompt.md +27 -2
- package/prompts/structure/generate/user-prompt.md +18 -0
- package/prompts/structure/update/system-prompt.md +12 -0
- package/prompts/structure/update/user-prompt.md +3 -0
- package/tests/agents/clear/choose-contents.test.mjs +8 -4
- package/tests/agents/generate/check-need-generate-structure.test.mjs +53 -63
- package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +277 -0
- package/tests/agents/init/init.test.mjs +18 -18
- package/tests/agents/publish/publish-docs.test.mjs +79 -0
- package/tests/agents/update/check-document.test.mjs +7 -67
- package/tests/agents/utils/load-sources.test.mjs +90 -90
- package/tests/agents/utils/transform-detail-datasources.test.mjs +153 -196
- package/tests/utils/file-utils.test.mjs +309 -1
- package/utils/auth-utils.mjs +9 -3
- package/utils/constants/index.mjs +3 -1
- package/utils/file-utils.mjs +315 -0
- package/utils/utils.mjs +89 -50
- package/docs/advanced-how-it-works.ja.md +0 -101
- package/docs/advanced-how-it-works.md +0 -101
- package/docs/advanced-how-it-works.zh-TW.md +0 -101
- package/docs/advanced-how-it-works.zh.md +0 -101
- package/docs/advanced-quality-assurance.ja.md +0 -92
- package/docs/advanced-quality-assurance.md +0 -92
- package/docs/advanced-quality-assurance.zh-TW.md +0 -92
- package/docs/advanced-quality-assurance.zh.md +0 -92
- package/docs/advanced.ja.md +0 -20
- package/docs/advanced.md +0 -20
- package/docs/advanced.zh-TW.md +0 -20
- package/docs/advanced.zh.md +0 -20
- package/docs/changelog.ja.md +0 -486
- package/docs/changelog.md +0 -486
- package/docs/changelog.zh-TW.md +0 -486
- package/docs/changelog.zh.md +0 -486
- package/docs/cli-reference.ja.md +0 -311
- package/docs/cli-reference.md +0 -311
- package/docs/cli-reference.zh-TW.md +0 -311
- package/docs/cli-reference.zh.md +0 -311
- package/docs/configuration-interactive-setup.ja.md +0 -138
- package/docs/configuration-interactive-setup.md +0 -138
- package/docs/configuration-interactive-setup.zh-TW.md +0 -138
- package/docs/configuration-interactive-setup.zh.md +0 -138
- package/docs/configuration-language-support.ja.md +0 -64
- package/docs/configuration-language-support.md +0 -64
- package/docs/configuration-language-support.zh-TW.md +0 -64
- package/docs/configuration-language-support.zh.md +0 -64
- package/docs/configuration-llm-setup.ja.md +0 -56
- package/docs/configuration-llm-setup.md +0 -56
- package/docs/configuration-llm-setup.zh-TW.md +0 -56
- package/docs/configuration-llm-setup.zh.md +0 -56
- package/docs/configuration-preferences.ja.md +0 -144
- package/docs/configuration-preferences.md +0 -144
- package/docs/configuration-preferences.zh-TW.md +0 -144
- package/docs/configuration-preferences.zh.md +0 -144
- package/docs/features-generate-documentation.ja.md +0 -95
- package/docs/features-generate-documentation.md +0 -95
- package/docs/features-generate-documentation.zh-TW.md +0 -95
- package/docs/features-generate-documentation.zh.md +0 -95
- package/docs/features-publish-your-docs.ja.md +0 -130
- package/docs/features-publish-your-docs.md +0 -130
- package/docs/features-publish-your-docs.zh-TW.md +0 -130
- package/docs/features-publish-your-docs.zh.md +0 -130
- package/docs/features-translate-documentation.ja.md +0 -90
- package/docs/features-translate-documentation.md +0 -90
- package/docs/features-translate-documentation.zh-TW.md +0 -90
- package/docs/features-translate-documentation.zh.md +0 -90
- package/docs/features-update-and-refine.ja.md +0 -142
- package/docs/features-update-and-refine.md +0 -142
- package/docs/features-update-and-refine.zh-TW.md +0 -143
- package/docs/features-update-and-refine.zh.md +0 -142
- package/docs/features.ja.md +0 -62
- package/docs/features.md +0 -62
- package/docs/features.zh-TW.md +0 -62
- package/docs/features.zh.md +0 -62
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import path, { dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
2
5
|
import transformDetailDatasources from "../../../agents/utils/transform-detail-datasources.mjs";
|
|
3
6
|
import * as utils from "../../../utils/utils.mjs";
|
|
4
7
|
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
5
10
|
describe("transformDetailDatasources utility", () => {
|
|
6
11
|
let normalizePathSpy;
|
|
7
12
|
let toRelativePathSpy;
|
|
13
|
+
let testDir;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
// Create test directory
|
|
17
|
+
const uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
18
|
+
testDir = path.join(__dirname, `test-transform-${uniqueId}`);
|
|
19
|
+
await mkdir(testDir, { recursive: true });
|
|
8
20
|
|
|
9
|
-
beforeEach(() => {
|
|
10
21
|
// Spy on utility functions
|
|
11
22
|
normalizePathSpy = spyOn(utils, "normalizePath").mockImplementation((path) =>
|
|
12
23
|
path?.replace(/\\/g, "/").replace(/^\.\//, ""),
|
|
@@ -16,117 +27,145 @@ describe("transformDetailDatasources utility", () => {
|
|
|
16
27
|
);
|
|
17
28
|
});
|
|
18
29
|
|
|
19
|
-
afterEach(() => {
|
|
30
|
+
afterEach(async () => {
|
|
20
31
|
// Restore all spies
|
|
21
32
|
normalizePathSpy?.mockRestore();
|
|
22
33
|
toRelativePathSpy?.mockRestore();
|
|
34
|
+
|
|
35
|
+
// Clean up test directory
|
|
36
|
+
try {
|
|
37
|
+
await rm(testDir, { recursive: true, force: true });
|
|
38
|
+
} catch {
|
|
39
|
+
console.warn(`Warning: Could not clean up test directory: ${testDir}`);
|
|
40
|
+
}
|
|
23
41
|
});
|
|
24
42
|
|
|
25
43
|
// BASIC FUNCTIONALITY TESTS
|
|
26
|
-
test("should transform simple datasources correctly", () => {
|
|
44
|
+
test("should transform simple datasources correctly", async () => {
|
|
45
|
+
// Create test files
|
|
46
|
+
const guidePath = path.join(testDir, "guide.md");
|
|
47
|
+
const apiPath = path.join(testDir, "api.md");
|
|
48
|
+
await writeFile(guidePath, "# User Guide\n\nThis is a guide.");
|
|
49
|
+
await writeFile(apiPath, "# API Reference\n\nAPI documentation.");
|
|
50
|
+
|
|
51
|
+
// Mock normalizePath to return the actual file path
|
|
52
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
53
|
+
|
|
27
54
|
const input = {
|
|
28
|
-
sourceIds: [
|
|
29
|
-
datasourcesList: [
|
|
30
|
-
{ sourceId: "/docs/guide.md", content: "# User Guide\n\nThis is a guide." },
|
|
31
|
-
{ sourceId: "/docs/api.md", content: "# API Reference\n\nAPI documentation." },
|
|
32
|
-
],
|
|
55
|
+
sourceIds: [guidePath, apiPath],
|
|
33
56
|
};
|
|
34
57
|
|
|
35
58
|
const result = transformDetailDatasources(input);
|
|
36
59
|
|
|
37
|
-
expect(normalizePathSpy).toHaveBeenCalledWith(
|
|
38
|
-
expect(normalizePathSpy).toHaveBeenCalledWith(
|
|
39
|
-
expect(toRelativePathSpy).toHaveBeenCalledWith(
|
|
40
|
-
expect(toRelativePathSpy).toHaveBeenCalledWith(
|
|
60
|
+
expect(normalizePathSpy).toHaveBeenCalledWith(guidePath);
|
|
61
|
+
expect(normalizePathSpy).toHaveBeenCalledWith(apiPath);
|
|
62
|
+
expect(toRelativePathSpy).toHaveBeenCalledWith(guidePath);
|
|
63
|
+
expect(toRelativePathSpy).toHaveBeenCalledWith(apiPath);
|
|
41
64
|
|
|
42
|
-
expect(result).
|
|
43
|
-
|
|
44
|
-
"// sourceId: docs/guide.md\n# User Guide\n\nThis is a guide.\n" +
|
|
45
|
-
"// sourceId: docs/api.md\n# API Reference\n\nAPI documentation.\n",
|
|
46
|
-
});
|
|
65
|
+
expect(result.detailDataSources).toContain("# User Guide\n\nThis is a guide.");
|
|
66
|
+
expect(result.detailDataSources).toContain("# API Reference\n\nAPI documentation.");
|
|
47
67
|
});
|
|
48
68
|
|
|
49
|
-
test("should handle single datasource", () => {
|
|
69
|
+
test("should handle single datasource", async () => {
|
|
70
|
+
// Create test file
|
|
71
|
+
const readmePath = path.join(testDir, "readme.md");
|
|
72
|
+
await writeFile(readmePath, "# README\n\nProject documentation.");
|
|
73
|
+
|
|
74
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
75
|
+
|
|
50
76
|
const input = {
|
|
51
|
-
sourceIds: [
|
|
52
|
-
datasourcesList: [
|
|
53
|
-
{ sourceId: "/docs/readme.md", content: "# README\n\nProject documentation." },
|
|
54
|
-
],
|
|
77
|
+
sourceIds: [readmePath],
|
|
55
78
|
};
|
|
56
79
|
|
|
57
80
|
const result = transformDetailDatasources(input);
|
|
58
81
|
|
|
59
|
-
expect(result.detailDataSources).
|
|
60
|
-
"// sourceId: docs/readme.md\n# README\n\nProject documentation.\n",
|
|
61
|
-
);
|
|
82
|
+
expect(result.detailDataSources).toContain("# README\n\nProject documentation.");
|
|
62
83
|
});
|
|
63
84
|
|
|
64
|
-
test("should maintain order of sourceIds", () => {
|
|
85
|
+
test("should maintain order of sourceIds", async () => {
|
|
86
|
+
// Create test files
|
|
87
|
+
const cPath = path.join(testDir, "c.md");
|
|
88
|
+
const aPath = path.join(testDir, "a.md");
|
|
89
|
+
const bPath = path.join(testDir, "b.md");
|
|
90
|
+
await writeFile(cPath, "Content C");
|
|
91
|
+
await writeFile(aPath, "Content A");
|
|
92
|
+
await writeFile(bPath, "Content B");
|
|
93
|
+
|
|
94
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
95
|
+
|
|
65
96
|
const input = {
|
|
66
|
-
sourceIds: [
|
|
67
|
-
datasourcesList: [
|
|
68
|
-
{ sourceId: "/docs/a.md", content: "Content A" },
|
|
69
|
-
{ sourceId: "/docs/b.md", content: "Content B" },
|
|
70
|
-
{ sourceId: "/docs/c.md", content: "Content C" },
|
|
71
|
-
],
|
|
97
|
+
sourceIds: [cPath, aPath, bPath],
|
|
72
98
|
};
|
|
73
99
|
|
|
74
100
|
const result = transformDetailDatasources(input);
|
|
75
101
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
102
|
+
// Check order by finding indices
|
|
103
|
+
const indexC = result.detailDataSources.indexOf("Content C");
|
|
104
|
+
const indexA = result.detailDataSources.indexOf("Content A");
|
|
105
|
+
const indexB = result.detailDataSources.indexOf("Content B");
|
|
106
|
+
|
|
107
|
+
expect(indexC).toBeLessThan(indexA);
|
|
108
|
+
expect(indexA).toBeLessThan(indexB);
|
|
81
109
|
});
|
|
82
110
|
|
|
83
111
|
// PATH NORMALIZATION TESTS
|
|
84
|
-
test("should normalize paths correctly", () => {
|
|
85
|
-
|
|
112
|
+
test("should normalize paths correctly", async () => {
|
|
113
|
+
// Create test files
|
|
114
|
+
const guidePath = path.join(testDir, "guide.md");
|
|
115
|
+
const apiPath = path.join(testDir, "api.md");
|
|
116
|
+
await writeFile(guidePath, "Guide content");
|
|
117
|
+
await writeFile(apiPath, "API content");
|
|
118
|
+
|
|
119
|
+
normalizePathSpy.mockImplementation((p) => p?.replace(/\\/g, "/"));
|
|
86
120
|
|
|
87
121
|
const input = {
|
|
88
|
-
sourceIds: [
|
|
89
|
-
datasourcesList: [
|
|
90
|
-
{ sourceId: "docs\\guide.md", content: "Guide content" },
|
|
91
|
-
{ sourceId: "/docs/api.md", content: "API content" },
|
|
92
|
-
],
|
|
122
|
+
sourceIds: [guidePath, apiPath],
|
|
93
123
|
};
|
|
94
124
|
|
|
95
125
|
const result = transformDetailDatasources(input);
|
|
96
126
|
|
|
97
|
-
expect(normalizePathSpy).toHaveBeenCalledWith(
|
|
98
|
-
expect(normalizePathSpy).toHaveBeenCalledWith(
|
|
127
|
+
expect(normalizePathSpy).toHaveBeenCalledWith(guidePath);
|
|
128
|
+
expect(normalizePathSpy).toHaveBeenCalledWith(apiPath);
|
|
99
129
|
expect(result.detailDataSources).toContain("Guide content");
|
|
100
130
|
expect(result.detailDataSources).toContain("API content");
|
|
101
131
|
});
|
|
102
132
|
|
|
103
|
-
test("should handle relative path conversion", () => {
|
|
104
|
-
|
|
133
|
+
test("should handle relative path conversion", async () => {
|
|
134
|
+
// Create test files
|
|
135
|
+
const absPath = path.join(testDir, "abs-file.md");
|
|
136
|
+
const relPath = path.join(testDir, "rel-file.md");
|
|
137
|
+
await writeFile(absPath, "Absolute content");
|
|
138
|
+
await writeFile(relPath, "Relative content");
|
|
139
|
+
|
|
140
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
141
|
+
toRelativePathSpy.mockImplementation((p) => p?.replace(/^\/+/, "").replace(/^\.\//, ""));
|
|
105
142
|
|
|
106
143
|
const input = {
|
|
107
|
-
sourceIds: [
|
|
108
|
-
datasourcesList: [
|
|
109
|
-
{ sourceId: "/abs/path/file.md", content: "Absolute content" },
|
|
110
|
-
{ sourceId: "./rel/path/file.md", content: "Relative content" },
|
|
111
|
-
],
|
|
144
|
+
sourceIds: [absPath, relPath],
|
|
112
145
|
};
|
|
113
146
|
|
|
114
147
|
const result = transformDetailDatasources(input);
|
|
115
148
|
|
|
116
|
-
expect(toRelativePathSpy).toHaveBeenCalledWith(
|
|
117
|
-
expect(toRelativePathSpy).toHaveBeenCalledWith(
|
|
118
|
-
expect(result.detailDataSources).toContain("
|
|
119
|
-
expect(result.detailDataSources).toContain("
|
|
149
|
+
expect(toRelativePathSpy).toHaveBeenCalledWith(absPath);
|
|
150
|
+
expect(toRelativePathSpy).toHaveBeenCalledWith(relPath);
|
|
151
|
+
expect(result.detailDataSources).toContain("Absolute content");
|
|
152
|
+
expect(result.detailDataSources).toContain("Relative content");
|
|
120
153
|
});
|
|
121
154
|
|
|
122
155
|
// MISSING DATA TESTS
|
|
123
|
-
test("should filter out sourceIds
|
|
156
|
+
test("should filter out sourceIds for files that don't exist", async () => {
|
|
157
|
+
// Create only some test files
|
|
158
|
+
const guidePath = path.join(testDir, "guide.md");
|
|
159
|
+
const apiPath = path.join(testDir, "api.md");
|
|
160
|
+
const missingPath = path.join(testDir, "missing.md");
|
|
161
|
+
await writeFile(guidePath, "Guide content");
|
|
162
|
+
await writeFile(apiPath, "API content");
|
|
163
|
+
// missingPath intentionally not created
|
|
164
|
+
|
|
165
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
166
|
+
|
|
124
167
|
const input = {
|
|
125
|
-
sourceIds: [
|
|
126
|
-
datasourcesList: [
|
|
127
|
-
{ sourceId: "/docs/guide.md", content: "Guide content" },
|
|
128
|
-
{ sourceId: "/docs/api.md", content: "API content" },
|
|
129
|
-
],
|
|
168
|
+
sourceIds: [guidePath, missingPath, apiPath],
|
|
130
169
|
};
|
|
131
170
|
|
|
132
171
|
const result = transformDetailDatasources(input);
|
|
@@ -134,27 +173,11 @@ describe("transformDetailDatasources utility", () => {
|
|
|
134
173
|
expect(result.detailDataSources).toContain("Guide content");
|
|
135
174
|
expect(result.detailDataSources).toContain("API content");
|
|
136
175
|
expect(result.detailDataSources).not.toContain("missing");
|
|
137
|
-
expect(result.detailDataSources.split("// sourceId:")).toHaveLength(3); // Empty first element + 2 sources
|
|
138
176
|
});
|
|
139
177
|
|
|
140
178
|
test("should handle empty sourceIds array", () => {
|
|
141
179
|
const input = {
|
|
142
180
|
sourceIds: [],
|
|
143
|
-
datasourcesList: [
|
|
144
|
-
{ sourceId: "/docs/guide.md", content: "Guide content" },
|
|
145
|
-
{ sourceId: "/docs/api.md", content: "API content" },
|
|
146
|
-
],
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const result = transformDetailDatasources(input);
|
|
150
|
-
|
|
151
|
-
expect(result.detailDataSources).toBe("");
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test("should handle empty datasourcesList array", () => {
|
|
155
|
-
const input = {
|
|
156
|
-
sourceIds: ["/docs/guide.md", "/docs/api.md"],
|
|
157
|
-
datasourcesList: [],
|
|
158
181
|
};
|
|
159
182
|
|
|
160
183
|
const result = transformDetailDatasources(input);
|
|
@@ -166,7 +189,6 @@ describe("transformDetailDatasources utility", () => {
|
|
|
166
189
|
test("should handle null sourceIds", () => {
|
|
167
190
|
const input = {
|
|
168
191
|
sourceIds: null,
|
|
169
|
-
datasourcesList: [{ sourceId: "/docs/guide.md", content: "Guide content" }],
|
|
170
192
|
};
|
|
171
193
|
|
|
172
194
|
const result = transformDetailDatasources(input);
|
|
@@ -177,7 +199,6 @@ describe("transformDetailDatasources utility", () => {
|
|
|
177
199
|
test("should handle undefined sourceIds", () => {
|
|
178
200
|
const input = {
|
|
179
201
|
sourceIds: undefined,
|
|
180
|
-
datasourcesList: [{ sourceId: "/docs/guide.md", content: "Guide content" }],
|
|
181
202
|
};
|
|
182
203
|
|
|
183
204
|
const result = transformDetailDatasources(input);
|
|
@@ -185,179 +206,115 @@ describe("transformDetailDatasources utility", () => {
|
|
|
185
206
|
expect(result.detailDataSources).toBe("");
|
|
186
207
|
});
|
|
187
208
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
const result = transformDetailDatasources(input);
|
|
209
|
+
// CONTENT FORMATTING TESTS
|
|
210
|
+
test("should format content with proper sourceId comments", async () => {
|
|
211
|
+
const mainPath = path.join(testDir, "main.js");
|
|
212
|
+
await writeFile(mainPath, "console.log('Hello World');\nprocess.exit(0);");
|
|
195
213
|
|
|
196
|
-
|
|
197
|
-
});
|
|
214
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
198
215
|
|
|
199
|
-
test("should handle undefined datasourcesList", () => {
|
|
200
216
|
const input = {
|
|
201
|
-
sourceIds: [
|
|
202
|
-
datasourcesList: undefined,
|
|
217
|
+
sourceIds: [mainPath],
|
|
203
218
|
};
|
|
204
219
|
|
|
205
220
|
const result = transformDetailDatasources(input);
|
|
206
221
|
|
|
207
|
-
expect(result.detailDataSources).
|
|
222
|
+
expect(result.detailDataSources).toContain("console.log('Hello World');\nprocess.exit(0);");
|
|
223
|
+
expect(result.detailDataSources).toContain("// sourceId:");
|
|
208
224
|
});
|
|
209
225
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
sourceIds: ["/project/src/main.js"],
|
|
214
|
-
datasourcesList: [
|
|
215
|
-
{
|
|
216
|
-
sourceId: "/project/src/main.js",
|
|
217
|
-
content: "console.log('Hello World');\nprocess.exit(0);",
|
|
218
|
-
},
|
|
219
|
-
],
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
const result = transformDetailDatasources(input);
|
|
226
|
+
test("should handle empty content", async () => {
|
|
227
|
+
const emptyPath = path.join(testDir, "empty.md");
|
|
228
|
+
await writeFile(emptyPath, "");
|
|
223
229
|
|
|
224
|
-
|
|
225
|
-
"// sourceId: project/src/main.js\nconsole.log('Hello World');\nprocess.exit(0);\n",
|
|
226
|
-
);
|
|
227
|
-
});
|
|
230
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
228
231
|
|
|
229
|
-
test("should handle empty content", () => {
|
|
230
232
|
const input = {
|
|
231
|
-
sourceIds: [
|
|
232
|
-
datasourcesList: [{ sourceId: "/docs/empty.md", content: "" }],
|
|
233
|
+
sourceIds: [emptyPath],
|
|
233
234
|
};
|
|
234
235
|
|
|
235
236
|
const result = transformDetailDatasources(input);
|
|
236
237
|
|
|
237
|
-
// Empty content
|
|
238
|
-
expect(result.detailDataSources).
|
|
238
|
+
// Empty file content still gets included with sourceId comment
|
|
239
|
+
expect(result.detailDataSources).toContain("// sourceId:");
|
|
240
|
+
expect(result.detailDataSources.trim()).not.toBe("");
|
|
239
241
|
});
|
|
240
242
|
|
|
241
|
-
test("should handle whitespace-only content", () => {
|
|
243
|
+
test("should handle whitespace-only content", async () => {
|
|
244
|
+
const whitespacePath = path.join(testDir, "whitespace.md");
|
|
245
|
+
await writeFile(whitespacePath, " \n\t ");
|
|
246
|
+
|
|
247
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
248
|
+
|
|
242
249
|
const input = {
|
|
243
|
-
sourceIds: [
|
|
244
|
-
datasourcesList: [{ sourceId: "/docs/whitespace.md", content: " \n\t " }],
|
|
250
|
+
sourceIds: [whitespacePath],
|
|
245
251
|
};
|
|
246
252
|
|
|
247
253
|
const result = transformDetailDatasources(input);
|
|
248
254
|
|
|
249
255
|
// Whitespace content is truthy, so it should be included
|
|
250
|
-
expect(result.detailDataSources).
|
|
256
|
+
expect(result.detailDataSources).toContain(" \n\t ");
|
|
251
257
|
});
|
|
252
258
|
|
|
253
|
-
test("should handle content with special characters", () => {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
datasourcesList: [
|
|
257
|
-
{
|
|
258
|
-
sourceId: "/docs/特殊字符.md",
|
|
259
|
-
content: "# 中文标题\n\n这是一个包含特殊字符的文档: @#$%^&*()",
|
|
260
|
-
},
|
|
261
|
-
],
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
const result = transformDetailDatasources(input);
|
|
259
|
+
test("should handle content with special characters", async () => {
|
|
260
|
+
const specialPath = path.join(testDir, "特殊字符.md");
|
|
261
|
+
await writeFile(specialPath, "# 中文标题\n\n这是一个包含特殊字符的文档: @#$%^&*()");
|
|
265
262
|
|
|
266
|
-
|
|
267
|
-
expect(result.detailDataSources).toContain("中文标题");
|
|
268
|
-
expect(result.detailDataSources).toContain("@#$%^&*()");
|
|
269
|
-
});
|
|
263
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
270
264
|
|
|
271
|
-
// LARGE DATA TESTS
|
|
272
|
-
test("should handle multiple large datasources", () => {
|
|
273
|
-
const largeContent = "A".repeat(1000);
|
|
274
265
|
const input = {
|
|
275
|
-
sourceIds:
|
|
276
|
-
datasourcesList: Array.from({ length: 50 }, (_, i) => ({
|
|
277
|
-
sourceId: `/docs/file-${i}.md`,
|
|
278
|
-
content: `${largeContent}-${i}`,
|
|
279
|
-
})),
|
|
266
|
+
sourceIds: [specialPath],
|
|
280
267
|
};
|
|
281
268
|
|
|
282
269
|
const result = transformDetailDatasources(input);
|
|
283
270
|
|
|
284
|
-
expect(result.detailDataSources.
|
|
285
|
-
expect(result.detailDataSources).toContain("
|
|
286
|
-
expect(result.detailDataSources).toContain("file-49.md");
|
|
287
|
-
expect(result.detailDataSources.length).toBeGreaterThan(50000); // Should be quite large
|
|
271
|
+
expect(result.detailDataSources).toContain("中文标题");
|
|
272
|
+
expect(result.detailDataSources).toContain("@#$%^&*()");
|
|
288
273
|
});
|
|
289
274
|
|
|
290
275
|
// DUPLICATE HANDLING TESTS
|
|
291
|
-
test("should handle duplicate sourceIds in list", () => {
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
datasourcesList: [{ sourceId: "/docs/guide.md", content: "Guide content" }],
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
const result = transformDetailDatasources(input);
|
|
276
|
+
test("should handle duplicate sourceIds in list", async () => {
|
|
277
|
+
const guidePath = path.join(testDir, "guide.md");
|
|
278
|
+
await writeFile(guidePath, "Guide content");
|
|
298
279
|
|
|
299
|
-
|
|
300
|
-
"// sourceId: docs/guide.md\nGuide content\n" + "// sourceId: docs/guide.md\nGuide content\n",
|
|
301
|
-
);
|
|
302
|
-
});
|
|
280
|
+
normalizePathSpy.mockImplementation((p) => p);
|
|
303
281
|
|
|
304
|
-
test("should handle duplicate entries in datasourcesList", () => {
|
|
305
282
|
const input = {
|
|
306
|
-
sourceIds: [
|
|
307
|
-
datasourcesList: [
|
|
308
|
-
{ sourceId: "/docs/guide.md", content: "First content" },
|
|
309
|
-
{ sourceId: "/docs/guide.md", content: "Second content" },
|
|
310
|
-
],
|
|
283
|
+
sourceIds: [guidePath, guidePath], // Duplicate paths
|
|
311
284
|
};
|
|
312
285
|
|
|
313
286
|
const result = transformDetailDatasources(input);
|
|
314
287
|
|
|
315
|
-
//
|
|
316
|
-
|
|
288
|
+
// Both duplicates should be included
|
|
289
|
+
const matches = result.detailDataSources.match(/Guide content/g);
|
|
290
|
+
expect(matches?.length).toBe(2);
|
|
317
291
|
});
|
|
318
292
|
|
|
319
293
|
// RETURN VALUE STRUCTURE TESTS
|
|
320
|
-
test("should always return object with detailDataSources property", () => {
|
|
321
|
-
const inputs = [
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
{ sourceIds: ["/test"], datasourcesList: [{ sourceId: "/test", content: "test" }] },
|
|
325
|
-
];
|
|
326
|
-
|
|
327
|
-
inputs.forEach((input) => {
|
|
294
|
+
test("should always return object with detailDataSources property", async () => {
|
|
295
|
+
const inputs = [{ sourceIds: [] }, { sourceIds: null }];
|
|
296
|
+
|
|
297
|
+
for (const input of inputs) {
|
|
328
298
|
const result = transformDetailDatasources(input);
|
|
329
299
|
expect(result).toHaveProperty("detailDataSources");
|
|
330
300
|
expect(typeof result.detailDataSources).toBe("string");
|
|
331
|
-
}
|
|
301
|
+
}
|
|
332
302
|
});
|
|
333
303
|
|
|
334
304
|
// EDGE CASES
|
|
335
|
-
test("should handle sourceId with null or undefined values", () => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const input = {
|
|
340
|
-
sourceIds: [null, undefined, "/docs/valid.md"],
|
|
341
|
-
datasourcesList: [{ sourceId: "/docs/valid.md", content: "Valid content" }],
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const result = transformDetailDatasources(input);
|
|
305
|
+
test("should handle sourceId with null or undefined values", async () => {
|
|
306
|
+
const validPath = path.join(testDir, "valid.md");
|
|
307
|
+
await writeFile(validPath, "Valid content");
|
|
345
308
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
});
|
|
309
|
+
normalizePathSpy.mockImplementation((p) => p || "");
|
|
310
|
+
toRelativePathSpy.mockImplementation((p) => p || "");
|
|
349
311
|
|
|
350
|
-
test("should handle datasource with null sourceId", () => {
|
|
351
312
|
const input = {
|
|
352
|
-
sourceIds: [
|
|
353
|
-
datasourcesList: [
|
|
354
|
-
{ sourceId: null, content: "Null sourceId content" },
|
|
355
|
-
{ sourceId: "/docs/guide.md", content: "Valid content" },
|
|
356
|
-
],
|
|
313
|
+
sourceIds: [null, undefined, validPath],
|
|
357
314
|
};
|
|
358
315
|
|
|
359
316
|
const result = transformDetailDatasources(input);
|
|
360
317
|
|
|
361
|
-
expect(result.detailDataSources).
|
|
318
|
+
expect(result.detailDataSources).toContain("Valid content");
|
|
362
319
|
});
|
|
363
320
|
});
|