Files
oh-my-opencode/src/hooks/auto-update-checker/constants.test.ts
T
YeonGyu-Kim 4344a41eae fix(auto-update): resolve cached version when installed as oh-my-openagent (#3257)
The auto-update-checker's version resolver hardcoded the canonical
oh-my-opencode package name in three read paths:

  1. INSTALLED_PACKAGE_JSON pointed only at
     cache/node_modules/oh-my-opencode/package.json
  2. findPackageJsonUp() rejected any walked-up package.json whose name
     did not equal PACKAGE_NAME
  3. getLocalDevPath() only matched file:// plugin entries whose path
     contained the canonical name

The publish pipeline ships the same code under two npm package names
(oh-my-opencode canonical, oh-my-openagent alias). Users who add
"oh-my-openagent" to their opencode config end up with
node_modules/oh-my-openagent/package.json, so every read path above
silently missed the installed version and the startup toast fell back
to "unknown".

Introduce ACCEPTED_PACKAGE_NAMES + INSTALLED_PACKAGE_JSON_CANDIDATES in
constants.ts and teach the three readers to accept both names. Writes
are untouched (sync-package-json, pinned-version-updater, cache
invalidation) because the auto-update-checker still owns its own cache
workspace and writes to the canonical name there.

Tests: 54 auto-update-checker tests pass (4 new), full 4444-test suite
passes, tsc clean. New tests cover both install paths, the walk-up
resolver, and the priority order when both candidates exist.

Closes #3257
2026-04-09 07:29:07 +09:00

50 lines
2.1 KiB
TypeScript

import { describe, expect, it } from "bun:test"
import { readFileSync } from "node:fs"
import { join } from "node:path"
import { fileURLToPath } from "node:url"
import { getOpenCodeCacheDir } from "../../shared/data-path"
describe("auto-update-checker constants", () => {
it("uses the OpenCode cache directory for installed package metadata", async () => {
const { CACHE_DIR, INSTALLED_PACKAGE_JSON, PACKAGE_NAME } = await import(`./constants?test=${Date.now()}`)
expect(CACHE_DIR).toBe(join(getOpenCodeCacheDir(), "packages"))
expect(INSTALLED_PACKAGE_JSON).toBe(
join(getOpenCodeCacheDir(), "packages", "node_modules", PACKAGE_NAME, "package.json")
)
})
it("PACKAGE_NAME matches the published package.json name", async () => {
// given the canonical package.json shipped with the plugin
const here = fileURLToPath(import.meta.url)
const repoPackageJsonPath = join(here, "..", "..", "..", "..", "package.json")
const repoPackageJson = JSON.parse(readFileSync(repoPackageJsonPath, "utf-8")) as { name: string }
// when the auto-update-checker constants are loaded
const { PACKAGE_NAME } = await import(`./constants?test=${Date.now()}`)
// then PACKAGE_NAME equals the actually published package name
expect(PACKAGE_NAME).toBe(repoPackageJson.name)
})
it("ACCEPTED_PACKAGE_NAMES contains both the canonical and aliased npm names (GH-3257)", async () => {
const { ACCEPTED_PACKAGE_NAMES } = await import(`./constants?test=${Date.now()}`)
expect(ACCEPTED_PACKAGE_NAMES).toContain("oh-my-opencode")
expect(ACCEPTED_PACKAGE_NAMES).toContain("oh-my-openagent")
})
it("INSTALLED_PACKAGE_JSON_CANDIDATES covers every accepted package name (GH-3257)", async () => {
const { ACCEPTED_PACKAGE_NAMES, INSTALLED_PACKAGE_JSON_CANDIDATES, CACHE_DIR } = await import(
`./constants?test=${Date.now()}`
)
expect(INSTALLED_PACKAGE_JSON_CANDIDATES).toHaveLength(ACCEPTED_PACKAGE_NAMES.length)
for (const name of ACCEPTED_PACKAGE_NAMES) {
expect(INSTALLED_PACKAGE_JSON_CANDIDATES).toContain(
join(CACHE_DIR, "node_modules", name, "package.json")
)
}
})
})