mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-30 16:45:48 +08:00
138 lines
3.9 KiB
JavaScript
138 lines
3.9 KiB
JavaScript
/**
|
|
* Tests for the published OpenCode hook plugin surface.
|
|
*/
|
|
|
|
const assert = require("node:assert")
|
|
const fs = require("node:fs")
|
|
const os = require("node:os")
|
|
const path = require("node:path")
|
|
const { spawnSync } = require("node:child_process")
|
|
const { pathToFileURL } = require("node:url")
|
|
|
|
function runTest(name, fn) {
|
|
return Promise.resolve()
|
|
.then(fn)
|
|
.then(() => {
|
|
console.log(` ✓ ${name}`)
|
|
return { passed: 1, failed: 0 }
|
|
})
|
|
.catch((error) => {
|
|
console.log(` ✗ ${name}`)
|
|
console.error(` ${error.stack || error.message}`)
|
|
return { passed: 0, failed: 1 }
|
|
})
|
|
}
|
|
|
|
async function loadPlugin() {
|
|
const repoRoot = path.join(__dirname, "..")
|
|
const buildResult = spawnSync("node", [path.join(repoRoot, "scripts", "build-opencode.js")], {
|
|
cwd: repoRoot,
|
|
encoding: "utf8",
|
|
})
|
|
assert.strictEqual(buildResult.status, 0, buildResult.stderr || buildResult.stdout)
|
|
const pluginUrl = pathToFileURL(
|
|
path.join(repoRoot, ".opencode", "dist", "plugins", "ecc-hooks.js")
|
|
).href
|
|
return import(pluginUrl)
|
|
}
|
|
|
|
function createClient() {
|
|
const logs = []
|
|
return {
|
|
logs,
|
|
app: {
|
|
log: ({ body }) => {
|
|
logs.push(body)
|
|
return Promise.resolve()
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
function createFailingShell() {
|
|
const calls = []
|
|
const shell = (strings, ...values) => {
|
|
calls.push(String.raw({ raw: strings }, ...values))
|
|
const error = new Error("OpenCode plugin file probes must not use shell commands")
|
|
return {
|
|
then: (_resolve, reject) => reject(error),
|
|
text: async () => {
|
|
throw error
|
|
},
|
|
}
|
|
}
|
|
shell.calls = calls
|
|
return shell
|
|
}
|
|
|
|
async function withTempProject(files, fn) {
|
|
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), "ecc-opencode-plugin-"))
|
|
try {
|
|
for (const file of files) {
|
|
const filePath = path.join(projectDir, file)
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
fs.writeFileSync(filePath, "")
|
|
}
|
|
return await fn(projectDir)
|
|
} finally {
|
|
fs.rmSync(projectDir, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log("\n=== Testing OpenCode plugin hooks ===\n")
|
|
|
|
const { ECCHooksPlugin } = await loadPlugin()
|
|
const tests = [
|
|
[
|
|
"shell.env detects project markers without shelling out to test -f",
|
|
async () => withTempProject(
|
|
["pnpm-lock.yaml", "tsconfig.json", "pyproject.toml"],
|
|
async (projectDir) => {
|
|
const client = createClient()
|
|
const $ = createFailingShell()
|
|
const hooks = await ECCHooksPlugin({ client, $, directory: projectDir })
|
|
|
|
const env = await hooks["shell.env"]()
|
|
|
|
assert.deepStrictEqual($.calls, [], `Unexpected shell probes: ${$.calls.join(", ")}`)
|
|
assert.strictEqual(env.PROJECT_ROOT, projectDir)
|
|
assert.strictEqual(env.PACKAGE_MANAGER, "pnpm")
|
|
assert.strictEqual(env.DETECTED_LANGUAGES, "typescript,python")
|
|
assert.strictEqual(env.PRIMARY_LANGUAGE, "typescript")
|
|
}
|
|
),
|
|
],
|
|
[
|
|
"session.created checks CLAUDE.md through fs instead of shell test",
|
|
async () => withTempProject(["CLAUDE.md"], async (projectDir) => {
|
|
const client = createClient()
|
|
const $ = createFailingShell()
|
|
const hooks = await ECCHooksPlugin({ client, $, directory: projectDir })
|
|
|
|
await hooks["session.created"]()
|
|
|
|
assert.deepStrictEqual($.calls, [], `Unexpected shell probes: ${$.calls.join(", ")}`)
|
|
assert.ok(
|
|
client.logs.some((entry) => entry.message === "[ECC] Found CLAUDE.md - loading project context"),
|
|
"Expected CLAUDE.md detection log"
|
|
)
|
|
}),
|
|
],
|
|
]
|
|
|
|
let passed = 0
|
|
let failed = 0
|
|
for (const [name, fn] of tests) {
|
|
const result = await runTest(name, fn)
|
|
passed += result.passed
|
|
failed += result.failed
|
|
}
|
|
|
|
console.log(`\nPassed: ${passed}`)
|
|
console.log(`Failed: ${failed}`)
|
|
process.exit(failed > 0 ? 1 : 0)
|
|
}
|
|
|
|
main()
|