@aigne/doc-smith 0.5.1 → 0.7.0
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/.github/workflows/ci.yml +46 -0
- package/.github/workflows/reviewer.yml +2 -1
- package/CHANGELOG.md +17 -0
- package/agents/chat.yaml +30 -0
- package/agents/check-detail-result.mjs +2 -1
- package/agents/check-detail.mjs +1 -0
- package/agents/check-structure-plan.mjs +1 -1
- package/agents/docs-fs.yaml +25 -0
- package/agents/exit.mjs +6 -0
- package/agents/feedback-refiner.yaml +5 -1
- package/agents/find-items-by-paths.mjs +10 -4
- package/agents/fs.mjs +60 -0
- package/agents/input-generator.mjs +159 -90
- package/agents/load-config.mjs +0 -5
- package/agents/load-sources.mjs +119 -12
- package/agents/publish-docs.mjs +28 -11
- package/agents/retranslate.yaml +1 -1
- package/agents/team-publish-docs.yaml +2 -2
- package/aigne.yaml +1 -0
- package/package.json +13 -10
- package/prompts/content-detail-generator.md +12 -4
- package/prompts/document/custom-components.md +80 -0
- package/prompts/document/d2-chart/diy-examples.md +44 -0
- package/prompts/document/d2-chart/official-examples.md +708 -0
- package/prompts/document/d2-chart/rules.md +48 -0
- package/prompts/document/detail-generator.md +13 -15
- package/prompts/document/structure-planning.md +1 -3
- package/prompts/feedback-refiner.md +81 -60
- package/prompts/structure-planning.md +20 -3
- package/tests/check-detail-result.test.mjs +50 -2
- package/tests/conflict-resolution.test.mjs +237 -0
- package/tests/input-generator.test.mjs +940 -0
- package/tests/load-sources.test.mjs +627 -3
- package/tests/preferences-utils.test.mjs +94 -0
- package/tests/save-value-to-config.test.mjs +182 -5
- package/tests/utils.test.mjs +49 -0
- package/utils/auth-utils.mjs +1 -1
- package/utils/conflict-detector.mjs +72 -1
- package/utils/constants.mjs +139 -126
- package/utils/kroki-utils.mjs +162 -0
- package/utils/markdown-checker.mjs +175 -67
- package/utils/utils.mjs +97 -29
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { parse as parseYAML } from "yaml";
|
|
3
|
+
import { generateYAML } from "../agents/input-generator.mjs";
|
|
4
|
+
|
|
5
|
+
describe("generateYAML", () => {
|
|
6
|
+
// Helper function to parse YAML and verify it's valid
|
|
7
|
+
function parseAndValidateYAML(yamlString) {
|
|
8
|
+
let config;
|
|
9
|
+
expect(() => {
|
|
10
|
+
config = parseYAML(yamlString);
|
|
11
|
+
}).not.toThrow(); // YAML should be parseable
|
|
12
|
+
expect(config).toBeDefined();
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
describe("Complete valid user scenarios", () => {
|
|
16
|
+
test("should handle typical developer-focused configuration", () => {
|
|
17
|
+
const input = {
|
|
18
|
+
// Question 1: Document Purpose (checkbox, at least 1)
|
|
19
|
+
documentPurpose: ["getStarted", "findAnswers"],
|
|
20
|
+
|
|
21
|
+
// Question 2: Target Audience (checkbox, at least 1)
|
|
22
|
+
targetAudienceTypes: ["developers"],
|
|
23
|
+
|
|
24
|
+
// Question 3: Reader Knowledge Level (select, single choice)
|
|
25
|
+
readerKnowledgeLevel: "domainFamiliar",
|
|
26
|
+
|
|
27
|
+
// Question 4: Documentation Depth (select, single choice)
|
|
28
|
+
documentationDepth: "balancedCoverage",
|
|
29
|
+
|
|
30
|
+
// Question 5: Primary Language (select, single choice)
|
|
31
|
+
locale: "en",
|
|
32
|
+
|
|
33
|
+
// Question 6: Translation Languages (checkbox, optional)
|
|
34
|
+
translateLanguages: ["zh", "ja"],
|
|
35
|
+
|
|
36
|
+
// Question 7: Documentation Directory (input, with default)
|
|
37
|
+
docsDir: ".aigne/doc-smith/docs",
|
|
38
|
+
|
|
39
|
+
// Question 8: Source Paths (multiple inputs, with default)
|
|
40
|
+
sourcesPath: ["./src", "./lib"],
|
|
41
|
+
|
|
42
|
+
// Project Info (from getProjectInfo)
|
|
43
|
+
projectName: "My Awesome Project",
|
|
44
|
+
projectDesc: "A comprehensive library for developers",
|
|
45
|
+
projectLogo: "assets/logo.png",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const result = generateYAML(input);
|
|
49
|
+
|
|
50
|
+
// Parse and validate YAML structure
|
|
51
|
+
const config = parseAndValidateYAML(result);
|
|
52
|
+
|
|
53
|
+
// Verify project information
|
|
54
|
+
expect(config.projectName).toBe("My Awesome Project");
|
|
55
|
+
expect(config.projectDesc).toBe("A comprehensive library for developers");
|
|
56
|
+
expect(config.projectLogo).toBe("assets/logo.png");
|
|
57
|
+
|
|
58
|
+
// Verify document purpose array
|
|
59
|
+
expect(Array.isArray(config.documentPurpose)).toBe(true);
|
|
60
|
+
expect(config.documentPurpose).toEqual(["getStarted", "findAnswers"]);
|
|
61
|
+
|
|
62
|
+
// Verify target audience array
|
|
63
|
+
expect(Array.isArray(config.targetAudienceTypes)).toBe(true);
|
|
64
|
+
expect(config.targetAudienceTypes).toEqual(["developers"]);
|
|
65
|
+
|
|
66
|
+
// Verify single value fields
|
|
67
|
+
expect(config.readerKnowledgeLevel).toBe("domainFamiliar");
|
|
68
|
+
expect(config.documentationDepth).toBe("balancedCoverage");
|
|
69
|
+
expect(config.locale).toBe("en");
|
|
70
|
+
|
|
71
|
+
// Verify translation languages array
|
|
72
|
+
expect(Array.isArray(config.translateLanguages)).toBe(true);
|
|
73
|
+
expect(config.translateLanguages).toEqual(["zh", "ja"]);
|
|
74
|
+
|
|
75
|
+
// Verify paths
|
|
76
|
+
expect(config.docsDir).toBe(".aigne/doc-smith/docs");
|
|
77
|
+
expect(Array.isArray(config.sourcesPath)).toBe(true);
|
|
78
|
+
expect(config.sourcesPath).toEqual(["./src", "./lib"]);
|
|
79
|
+
|
|
80
|
+
// Verify comments are present (using string matching for comments)
|
|
81
|
+
expect(result).toContain("# Project information for documentation publishing");
|
|
82
|
+
expect(result).toContain("# Documentation Configuration");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("should handle end-user focused minimal configuration", () => {
|
|
86
|
+
const input = {
|
|
87
|
+
documentPurpose: ["getStarted"],
|
|
88
|
+
targetAudienceTypes: ["endUsers"],
|
|
89
|
+
readerKnowledgeLevel: "completeBeginners",
|
|
90
|
+
documentationDepth: "essentialOnly",
|
|
91
|
+
locale: "en",
|
|
92
|
+
translateLanguages: [],
|
|
93
|
+
docsDir: "./docs",
|
|
94
|
+
sourcesPath: ["./"],
|
|
95
|
+
projectName: "User-Friendly App",
|
|
96
|
+
projectDesc: "Simple app for everyone",
|
|
97
|
+
projectLogo: "",
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const result = generateYAML(input);
|
|
101
|
+
|
|
102
|
+
// Parse and validate YAML structure
|
|
103
|
+
const config = parseAndValidateYAML(result);
|
|
104
|
+
|
|
105
|
+
// Verify configuration values
|
|
106
|
+
expect(config.documentPurpose).toEqual(["getStarted"]);
|
|
107
|
+
expect(config.targetAudienceTypes).toEqual(["endUsers"]);
|
|
108
|
+
expect(config.readerKnowledgeLevel).toBe("completeBeginners");
|
|
109
|
+
expect(config.documentationDepth).toBe("essentialOnly");
|
|
110
|
+
expect(config.locale).toBe("en");
|
|
111
|
+
expect(config.translateLanguages).toEqual(undefined);
|
|
112
|
+
expect(config.docsDir).toBe("./docs");
|
|
113
|
+
expect(config.sourcesPath).toEqual(["./"]);
|
|
114
|
+
expect(config.projectName).toBe("User-Friendly App");
|
|
115
|
+
expect(config.projectDesc).toBe("Simple app for everyone");
|
|
116
|
+
expect(config.projectLogo).toBe("");
|
|
117
|
+
|
|
118
|
+
// Verify comments for empty translateLanguages (string matching for comments)
|
|
119
|
+
expect(result).toContain("# translateLanguages: # List of languages to translate");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("should handle mixed purpose with priority selection", () => {
|
|
123
|
+
// Simulates user selecting mixedPurpose first, then choosing top 2 priorities
|
|
124
|
+
const input = {
|
|
125
|
+
documentPurpose: ["completeTasks", "findAnswers"], // The 2 priorities selected after mixedPurpose
|
|
126
|
+
targetAudienceTypes: ["developers", "devops"],
|
|
127
|
+
readerKnowledgeLevel: "experiencedUsers",
|
|
128
|
+
documentationDepth: "comprehensive",
|
|
129
|
+
locale: "zh-CN",
|
|
130
|
+
translateLanguages: ["en"],
|
|
131
|
+
docsDir: "./documentation",
|
|
132
|
+
sourcesPath: ["./src/**/*.js", "./lib/**/*.ts"],
|
|
133
|
+
projectName: "Enterprise Solution",
|
|
134
|
+
projectDesc: "Advanced enterprise-grade solution",
|
|
135
|
+
projectLogo: "brand/logo.svg",
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const result = generateYAML(input);
|
|
139
|
+
|
|
140
|
+
expect(result).toContain("- completeTasks");
|
|
141
|
+
expect(result).toContain("- findAnswers");
|
|
142
|
+
expect(result).toContain("- developers");
|
|
143
|
+
expect(result).toContain("- devops");
|
|
144
|
+
expect(result).toContain("locale: zh-CN");
|
|
145
|
+
expect(result).toContain("- en");
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe("Document Purpose combinations", () => {
|
|
150
|
+
test("should handle single purpose selection", () => {
|
|
151
|
+
const validPurposes = [
|
|
152
|
+
"getStarted",
|
|
153
|
+
"completeTasks",
|
|
154
|
+
"findAnswers",
|
|
155
|
+
"understandSystem",
|
|
156
|
+
"solveProblems",
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
validPurposes.forEach((purpose) => {
|
|
160
|
+
const input = {
|
|
161
|
+
documentPurpose: [purpose],
|
|
162
|
+
targetAudienceTypes: ["developers"],
|
|
163
|
+
locale: "en",
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const result = generateYAML(input);
|
|
167
|
+
const config = parseAndValidateYAML(result);
|
|
168
|
+
|
|
169
|
+
expect(config.documentPurpose).toEqual([purpose]);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("should handle multiple purpose combinations", () => {
|
|
174
|
+
const combinations = [
|
|
175
|
+
["getStarted", "completeTasks"],
|
|
176
|
+
["findAnswers", "solveProblems"],
|
|
177
|
+
["understandSystem", "completeTasks", "findAnswers"],
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
combinations.forEach((purposes) => {
|
|
181
|
+
const input = {
|
|
182
|
+
documentPurpose: purposes,
|
|
183
|
+
targetAudienceTypes: ["developers"],
|
|
184
|
+
locale: "en",
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const result = generateYAML(input);
|
|
188
|
+
const config = parseAndValidateYAML(result);
|
|
189
|
+
|
|
190
|
+
expect(config.documentPurpose).toEqual(purposes);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("Target Audience combinations", () => {
|
|
196
|
+
test("should handle all valid audience types", () => {
|
|
197
|
+
const validAudiences = [
|
|
198
|
+
"endUsers",
|
|
199
|
+
"developers",
|
|
200
|
+
"devops",
|
|
201
|
+
"decisionMakers",
|
|
202
|
+
"supportTeams",
|
|
203
|
+
"mixedTechnical",
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
validAudiences.forEach((audience) => {
|
|
207
|
+
const input = {
|
|
208
|
+
documentPurpose: ["getStarted"],
|
|
209
|
+
targetAudienceTypes: [audience],
|
|
210
|
+
locale: "en",
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const result = generateYAML(input);
|
|
214
|
+
expect(result).toContain(`- ${audience}`);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test("should handle mixed audience selections", () => {
|
|
219
|
+
const input = {
|
|
220
|
+
documentPurpose: ["completeTasks"],
|
|
221
|
+
targetAudienceTypes: ["developers", "devops", "supportTeams"],
|
|
222
|
+
locale: "en",
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const result = generateYAML(input);
|
|
226
|
+
expect(result).toContain("- developers");
|
|
227
|
+
expect(result).toContain("- devops");
|
|
228
|
+
expect(result).toContain("- supportTeams");
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe("Knowledge Level scenarios", () => {
|
|
233
|
+
test("should handle all valid knowledge levels", () => {
|
|
234
|
+
const validLevels = [
|
|
235
|
+
"completeBeginners",
|
|
236
|
+
"domainFamiliar",
|
|
237
|
+
"hasBasicKnowledge",
|
|
238
|
+
"experiencedUsers",
|
|
239
|
+
"emergencyTroubleshooting",
|
|
240
|
+
"exploringEvaluating",
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
validLevels.forEach((level) => {
|
|
244
|
+
const input = {
|
|
245
|
+
documentPurpose: ["getStarted"],
|
|
246
|
+
targetAudienceTypes: ["developers"],
|
|
247
|
+
readerKnowledgeLevel: level,
|
|
248
|
+
locale: "en",
|
|
249
|
+
docsDir: "./docs", // Provide required field to avoid YAML generation bug
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const result = generateYAML(input);
|
|
253
|
+
const config = parseAndValidateYAML(result);
|
|
254
|
+
|
|
255
|
+
expect(config.readerKnowledgeLevel).toBe(level);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe("Documentation Depth scenarios", () => {
|
|
261
|
+
test("should handle all valid depth levels", () => {
|
|
262
|
+
const validDepths = ["essentialOnly", "balancedCoverage", "comprehensive", "aiDecide"];
|
|
263
|
+
|
|
264
|
+
validDepths.forEach((depth) => {
|
|
265
|
+
const input = {
|
|
266
|
+
documentPurpose: ["getStarted"],
|
|
267
|
+
targetAudienceTypes: ["developers"],
|
|
268
|
+
documentationDepth: depth,
|
|
269
|
+
locale: "en",
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const result = generateYAML(input);
|
|
273
|
+
expect(result).toContain(`documentationDepth: ${depth}`);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe("Locale and translation scenarios", () => {
|
|
279
|
+
test("should handle all supported locales", () => {
|
|
280
|
+
const supportedLocales = [
|
|
281
|
+
"en",
|
|
282
|
+
"zh",
|
|
283
|
+
"ja",
|
|
284
|
+
"ko",
|
|
285
|
+
"es",
|
|
286
|
+
"fr",
|
|
287
|
+
"de",
|
|
288
|
+
"it",
|
|
289
|
+
"pt",
|
|
290
|
+
"ru",
|
|
291
|
+
"ar",
|
|
292
|
+
"hi",
|
|
293
|
+
"th",
|
|
294
|
+
"vi",
|
|
295
|
+
"id",
|
|
296
|
+
"ms",
|
|
297
|
+
"tl",
|
|
298
|
+
"tr",
|
|
299
|
+
"pl",
|
|
300
|
+
"nl",
|
|
301
|
+
"sv",
|
|
302
|
+
"da",
|
|
303
|
+
"no",
|
|
304
|
+
"fi",
|
|
305
|
+
"hu",
|
|
306
|
+
"cs",
|
|
307
|
+
"sk",
|
|
308
|
+
"ro",
|
|
309
|
+
"bg",
|
|
310
|
+
"hr",
|
|
311
|
+
"sl",
|
|
312
|
+
"et",
|
|
313
|
+
"lv",
|
|
314
|
+
"lt",
|
|
315
|
+
"mt",
|
|
316
|
+
"el",
|
|
317
|
+
"he",
|
|
318
|
+
"fa",
|
|
319
|
+
"ur",
|
|
320
|
+
"bn",
|
|
321
|
+
"ta",
|
|
322
|
+
"te",
|
|
323
|
+
"kn",
|
|
324
|
+
"ml",
|
|
325
|
+
"gu",
|
|
326
|
+
"pa",
|
|
327
|
+
"or",
|
|
328
|
+
"as",
|
|
329
|
+
"ne",
|
|
330
|
+
"si",
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
// Test a subset to keep test reasonable
|
|
334
|
+
const testLocales = supportedLocales.slice(0, 10);
|
|
335
|
+
|
|
336
|
+
testLocales.forEach((locale) => {
|
|
337
|
+
const input = {
|
|
338
|
+
documentPurpose: ["getStarted"],
|
|
339
|
+
targetAudienceTypes: ["developers"],
|
|
340
|
+
locale: locale,
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const result = generateYAML(input);
|
|
344
|
+
const config = parseAndValidateYAML(result);
|
|
345
|
+
|
|
346
|
+
expect(config.locale).toBe(locale);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
test("should handle complex locale formats", () => {
|
|
351
|
+
const complexLocales = ["zh-CN", "zh-TW", "en-US", "en-GB", "pt-BR", "es-ES", "fr-CA"];
|
|
352
|
+
|
|
353
|
+
complexLocales.forEach((locale) => {
|
|
354
|
+
const input = {
|
|
355
|
+
documentPurpose: ["getStarted"],
|
|
356
|
+
targetAudienceTypes: ["developers"],
|
|
357
|
+
locale: locale,
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const result = generateYAML(input);
|
|
361
|
+
expect(result).toContain(`locale: ${locale}`);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test("should handle translation language combinations", () => {
|
|
366
|
+
const input = {
|
|
367
|
+
documentPurpose: ["getStarted"],
|
|
368
|
+
targetAudienceTypes: ["developers"],
|
|
369
|
+
locale: "en",
|
|
370
|
+
translateLanguages: ["zh", "ja", "ko", "es", "fr"],
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const result = generateYAML(input);
|
|
374
|
+
expect(result).toContain("translateLanguages:");
|
|
375
|
+
expect(result).toContain("- zh");
|
|
376
|
+
expect(result).toContain("- ja");
|
|
377
|
+
expect(result).toContain("- ko");
|
|
378
|
+
expect(result).toContain("- es");
|
|
379
|
+
expect(result).toContain("- fr");
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("should handle empty translation languages", () => {
|
|
383
|
+
const input = {
|
|
384
|
+
documentPurpose: ["getStarted"],
|
|
385
|
+
targetAudienceTypes: ["developers"],
|
|
386
|
+
locale: "en",
|
|
387
|
+
translateLanguages: [],
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const result = generateYAML(input);
|
|
391
|
+
expect(result).toContain("# translateLanguages: # List of languages to translate");
|
|
392
|
+
expect(result).toContain("# - zh # Example: Chinese translation");
|
|
393
|
+
expect(result).toContain("# - en # Example: English translation");
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe("Project info from GitHub/Git scenarios - Strict YAML validation", () => {
|
|
398
|
+
test("should handle typical GitHub project names with various formats", () => {
|
|
399
|
+
const githubProjectNames = [
|
|
400
|
+
// Common GitHub naming patterns
|
|
401
|
+
"awesome-project",
|
|
402
|
+
"my_awesome_project",
|
|
403
|
+
"AwesomeProject",
|
|
404
|
+
"project-v2.0.1",
|
|
405
|
+
"project_name_2024",
|
|
406
|
+
"some-org.awesome-project",
|
|
407
|
+
"project.config.js",
|
|
408
|
+
"@scoped/package-name",
|
|
409
|
+
"react-native-component",
|
|
410
|
+
"vue3-typescript-starter",
|
|
411
|
+
"nestjs-api-boilerplate",
|
|
412
|
+
"k8s-deployment-tools",
|
|
413
|
+
];
|
|
414
|
+
|
|
415
|
+
githubProjectNames.forEach((projectName) => {
|
|
416
|
+
const input = {
|
|
417
|
+
documentPurpose: ["getStarted"],
|
|
418
|
+
targetAudienceTypes: ["developers"],
|
|
419
|
+
locale: "en",
|
|
420
|
+
docsDir: "./docs",
|
|
421
|
+
projectName,
|
|
422
|
+
projectDesc: `Description for ${projectName}`,
|
|
423
|
+
projectLogo: "assets/logo.png",
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const result = generateYAML(input);
|
|
427
|
+
const config = parseAndValidateYAML(result);
|
|
428
|
+
|
|
429
|
+
expect(config.projectName).toBe(projectName);
|
|
430
|
+
expect(config.projectDesc).toBe(`Description for ${projectName}`);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test("should handle project names with special characters and symbols", () => {
|
|
435
|
+
const specialCharacterNames = [
|
|
436
|
+
// YAML potentially problematic characters
|
|
437
|
+
"project: with colon",
|
|
438
|
+
'project "with quotes"',
|
|
439
|
+
"project 'with single quotes'",
|
|
440
|
+
"project [with brackets]",
|
|
441
|
+
"project {with braces}",
|
|
442
|
+
"project | with pipe",
|
|
443
|
+
"project > with gt",
|
|
444
|
+
"project < with lt",
|
|
445
|
+
"project & with ampersand",
|
|
446
|
+
"project % with percent",
|
|
447
|
+
"project # with hash",
|
|
448
|
+
"project @ with at",
|
|
449
|
+
"project ! with exclamation",
|
|
450
|
+
"project ? with question",
|
|
451
|
+
"project * with asterisk",
|
|
452
|
+
"project ~ with tilde",
|
|
453
|
+
"project ` with backtick",
|
|
454
|
+
"project \\ with backslash",
|
|
455
|
+
"project / with slash",
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
specialCharacterNames.forEach((projectName) => {
|
|
459
|
+
const input = {
|
|
460
|
+
documentPurpose: ["getStarted"],
|
|
461
|
+
targetAudienceTypes: ["developers"],
|
|
462
|
+
locale: "en",
|
|
463
|
+
docsDir: "./docs",
|
|
464
|
+
projectName,
|
|
465
|
+
projectDesc: "Project with special characters",
|
|
466
|
+
projectLogo: "logo.png",
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
const result = generateYAML(input);
|
|
470
|
+
const config = parseAndValidateYAML(result);
|
|
471
|
+
|
|
472
|
+
// YAML should be valid and preserve the exact project name
|
|
473
|
+
expect(config.projectName).toBe(projectName);
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test("should handle project descriptions with complex formatting", () => {
|
|
478
|
+
const complexDescriptions = [
|
|
479
|
+
// Multi-line with various formatting
|
|
480
|
+
"Line 1: Overview\nLine 2: Features\n\nLine 4: Usage",
|
|
481
|
+
"Description with\ttabs\tand\nnewlines",
|
|
482
|
+
"Description with 'single quotes' and \"double quotes\"",
|
|
483
|
+
"Description with [links](http://example.com) and *emphasis*",
|
|
484
|
+
"Description with #hashtags and @mentions",
|
|
485
|
+
'JSON-like content: {"key": "value", "array": [1, 2, 3]}',
|
|
486
|
+
"YAML-like content:\n key: value\n list:\n - item1\n - item2",
|
|
487
|
+
"Code snippets: `npm install` and ```javascript\nconsole.log('hello');\n```",
|
|
488
|
+
"URLs: https://github.com/user/repo and http://example.com:8080/path?query=value",
|
|
489
|
+
"Email: user@example.com and file paths: /usr/local/bin/app",
|
|
490
|
+
];
|
|
491
|
+
|
|
492
|
+
complexDescriptions.forEach((projectDesc) => {
|
|
493
|
+
const input = {
|
|
494
|
+
documentPurpose: ["getStarted"],
|
|
495
|
+
targetAudienceTypes: ["developers"],
|
|
496
|
+
locale: "en",
|
|
497
|
+
docsDir: "./docs",
|
|
498
|
+
projectName: "Test Project",
|
|
499
|
+
projectDesc,
|
|
500
|
+
projectLogo: "logo.png",
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const result = generateYAML(input);
|
|
504
|
+
const config = parseAndValidateYAML(result);
|
|
505
|
+
|
|
506
|
+
// YAML should be valid and preserve the exact description
|
|
507
|
+
expect(config.projectDesc).toBe(projectDesc);
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test("should handle international and emoji-rich project info", () => {
|
|
512
|
+
const internationalCases = [
|
|
513
|
+
{
|
|
514
|
+
projectName: "项目名称-中文",
|
|
515
|
+
projectDesc: "这是一个中文项目描述,包含中文标点符号:,。!?",
|
|
516
|
+
locale: "zh-CN",
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
projectName: "プロジェクト名前-日本語",
|
|
520
|
+
projectDesc: "これは日本語のプロジェクト説明です。ひらがな、カタカナ、漢字を含みます。",
|
|
521
|
+
locale: "ja",
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
projectName: "proyecto-español",
|
|
525
|
+
projectDesc: "Descripción del proyecto con acentos: ñáéíóúü y signos ¡¿",
|
|
526
|
+
locale: "es",
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
projectName: "проект-русский",
|
|
530
|
+
projectDesc: "Описание проекта на русском языке с кириллицей",
|
|
531
|
+
locale: "ru",
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
projectName: "مشروع-عربي",
|
|
535
|
+
projectDesc: "وصف المشروع باللغة العربية من اليمين إلى اليسار",
|
|
536
|
+
locale: "ar",
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
projectName: "🚀 Awesome Project 🎉",
|
|
540
|
+
projectDesc: "Project with emojis: 📱💻🔥⚡🌟✨🎯🚀💡🔧⭐🎨🎪🎭",
|
|
541
|
+
locale: "en",
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
projectName: "Mixed語言Project混合नाम",
|
|
545
|
+
projectDesc: "Multi-language混合description with हिंदी, 中文, English, and العربية",
|
|
546
|
+
locale: "en",
|
|
547
|
+
},
|
|
548
|
+
];
|
|
549
|
+
|
|
550
|
+
internationalCases.forEach(({ projectName, projectDesc, locale }) => {
|
|
551
|
+
const input = {
|
|
552
|
+
documentPurpose: ["getStarted"],
|
|
553
|
+
targetAudienceTypes: ["developers"],
|
|
554
|
+
locale,
|
|
555
|
+
docsDir: "./docs",
|
|
556
|
+
projectName,
|
|
557
|
+
projectDesc,
|
|
558
|
+
projectLogo: "assets/logo.svg",
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
const result = generateYAML(input);
|
|
562
|
+
const config = parseAndValidateYAML(result);
|
|
563
|
+
|
|
564
|
+
expect(config.projectName).toBe(projectName);
|
|
565
|
+
expect(config.projectDesc).toBe(projectDesc);
|
|
566
|
+
expect(config.locale).toBe(locale);
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
test("should handle project logos with various path formats", () => {
|
|
571
|
+
const logoPaths = [
|
|
572
|
+
// Different path formats that might come from GitHub
|
|
573
|
+
"logo.png",
|
|
574
|
+
"assets/logo.svg",
|
|
575
|
+
"docs/images/logo-128x128.png",
|
|
576
|
+
"public/icons/favicon.ico",
|
|
577
|
+
".github/logo.jpg",
|
|
578
|
+
"static/brand/logo_dark.png",
|
|
579
|
+
"src/assets/images/logo@2x.png",
|
|
580
|
+
"media/logos/company-logo.webp",
|
|
581
|
+
"https://raw.githubusercontent.com/user/repo/main/logo.png",
|
|
582
|
+
"https://github.com/user/repo/blob/main/assets/logo.svg?raw=true",
|
|
583
|
+
// Paths with special characters
|
|
584
|
+
"assets/logo with spaces.png",
|
|
585
|
+
"logos/logo-企业.svg",
|
|
586
|
+
"images/логотип.png",
|
|
587
|
+
"assets/logo_v2.0-beta.png",
|
|
588
|
+
"brand/logo[dark].png",
|
|
589
|
+
"icons/logo{small}.ico",
|
|
590
|
+
];
|
|
591
|
+
|
|
592
|
+
logoPaths.forEach((projectLogo) => {
|
|
593
|
+
const input = {
|
|
594
|
+
documentPurpose: ["getStarted"],
|
|
595
|
+
targetAudienceTypes: ["developers"],
|
|
596
|
+
locale: "en",
|
|
597
|
+
docsDir: "./docs",
|
|
598
|
+
projectName: "Test Project",
|
|
599
|
+
projectDesc: "Project with various logo paths",
|
|
600
|
+
projectLogo,
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
const result = generateYAML(input);
|
|
604
|
+
const config = parseAndValidateYAML(result);
|
|
605
|
+
|
|
606
|
+
expect(config.projectLogo).toBe(projectLogo);
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
test("should handle edge cases from GitHub repository parsing", () => {
|
|
611
|
+
const edgeCases = [
|
|
612
|
+
{
|
|
613
|
+
name: "Empty values",
|
|
614
|
+
projectName: "",
|
|
615
|
+
projectDesc: "",
|
|
616
|
+
projectLogo: "",
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
name: "Whitespace-only values",
|
|
620
|
+
projectName: " ",
|
|
621
|
+
projectDesc: "\n\n \t \n",
|
|
622
|
+
projectLogo: " ",
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
name: "Very long values",
|
|
626
|
+
projectName: "a".repeat(200),
|
|
627
|
+
projectDesc:
|
|
628
|
+
"This is a very long description that might come from a detailed README file. ".repeat(
|
|
629
|
+
50,
|
|
630
|
+
),
|
|
631
|
+
projectLogo:
|
|
632
|
+
"assets/very/deep/path/to/a/logo/file/that/might/exist/in/some/repository/structure/logo.png",
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
name: "YAML reserved words",
|
|
636
|
+
projectName: "true",
|
|
637
|
+
projectDesc: "false",
|
|
638
|
+
projectLogo: "null",
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
name: "Numeric strings",
|
|
642
|
+
projectName: "123",
|
|
643
|
+
projectDesc: "456.789",
|
|
644
|
+
projectLogo: "0x123.png",
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
name: "Boolean-like strings",
|
|
648
|
+
projectName: "yes",
|
|
649
|
+
projectDesc: "no",
|
|
650
|
+
projectLogo: "on.svg",
|
|
651
|
+
},
|
|
652
|
+
];
|
|
653
|
+
|
|
654
|
+
edgeCases.forEach(({ projectName, projectDesc, projectLogo }) => {
|
|
655
|
+
const input = {
|
|
656
|
+
documentPurpose: ["getStarted"],
|
|
657
|
+
targetAudienceTypes: ["developers"],
|
|
658
|
+
locale: "en",
|
|
659
|
+
docsDir: "./docs",
|
|
660
|
+
projectName,
|
|
661
|
+
projectDesc,
|
|
662
|
+
projectLogo,
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
const result = generateYAML(input);
|
|
666
|
+
const config = parseAndValidateYAML(result);
|
|
667
|
+
|
|
668
|
+
// All values should be preserved exactly as input
|
|
669
|
+
expect(config.projectName).toBe(projectName);
|
|
670
|
+
expect(config.projectDesc).toBe(projectDesc);
|
|
671
|
+
expect(config.projectLogo).toBe(projectLogo);
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
test("should handle GitHub-specific metadata patterns", () => {
|
|
676
|
+
const githubPatterns = [
|
|
677
|
+
{
|
|
678
|
+
projectName: "facebook/react",
|
|
679
|
+
projectDesc:
|
|
680
|
+
"A declarative, efficient, and flexible JavaScript library for building user interfaces.",
|
|
681
|
+
projectLogo:
|
|
682
|
+
"https://github.com/facebook/react/blob/main/fixtures/attribute-behavior/src/logo.svg",
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
projectName: "microsoft/vscode",
|
|
686
|
+
projectDesc:
|
|
687
|
+
"Visual Studio Code - The editor you love. Built for developers, by developers.",
|
|
688
|
+
projectLogo: "resources/linux/code.png",
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
projectName: "vercel/next.js",
|
|
692
|
+
projectDesc: "The React Framework – created and maintained by @vercel.",
|
|
693
|
+
projectLogo: "docs/assets/next-logo.svg",
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
projectName: "nodejs/node",
|
|
697
|
+
projectDesc: "Node.js JavaScript runtime ✨🐢🚀✨",
|
|
698
|
+
projectLogo: "src/res/node.ico",
|
|
699
|
+
},
|
|
700
|
+
];
|
|
701
|
+
|
|
702
|
+
githubPatterns.forEach(({ projectName, projectDesc, projectLogo }) => {
|
|
703
|
+
const input = {
|
|
704
|
+
documentPurpose: ["getStarted"],
|
|
705
|
+
targetAudienceTypes: ["developers"],
|
|
706
|
+
locale: "en",
|
|
707
|
+
docsDir: "./docs",
|
|
708
|
+
projectName,
|
|
709
|
+
projectDesc,
|
|
710
|
+
projectLogo,
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
const result = generateYAML(input);
|
|
714
|
+
const config = parseAndValidateYAML(result);
|
|
715
|
+
|
|
716
|
+
expect(config.projectName).toBe(projectName);
|
|
717
|
+
expect(config.projectDesc).toBe(projectDesc);
|
|
718
|
+
expect(config.projectLogo).toBe(projectLogo);
|
|
719
|
+
});
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
test("should handle malformed or unusual project info", () => {
|
|
723
|
+
const malformedCases = [
|
|
724
|
+
{
|
|
725
|
+
name: "HTML-like content",
|
|
726
|
+
projectName: "<script>alert('xss')</script>",
|
|
727
|
+
projectDesc: "<h1>Title</h1><p>Description with <a href='#'>links</a></p>",
|
|
728
|
+
projectLogo: "<img src='logo.png' alt='Logo'/>",
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
name: "Markdown content",
|
|
732
|
+
projectName: "# My Project",
|
|
733
|
+
projectDesc:
|
|
734
|
+
"## Description\n\n- Feature 1\n- Feature 2\n\n```js\nconsole.log('hello');\n```",
|
|
735
|
+
projectLogo: "",
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
name: "Control characters",
|
|
739
|
+
projectName: "Project\x00Name",
|
|
740
|
+
projectDesc: "Description\x01with\x02control\x03characters",
|
|
741
|
+
projectLogo: "logo\x04.png",
|
|
742
|
+
},
|
|
743
|
+
];
|
|
744
|
+
|
|
745
|
+
malformedCases.forEach(({ projectName, projectDesc, projectLogo }) => {
|
|
746
|
+
const input = {
|
|
747
|
+
documentPurpose: ["getStarted"],
|
|
748
|
+
targetAudienceTypes: ["developers"],
|
|
749
|
+
locale: "en",
|
|
750
|
+
docsDir: "./docs",
|
|
751
|
+
projectName,
|
|
752
|
+
projectDesc,
|
|
753
|
+
projectLogo,
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
const result = generateYAML(input);
|
|
757
|
+
const config = parseAndValidateYAML(result);
|
|
758
|
+
|
|
759
|
+
// Even malformed content should be handled safely
|
|
760
|
+
expect(config.projectName).toBe(projectName);
|
|
761
|
+
expect(config.projectDesc).toBe(projectDesc);
|
|
762
|
+
expect(config.projectLogo).toBe(projectLogo);
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
describe("User input path scenarios", () => {
|
|
768
|
+
test("should handle documentation directory variations", () => {
|
|
769
|
+
const docDirVariations = [
|
|
770
|
+
"./docs",
|
|
771
|
+
".aigne/doc-smith/docs",
|
|
772
|
+
"/absolute/path/to/docs",
|
|
773
|
+
"~/user/docs",
|
|
774
|
+
"../relative/docs",
|
|
775
|
+
"docs with spaces",
|
|
776
|
+
"文档目录",
|
|
777
|
+
];
|
|
778
|
+
|
|
779
|
+
docDirVariations.forEach((docsDir) => {
|
|
780
|
+
const input = {
|
|
781
|
+
documentPurpose: ["getStarted"],
|
|
782
|
+
targetAudienceTypes: ["developers"],
|
|
783
|
+
locale: "en",
|
|
784
|
+
docsDir: docsDir,
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
const result = generateYAML(input);
|
|
788
|
+
expect(result).toContain("docsDir:");
|
|
789
|
+
expect(result).toBeDefined();
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
test("should handle various source path patterns", () => {
|
|
794
|
+
const input = {
|
|
795
|
+
documentPurpose: ["getStarted"],
|
|
796
|
+
targetAudienceTypes: ["developers"],
|
|
797
|
+
locale: "en",
|
|
798
|
+
sourcesPath: [
|
|
799
|
+
"./src",
|
|
800
|
+
"./lib",
|
|
801
|
+
"packages/*/src",
|
|
802
|
+
"apps/**/*.ts",
|
|
803
|
+
"!**/*.test.js",
|
|
804
|
+
"src with spaces",
|
|
805
|
+
"源代码/模块",
|
|
806
|
+
],
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
const result = generateYAML(input);
|
|
810
|
+
expect(result).toContain("sourcesPath:");
|
|
811
|
+
expect(result).toContain("- ./src");
|
|
812
|
+
expect(result).toContain("- ./lib");
|
|
813
|
+
expect(result).toContain("- packages/*/src");
|
|
814
|
+
expect(result).toBeDefined();
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
test("should handle single source path", () => {
|
|
818
|
+
const input = {
|
|
819
|
+
documentPurpose: ["getStarted"],
|
|
820
|
+
targetAudienceTypes: ["developers"],
|
|
821
|
+
locale: "en",
|
|
822
|
+
sourcesPath: ["./"],
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
const result = generateYAML(input);
|
|
826
|
+
expect(result).toContain("sourcesPath:");
|
|
827
|
+
expect(result).toContain("- ./");
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
test("should handle complex glob patterns from user input", () => {
|
|
831
|
+
const input = {
|
|
832
|
+
documentPurpose: ["findAnswers"],
|
|
833
|
+
targetAudienceTypes: ["developers"],
|
|
834
|
+
locale: "en",
|
|
835
|
+
sourcesPath: [
|
|
836
|
+
"**/*.{js,ts,jsx,tsx}",
|
|
837
|
+
"src/**/*.{vue,svelte}",
|
|
838
|
+
"!**/node_modules/**",
|
|
839
|
+
"{packages,apps}/**/*.py",
|
|
840
|
+
"docs/**/*.md",
|
|
841
|
+
],
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
const result = generateYAML(input);
|
|
845
|
+
expect(result).toContain("sourcesPath:");
|
|
846
|
+
expect(result).toBeDefined();
|
|
847
|
+
expect(typeof result).toBe("string");
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
describe("Edge cases that should not occur from init() but may happen", () => {
|
|
852
|
+
test("should handle undefined required fields - exposes bug", () => {
|
|
853
|
+
// This could happen if init() has bugs or incomplete validation
|
|
854
|
+
const input = {
|
|
855
|
+
documentPurpose: ["getStarted"],
|
|
856
|
+
targetAudienceTypes: ["developers"],
|
|
857
|
+
locale: undefined, // Should not happen from init()
|
|
858
|
+
docsDir: undefined, // Should not happen from init()
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
const result = generateYAML(input);
|
|
862
|
+
|
|
863
|
+
// This test will FAIL because the function generates invalid YAML
|
|
864
|
+
// The YAML should be parseable and contain proper default values
|
|
865
|
+
const config = parseAndValidateYAML(result);
|
|
866
|
+
|
|
867
|
+
// These expectations will FAIL because function generates invalid "{}" values
|
|
868
|
+
expect(config.locale).toBe("en"); // Should default to "en"
|
|
869
|
+
expect(config.docsDir).toBe("./aigne/doc-smith/docs"); // Should default to "./docs"
|
|
870
|
+
|
|
871
|
+
// Verify other fields work correctly
|
|
872
|
+
expect(config.documentPurpose).toEqual(["getStarted"]);
|
|
873
|
+
expect(config.targetAudienceTypes).toEqual(["developers"]);
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
test("should handle empty arrays from validation failures", () => {
|
|
877
|
+
// This could happen if validation fails but doesn't stop execution
|
|
878
|
+
const input = {
|
|
879
|
+
documentPurpose: [], // Should not happen due to validation
|
|
880
|
+
targetAudienceTypes: [], // Should not happen due to validation
|
|
881
|
+
locale: "en",
|
|
882
|
+
docsDir: "./docs",
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
const result = generateYAML(input);
|
|
886
|
+
expect(result).toContain("documentPurpose: []");
|
|
887
|
+
expect(result).toContain("targetAudienceTypes: []");
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
describe("YAML output structure validation", () => {
|
|
892
|
+
test("should maintain consistent structure across different inputs", () => {
|
|
893
|
+
const inputs = [
|
|
894
|
+
{
|
|
895
|
+
documentPurpose: ["getStarted"],
|
|
896
|
+
targetAudienceTypes: ["endUsers"],
|
|
897
|
+
locale: "en",
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
documentPurpose: ["findAnswers", "completeTasks"],
|
|
901
|
+
targetAudienceTypes: ["developers", "devops"],
|
|
902
|
+
locale: "zh-CN",
|
|
903
|
+
translateLanguages: ["en", "ja"],
|
|
904
|
+
},
|
|
905
|
+
];
|
|
906
|
+
|
|
907
|
+
inputs.forEach((input) => {
|
|
908
|
+
const result = generateYAML(input);
|
|
909
|
+
|
|
910
|
+
// Should always include these sections
|
|
911
|
+
expect(result).toContain("# Project information for documentation publishing");
|
|
912
|
+
expect(result).toContain("# Documentation Configuration");
|
|
913
|
+
expect(result).toContain("projectName:");
|
|
914
|
+
expect(result).toContain("documentPurpose:");
|
|
915
|
+
expect(result).toContain("targetAudienceTypes:");
|
|
916
|
+
expect(result).toContain("locale:");
|
|
917
|
+
expect(result).toContain("sourcesPath:");
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
test("should include all necessary comments and examples", () => {
|
|
922
|
+
const input = {
|
|
923
|
+
documentPurpose: ["getStarted"],
|
|
924
|
+
targetAudienceTypes: ["developers"],
|
|
925
|
+
locale: "en",
|
|
926
|
+
translateLanguages: [],
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const result = generateYAML(input);
|
|
930
|
+
|
|
931
|
+
expect(result).toContain("# Purpose: What's the main outcome");
|
|
932
|
+
expect(result).toContain("# Available options (uncomment and modify as needed):");
|
|
933
|
+
expect(result).toContain("# Target Audience: Who will be reading this most often?");
|
|
934
|
+
expect(result).toContain("# Reader Knowledge Level:");
|
|
935
|
+
expect(result).toContain("# Documentation Depth:");
|
|
936
|
+
expect(result).toContain("# Custom Rules:");
|
|
937
|
+
expect(result).toContain("# Glossary:");
|
|
938
|
+
});
|
|
939
|
+
});
|
|
940
|
+
});
|