diff --git a/packages/server/src/server/plugins/index.posix.test.ts b/packages/server/src/server/plugins/index.posix.test.ts index 31b69c9c0b..5b6985a55e 100644 --- a/packages/server/src/server/plugins/index.posix.test.ts +++ b/packages/server/src/server/plugins/index.posix.test.ts @@ -15,7 +15,7 @@ import { tmpdir } from "node:os"; import path from "node:path"; import { pathToFileURL } from "node:url"; import pino from "pino"; -import { afterEach, beforeAll, describe, expect, it } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { DaemonConfigStore } from "../daemon-config-store.js"; import { PluginService } from "./index.js"; import { BuiltinPluginLoader } from "./builtin/index.js"; @@ -638,91 +638,6 @@ describe("PluginService", () => { await service.stopAllPlugins(); }); - it("resolves a bare registry id even when a matching directory exists in the daemon cwd", async () => { - const home = await mkdtemp(path.join(tmpdir(), "paseo-plugin-home-")); - const owner = path.join(process.cwd(), `registry-shadow-${randomUUID()}`); - await mkdir(owner); - roots.push(home, owner); - const source = `${path.basename(owner)}/example`; - const repository = await createPlugin("registry-example", "export default () => () => {};\n"); - await mkdir(path.join(owner, "example")); - await cp(repository, path.join(owner, "example"), { recursive: true }); - await runGitCommand(["init", "-b", "main"], { cwd: repository }); - await runGitCommand(["add", "-A"], { cwd: repository }); - await runGitCommand( - [ - "-c", - "user.name=Paseo Tests", - "-c", - "user.email=paseo@example.test", - "commit", - "-m", - "fixture", - ], - { cwd: repository }, - ); - const { stdout } = await runGitCommand(["rev-parse", "HEAD"], { cwd: repository }); - const requests: Array = []; - const server = createServer((request, response) => { - requests.push(request.url); - response.setHeader("Content-Type", "application/json"); - response.end( - JSON.stringify({ - id: source, - name: "Example", - description: "Test", - categories: [], - author: { github: path.basename(owner) }, - repository: { url: "https://github.com/fixture/example" }, - artifact: { - kind: "git", - remote: pathToFileURL(repository).href, - commit: stdout.trim(), - pluginPath: ".", - }, - media: [], - submittedAt: "2026-10-03", - reviewedAt: "2026-10-03", - updatedAt: "2026-10-03", - publishedAt: "2026-10-03", - readme: "# Test", - }), - ); - }); - await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); - const address = server.address(); - if (!address || typeof address === "string") throw new Error("Missing registry address"); - const url = `http://127.0.0.1:${address.port}`; - const store = createStore(home); - await store.patch({ pluginsEnabled: false }); - const service = bindTestSessionHost( - new PluginService(pino({ level: "silent" }), store, "0.4.0", { - managedSources: new ManagedPluginSources(home, { defaultUrl: url }), - }), - ); - try { - await service.start(); - await expect(service.installSource({ source })).resolves.toMatchObject({ - id: "registry-example", - status: "disabled", - installation: { - identity: { kind: "git", registry: { url, id: source } }, - currentRevision: stdout.trim(), - }, - }); - expect(requests).toEqual([`/plugins/${source}.json`]); - await expect( - service.installSource({ source: `./${source}`, id: "local-example" }), - ).resolves.toMatchObject({ - installation: { identity: { kind: "directory", path: path.join(owner, "example") } }, - }); - expect(requests).toEqual([`/plugins/${source}.json`]); - } finally { - await service.stopAllPlugins(); - await new Promise((resolve) => server.close(() => resolve())); - } - }, 30_000); - it("names a missing explicit directory instead of trying a managed source", async () => { const home = await mkdtemp(path.join(tmpdir(), "paseo-plugin-home-")); roots.push(home); @@ -1526,6 +1441,105 @@ export default function contribute(plugin: unknown) { }); }); +describe("PluginService registry source resolution", () => { + let home: string; + let owner: string; + let source: string; + let repository: string; + let revision: string; + + // Prepare the real Git fixture before the install deadline starts. On Windows, + // these four Git launches can consume much of the test’s 30-second budget. + beforeEach(async () => { + home = await mkdtemp(path.join(tmpdir(), "paseo-plugin-home-")); + owner = path.join(process.cwd(), `registry-shadow-${randomUUID()}`); + await mkdir(owner); + roots.push(home, owner); + source = `${path.basename(owner)}/example`; + repository = await createPlugin("registry-example", "export default () => () => {};\n"); + await mkdir(path.join(owner, "example")); + await cp(repository, path.join(owner, "example"), { recursive: true }); + await runGitCommand(["init", "-b", "main"], { cwd: repository }); + await runGitCommand(["add", "-A"], { cwd: repository }); + await runGitCommand( + [ + "-c", + "user.name=Paseo Tests", + "-c", + "user.email=paseo@example.test", + "commit", + "-m", + "fixture", + ], + { cwd: repository }, + ); + const { stdout } = await runGitCommand(["rev-parse", "HEAD"], { cwd: repository }); + revision = stdout.trim(); + }); + + it("resolves a bare registry id even when a matching directory exists in the daemon cwd", async () => { + const requests: Array = []; + const server = createServer((request, response) => { + requests.push(request.url); + response.setHeader("Content-Type", "application/json"); + response.end( + JSON.stringify({ + id: source, + name: "Example", + description: "Test", + categories: [], + author: { github: path.basename(owner) }, + repository: { url: "https://github.com/fixture/example" }, + artifact: { + kind: "git", + remote: pathToFileURL(repository).href, + commit: revision, + pluginPath: ".", + }, + media: [], + submittedAt: "2026-10-03", + reviewedAt: "2026-10-03", + updatedAt: "2026-10-03", + publishedAt: "2026-10-03", + readme: "# Test", + }), + ); + }); + await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); + const address = server.address(); + if (!address || typeof address === "string") throw new Error("Missing registry address"); + const url = `http://127.0.0.1:${address.port}`; + const store = createStore(home); + await store.patch({ pluginsEnabled: false }); + const service = bindTestSessionHost( + new PluginService(pino({ level: "silent" }), store, "0.4.0", { + managedSources: new ManagedPluginSources(home, { defaultUrl: url }), + }), + ); + try { + await service.start(); + await expect(service.installSource({ source })).resolves.toMatchObject({ + id: "registry-example", + status: "disabled", + installation: { + identity: { kind: "git", registry: { url, id: source } }, + currentRevision: revision, + }, + }); + expect(requests).toEqual([`/plugins/${source}.json`]); + await expect( + service.installSource({ source: `./${source}`, id: "local-example" }), + ).resolves.toMatchObject({ + installation: { identity: { kind: "directory", path: path.join(owner, "example") } }, + }); + expect(requests).toEqual([`/plugins/${source}.json`]); + } finally { + await service.stopAllPlugins(); + await new Promise((resolve) => server.close(() => resolve())); + } + }, 30_000); +}); + describe("npm plugin installation", () => { let registry: Awaited>;