@aigne/doc-smith 0.8.11-beta.6 → 0.8.11
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 +2 -0
- package/.aigne/doc-smith/output/structure-plan.json +2 -2
- package/.aigne/doc-smith/preferences.yml +28 -20
- package/.aigne/doc-smith/upload-cache.yaml +702 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/agents/generate/document-structure-tools/add-document.mjs +35 -10
- package/agents/generate/document-structure-tools/delete-document.mjs +35 -12
- package/agents/generate/document-structure-tools/move-document.mjs +43 -17
- package/agents/generate/document-structure-tools/update-document.mjs +37 -10
- package/agents/generate/update-document-structure.yaml +1 -7
- package/agents/generate/user-review-document-structure.mjs +5 -4
- package/agents/translate/translate-document.yaml +1 -9
- package/agents/update/check-update-is-single.mjs +2 -1
- package/agents/update/document-tools/update-document-content.mjs +24 -14
- package/agents/update/fs-tools/glob.mjs +184 -0
- package/agents/update/fs-tools/grep.mjs +317 -0
- package/agents/update/fs-tools/read-file.mjs +307 -0
- package/agents/update/generate-document.yaml +4 -7
- package/agents/update/update-document-detail.yaml +6 -10
- package/agents/update/user-review-document.mjs +13 -13
- 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/docs/advanced-how-it-works.ja.md +31 -31
- package/docs/advanced-how-it-works.md +9 -9
- package/docs/advanced-how-it-works.zh-TW.md +24 -24
- package/docs/advanced-how-it-works.zh.md +20 -20
- package/docs/advanced-quality-assurance.ja.md +57 -61
- package/docs/advanced-quality-assurance.md +57 -61
- package/docs/advanced-quality-assurance.zh-TW.md +57 -61
- package/docs/advanced-quality-assurance.zh.md +57 -61
- package/docs/advanced.ja.md +8 -4
- package/docs/advanced.md +7 -3
- package/docs/advanced.zh-TW.md +9 -5
- package/docs/advanced.zh.md +9 -5
- package/docs/changelog.ja.md +206 -29
- package/docs/changelog.md +177 -0
- package/docs/changelog.zh-TW.md +229 -52
- package/docs/changelog.zh.md +204 -27
- package/docs/cli-reference.ja.md +82 -52
- package/docs/cli-reference.md +56 -26
- package/docs/cli-reference.zh-TW.md +82 -52
- package/docs/cli-reference.zh.md +70 -40
- package/docs/configuration-interactive-setup.ja.md +45 -42
- package/docs/configuration-interactive-setup.md +8 -5
- package/docs/configuration-interactive-setup.zh-TW.md +26 -23
- package/docs/configuration-interactive-setup.zh.md +25 -22
- package/docs/configuration-language-support.ja.md +33 -63
- package/docs/configuration-language-support.md +32 -62
- package/docs/configuration-language-support.zh-TW.md +35 -65
- package/docs/configuration-language-support.zh.md +32 -62
- package/docs/configuration-llm-setup.ja.md +25 -23
- package/docs/configuration-llm-setup.md +20 -18
- package/docs/configuration-llm-setup.zh-TW.md +21 -19
- package/docs/configuration-llm-setup.zh.md +20 -18
- package/docs/configuration-preferences.ja.md +67 -52
- package/docs/configuration-preferences.md +56 -41
- package/docs/configuration-preferences.zh-TW.md +69 -54
- package/docs/configuration-preferences.zh.md +68 -53
- package/docs/configuration.ja.md +65 -81
- package/docs/configuration.md +19 -35
- package/docs/configuration.zh-TW.md +62 -79
- package/docs/configuration.zh.md +50 -67
- package/docs/features-generate-documentation.ja.md +44 -69
- package/docs/features-generate-documentation.md +36 -61
- package/docs/features-generate-documentation.zh-TW.md +42 -67
- package/docs/features-generate-documentation.zh.md +41 -67
- package/docs/features-publish-your-docs.ja.md +36 -36
- package/docs/features-publish-your-docs.md +2 -2
- package/docs/features-publish-your-docs.zh-TW.md +21 -21
- package/docs/features-publish-your-docs.zh.md +23 -23
- package/docs/features-translate-documentation.ja.md +40 -31
- package/docs/features-translate-documentation.md +15 -6
- package/docs/features-translate-documentation.zh-TW.md +37 -28
- package/docs/features-translate-documentation.zh.md +23 -14
- package/docs/features-update-and-refine.ja.md +68 -118
- package/docs/features-update-and-refine.md +58 -108
- package/docs/features-update-and-refine.zh-TW.md +67 -116
- package/docs/features-update-and-refine.zh.md +64 -114
- package/docs/features.ja.md +29 -19
- package/docs/features.md +25 -15
- package/docs/features.zh-TW.md +28 -18
- package/docs/features.zh.md +31 -21
- package/docs/getting-started.ja.md +40 -43
- package/docs/getting-started.md +36 -39
- package/docs/getting-started.zh-TW.md +38 -41
- package/docs/getting-started.zh.md +45 -48
- package/docs/overview.ja.md +63 -11
- package/docs/overview.md +60 -8
- package/docs/overview.zh-TW.md +67 -15
- package/docs/overview.zh.md +62 -10
- package/media.md +9 -9
- package/package.json +1 -1
- package/prompts/detail/custom/custom-components.md +304 -188
- package/prompts/detail/document-rules.md +4 -4
- package/prompts/detail/generate-document.md +21 -8
- package/prompts/detail/update-document.md +8 -12
- package/prompts/structure/update-document-structure.md +12 -8
- package/prompts/utils/feedback-refiner.md +3 -3
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +9 -9
- package/tests/agents/generate/user-review-document-structure.test.mjs +29 -8
- package/tests/agents/update/document-tools/update-document-content.test.mjs +115 -112
- package/tests/agents/update/fs-tools/glob.test.mjs +438 -0
- package/tests/agents/update/fs-tools/grep.test.mjs +279 -0
- package/tests/agents/update/fs-tools/read-file.test.mjs +553 -0
- package/tests/agents/update/user-review-document.test.mjs +48 -27
- package/types/document-schema.mjs +5 -6
- package/types/document-structure-schema.mjs +20 -8
|
@@ -1,326 +1,329 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
1
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import updateDocumentContent from "../../../../agents/update/document-tools/update-document-content.mjs";
|
|
3
3
|
|
|
4
4
|
describe("update-document-content", () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
let mockOptions;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
mockOptions = {
|
|
9
|
+
context: {
|
|
10
|
+
userContext: {
|
|
11
|
+
currentContent: "",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
11
15
|
});
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("should return error when originalContent is empty string", async () => {
|
|
21
|
-
const result = await updateDocumentContent({ originalContent: "", diffPatch: "valid patch" });
|
|
22
|
-
expect(result.success).toBe(false);
|
|
23
|
-
expect(result.error).toContain("Original content is required");
|
|
24
|
-
expect(result.message).toBe("Invalid input parameters");
|
|
25
|
-
});
|
|
17
|
+
// Helper function to extract content from page_content wrapper
|
|
18
|
+
function extractContent(wrappedContent) {
|
|
19
|
+
const match = wrappedContent.match(/<page_content>\s*([\s\S]*?)\s*<\/page_content>/);
|
|
20
|
+
return match ? match[1] : wrappedContent;
|
|
21
|
+
}
|
|
26
22
|
|
|
23
|
+
// INPUT VALIDATION TESTS
|
|
27
24
|
test("should return error when diffPatch is not provided", async () => {
|
|
28
|
-
|
|
25
|
+
mockOptions.context.userContext.currentContent = "original content";
|
|
26
|
+
const result = await updateDocumentContent({}, mockOptions);
|
|
29
27
|
expect(result.success).toBe(false);
|
|
30
|
-
expect(result.error).toContain("diffPatch");
|
|
31
|
-
expect(result.message).toBe("Invalid input parameters");
|
|
28
|
+
expect(result.error.message).toContain("diffPatch");
|
|
32
29
|
});
|
|
33
30
|
|
|
34
31
|
test("should return error when diffPatch is not a string", async () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
diffPatch: null,
|
|
38
|
-
});
|
|
32
|
+
mockOptions.context.userContext.currentContent = "original content";
|
|
33
|
+
const result = await updateDocumentContent({ diffPatch: null }, mockOptions);
|
|
39
34
|
expect(result.success).toBe(false);
|
|
40
|
-
expect(result.error).toContain("diffPatch");
|
|
41
|
-
expect(result.message).toBe("Invalid input parameters");
|
|
35
|
+
expect(result.error.message).toContain("diffPatch");
|
|
42
36
|
});
|
|
43
37
|
|
|
44
38
|
test("should return error when diffPatch is empty string", async () => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
diffPatch: "",
|
|
48
|
-
});
|
|
39
|
+
mockOptions.context.userContext.currentContent = "original content";
|
|
40
|
+
const result = await updateDocumentContent({ diffPatch: "" }, mockOptions);
|
|
49
41
|
expect(result.success).toBe(false);
|
|
50
|
-
expect(result.error).toContain("Diff patch is required");
|
|
51
|
-
expect(result.message).toBe("Invalid input parameters");
|
|
42
|
+
expect(result.error.message).toContain("Diff patch is required");
|
|
52
43
|
});
|
|
53
44
|
|
|
54
45
|
// SUCCESSFUL PATCH APPLICATION TESTS
|
|
55
46
|
test("should successfully apply simple diff patch", async () => {
|
|
56
|
-
|
|
47
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
57
48
|
const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n-line 2\n+updated line 2\n line 3";
|
|
58
49
|
|
|
59
|
-
const result = await updateDocumentContent({
|
|
50
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
60
51
|
|
|
61
52
|
expect(result.success).toBe(true);
|
|
62
|
-
expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
|
|
63
|
-
expect(result.message).
|
|
53
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
54
|
+
expect(result.message).toContain("Document content updated successfully");
|
|
64
55
|
});
|
|
65
56
|
|
|
66
57
|
test("should handle diff with multiple hunks", async () => {
|
|
67
|
-
|
|
58
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
68
59
|
const diffPatch =
|
|
69
60
|
"@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2\n@@ -4,2 +4,2 @@\n line 4\n-line 5\n+updated line 5";
|
|
70
61
|
|
|
71
|
-
const result = await updateDocumentContent({
|
|
62
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
72
63
|
|
|
73
64
|
expect(result.success).toBe(true);
|
|
74
|
-
expect(result.updatedContent).toBe(
|
|
65
|
+
expect(extractContent(result.updatedContent)).toBe(
|
|
66
|
+
"updated line 1\nline 2\nline 3\nline 4\nupdated line 5",
|
|
67
|
+
);
|
|
75
68
|
});
|
|
76
69
|
|
|
77
70
|
test("should handle diff with additions only", async () => {
|
|
78
|
-
|
|
71
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
79
72
|
const diffPatch = "@@ -2,0 +3,2 @@\n line 2\n+new line 3\n+new line 4";
|
|
80
73
|
|
|
81
|
-
const result = await updateDocumentContent({
|
|
74
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
82
75
|
|
|
83
76
|
expect(result.success).toBe(true);
|
|
84
|
-
expect(result.updatedContent).toBe("line 1\nline 2\nnew line 3\nnew line 4");
|
|
77
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\nline 2\nnew line 3\nnew line 4");
|
|
85
78
|
});
|
|
86
79
|
|
|
87
80
|
test("should handle diff with deletions only", async () => {
|
|
88
|
-
|
|
81
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
|
|
89
82
|
const diffPatch = "@@ -2,2 +2,0 @@\n line 1\n-line 2\n-line 3\n line 4";
|
|
90
83
|
|
|
91
|
-
const result = await updateDocumentContent({
|
|
84
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
92
85
|
|
|
93
86
|
expect(result.success).toBe(true);
|
|
94
|
-
expect(result.updatedContent).toBe("line 1\nline 4");
|
|
87
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\nline 4");
|
|
95
88
|
});
|
|
96
89
|
|
|
97
90
|
test("should handle diff with context lines", async () => {
|
|
98
|
-
|
|
91
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
99
92
|
const diffPatch =
|
|
100
93
|
"@@ -2,3 +2,3 @@\n line 1\n line 2\n-line 3\n+updated line 3\n line 4\n line 5";
|
|
101
94
|
|
|
102
|
-
const result = await updateDocumentContent({
|
|
95
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
103
96
|
|
|
104
97
|
expect(result.success).toBe(true);
|
|
105
|
-
expect(result.updatedContent).toBe(
|
|
98
|
+
expect(extractContent(result.updatedContent)).toBe(
|
|
99
|
+
"line 1\nline 2\nupdated line 3\nline 4\nline 5",
|
|
100
|
+
);
|
|
106
101
|
});
|
|
107
102
|
|
|
108
103
|
// DIFF PATCH PARSING TESTS
|
|
109
104
|
test("should return error for invalid diff format", async () => {
|
|
110
|
-
|
|
105
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
111
106
|
const diffPatch = "invalid diff format";
|
|
112
107
|
|
|
113
|
-
const result = await updateDocumentContent({
|
|
108
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
114
109
|
|
|
115
110
|
expect(result).toEqual({
|
|
116
111
|
success: false,
|
|
117
|
-
error: "No valid hunks found in diff",
|
|
118
|
-
message: "Invalid diff format: No valid hunks found or parsing failed",
|
|
112
|
+
error: { message: "No valid hunks found in diff" },
|
|
119
113
|
});
|
|
120
114
|
});
|
|
121
115
|
|
|
122
116
|
test("should return error for empty diff", async () => {
|
|
123
|
-
|
|
117
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
124
118
|
const diffPatch = "\n\n";
|
|
125
119
|
|
|
126
|
-
const result = await updateDocumentContent({
|
|
120
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
127
121
|
|
|
128
122
|
expect(result).toEqual({
|
|
129
123
|
success: false,
|
|
130
|
-
error: "No valid hunks found in diff",
|
|
131
|
-
message: "Invalid diff format: No valid hunks found or parsing failed",
|
|
124
|
+
error: { message: "No valid hunks found in diff" },
|
|
132
125
|
});
|
|
133
126
|
});
|
|
134
127
|
|
|
135
128
|
test("should handle malformed hunk headers gracefully", async () => {
|
|
136
|
-
|
|
129
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2";
|
|
137
130
|
const diffPatch = "@@malformed header@@\n-line 1\n+updated line 1";
|
|
138
131
|
|
|
139
|
-
const result = await updateDocumentContent({
|
|
132
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
140
133
|
|
|
141
134
|
expect(result.success).toBe(false);
|
|
142
|
-
expect(result.message).
|
|
135
|
+
expect(result.error.message).toContain("No valid hunks found");
|
|
143
136
|
});
|
|
144
137
|
|
|
145
138
|
// LINE NUMBER FIXING TESTS
|
|
146
139
|
test("should fix line numbers when patch position is off", async () => {
|
|
147
|
-
|
|
140
|
+
mockOptions.context.userContext.currentContent = "prefix line\nline 1\nline 2\nline 3";
|
|
148
141
|
// This diff patch expects to find "line 1" at line 1, but it's actually at line 2
|
|
149
142
|
const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
|
|
150
143
|
|
|
151
|
-
const result = await updateDocumentContent({
|
|
144
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
152
145
|
|
|
153
146
|
expect(result.success).toBe(true);
|
|
154
|
-
expect(result.updatedContent).toBe(
|
|
147
|
+
expect(extractContent(result.updatedContent)).toBe(
|
|
148
|
+
"prefix line\nupdated line 1\nline 2\nline 3",
|
|
149
|
+
);
|
|
155
150
|
});
|
|
156
151
|
|
|
157
152
|
test("should use fuzzy matching when exact match fails", async () => {
|
|
158
|
-
|
|
153
|
+
mockOptions.context.userContext.currentContent =
|
|
154
|
+
"similar line 1\nsimilar line 2\ndifferent content\nsimilar line 3";
|
|
159
155
|
// This patch refers to lines that are similar but not exactly matching
|
|
160
156
|
const diffPatch = "@@ -10,2 +10,2 @@\n-similar line 1\n+updated line 1\n similar line 2";
|
|
161
157
|
|
|
162
|
-
const result = await updateDocumentContent({
|
|
158
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
163
159
|
|
|
164
160
|
expect(result.success).toBe(true);
|
|
165
|
-
expect(result.updatedContent).toBe(
|
|
161
|
+
expect(extractContent(result.updatedContent)).toBe(
|
|
166
162
|
"updated line 1\nsimilar line 2\ndifferent content\nsimilar line 3",
|
|
167
163
|
);
|
|
168
164
|
});
|
|
169
165
|
|
|
170
166
|
test("should return error when no matching context found", async () => {
|
|
171
|
-
|
|
167
|
+
mockOptions.context.userContext.currentContent =
|
|
168
|
+
"completely different content\nnothing matches";
|
|
172
169
|
const diffPatch =
|
|
173
170
|
"@@ -1,2 +1,2 @@\n-line that doesn't exist\n+updated line\n another nonexistent line";
|
|
174
171
|
|
|
175
|
-
const result = await updateDocumentContent({
|
|
172
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
176
173
|
|
|
177
174
|
expect(result.success).toBe(false);
|
|
178
|
-
expect(result.error).toContain("Cannot find matching context");
|
|
179
|
-
expect(result.message).toBe("Cannot fix diff line number issues");
|
|
175
|
+
expect(result.error.message).toContain("Cannot find matching context");
|
|
180
176
|
});
|
|
181
177
|
|
|
182
178
|
// COMPLEX DIFF SCENARIOS
|
|
183
179
|
test("should handle diff with no context lines", async () => {
|
|
184
|
-
|
|
180
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
185
181
|
const diffPatch = "@@ -2,1 +2,1 @@\n-line 2\n+updated line 2";
|
|
186
182
|
|
|
187
|
-
const result = await updateDocumentContent({
|
|
183
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
188
184
|
|
|
189
185
|
expect(result.success).toBe(true);
|
|
190
|
-
expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
|
|
186
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
191
187
|
});
|
|
192
188
|
|
|
193
189
|
test("should handle diff with single line count (implicit 1)", async () => {
|
|
194
|
-
|
|
190
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
195
191
|
const diffPatch = "@@ -2 +2 @@\n-line 2\n+updated line 2";
|
|
196
192
|
|
|
197
|
-
const result = await updateDocumentContent({
|
|
193
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
198
194
|
|
|
199
195
|
expect(result.success).toBe(true);
|
|
200
|
-
expect(result.updatedContent).toBe("line 1\nupdated line 2\nline 3");
|
|
196
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\nupdated line 2\nline 3");
|
|
201
197
|
});
|
|
202
198
|
|
|
203
199
|
test("should handle multiple changes in single hunk", async () => {
|
|
204
|
-
|
|
200
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4\nline 5";
|
|
205
201
|
const diffPatch =
|
|
206
202
|
"@@ -2,3 +2,4 @@\n line 1\n-line 2\n-line 3\n+updated line 2\n+new line\n+updated line 3\n line 4";
|
|
207
203
|
|
|
208
|
-
const result = await updateDocumentContent({
|
|
204
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
209
205
|
|
|
210
206
|
expect(result.success).toBe(true);
|
|
211
|
-
expect(result.updatedContent).toBe(
|
|
207
|
+
expect(extractContent(result.updatedContent)).toBe(
|
|
212
208
|
"line 1\nupdated line 2\nnew line\nupdated line 3\nline 4\nline 5",
|
|
213
209
|
);
|
|
214
210
|
});
|
|
215
211
|
|
|
216
212
|
// EDGE CASES
|
|
217
213
|
test("should handle empty lines in diff", async () => {
|
|
218
|
-
|
|
214
|
+
mockOptions.context.userContext.currentContent = "line 1\n\nline 3";
|
|
219
215
|
const diffPatch = "@@ -1,3 +1,3 @@\n line 1\n \n-line 3\n+updated line 3";
|
|
220
216
|
|
|
221
|
-
const result = await updateDocumentContent({
|
|
217
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
222
218
|
|
|
223
219
|
expect(result.success).toBe(true);
|
|
224
|
-
expect(result.updatedContent).toBe("line 1\n\nupdated line 3");
|
|
220
|
+
expect(extractContent(result.updatedContent)).toBe("line 1\n\nupdated line 3");
|
|
225
221
|
});
|
|
226
222
|
|
|
227
223
|
test("should handle diff with trailing newlines", async () => {
|
|
228
|
-
|
|
224
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\n";
|
|
229
225
|
const diffPatch = "@@ -1,2 +1,2 @@\n-line 1\n+updated line 1\n line 2";
|
|
230
226
|
|
|
231
|
-
const result = await updateDocumentContent({
|
|
227
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
232
228
|
|
|
233
229
|
expect(result.success).toBe(true);
|
|
234
|
-
|
|
230
|
+
// Note: applyPatch may normalize trailing newlines
|
|
231
|
+
const content = extractContent(result.updatedContent);
|
|
232
|
+
expect(content).toContain("updated line 1");
|
|
233
|
+
expect(content).toContain("line 2");
|
|
235
234
|
});
|
|
236
235
|
|
|
237
236
|
// REALISTIC DOCUMENTATION UPDATE SCENARIOS
|
|
238
237
|
test("should handle updating code blocks", async () => {
|
|
239
|
-
|
|
238
|
+
mockOptions.context.userContext.currentContent =
|
|
240
239
|
"# API Reference\n\n```javascript\nfunction oldFunction() {\n return 'old';\n}\n```\n\nDescription here.";
|
|
241
240
|
const diffPatch =
|
|
242
241
|
"@@ -3,3 +3,3 @@\n # API Reference\n \n ```javascript\n-function oldFunction() {\n- return 'old';\n+function newFunction() {\n+ return 'new';\n }\n ```";
|
|
243
242
|
|
|
244
|
-
const result = await updateDocumentContent({
|
|
243
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
245
244
|
|
|
246
245
|
expect(result.success).toBe(true);
|
|
247
|
-
|
|
248
|
-
expect(
|
|
246
|
+
const content = extractContent(result.updatedContent);
|
|
247
|
+
expect(content).toContain("function newFunction()");
|
|
248
|
+
expect(content).toContain("return 'new';");
|
|
249
249
|
});
|
|
250
250
|
|
|
251
251
|
test("should handle adding new sections", async () => {
|
|
252
|
-
|
|
252
|
+
mockOptions.context.userContext.currentContent =
|
|
253
253
|
"# Documentation\n\n## Section 1\n\nContent 1\n\n## Section 3\n\nContent 3";
|
|
254
254
|
const diffPatch =
|
|
255
255
|
"@@ -4,0 +5,3 @@\n Content 1\n \n+## Section 2\n+\n+Content 2\n+\n ## Section 3";
|
|
256
256
|
|
|
257
|
-
const result = await updateDocumentContent({
|
|
257
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
258
258
|
|
|
259
259
|
expect(result.success).toBe(true);
|
|
260
|
-
|
|
261
|
-
expect(
|
|
260
|
+
const content = extractContent(result.updatedContent);
|
|
261
|
+
expect(content).toContain("## Section 2");
|
|
262
|
+
expect(content).toContain("Content 2");
|
|
262
263
|
});
|
|
263
264
|
|
|
264
265
|
test("should handle removing outdated content", async () => {
|
|
265
|
-
|
|
266
|
+
mockOptions.context.userContext.currentContent =
|
|
266
267
|
"# Guide\n\n## Current Feature\n\nThis is current.\n\n## Deprecated Feature\n\nThis is deprecated.\n\n## Another Feature\n\nThis is also current.";
|
|
267
268
|
const diffPatch =
|
|
268
269
|
"@@ -5,4 +5,0 @@\n This is current.\n \n-## Deprecated Feature\n-\n-This is deprecated.\n-\n ## Another Feature";
|
|
269
270
|
|
|
270
|
-
const result = await updateDocumentContent({
|
|
271
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
271
272
|
|
|
272
273
|
expect(result.success).toBe(true);
|
|
273
|
-
|
|
274
|
-
expect(
|
|
275
|
-
expect(
|
|
274
|
+
const content = extractContent(result.updatedContent);
|
|
275
|
+
expect(content).not.toContain("Deprecated Feature");
|
|
276
|
+
expect(content).toContain("Current Feature");
|
|
277
|
+
expect(content).toContain("Another Feature");
|
|
276
278
|
});
|
|
277
279
|
|
|
278
280
|
// ERROR SCENARIOS WITH REALISTIC CONTENT
|
|
279
281
|
test("should handle conflicting patches gracefully", async () => {
|
|
280
|
-
|
|
282
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3";
|
|
281
283
|
// This patch tries to modify content that doesn't match exactly
|
|
282
284
|
const diffPatch =
|
|
283
285
|
"@@ -1,3 +1,3 @@\n-different line 1\n-different line 2\n+updated line 1\n+updated line 2\n line 3";
|
|
284
286
|
|
|
285
|
-
const result = await updateDocumentContent({
|
|
287
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
286
288
|
|
|
287
289
|
expect(result.success).toBe(false);
|
|
288
|
-
expect(result.error).toContain("Cannot find matching context");
|
|
290
|
+
expect(result.error.message).toContain("Cannot find matching context");
|
|
289
291
|
});
|
|
290
292
|
|
|
291
293
|
test("should handle patches with incorrect line counts", async () => {
|
|
292
|
-
|
|
294
|
+
mockOptions.context.userContext.currentContent = "line 1\nline 2\nline 3\nline 4";
|
|
293
295
|
// Incorrect line count in hunk header (says 5 lines but content has 4)
|
|
294
296
|
const diffPatch = "@@ -1,5 +1,3 @@\n-line 1\n-line 2\n line 3\n line 4";
|
|
295
297
|
|
|
296
|
-
const result = await updateDocumentContent({
|
|
298
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
297
299
|
|
|
298
300
|
expect(result.success).toBe(true);
|
|
299
|
-
expect(result.updatedContent).toBe("line 3\nline 4");
|
|
301
|
+
expect(extractContent(result.updatedContent)).toBe("line 3\nline 4");
|
|
300
302
|
});
|
|
301
303
|
|
|
302
304
|
// FUZZY MATCHING EDGE CASES
|
|
303
305
|
test("should succeed fuzzy matching with high similarity", async () => {
|
|
304
|
-
|
|
306
|
+
mockOptions.context.userContext.currentContent =
|
|
305
307
|
"function calculateTotal(items) {\n let total = 0;\n for (item of items) {\n total += item.price;\n }\n return total;\n}";
|
|
306
308
|
// Patch has slight differences but should match with fuzzy matching
|
|
307
309
|
const diffPatch =
|
|
308
310
|
"@@ -2,2 +2,2 @@\n function calculateTotal(items) {\n- let total = 0;\n+ let sum = 0;\n for (item of items) {";
|
|
309
311
|
|
|
310
|
-
const result = await updateDocumentContent({
|
|
312
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
311
313
|
|
|
312
314
|
expect(result.success).toBe(true);
|
|
313
|
-
expect(result.updatedContent).toContain("let sum = 0;");
|
|
315
|
+
expect(extractContent(result.updatedContent)).toContain("let sum = 0;");
|
|
314
316
|
});
|
|
315
317
|
|
|
316
318
|
test("should fail fuzzy matching with low similarity", async () => {
|
|
317
|
-
|
|
319
|
+
mockOptions.context.userContext.currentContent =
|
|
320
|
+
"completely different content\nwith nothing similar\nat all";
|
|
318
321
|
const diffPatch =
|
|
319
322
|
"@@ -1,2 +1,2 @@\n-some totally different text\n+updated text\n that has no relation";
|
|
320
323
|
|
|
321
|
-
const result = await updateDocumentContent({
|
|
324
|
+
const result = await updateDocumentContent({ diffPatch }, mockOptions);
|
|
322
325
|
|
|
323
326
|
expect(result.success).toBe(false);
|
|
324
|
-
expect(result.error).toContain("Cannot find matching context");
|
|
327
|
+
expect(result.error.message).toContain("Cannot find matching context");
|
|
325
328
|
});
|
|
326
329
|
});
|