Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion packages/opencode/test/cli/skill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { describe, test, expect } from "bun:test"
import fs from "fs/promises"
import path from "path"
import { tmpdir } from "../fixture/fixture"
import { detectToolReferences, SHELL_BUILTINS } from "../../src/cli/cmd/skill-helpers"
import { detectToolReferences, SHELL_BUILTINS, skillSource } from "../../src/cli/cmd/skill-helpers"
import os from "os"

// ---------------------------------------------------------------------------
// Unit tests — import production code directly (no duplication)
Expand Down Expand Up @@ -456,6 +457,44 @@ describe("skill install — symlink safety", () => {
})
})

// ---------------------------------------------------------------------------
// skillSource trust classification — determines builtin / global / project label
// ---------------------------------------------------------------------------

describe("skillSource", () => {
// Global.Path.home reads process.env.OPENCODE_TEST_HOME || os.homedir()
const home = process.env.OPENCODE_TEST_HOME || os.homedir()

test("builtin: prefix → builtin", () => {
expect(skillSource("builtin:dbt-run")).toBe("builtin")
expect(skillSource("builtin:")).toBe("builtin")
})

test("~/.altimate/builtin/... → builtin", () => {
expect(skillSource(path.join(home, ".altimate", "builtin", "dbt-run", "SKILL.md"))).toBe("builtin")
})

test("~/.claude/skills/... → global", () => {
expect(skillSource(path.join(home, ".claude", "skills", "my-skill", "SKILL.md"))).toBe("global")
})

test("~/.agents/skills/... → global", () => {
expect(skillSource(path.join(home, ".agents", "skills", "my-skill", "SKILL.md"))).toBe("global")
})

test("~/.altimate-code/skills/... → global", () => {
expect(skillSource(path.join(home, ".altimate-code", "skills", "custom", "SKILL.md"))).toBe("global")
})

test("project path → project", () => {
expect(skillSource("/home/user/myproject/.opencode/skills/custom/SKILL.md")).toBe("project")
})

test("random path with no skill dir match → project", () => {
expect(skillSource("/tmp/something/SKILL.md")).toBe("project")
})
})

describe("GitHub URL normalization", () => {
test("extracts owner/repo from web URLs", () => {
const re = /^https?:\/\/github\.com\/([^/]+\/[^/]+?)(?:\/(?:tree|blob)\/.*)?$/
Expand Down
32 changes: 32 additions & 0 deletions packages/opencode/test/util/fn.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, test, expect } from "bun:test"
import { z } from "zod"
import { fn } from "../../src/util/fn"

describe("fn: zod-validated function wrapper", () => {
test("passes validated input to callback", () => {
const add = fn(z.object({ a: z.number(), b: z.number() }), ({ a, b }) => a + b)
expect(add({ a: 1, b: 2 })).toBe(3)
})

test("throws ZodError on invalid input", () => {
const greet = fn(z.object({ name: z.string() }), ({ name }) => `hi ${name}`)
expect(() => greet({ name: 42 } as any)).toThrow()
})

test(".force() bypasses validation", () => {
const double = fn(z.number().int(), (n) => n * 2)
// 1.5 is not an int, but .force skips validation
expect(double.force(1.5)).toBe(3)
})

test(".schema exposes the original zod schema", () => {
const schema = z.string().email()
const validate = fn(schema, (s) => s.toUpperCase())
expect(validate.schema).toBe(schema)
})

test("rejects unknown keys with strict schema", () => {
const strict = fn(z.object({ id: z.number() }).strict(), ({ id }) => id)
expect(() => strict({ id: 1, extra: true } as any)).toThrow()
})
})
Loading