supermemory/packages/docs-test/run.ts
MaheshtheDev d42e71f8bb fix(docs-test): Windows venvs and failing TypeScript examples (#1804)
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>
2026-10-13 19:59:35 +00:00

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
})
}