Skip to content

Commit 5748e31

Browse files
committed
add: tests
1 parent ca5cedb commit 5748e31

5 files changed

Lines changed: 1336 additions & 1 deletion

File tree

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
2+
import fs from "fs-extra";
3+
import path from "path";
4+
import os from "os";
5+
import { flattenMarkdown, copyToDocs, locateSDKDir } from "../lib/files.js";
6+
import { CONSTANTS } from "../lib/constants.js";
7+
8+
describe("flattenMarkdown", () => {
9+
let tempDir: string;
10+
11+
beforeEach(async () => {
12+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "flatten-test-"));
13+
});
14+
15+
afterEach(async () => {
16+
await fs.remove(tempDir);
17+
});
18+
19+
describe("removeUnwantedFiles", () => {
20+
it("removes README.md, index.md, and index.mdx", async () => {
21+
await fs.writeFile(path.join(tempDir, "README.md"), "# Readme");
22+
await fs.writeFile(path.join(tempDir, "index.md"), "# Index");
23+
await fs.writeFile(path.join(tempDir, "index.mdx"), "# Index MDX");
24+
await fs.writeFile(path.join(tempDir, "Sandbox.md"), "# Keep this");
25+
26+
await flattenMarkdown(tempDir);
27+
28+
expect(await fs.pathExists(path.join(tempDir, "README.md"))).toBe(false);
29+
expect(await fs.pathExists(path.join(tempDir, "index.md"))).toBe(false);
30+
expect(await fs.pathExists(path.join(tempDir, "index.mdx"))).toBe(false);
31+
expect(await fs.pathExists(path.join(tempDir, "Sandbox.mdx"))).toBe(true);
32+
});
33+
});
34+
35+
describe("flattenNestedFiles", () => {
36+
it("flattens nested md files to top level", async () => {
37+
const nestedDir = path.join(tempDir, "modules", "sandbox");
38+
await fs.ensureDir(nestedDir);
39+
await fs.writeFile(path.join(nestedDir, "Sandbox.md"), "# Sandbox");
40+
41+
await flattenMarkdown(tempDir);
42+
43+
// nested file should be flattened with path prefix
44+
expect(
45+
await fs.pathExists(
46+
path.join(tempDir, "modules-sandbox-Sandbox.mdx")
47+
)
48+
).toBe(true);
49+
// original nested directory should be removed
50+
expect(await fs.pathExists(nestedDir)).toBe(false);
51+
});
52+
53+
it("renames page.md to parent directory name", async () => {
54+
const nestedDir = path.join(tempDir, "sandbox");
55+
await fs.ensureDir(nestedDir);
56+
await fs.writeFile(path.join(nestedDir, "page.md"), "# Page content");
57+
58+
await flattenMarkdown(tempDir);
59+
60+
expect(await fs.pathExists(path.join(tempDir, "sandbox.mdx"))).toBe(true);
61+
});
62+
63+
it("renames index.md in nested dirs to parent directory name", async () => {
64+
const nestedDir = path.join(tempDir, "filesystem");
65+
await fs.ensureDir(nestedDir);
66+
await fs.writeFile(
67+
path.join(nestedDir, "index.md"),
68+
"# Filesystem index"
69+
);
70+
71+
await flattenMarkdown(tempDir);
72+
73+
expect(await fs.pathExists(path.join(tempDir, "filesystem.mdx"))).toBe(
74+
true
75+
);
76+
});
77+
78+
it("handles deeply nested files", async () => {
79+
const deepDir = path.join(tempDir, "a", "b", "c");
80+
await fs.ensureDir(deepDir);
81+
await fs.writeFile(path.join(deepDir, "Deep.md"), "# Deep file");
82+
83+
await flattenMarkdown(tempDir);
84+
85+
expect(await fs.pathExists(path.join(tempDir, "a-b-c-Deep.mdx"))).toBe(
86+
true
87+
);
88+
});
89+
});
90+
91+
describe("convertMdToMdx", () => {
92+
it("converts .md files to .mdx with frontmatter", async () => {
93+
await fs.writeFile(path.join(tempDir, "Test.md"), "# Test content");
94+
95+
await flattenMarkdown(tempDir);
96+
97+
const mdxPath = path.join(tempDir, "Test.mdx");
98+
expect(await fs.pathExists(mdxPath)).toBe(true);
99+
expect(await fs.pathExists(path.join(tempDir, "Test.md"))).toBe(false);
100+
101+
const content = await fs.readFile(mdxPath, "utf-8");
102+
expect(content).toContain("---");
103+
expect(content).toContain('sidebarTitle: "Test"');
104+
expect(content).toContain("# Test content");
105+
});
106+
107+
it("generates correct title from snake_case filenames", async () => {
108+
await fs.writeFile(
109+
path.join(tempDir, "sandbox_sync.md"),
110+
"# Content"
111+
);
112+
113+
await flattenMarkdown(tempDir);
114+
115+
const content = await fs.readFile(
116+
path.join(tempDir, "sandbox_sync.mdx"),
117+
"utf-8"
118+
);
119+
expect(content).toContain('sidebarTitle: "Sandbox Sync"');
120+
});
121+
});
122+
123+
describe("ensureFrontmatter", () => {
124+
it("adds frontmatter to mdx files without it", async () => {
125+
// create mdx file without frontmatter
126+
await fs.writeFile(
127+
path.join(tempDir, "NeedsFrontmatter.mdx"),
128+
"# No frontmatter"
129+
);
130+
131+
await flattenMarkdown(tempDir);
132+
133+
const content = await fs.readFile(
134+
path.join(tempDir, "NeedsFrontmatter.mdx"),
135+
"utf-8"
136+
);
137+
expect(content.startsWith("---")).toBe(true);
138+
expect(content).toContain('sidebarTitle: "NeedsFrontmatter"');
139+
});
140+
141+
it("does not duplicate frontmatter if already present", async () => {
142+
const existingFrontmatter = `---
143+
sidebarTitle: "Existing"
144+
---
145+
146+
# Content`;
147+
await fs.writeFile(
148+
path.join(tempDir, "HasFrontmatter.mdx"),
149+
existingFrontmatter
150+
);
151+
152+
await flattenMarkdown(tempDir);
153+
154+
const content = await fs.readFile(
155+
path.join(tempDir, "HasFrontmatter.mdx"),
156+
"utf-8"
157+
);
158+
// should still have exactly one frontmatter block
159+
const frontmatterCount = (content.match(/---/g) || []).length;
160+
expect(frontmatterCount).toBe(2); // opening and closing ---
161+
expect(content).toContain('sidebarTitle: "Existing"');
162+
});
163+
});
164+
165+
describe("full workflow", () => {
166+
it("processes complex directory structure correctly", async () => {
167+
// create complex structure
168+
await fs.writeFile(path.join(tempDir, "README.md"), "# Remove me");
169+
await fs.writeFile(path.join(tempDir, "TopLevel.md"), "# Top level");
170+
171+
const modulesDir = path.join(tempDir, "modules");
172+
await fs.ensureDir(modulesDir);
173+
await fs.writeFile(path.join(modulesDir, "page.md"), "# Modules page");
174+
await fs.writeFile(path.join(modulesDir, "Helper.md"), "# Helper");
175+
176+
const sandboxDir = path.join(modulesDir, "sandbox");
177+
await fs.ensureDir(sandboxDir);
178+
await fs.writeFile(path.join(sandboxDir, "Sandbox.md"), "# Sandbox class");
179+
180+
await flattenMarkdown(tempDir);
181+
182+
// check results
183+
expect(await fs.pathExists(path.join(tempDir, "README.md"))).toBe(false);
184+
expect(await fs.pathExists(path.join(tempDir, "TopLevel.mdx"))).toBe(true);
185+
expect(await fs.pathExists(path.join(tempDir, "modules.mdx"))).toBe(true);
186+
expect(await fs.pathExists(path.join(tempDir, "modules-Helper.mdx"))).toBe(
187+
true
188+
);
189+
expect(
190+
await fs.pathExists(path.join(tempDir, "modules-sandbox-Sandbox.mdx"))
191+
).toBe(true);
192+
193+
// verify all have frontmatter
194+
const files = await fs.readdir(tempDir);
195+
for (const file of files) {
196+
if (file.endsWith(".mdx")) {
197+
const content = await fs.readFile(path.join(tempDir, file), "utf-8");
198+
expect(content.startsWith("---")).toBe(true);
199+
}
200+
}
201+
202+
// verify directories are removed
203+
expect(await fs.pathExists(modulesDir)).toBe(false);
204+
});
205+
});
206+
});
207+
208+
describe("locateSDKDir", () => {
209+
let tempDir: string;
210+
211+
beforeEach(async () => {
212+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "locate-sdk-test-"));
213+
});
214+
215+
afterEach(async () => {
216+
await fs.remove(tempDir);
217+
});
218+
219+
it("returns sdkPath when it exists", async () => {
220+
const sdkDir = path.join(tempDir, "packages", "sdk");
221+
await fs.ensureDir(sdkDir);
222+
223+
const result = await locateSDKDir(tempDir, "packages/sdk");
224+
225+
expect(result).toBe(sdkDir);
226+
});
227+
228+
it("returns null when sdkPath does not exist", async () => {
229+
const result = await locateSDKDir(tempDir, "nonexistent/path");
230+
231+
expect(result).toBeNull();
232+
});
233+
234+
it("returns first existing path from sdkPaths array", async () => {
235+
const secondPath = path.join(tempDir, "js");
236+
await fs.ensureDir(secondPath);
237+
238+
const result = await locateSDKDir(tempDir, undefined, [
239+
"python",
240+
"js",
241+
"go",
242+
]);
243+
244+
expect(result).toBe(secondPath);
245+
});
246+
247+
it("returns null when no sdkPaths exist", async () => {
248+
const result = await locateSDKDir(tempDir, undefined, [
249+
"nonexistent1",
250+
"nonexistent2",
251+
]);
252+
253+
expect(result).toBeNull();
254+
});
255+
256+
it("returns repoDir when no paths specified", async () => {
257+
const result = await locateSDKDir(tempDir);
258+
259+
expect(result).toBe(tempDir);
260+
});
261+
262+
it("sdkPath takes priority over sdkPaths", async () => {
263+
const sdkPathDir = path.join(tempDir, "primary");
264+
const sdkPathsDir = path.join(tempDir, "fallback");
265+
await fs.ensureDir(sdkPathDir);
266+
await fs.ensureDir(sdkPathsDir);
267+
268+
const result = await locateSDKDir(tempDir, "primary", ["fallback"]);
269+
270+
expect(result).toBe(sdkPathDir);
271+
});
272+
});
273+
274+
describe("copyToDocs", () => {
275+
let srcDir: string;
276+
let destDir: string;
277+
278+
beforeEach(async () => {
279+
srcDir = await fs.mkdtemp(path.join(os.tmpdir(), "copy-src-"));
280+
destDir = await fs.mkdtemp(path.join(os.tmpdir(), "copy-dest-"));
281+
});
282+
283+
afterEach(async () => {
284+
await fs.remove(srcDir);
285+
await fs.remove(destDir);
286+
});
287+
288+
it("copies non-empty mdx files to destination", async () => {
289+
await fs.writeFile(
290+
path.join(srcDir, "Test.mdx"),
291+
'---\nsidebarTitle: "Test"\n---\n\n# Content'
292+
);
293+
await fs.writeFile(
294+
path.join(srcDir, "Another.mdx"),
295+
'---\nsidebarTitle: "Another"\n---\n\n# More'
296+
);
297+
298+
const result = await copyToDocs(srcDir, destDir, "SDK", "v1.0.0");
299+
300+
expect(result).toBe(true);
301+
expect(await fs.pathExists(path.join(destDir, "Test.mdx"))).toBe(true);
302+
expect(await fs.pathExists(path.join(destDir, "Another.mdx"))).toBe(true);
303+
});
304+
305+
it("returns false when no mdx files exist", async () => {
306+
// srcDir is empty
307+
308+
const result = await copyToDocs(srcDir, destDir, "SDK", "v1.0.0");
309+
310+
expect(result).toBe(false);
311+
});
312+
313+
it("skips empty mdx files", async () => {
314+
await fs.writeFile(path.join(srcDir, "Empty.mdx"), "");
315+
await fs.writeFile(
316+
path.join(srcDir, "Valid.mdx"),
317+
'---\nsidebarTitle: "Valid"\n---\n\n# Content'
318+
);
319+
320+
const result = await copyToDocs(srcDir, destDir, "SDK", "v1.0.0");
321+
322+
expect(result).toBe(true);
323+
expect(await fs.pathExists(path.join(destDir, "Valid.mdx"))).toBe(true);
324+
expect(await fs.pathExists(path.join(destDir, "Empty.mdx"))).toBe(false);
325+
});
326+
327+
it("returns false when only empty mdx files exist", async () => {
328+
await fs.writeFile(path.join(srcDir, "Empty1.mdx"), "");
329+
await fs.writeFile(path.join(srcDir, "Empty2.mdx"), "");
330+
331+
const result = await copyToDocs(srcDir, destDir, "SDK", "v1.0.0");
332+
333+
expect(result).toBe(false);
334+
});
335+
336+
it("creates destination directory if it does not exist", async () => {
337+
const newDest = path.join(destDir, "nested", "path");
338+
await fs.writeFile(
339+
path.join(srcDir, "Test.mdx"),
340+
'---\nsidebarTitle: "Test"\n---\n\n# Content'
341+
);
342+
343+
const result = await copyToDocs(srcDir, newDest, "SDK", "v1.0.0");
344+
345+
expect(result).toBe(true);
346+
expect(await fs.pathExists(newDest)).toBe(true);
347+
expect(await fs.pathExists(path.join(newDest, "Test.mdx"))).toBe(true);
348+
});
349+
350+
it("ignores non-mdx files", async () => {
351+
await fs.writeFile(path.join(srcDir, "readme.txt"), "text file");
352+
await fs.writeFile(path.join(srcDir, "config.json"), "{}");
353+
await fs.writeFile(
354+
path.join(srcDir, "Valid.mdx"),
355+
'---\nsidebarTitle: "Valid"\n---\n\n# Content'
356+
);
357+
358+
const result = await copyToDocs(srcDir, destDir, "SDK", "v1.0.0");
359+
360+
expect(result).toBe(true);
361+
expect(await fs.pathExists(path.join(destDir, "Valid.mdx"))).toBe(true);
362+
expect(await fs.pathExists(path.join(destDir, "readme.txt"))).toBe(false);
363+
expect(await fs.pathExists(path.join(destDir, "config.json"))).toBe(false);
364+
});
365+
});
366+

0 commit comments

Comments
 (0)