Skip to content

Commit 9eddb67

Browse files
committed
feat: add input validation to getErrorMessage for null/undefined params
Signed-off-by: leocavalcante <leo@cavalcante.dev>
1 parent d5047d6 commit 9eddb67

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

src/paths.mjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ export const AGENTS_TARGET_DIR = join(homedir(), ".config", "opencode", "agents"
109109
* // Returns: "Source file not found: missing.md"
110110
*/
111111
export function getErrorMessage(error, file, targetPath) {
112+
if (typeof file !== "string") {
113+
throw new TypeError(
114+
`getErrorMessage: file must be a string, got ${file === null ? "null" : typeof file}`,
115+
)
116+
}
117+
if (file.trim() === "") {
118+
throw new TypeError("getErrorMessage: file must not be empty")
119+
}
120+
if (typeof targetPath !== "string") {
121+
throw new TypeError(
122+
`getErrorMessage: targetPath must be a string, got ${targetPath === null ? "null" : typeof targetPath}`,
123+
)
124+
}
125+
if (targetPath.trim() === "") {
126+
throw new TypeError("getErrorMessage: targetPath must not be empty")
127+
}
112128
const code = error.code
113129
switch (code) {
114130
case "EACCES":

tests/paths.test.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,104 @@ describe("paths.mjs exports", () => {
280280
const result = getErrorMessage(error, testFile, testTargetPath)
281281
expect(result).toBe("File is busy or locked. Try again later")
282282
})
283+
284+
describe("input validation", () => {
285+
const validError = new Error("test error")
286+
287+
it("should throw TypeError for null file", () => {
288+
expect(() =>
289+
getErrorMessage(validError, null as unknown as string, testTargetPath),
290+
).toThrow(TypeError)
291+
expect(() =>
292+
getErrorMessage(validError, null as unknown as string, testTargetPath),
293+
).toThrow("getErrorMessage: file must be a string, got null")
294+
})
295+
296+
it("should throw TypeError for undefined file", () => {
297+
expect(() =>
298+
getErrorMessage(validError, undefined as unknown as string, testTargetPath),
299+
).toThrow(TypeError)
300+
expect(() =>
301+
getErrorMessage(validError, undefined as unknown as string, testTargetPath),
302+
).toThrow("getErrorMessage: file must be a string, got undefined")
303+
})
304+
305+
it("should throw TypeError for non-string file", () => {
306+
expect(() => getErrorMessage(validError, 123 as unknown as string, testTargetPath)).toThrow(
307+
TypeError,
308+
)
309+
expect(() => getErrorMessage(validError, 123 as unknown as string, testTargetPath)).toThrow(
310+
"getErrorMessage: file must be a string, got number",
311+
)
312+
expect(() => getErrorMessage(validError, {} as unknown as string, testTargetPath)).toThrow(
313+
TypeError,
314+
)
315+
expect(() => getErrorMessage(validError, {} as unknown as string, testTargetPath)).toThrow(
316+
"getErrorMessage: file must be a string, got object",
317+
)
318+
})
319+
320+
it("should throw TypeError for empty string file", () => {
321+
expect(() => getErrorMessage(validError, "", testTargetPath)).toThrow(TypeError)
322+
expect(() => getErrorMessage(validError, "", testTargetPath)).toThrow(
323+
"getErrorMessage: file must not be empty",
324+
)
325+
})
326+
327+
it("should throw TypeError for whitespace-only file", () => {
328+
expect(() => getErrorMessage(validError, " ", testTargetPath)).toThrow(TypeError)
329+
expect(() => getErrorMessage(validError, " ", testTargetPath)).toThrow(
330+
"getErrorMessage: file must not be empty",
331+
)
332+
})
333+
334+
it("should throw TypeError for null targetPath", () => {
335+
expect(() => getErrorMessage(validError, testFile, null as unknown as string)).toThrow(
336+
TypeError,
337+
)
338+
expect(() => getErrorMessage(validError, testFile, null as unknown as string)).toThrow(
339+
"getErrorMessage: targetPath must be a string, got null",
340+
)
341+
})
342+
343+
it("should throw TypeError for undefined targetPath", () => {
344+
expect(() => getErrorMessage(validError, testFile, undefined as unknown as string)).toThrow(
345+
TypeError,
346+
)
347+
expect(() => getErrorMessage(validError, testFile, undefined as unknown as string)).toThrow(
348+
"getErrorMessage: targetPath must be a string, got undefined",
349+
)
350+
})
351+
352+
it("should throw TypeError for non-string targetPath", () => {
353+
expect(() => getErrorMessage(validError, testFile, 123 as unknown as string)).toThrow(
354+
TypeError,
355+
)
356+
expect(() => getErrorMessage(validError, testFile, 123 as unknown as string)).toThrow(
357+
"getErrorMessage: targetPath must be a string, got number",
358+
)
359+
expect(() => getErrorMessage(validError, testFile, {} as unknown as string)).toThrow(
360+
TypeError,
361+
)
362+
expect(() => getErrorMessage(validError, testFile, {} as unknown as string)).toThrow(
363+
"getErrorMessage: targetPath must be a string, got object",
364+
)
365+
})
366+
367+
it("should throw TypeError for empty string targetPath", () => {
368+
expect(() => getErrorMessage(validError, testFile, "")).toThrow(TypeError)
369+
expect(() => getErrorMessage(validError, testFile, "")).toThrow(
370+
"getErrorMessage: targetPath must not be empty",
371+
)
372+
})
373+
374+
it("should throw TypeError for whitespace-only targetPath", () => {
375+
expect(() => getErrorMessage(validError, testFile, " ")).toThrow(TypeError)
376+
expect(() => getErrorMessage(validError, testFile, " ")).toThrow(
377+
"getErrorMessage: targetPath must not be empty",
378+
)
379+
})
380+
})
283381
})
284382

285383
describe("constants", () => {

0 commit comments

Comments
 (0)