feat(FN-3564): isolate plugin loader test state to prevent cross-test conta
Refactored plugin-loader tests and implementation to isolate plugin test contamination, improving test independence in `@fusion/core`. Fusion-Task-Id: FN-3564
This commit is contained in:
@@ -34,6 +34,7 @@ describe("PluginRunner", () => {
|
||||
getPluginTools: ReturnType<typeof vi.fn>;
|
||||
getPluginRoutes: ReturnType<typeof vi.fn>;
|
||||
getPluginUiSlots: ReturnType<typeof vi.fn>;
|
||||
getPluginUiContributions: ReturnType<typeof vi.fn>;
|
||||
getPluginRuntimes: ReturnType<typeof vi.fn>;
|
||||
getPluginSkills: ReturnType<typeof vi.fn>;
|
||||
getPluginWorkflowSteps: ReturnType<typeof vi.fn>;
|
||||
@@ -94,6 +95,7 @@ describe("PluginRunner", () => {
|
||||
getPluginTools: vi.fn().mockReturnValue([]),
|
||||
getPluginRoutes: vi.fn().mockReturnValue([]),
|
||||
getPluginUiSlots: vi.fn().mockReturnValue([]),
|
||||
getPluginUiContributions: vi.fn().mockReturnValue([]),
|
||||
getPluginRuntimes: vi.fn().mockReturnValue([]),
|
||||
getPluginSkills: vi.fn().mockReturnValue([]),
|
||||
getPluginWorkflowSteps: vi.fn().mockReturnValue([]),
|
||||
@@ -534,6 +536,50 @@ describe("PluginRunner", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPluginUiContributions()", () => {
|
||||
it("returns structured contributions from pluginLoader", () => {
|
||||
const contributions = [
|
||||
{
|
||||
pluginId: "plugin-a",
|
||||
contribution: {
|
||||
surface: "settings-config-section",
|
||||
contributionId: "cfg-a",
|
||||
sectionId: "openai",
|
||||
title: "OpenAI settings",
|
||||
pluginSettingKeys: ["openai.apiKey"],
|
||||
},
|
||||
},
|
||||
];
|
||||
mockPluginLoader.getPluginUiContributions.mockReturnValue(contributions);
|
||||
|
||||
const result = pluginRunner.getPluginUiContributions();
|
||||
|
||||
expect(result).toEqual(contributions);
|
||||
expect(mockPluginLoader.getPluginUiContributions).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("uses cached contributions until invalidated", () => {
|
||||
const contributions = [
|
||||
{
|
||||
pluginId: "plugin-a",
|
||||
contribution: {
|
||||
surface: "onboarding-provider-recommendation",
|
||||
contributionId: "rec-a",
|
||||
providerId: "openai",
|
||||
title: "OpenAI",
|
||||
reason: "default",
|
||||
},
|
||||
},
|
||||
];
|
||||
mockPluginLoader.getPluginUiContributions.mockReturnValue(contributions);
|
||||
|
||||
pluginRunner.getPluginUiContributions();
|
||||
pluginRunner.getPluginUiContributions();
|
||||
|
||||
expect(mockPluginLoader.getPluginUiContributions).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPluginRuntimes()", () => {
|
||||
it("should return empty array when no plugins have runtimes", async () => {
|
||||
mockPluginLoader.getPluginRuntimes.mockReturnValue([]);
|
||||
|
||||
@@ -15,6 +15,7 @@ import type {
|
||||
PluginToolDefinition,
|
||||
PluginRouteDefinition,
|
||||
PluginUiSlotDefinition,
|
||||
PluginUiContributionDefinition,
|
||||
PluginRuntimeRegistration,
|
||||
PluginContext,
|
||||
PluginSkillContribution,
|
||||
@@ -68,6 +69,11 @@ interface CachedUiSlots {
|
||||
version: number;
|
||||
}
|
||||
|
||||
interface CachedUiContributions {
|
||||
contributions: Array<{ pluginId: string; contribution: PluginUiContributionDefinition }>;
|
||||
version: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached runtimes - rebuilt when plugin state changes
|
||||
*/
|
||||
@@ -112,6 +118,7 @@ export class PluginRunner {
|
||||
private cachedTools: CachedTools | null = null;
|
||||
private cachedRoutes: CachedRoutes | null = null;
|
||||
private cachedUiSlots: CachedUiSlots | null = null;
|
||||
private cachedUiContributions: CachedUiContributions | null = null;
|
||||
private cachedRuntimes: CachedRuntimes | null = null;
|
||||
private cachedSkills: CachedSkills | null = null;
|
||||
private cachedWorkflowSteps: CachedWorkflowSteps | null = null;
|
||||
@@ -121,6 +128,7 @@ export class PluginRunner {
|
||||
private toolsCacheVersion = 0;
|
||||
private routesCacheVersion = 0;
|
||||
private uiSlotsCacheVersion = 0;
|
||||
private uiContributionsCacheVersion = 0;
|
||||
private runtimesCacheVersion = 0;
|
||||
private skillsCacheVersion = 0;
|
||||
private workflowStepsCacheVersion = 0;
|
||||
@@ -196,6 +204,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -284,6 +293,16 @@ export class PluginRunner {
|
||||
return this.cachedUiSlots.slots;
|
||||
}
|
||||
|
||||
getPluginUiContributions(): Array<{ pluginId: string; contribution: PluginUiContributionDefinition }> {
|
||||
if (!this.cachedUiContributions || this.cachedUiContributions.version !== this.uiContributionsCacheVersion) {
|
||||
this.cachedUiContributions = {
|
||||
contributions: this.options.pluginLoader.getPluginUiContributions(),
|
||||
version: this.uiContributionsCacheVersion,
|
||||
};
|
||||
}
|
||||
return this.cachedUiContributions.contributions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all runtime registrations from loaded plugins.
|
||||
* Runtimes are cached and only rebuilt when plugin state changes.
|
||||
@@ -404,6 +423,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -423,6 +443,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -447,6 +468,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -471,6 +493,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -494,6 +517,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -509,6 +533,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -524,6 +549,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -539,6 +565,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -554,6 +581,7 @@ export class PluginRunner {
|
||||
this.invalidateToolsCache();
|
||||
this.invalidateRoutesCache();
|
||||
this.invalidateUiSlotsCache();
|
||||
this.invalidateUiContributionsCache();
|
||||
this.invalidateRuntimesCache();
|
||||
this.invalidateSkillsCache();
|
||||
this.invalidateWorkflowStepsCache();
|
||||
@@ -757,6 +785,11 @@ export class PluginRunner {
|
||||
this.log.log(`UI slots cache invalidated (version: ${this.uiSlotsCacheVersion})`);
|
||||
}
|
||||
|
||||
private invalidateUiContributionsCache(): void {
|
||||
this.uiContributionsCacheVersion++;
|
||||
this.log.log(`UI contributions cache invalidated (version: ${this.uiContributionsCacheVersion})`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the runtimes cache, forcing rebuild on next access.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user