test: implement fuzzing

This commit is contained in:
shadcn
2025-03-27 17:41:32 +04:00
parent 074eed5605
commit 51e1940525
3 changed files with 181 additions and 1 deletions

View File

@@ -0,0 +1,78 @@
import { describe, expect, test } from "vitest"
import { highlighter } from "../../src/utils/highlighter"
import { generateRandomString } from "../../test/fuzz-utils"
describe("fuzzing", () => {
test("should handle various input strings", () => {
const testCases = Array.from({ length: 100 }, () => ({
text: generateRandomString(Math.floor(Math.random() * 100) + 1),
}))
for (const { text } of testCases) {
try {
// Test each highlighter function
const errorResult = highlighter.error(text)
const warnResult = highlighter.warn(text)
const infoResult = highlighter.info(text)
const successResult = highlighter.success(text)
// All results should be strings
expect(typeof errorResult).toBe("string")
expect(typeof warnResult).toBe("string")
expect(typeof infoResult).toBe("string")
expect(typeof successResult).toBe("string")
// All results should have the same length as input
expect(errorResult.length).toBe(text.length)
expect(warnResult.length).toBe(text.length)
expect(infoResult.length).toBe(text.length)
expect(successResult.length).toBe(text.length)
} catch (error) {
console.error(`Failed with text: ${text}`, error)
throw error
}
}
})
test("should handle edge cases", () => {
const edgeCases = [
"", // Empty string
" ", // Single space
" ", // Multiple spaces
"0", // Zero as string
"null", // "null" as string
"undefined", // "undefined" as string
"NaN", // "NaN" as string
"true", // "true" as string
"false", // "false" as string
"[]", // Empty array as string
"{}", // Empty object as string
]
for (const text of edgeCases) {
try {
// Test each highlighter function
const errorResult = highlighter.error(text)
const warnResult = highlighter.warn(text)
const infoResult = highlighter.info(text)
const successResult = highlighter.success(text)
// All results should be strings
expect(typeof errorResult).toBe("string")
expect(typeof warnResult).toBe("string")
expect(typeof infoResult).toBe("string")
expect(typeof successResult).toBe("string")
// All results should have the same length as input
expect(errorResult.length).toBe(text.length)
expect(warnResult.length).toBe(text.length)
expect(infoResult.length).toBe(text.length)
expect(successResult.length).toBe(text.length)
} catch (error) {
console.error(`Failed with edge case: ${text}`, error)
throw error
}
}
})
})

View File

@@ -0,0 +1,16 @@
export const generateRandomString = (length: number): string => {
const chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?"
return Array.from(
{ length },
() => chars[Math.floor(Math.random() * chars.length)]
).join("")
}
export const generateRandomPath = (): string => {
const segments = Array.from(
{ length: Math.floor(Math.random() * 5) + 1 },
() => generateRandomString(Math.floor(Math.random() * 10) + 1)
)
return segments.join("/")
}

View File

@@ -1,8 +1,9 @@
import path from "path"
import { loadConfig, type ConfigLoaderSuccessResult } from "tsconfig-paths"
import { expect, test } from "vitest"
import { describe, expect, test } from "vitest"
import { resolveImport } from "../../src/utils/resolve-import"
import { generateRandomPath } from "../fuzz-utils"
test("resolve import", async () => {
expect(
@@ -79,3 +80,88 @@ test("resolve import without base url", async () => {
path.resolve(cwd, "foo/bar")
)
})
describe("fuzzing", () => {
test("should handle various import paths", async () => {
const generateRandomConfig = (): Pick<
ConfigLoaderSuccessResult,
"absoluteBaseUrl" | "paths"
> => ({
absoluteBaseUrl: generateRandomPath(),
paths: {
"@/*": [generateRandomPath()],
"@/components/*": [generateRandomPath()],
"@/lib/*": [generateRandomPath()],
},
})
const testCases = Array.from({ length: 100 }, () => ({
importPath: generateRandomPath(),
config: generateRandomConfig(),
}))
for (const { importPath, config } of testCases) {
try {
const result = await resolveImport(importPath, config)
// Should either return undefined or a valid path
if (result) {
expect(typeof result).toBe("string")
expect(result.length).toBeGreaterThan(0)
}
} catch (error) {
// Expected for invalid paths
expect(error).toBeDefined()
}
}
})
test("should handle edge cases", async () => {
const edgeCases: Array<{
importPath: string
config: Pick<ConfigLoaderSuccessResult, "absoluteBaseUrl" | "paths">
}> = [
{
importPath: "",
config: {
absoluteBaseUrl: "",
paths: {
"@/*": [""],
},
},
},
{
importPath: "/",
config: {
absoluteBaseUrl: "/",
paths: {
"@/*": ["/"],
},
},
},
{
importPath: "@/components/button",
config: {
absoluteBaseUrl: "/",
paths: {
"@/*": ["/"],
"@/components/*": ["/components"],
},
},
},
]
for (const { importPath, config } of edgeCases) {
try {
const result = await resolveImport(importPath, config)
// Should either return undefined or a valid path
if (result) {
expect(typeof result).toBe("string")
expect(result.length).toBeGreaterThan(0)
}
} catch (error) {
console.error(`Failed with edge case:`, { importPath, config }, error)
throw error
}
}
})
})