Skip to content

Commit 068513a

Browse files
committed
test: add preuninstall error handling and verbose mode tests
Signed-off-by: leocavalcante <leo@cavalcante.dev>
1 parent 66d8119 commit 068513a

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

tests/install.test.ts

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,250 @@ The agent handles various tasks and operations in the system.
19211921
})
19221922
})
19231923

1924+
describe("preuninstall error handling", () => {
1925+
it("should show verbose skip message for files that don't exist in target", async () => {
1926+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
1927+
1928+
// Ensure target directory exists but is empty (no agents installed)
1929+
mkdirSync(AGENTS_TARGET_DIR, { recursive: true })
1930+
1931+
// Remove all agent files if they exist
1932+
const agentFiles = ["opencoder.md", "opencoder-planner.md", "opencoder-builder.md"]
1933+
for (const file of agentFiles) {
1934+
const targetPath = join(AGENTS_TARGET_DIR, file)
1935+
if (existsSync(targetPath)) {
1936+
rmSync(targetPath)
1937+
}
1938+
}
1939+
1940+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
1941+
cwd: process.cwd(),
1942+
stdout: "pipe",
1943+
stderr: "pipe",
1944+
})
1945+
1946+
const exitCode = await proc.exited
1947+
const stdout = await new Response(proc.stdout).text()
1948+
1949+
expect(exitCode).toBe(0)
1950+
1951+
// Should show verbose messages for skipped files
1952+
expect(stdout).toContain("[VERBOSE]")
1953+
expect(stdout).toContain("File does not exist, skipping")
1954+
1955+
// Should show processing for each agent file
1956+
expect(stdout).toContain("Processing: opencoder.md")
1957+
expect(stdout).toContain("Processing: opencoder-planner.md")
1958+
expect(stdout).toContain("Processing: opencoder-builder.md")
1959+
})
1960+
1961+
it("should show verbose skip message for partial installation (some files missing)", async () => {
1962+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
1963+
1964+
// Ensure target directory exists
1965+
mkdirSync(AGENTS_TARGET_DIR, { recursive: true })
1966+
1967+
// Install only one agent file
1968+
const sourcePath = join(process.cwd(), "agents", "opencoder.md")
1969+
const targetPath = join(AGENTS_TARGET_DIR, "opencoder.md")
1970+
if (existsSync(sourcePath)) {
1971+
const content = readFileSync(sourcePath, "utf-8")
1972+
writeFileSync(targetPath, content)
1973+
}
1974+
1975+
// Make sure other files don't exist
1976+
const otherFiles = ["opencoder-planner.md", "opencoder-builder.md"]
1977+
for (const file of otherFiles) {
1978+
const filePath = join(AGENTS_TARGET_DIR, file)
1979+
if (existsSync(filePath)) {
1980+
rmSync(filePath)
1981+
}
1982+
}
1983+
1984+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
1985+
cwd: process.cwd(),
1986+
stdout: "pipe",
1987+
stderr: "pipe",
1988+
})
1989+
1990+
const exitCode = await proc.exited
1991+
const stdout = await new Response(proc.stdout).text()
1992+
1993+
expect(exitCode).toBe(0)
1994+
1995+
// Should show that existing file would be removed
1996+
expect(stdout).toContain("Would remove:")
1997+
expect(stdout).toContain("opencoder.md")
1998+
1999+
// Should show skip messages for missing files
2000+
expect(stdout).toContain("File does not exist, skipping")
2001+
2002+
// Clean up
2003+
if (existsSync(targetPath)) {
2004+
rmSync(targetPath)
2005+
}
2006+
})
2007+
2008+
it("should display proper error message format in verbose mode", async () => {
2009+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
2010+
2011+
// Ensure target directory exists with some agents
2012+
mkdirSync(AGENTS_TARGET_DIR, { recursive: true })
2013+
2014+
const agentFiles = ["opencoder.md", "opencoder-planner.md", "opencoder-builder.md"]
2015+
for (const file of agentFiles) {
2016+
const sourcePath = join(process.cwd(), "agents", file)
2017+
const targetPath = join(AGENTS_TARGET_DIR, file)
2018+
if (existsSync(sourcePath)) {
2019+
const content = readFileSync(sourcePath, "utf-8")
2020+
writeFileSync(targetPath, content)
2021+
}
2022+
}
2023+
2024+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
2025+
cwd: process.cwd(),
2026+
stdout: "pipe",
2027+
stderr: "pipe",
2028+
})
2029+
2030+
const exitCode = await proc.exited
2031+
const stdout = await new Response(proc.stdout).text()
2032+
const stderr = await new Response(proc.stderr).text()
2033+
2034+
expect(exitCode).toBe(0)
2035+
2036+
// Should show verbose details for each file
2037+
expect(stdout).toContain("[VERBOSE] Processing:")
2038+
expect(stdout).toContain("[VERBOSE] Target path:")
2039+
expect(stdout).toContain("[VERBOSE] File exists, removing...")
2040+
expect(stdout).toContain("[VERBOSE] Successfully removed")
2041+
2042+
// Should not have any error messages for successful removal
2043+
expect(stderr).toBe("")
2044+
2045+
// Clean up
2046+
for (const file of agentFiles) {
2047+
const targetPath = join(AGENTS_TARGET_DIR, file)
2048+
if (existsSync(targetPath)) {
2049+
rmSync(targetPath)
2050+
}
2051+
}
2052+
})
2053+
2054+
it("should show removal summary in verbose mode", async () => {
2055+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
2056+
2057+
// Ensure target directory exists
2058+
mkdirSync(AGENTS_TARGET_DIR, { recursive: true })
2059+
2060+
const agentFiles = ["opencoder.md", "opencoder-planner.md", "opencoder-builder.md"]
2061+
for (const file of agentFiles) {
2062+
const sourcePath = join(process.cwd(), "agents", file)
2063+
const targetPath = join(AGENTS_TARGET_DIR, file)
2064+
if (existsSync(sourcePath)) {
2065+
const content = readFileSync(sourcePath, "utf-8")
2066+
writeFileSync(targetPath, content)
2067+
}
2068+
}
2069+
2070+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
2071+
cwd: process.cwd(),
2072+
stdout: "pipe",
2073+
stderr: "pipe",
2074+
})
2075+
2076+
const exitCode = await proc.exited
2077+
const stdout = await new Response(proc.stdout).text()
2078+
2079+
expect(exitCode).toBe(0)
2080+
2081+
// Should show the removal summary
2082+
expect(stdout).toContain("[VERBOSE] Removal summary: 3 files removed")
2083+
expect(stdout).toContain("Removed 3 agent(s)")
2084+
2085+
// Clean up
2086+
for (const file of agentFiles) {
2087+
const targetPath = join(AGENTS_TARGET_DIR, file)
2088+
if (existsSync(targetPath)) {
2089+
rmSync(targetPath)
2090+
}
2091+
}
2092+
})
2093+
2094+
it("should handle missing target directory gracefully in verbose mode", async () => {
2095+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
2096+
2097+
// Remove the target directory if it exists
2098+
const agentFiles = ["opencoder.md", "opencoder-planner.md", "opencoder-builder.md"]
2099+
2100+
// First, clean up any existing agent files
2101+
for (const file of agentFiles) {
2102+
const targetPath = join(AGENTS_TARGET_DIR, file)
2103+
if (existsSync(targetPath)) {
2104+
rmSync(targetPath)
2105+
}
2106+
}
2107+
2108+
// Try to remove the directory if it's empty
2109+
if (existsSync(AGENTS_TARGET_DIR)) {
2110+
const files = readdirSync(AGENTS_TARGET_DIR)
2111+
if (files.length === 0) {
2112+
rmSync(AGENTS_TARGET_DIR, { recursive: true })
2113+
}
2114+
}
2115+
2116+
// Only run this test if directory was successfully removed
2117+
if (!existsSync(AGENTS_TARGET_DIR)) {
2118+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
2119+
cwd: process.cwd(),
2120+
stdout: "pipe",
2121+
stderr: "pipe",
2122+
})
2123+
2124+
const exitCode = await proc.exited
2125+
const stdout = await new Response(proc.stdout).text()
2126+
2127+
expect(exitCode).toBe(0)
2128+
2129+
// Should show verbose message about target directory check
2130+
expect(stdout).toContain("[VERBOSE] Checking if target directory exists...")
2131+
expect(stdout).toContain("[VERBOSE] Target directory does not exist")
2132+
expect(stdout).toContain("No agents directory found, nothing to remove")
2133+
}
2134+
})
2135+
2136+
it("should show no agents installed message when target exists but has no agent files", async () => {
2137+
const { AGENTS_TARGET_DIR } = await import("../src/paths.mjs")
2138+
2139+
// Ensure target directory exists
2140+
mkdirSync(AGENTS_TARGET_DIR, { recursive: true })
2141+
2142+
// Remove all agent files
2143+
const agentFiles = ["opencoder.md", "opencoder-planner.md", "opencoder-builder.md"]
2144+
for (const file of agentFiles) {
2145+
const targetPath = join(AGENTS_TARGET_DIR, file)
2146+
if (existsSync(targetPath)) {
2147+
rmSync(targetPath)
2148+
}
2149+
}
2150+
2151+
const proc = Bun.spawn(["node", "preuninstall.mjs", "--dry-run", "--verbose"], {
2152+
cwd: process.cwd(),
2153+
stdout: "pipe",
2154+
stderr: "pipe",
2155+
})
2156+
2157+
const exitCode = await proc.exited
2158+
const stdout = await new Response(proc.stdout).text()
2159+
2160+
expect(exitCode).toBe(0)
2161+
2162+
// Should show verbose removal summary with 0 files
2163+
expect(stdout).toContain("[VERBOSE] Removal summary: 0 files removed")
2164+
expect(stdout).toContain("No agents were installed, nothing removed")
2165+
})
2166+
})
2167+
19242168
describe("CLI flags: --verbose", () => {
19252169
it("postinstall --verbose shows detailed output", async () => {
19262170
const proc = Bun.spawn(["node", "postinstall.mjs", "--dry-run", "--verbose"], {

0 commit comments

Comments
 (0)