test: clear plugin registry broad matchers

This commit is contained in:
Peter Steinberger
2026-05-10 14:44:45 +01:00
parent 089a2e8710
commit 4fc09608ef

View File

@@ -149,6 +149,49 @@ function createIndex(
};
}
function requireRecord(value: unknown, label: string): Record<string, unknown> {
expect(typeof value, label).toBe("object");
expect(value, label).not.toBeNull();
return value as Record<string, unknown>;
}
function requireArray(value: unknown, label: string): unknown[] {
expect(Array.isArray(value), label).toBe(true);
return value as unknown[];
}
function expectFields(record: Record<string, unknown>, expected: Record<string, unknown>) {
for (const [key, value] of Object.entries(expected)) {
expect(record[key], key).toEqual(value);
}
}
function expectPluginRecordFields(record: unknown, expected: Record<string, unknown>) {
expectFields(requireRecord(record, "plugin record"), expected);
}
function expectDiagnosticCodes(diagnostics: unknown, expectedCodes: string[]) {
const codes = requireArray(diagnostics, "diagnostics").map(
(diagnostic) => requireRecord(diagnostic, "diagnostic").code,
);
expect(codes).toEqual(expectedCodes);
}
function expectInstallRecord(
installRecords: unknown,
pluginId: string,
expected: Record<string, unknown>,
) {
const records = requireRecord(installRecords, "install records");
expectFields(requireRecord(records[pluginId], `${pluginId} install record`), expected);
}
function expectSnapshotPluginIds(snapshot: InstalledPluginIndex, expectedPluginIds: string[]) {
expect(listPluginRecords({ index: snapshot }).map((plugin) => plugin.pluginId)).toEqual(
expectedPluginIds,
);
}
describe("plugin registry facade", () => {
it("resolves relative plugin API paths against the plugin root", () => {
const pluginRoot = path.join(makeTempDir(), "plugins", "demo");
@@ -181,7 +224,7 @@ describe("plugin registry facade", () => {
});
expect(listPluginRecords({ index }).map((plugin) => plugin.pluginId)).toEqual(["demo"]);
expect(getPluginRecord({ index, pluginId: "demo" })).toMatchObject({
expectPluginRecordFields(getPluginRecord({ index, pluginId: "demo" }), {
pluginId: "demo",
enabled: true,
});
@@ -246,7 +289,7 @@ describe("plugin registry facade", () => {
preferPersisted: false,
});
expect(getPluginRecord({ index, pluginId: "demo" })).toMatchObject({
expectPluginRecordFields(getPluginRecord({ index, pluginId: "demo" }), {
pluginId: "demo",
enabled: false,
});
@@ -344,26 +387,19 @@ describe("plugin registry facade", () => {
expect(normalizePluginId("openai-chat")).toBe("openai");
expect(normalizePluginId("unknown-plugin")).toBe("unknown-plugin");
expect(
normalizePluginsConfigWithRegistry(
{
allow: ["openai-chat"],
entries: {
"OpenAI-Codex": {
enabled: false,
},
const normalizedConfig = normalizePluginsConfigWithRegistry(
{
allow: ["openai-chat"],
entries: {
"OpenAI-Codex": {
enabled: false,
},
},
index,
),
).toMatchObject({
allow: ["openai"],
entries: {
openai: {
enabled: false,
},
},
});
index,
);
expect(normalizedConfig.allow).toEqual(["openai"]);
expect(normalizedConfig.entries?.openai?.enabled).toBe(false);
});
it("normalizes plugin config ids from a provided manifest registry without rereading manifests", () => {
@@ -387,17 +423,14 @@ describe("plugin registry facade", () => {
});
expect(normalizePluginId("demo-chat")).toBe("demo");
expect(
normalizePluginsConfigWithRegistry(
{
allow: ["demo-chat"],
},
index,
{ manifestRegistry: lookUpTable.manifestRegistry },
),
).toMatchObject({
allow: ["demo"],
});
const normalizedConfig = normalizePluginsConfigWithRegistry(
{
allow: ["demo-chat"],
},
index,
{ manifestRegistry: lookUpTable.manifestRegistry },
);
expect(normalizedConfig.allow).toEqual(["demo"]);
});
it("reads the persisted registry before deriving from discovered candidates", async () => {
@@ -462,12 +495,8 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-source" }),
]);
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-source"]);
expectSnapshotPluginIds(result.snapshot, ["demo"]);
});
it("falls back to the derived registry when persisted manifest metadata is stale", async () => {
@@ -501,9 +530,7 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-source" }),
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-source"]);
expect(result.snapshot.plugins[0]?.manifestHash).not.toBe(persisted.plugins[0]?.manifestHash);
});
@@ -543,9 +570,7 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-source" }),
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-source"]);
expect(result.snapshot.plugins[0]?.packageJson?.hash).not.toBe(
persisted.plugins[0]?.packageJson?.hash,
);
@@ -583,9 +608,7 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-source" }),
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-source"]);
expect(result.snapshot.plugins[0]?.packageJson).toBeUndefined();
});
@@ -617,12 +640,8 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-source" }),
]);
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-source"]);
expectSnapshotPluginIds(result.snapshot, ["demo"]);
});
it("falls back to the derived registry when persisted policy is stale", async () => {
@@ -655,17 +674,11 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-stale-policy" }),
]);
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expect(result.snapshot.installRecords).toMatchObject({
persisted: {
source: "npm",
spec: "persisted-plugin@1.0.0",
},
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-stale-policy"]);
expectSnapshotPluginIds(result.snapshot, ["demo"]);
expectInstallRecord(result.snapshot.installRecords, "persisted", {
source: "npm",
spec: "persisted-plugin@1.0.0",
});
});
@@ -681,12 +694,8 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "persisted-registry-missing" }),
]);
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-missing"]);
expectSnapshotPluginIds(result.snapshot, ["demo"]);
});
it("derives fresh config-scoped registries when the persisted registry is missing", () => {
@@ -740,15 +749,11 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(result.diagnostics).toEqual([
expect.objectContaining({
code: "persisted-registry-disabled",
message: expect.stringContaining("deprecated break-glass compatibility switch"),
}),
]);
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expectDiagnosticCodes(result.diagnostics, ["persisted-registry-disabled"]);
expect(String(requireRecord(result.diagnostics[0], "diagnostic").message)).toContain(
"deprecated break-glass compatibility switch",
);
expectSnapshotPluginIds(result.snapshot, ["demo"]);
});
it("derives a fresh registry without dropping persisted install records", async () => {
@@ -776,14 +781,10 @@ describe("plugin registry facade", () => {
});
expect(result.source).toBe("derived");
expect(listPluginRecords({ index: result.snapshot }).map((plugin) => plugin.pluginId)).toEqual([
"demo",
]);
expect(result.snapshot.installRecords).toMatchObject({
persisted: {
source: "npm",
spec: "persisted-plugin@1.0.0",
},
expectSnapshotPluginIds(result.snapshot, ["demo"]);
expectInstallRecord(result.snapshot.installRecords, "persisted", {
source: "npm",
spec: "persisted-plugin@1.0.0",
});
});
@@ -794,16 +795,11 @@ describe("plugin registry facade", () => {
const candidate = createCandidate(pluginDir);
const env = hermeticEnv();
await expect(
inspectPluginRegistry({ stateDir, candidates: [candidate], env }),
).resolves.toMatchObject({
state: "missing",
refreshReasons: ["missing"],
persisted: null,
current: {
plugins: [expect.objectContaining({ pluginId: "demo" })],
},
});
const missingInspect = await inspectPluginRegistry({ stateDir, candidates: [candidate], env });
expect(missingInspect.state).toBe("missing");
expect(missingInspect.refreshReasons).toEqual(["missing"]);
expect(missingInspect.persisted).toBeNull();
expect(missingInspect.current.plugins.map((plugin) => plugin.pluginId)).toEqual(["demo"]);
await refreshPluginRegistry({
reason: "manual",
@@ -812,15 +808,10 @@ describe("plugin registry facade", () => {
env,
});
await expect(
inspectPluginRegistry({ stateDir, candidates: [candidate], env }),
).resolves.toMatchObject({
state: "fresh",
refreshReasons: [],
persisted: {
plugins: [expect.objectContaining({ pluginId: "demo" })],
},
});
const freshInspect = await inspectPluginRegistry({ stateDir, candidates: [candidate], env });
expect(freshInspect.state).toBe("fresh");
expect(freshInspect.refreshReasons).toEqual([]);
expect(freshInspect.persisted?.plugins.map((plugin) => plugin.pluginId)).toEqual(["demo"]);
});
it("preserves install records when refreshing the persisted registry", async () => {
@@ -846,15 +837,16 @@ describe("plugin registry facade", () => {
env: hermeticEnv(),
});
await expect(readPersistedInstalledPluginIndex({ stateDir })).resolves.toMatchObject({
installRecords: {
missing: {
source: "npm",
spec: "missing-plugin@1.0.0",
installPath: path.join(stateDir, "plugins", "missing"),
},
},
plugins: [],
const persisted = await readPersistedInstalledPluginIndex({ stateDir });
expect(persisted).not.toBeNull();
if (!persisted) {
throw new Error("Expected persisted plugin index");
}
expectInstallRecord(persisted.installRecords, "missing", {
source: "npm",
spec: "missing-plugin@1.0.0",
installPath: path.join(stateDir, "plugins", "missing"),
});
expect(persisted.plugins).toEqual([]);
});
});