mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-27 06:15:15 +00:00
Community fixes for the docs-test runner. - Python examples run on Windows: the runner picks `.venv/Scripts/python.exe` and reports a missing venv as a failed test (#1487). - TypeScript examples exit 1 when `main()` rejects, so broken examples no longer count as passed (#1495). Co-Authored-By: abhinav7x94 <204053250+abhinav7x94@users.noreply.github.com>
154 lines
3.5 KiB
TypeScript
154 lines
3.5 KiB
TypeScript
#!/usr/bin/env bun
|
|
import { spawn } from "node:child_process"
|
|
import path from "node:path"
|
|
|
|
const args = process.argv.slice(2)
|
|
const filter = args[0] // e.g., "typescript", "python", "integrations", or specific file
|
|
|
|
const TESTS_DIR = path.join(import.meta.dir, "tests")
|
|
|
|
interface TestFile {
|
|
name: string
|
|
path: string
|
|
type: "ts" | "py"
|
|
}
|
|
|
|
export function getPythonExecutable(
|
|
platform = process.platform,
|
|
baseDir = import.meta.dir,
|
|
): string {
|
|
return platform === "win32"
|
|
? path.join(baseDir, ".venv", "Scripts", "python.exe")
|
|
: path.join(baseDir, ".venv", "bin", "python3")
|
|
}
|
|
|
|
function getTests(): TestFile[] {
|
|
const tests: TestFile[] = []
|
|
|
|
// TypeScript tests
|
|
const tsTests = ["quickstart", "sdk", "search", "user-profiles"]
|
|
for (const t of tsTests) {
|
|
tests.push({
|
|
name: `typescript/${t}`,
|
|
path: path.join(TESTS_DIR, "typescript", `${t}.ts`),
|
|
type: "ts",
|
|
})
|
|
}
|
|
|
|
// Python tests
|
|
const pyTests = ["quickstart", "sdk", "search", "user_profiles"]
|
|
for (const t of pyTests) {
|
|
tests.push({
|
|
name: `python/${t}`,
|
|
path: path.join(TESTS_DIR, "python", `${t}.py`),
|
|
type: "py",
|
|
})
|
|
}
|
|
|
|
// Integration tests
|
|
const intTests = [
|
|
{ name: "ai-sdk", type: "ts" as const },
|
|
{ name: "openai-sdk", type: "ts" as const },
|
|
{ name: "openai-sdk", type: "py" as const },
|
|
{ name: "claude-memory", type: "ts" as const },
|
|
]
|
|
for (const t of intTests) {
|
|
tests.push({
|
|
name: `integrations/${t.name}`,
|
|
path: path.join(
|
|
TESTS_DIR,
|
|
"integrations",
|
|
`${t.name}.${t.type === "ts" ? "ts" : "py"}`,
|
|
),
|
|
type: t.type,
|
|
})
|
|
}
|
|
|
|
return tests
|
|
}
|
|
|
|
async function runTest(test: TestFile): Promise<boolean> {
|
|
return new Promise((resolve) => {
|
|
console.log(`\n${"=".repeat(60)}`)
|
|
console.log(`Running: ${test.name}`)
|
|
console.log("=".repeat(60))
|
|
|
|
const cmd = test.type === "ts" ? "bun" : getPythonExecutable()
|
|
const proc = spawn(cmd, [test.path], {
|
|
stdio: "inherit",
|
|
env: { ...process.env },
|
|
})
|
|
|
|
proc.once("error", (error) => {
|
|
console.error(`Failed to start ${test.name}: ${error.message}`)
|
|
if (test.type === "py" && "code" in error && error.code === "ENOENT") {
|
|
console.error(`Expected Python executable at: ${cmd}`)
|
|
console.error(
|
|
'Create it with "python -m venv .venv" and install requirements.txt.',
|
|
)
|
|
}
|
|
resolve(false)
|
|
})
|
|
|
|
proc.once("close", (code) => {
|
|
resolve(code === 0)
|
|
})
|
|
})
|
|
}
|
|
|
|
async function main() {
|
|
console.log("Supermemory Docs Test Runner")
|
|
console.log("============================\n")
|
|
|
|
let tests = getTests()
|
|
|
|
// Filter tests if specified
|
|
if (filter) {
|
|
tests = tests.filter(
|
|
(t) => t.name.includes(filter) || t.type === filter.replace(".", ""),
|
|
)
|
|
}
|
|
|
|
if (tests.length === 0) {
|
|
console.log("No tests matched the filter:", filter)
|
|
console.log("\nAvailable tests:")
|
|
getTests().forEach((t) => {
|
|
console.log(` - ${t.name} (${t.type})`)
|
|
})
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log(`Running ${tests.length} test(s)...\n`)
|
|
|
|
const results: { test: string; passed: boolean }[] = []
|
|
|
|
for (const test of tests) {
|
|
const passed = await runTest(test)
|
|
results.push({ test: test.name, passed })
|
|
}
|
|
|
|
// Summary
|
|
console.log(`\n${"=".repeat(60)}`)
|
|
console.log("SUMMARY")
|
|
console.log("=".repeat(60))
|
|
|
|
const passed = results.filter((r) => r.passed).length
|
|
const failed = results.filter((r) => !r.passed).length
|
|
|
|
for (const r of results) {
|
|
console.log(`${r.passed ? "✅" : "❌"} ${r.test}`)
|
|
}
|
|
|
|
console.log(`\nTotal: ${passed} passed, ${failed} failed`)
|
|
|
|
if (failed > 0) {
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
main().catch((error) => {
|
|
console.error(error)
|
|
process.exitCode = 1
|
|
})
|
|
}
|