From c56efa3499858a85293925aff9a3737587cc4786 Mon Sep 17 00:00:00 2001 From: Mike North Date: Mon, 1 Jun 2026 13:21:13 -0700 Subject: [PATCH] Remove stray pre-cutover files missed in merge --- LICENSE.md | 21 --- tests/build-standalone.test.ts | 117 ---------------- tests/codex-acceptance.test.ts | 240 --------------------------------- 3 files changed, 378 deletions(-) delete mode 100644 LICENSE.md delete mode 100644 tests/build-standalone.test.ts delete mode 100644 tests/codex-acceptance.test.ts diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 08eb851..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 Mike North - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/tests/build-standalone.test.ts b/tests/build-standalone.test.ts deleted file mode 100644 index 72e855c..0000000 --- a/tests/build-standalone.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Tests for src/build-standalone.ts. - * - * Regression focus: `dist/` must be a pure function of `plugins/`. Removing or - * renaming a plugin must not leave stale exports behind — the builder cleans - * the target roots it owns on every run, so no manual `rm` is ever required. - */ - -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { buildAll, TARGETS } from "../src/build-standalone.js"; - -let tmpRoot: string | undefined; - -beforeEach(() => { - // Silence the builder's progress logging during tests. - vi.spyOn(console, "log").mockImplementation(() => undefined); - vi.spyOn(console, "warn").mockImplementation(() => undefined); - vi.spyOn(console, "error").mockImplementation(() => undefined); -}); - -afterEach(() => { - vi.restoreAllMocks(); - if (tmpRoot !== undefined) { - fs.rmSync(tmpRoot, { recursive: true, force: true }); - tmpRoot = undefined; - } -}); - -function makeRoot(): string { - tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "build-standalone-test-")); - return tmpRoot; -} - -function write(root: string, rel: string, contents: string): void { - const file = path.join(root, rel); - fs.mkdirSync(path.dirname(file), { recursive: true }); - fs.writeFileSync(file, contents); -} - -/** A plugin with the minimum needed to produce output in both targets. */ -function writePlugin(root: string, name: string): void { - write(root, `plugins/${name}/GEMINI.md`, `# ${name} (gemini)\n`); - write(root, `plugins/${name}/POWER.md`, `# ${name} (kiro)\n`); -} - -describe("buildAll — stale artifact cleanup", () => { - it("removes dist output for a plugin that no longer exists in plugins/", () => { - const root = makeRoot(); - writePlugin(root, "current"); - - // Stale exports from a previously-built, now-removed plugin. - write(root, "dist/gemini/removed/GEMINI.md", "stale\n"); - write(root, "dist/kiro/removed/POWER.md", "stale\n"); - - buildAll(root); - - // Stale plugin dirs are gone from every target. - expect(fs.existsSync(path.join(root, "dist/gemini/removed"))).toBe(false); - expect(fs.existsSync(path.join(root, "dist/kiro/removed"))).toBe(false); - - // The current plugin is freshly built in every target. - expect(fs.existsSync(path.join(root, "dist/gemini/current/GEMINI.md"))).toBe( - true, - ); - expect(fs.existsSync(path.join(root, "dist/kiro/current/POWER.md"))).toBe( - true, - ); - }); - - it("clears all target roots when plugins/ is empty (fresh start)", () => { - const root = makeRoot(); - fs.mkdirSync(path.join(root, "plugins"), { recursive: true }); - write(root, "dist/gemini/removed/GEMINI.md", "stale\n"); - write(root, "dist/kiro/removed/POWER.md", "stale\n"); - - buildAll(root); - - for (const target of TARGETS) { - expect(fs.existsSync(path.join(root, "dist", target))).toBe(false); - } - }); - - it("does not leave content from a renamed plugin under its old name", () => { - const root = makeRoot(); - // First build under the old name. - writePlugin(root, "old-name"); - buildAll(root); - expect(fs.existsSync(path.join(root, "dist/gemini/old-name"))).toBe(true); - - // Rename: remove old, add new, rebuild. - fs.rmSync(path.join(root, "plugins/old-name"), { recursive: true }); - writePlugin(root, "new-name"); - buildAll(root); - - expect(fs.existsSync(path.join(root, "dist/gemini/old-name"))).toBe(false); - expect(fs.existsSync(path.join(root, "dist/gemini/new-name/GEMINI.md"))).toBe( - true, - ); - }); - - it("exits when plugins/ is missing entirely", () => { - const root = makeRoot(); - const exit = vi - .spyOn(process, "exit") - .mockImplementation((() => { - throw new Error("process.exit called"); - }) as never); - - expect(() => buildAll(path.join(root, "no-such-subdir"))).toThrow( - "process.exit called", - ); - expect(exit).toHaveBeenCalledWith(1); - }); -}); diff --git a/tests/codex-acceptance.test.ts b/tests/codex-acceptance.test.ts deleted file mode 100644 index 6b96427..0000000 --- a/tests/codex-acceptance.test.ts +++ /dev/null @@ -1,240 +0,0 @@ -/** - * Tests for scripts/codex-acceptance.ts — target resolution. - * - * The acceptance driver derives the marketplace + plugin from the marketplace - * manifest rather than hardcoding the example plugin. These tests exercise that - * resolution (including the "fresh start" empty case) and the manifest loader. - * - * @see https://developers.openai.com/codex/plugins/build — Codex plugin schema - */ - -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; -import { afterEach, describe, expect, it } from "vitest"; -import { - loadMarketplace, - parsePluginArg, - resolvePluginSelection, - type CodexMarketplace, -} from "../scripts/codex-acceptance.js"; - -const ROOT = "/repo"; - -/** Build a minimal valid marketplace manifest for resolution tests. */ -function makeMarketplace( - name: string, - plugins: Array<{ name: string; path?: string }>, -): CodexMarketplace { - return { - name, - plugins: plugins.map((p) => ({ - name: p.name, - source: { source: "local", path: p.path ?? `./plugins/${p.name}` }, - })), - }; -} - -describe("resolvePluginSelection", () => { - describe("single plugin", () => { - const single = makeMarketplace("mkt", [{ name: "alpha" }]); - - it("auto-selects the lone plugin when no --plugin is given", () => { - const r = resolvePluginSelection(single, { - pluginArg: undefined, - root: ROOT, - }); - expect(r).toEqual({ - kind: "ok", - target: { - marketplaceName: "mkt", - pluginName: "alpha", - pluginDir: path.join(ROOT, "./plugins/alpha"), - }, - }); - }); - - it("selects it when --plugin matches", () => { - const r = resolvePluginSelection(single, { - pluginArg: "alpha", - root: ROOT, - }); - expect(r.kind).toBe("ok"); - }); - - it("reports not-found when --plugin does not match", () => { - const r = resolvePluginSelection(single, { - pluginArg: "ghost", - root: ROOT, - }); - expect(r).toEqual({ - kind: "not-found", - requested: "ghost", - available: ["alpha"], - }); - }); - }); - - describe("multiple plugins", () => { - const multi = makeMarketplace("mkt", [{ name: "alpha" }, { name: "beta" }]); - - it("is ambiguous without --plugin", () => { - const r = resolvePluginSelection(multi, { - pluginArg: undefined, - root: ROOT, - }); - expect(r).toEqual({ kind: "ambiguous", available: ["alpha", "beta"] }); - }); - - it("selects the named plugin with --plugin", () => { - const r = resolvePluginSelection(multi, { - pluginArg: "beta", - root: ROOT, - }); - expect(r).toEqual({ - kind: "ok", - target: { - marketplaceName: "mkt", - pluginName: "beta", - pluginDir: path.join(ROOT, "./plugins/beta"), - }, - }); - }); - - it("reports not-found for an unknown --plugin", () => { - const r = resolvePluginSelection(multi, { - pluginArg: "ghost", - root: ROOT, - }); - expect(r).toEqual({ - kind: "not-found", - requested: "ghost", - available: ["alpha", "beta"], - }); - }); - }); - - describe("no plugins (fresh start)", () => { - const empty = makeMarketplace("mkt", []); - - it("is empty without --plugin so preflight can no-op", () => { - const r = resolvePluginSelection(empty, { - pluginArg: undefined, - root: ROOT, - }); - expect(r).toEqual({ kind: "empty" }); - }); - - it("reports not-found (empty list) when --plugin is given", () => { - const r = resolvePluginSelection(empty, { - pluginArg: "alpha", - root: ROOT, - }); - expect(r).toEqual({ - kind: "not-found", - requested: "alpha", - available: [], - }); - }); - }); - - it("derives pluginDir from the entry's source.path, not a name guess", () => { - const custom = makeMarketplace("mkt", [ - { name: "alpha", path: "./packages/custom-dir" }, - ]); - const r = resolvePluginSelection(custom, { - pluginArg: undefined, - root: ROOT, - }); - expect(r).toMatchObject({ - target: { pluginDir: path.join(ROOT, "./packages/custom-dir") }, - }); - }); -}); - -describe("parsePluginArg", () => { - it("reads `--plugin `", () => { - expect(parsePluginArg(["--plugin", "foo"])).toBe("foo"); - }); - - it("reads `--plugin=`", () => { - expect(parsePluginArg(["--plugin=foo"])).toBe("foo"); - }); - - it("returns undefined when absent", () => { - expect(parsePluginArg(["verify", "--other"])).toBeUndefined(); - }); - - it("returns undefined when `--plugin` has no value", () => { - expect(parsePluginArg(["--plugin"])).toBeUndefined(); - }); - - it("treats `--plugin` followed by another option as missing", () => { - expect(parsePluginArg(["--plugin", "--dry-run"])).toBeUndefined(); - }); - - it("treats an empty `--plugin=` as missing", () => { - expect(parsePluginArg(["--plugin="])).toBeUndefined(); - }); -}); - -describe("loadMarketplace", () => { - let tmpDir: string | undefined; - - afterEach(() => { - if (tmpDir !== undefined) { - fs.rmSync(tmpDir, { recursive: true, force: true }); - tmpDir = undefined; - } - }); - - function writeTmp(contents: string): string { - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codex-accept-test-")); - const file = path.join(tmpDir, "marketplace.json"); - fs.writeFileSync(file, contents); - return file; - } - - it("reports missing for a nonexistent file", () => { - const r = loadMarketplace(path.join(os.tmpdir(), "does-not-exist-xyz.json")); - expect(r).toEqual({ kind: "missing" }); - }); - - it("reports invalid for malformed JSON", () => { - const r = loadMarketplace(writeTmp("{ not json")); - expect(r.kind).toBe("invalid"); - if (r.kind === "invalid") expect(r.issues).toMatch(/not valid JSON/); - }); - - it("reports a read error distinctly from a JSON parse error", () => { - // A directory exists at the path but cannot be read as a file (EISDIR), - // exercising the read-error branch rather than the JSON-parse branch. - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codex-accept-test-")); - const dirAsFile = path.join(tmpDir, "marketplace.json"); - fs.mkdirSync(dirAsFile); - const r = loadMarketplace(dirAsFile); - expect(r.kind).toBe("invalid"); - if (r.kind === "invalid") { - expect(r.issues).toMatch(/could not read file/); - expect(r.issues).not.toMatch(/not valid JSON/); - } - }); - - it("reports invalid for a schema violation", () => { - // Missing required `name` and `plugins`. - const r = loadMarketplace(writeTmp(JSON.stringify({ owner: { name: "x" } }))); - expect(r.kind).toBe("invalid"); - if (r.kind === "invalid") expect(r.issues.length).toBeGreaterThan(0); - }); - - it("returns parsed data for a valid manifest", () => { - const r = loadMarketplace( - writeTmp(JSON.stringify(makeMarketplace("mkt", [{ name: "alpha" }]))), - ); - expect(r.kind).toBe("ok"); - if (r.kind === "ok") { - expect(r.data.name).toBe("mkt"); - expect(r.data.plugins.map((p) => p.name)).toEqual(["alpha"]); - } - }); -});