feat(FN-3778): add reports plugin scaffold with notification service improv
The merge introduces a new `fusion-plugin-reports` plugin scaffold with settings schema, manifest, entry point, and tests, alongside a mobile session switcher in the chat header. It also adds a mailbox notifications system with ntfy/webhook providers, cleans up roadmap types from core, and includes Fusion-Task-Id: FN-3778
This commit is contained in:
51
plugins/fusion-plugin-reports/src/__tests__/manifest.test.ts
Normal file
51
plugins/fusion-plugin-reports/src/__tests__/manifest.test.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import manifest from "../../manifest.json";
|
||||
import plugin from "../index.js";
|
||||
|
||||
const expectedKeys = [
|
||||
"dailyEnabled",
|
||||
"dailyCron",
|
||||
"weeklyEnabled",
|
||||
"weeklyCron",
|
||||
"timezone",
|
||||
"generationPromptDaily",
|
||||
"generationPromptWeekly",
|
||||
"reviewPrompt",
|
||||
"reviewPanelAgentIds",
|
||||
"reviewMinApprovals",
|
||||
"reviewBlockingMode",
|
||||
"sectionOrder",
|
||||
"enabledSections",
|
||||
"includeSystemSummary",
|
||||
"includePerAgentSections",
|
||||
"brandTitle",
|
||||
"brandLogoUrl",
|
||||
"themeMode",
|
||||
"accentColor",
|
||||
"approvalRequired",
|
||||
"autoPublishOnApproval",
|
||||
"approverAgentIds",
|
||||
"publishTargets",
|
||||
] as const;
|
||||
|
||||
describe("reports plugin manifest", () => {
|
||||
it("exports expected plugin id", () => {
|
||||
expect(plugin.manifest.id).toBe("fusion-plugin-reports");
|
||||
});
|
||||
|
||||
it("keeps runtime manifest metadata aligned with manifest.json", () => {
|
||||
expect(plugin.manifest.id).toBe(manifest.id);
|
||||
expect(plugin.manifest.name).toBe(manifest.name);
|
||||
expect(plugin.manifest.version).toBe(manifest.version);
|
||||
expect(plugin.manifest.description).toBe(manifest.description);
|
||||
expect(plugin.manifest.author).toBe(manifest.author);
|
||||
expect(plugin.manifest.fusionVersion).toBe(manifest.fusionVersion);
|
||||
});
|
||||
|
||||
it("includes full settings schema", () => {
|
||||
expect(plugin.manifest.settingsSchema).toBeDefined();
|
||||
for (const key of expectedKeys) {
|
||||
expect(plugin.manifest.settingsSchema).toHaveProperty(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
157
plugins/fusion-plugin-reports/src/__tests__/settings.test.ts
Normal file
157
plugins/fusion-plugin-reports/src/__tests__/settings.test.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { PluginSettingType } from "@fusion/plugin-sdk";
|
||||
import {
|
||||
DEFAULT_ACCENT_COLOR,
|
||||
DEFAULT_AUTO_PUBLISH_ON_APPROVAL,
|
||||
DEFAULT_BRAND_TITLE,
|
||||
DEFAULT_DAILY_CRON,
|
||||
DEFAULT_DAILY_ENABLED,
|
||||
DEFAULT_ENABLED_SECTIONS,
|
||||
DEFAULT_GENERATION_PROMPT_DAILY,
|
||||
DEFAULT_GENERATION_PROMPT_WEEKLY,
|
||||
DEFAULT_INCLUDE_PER_AGENT_SECTIONS,
|
||||
DEFAULT_INCLUDE_SYSTEM_SUMMARY,
|
||||
DEFAULT_PUBLISH_TARGETS,
|
||||
DEFAULT_REVIEW_BLOCKING_MODE,
|
||||
DEFAULT_REVIEW_MIN_APPROVALS,
|
||||
DEFAULT_REVIEW_PROMPT,
|
||||
DEFAULT_SECTION_ORDER,
|
||||
DEFAULT_THEME_MODE,
|
||||
DEFAULT_TIMEZONE,
|
||||
DEFAULT_WEEKLY_CRON,
|
||||
DEFAULT_WEEKLY_ENABLED,
|
||||
getAccentColor,
|
||||
getApprovalRequired,
|
||||
getApproverAgentIds,
|
||||
getAutoPublishOnApproval,
|
||||
getBrandLogoUrl,
|
||||
getBrandTitle,
|
||||
getDailyCron,
|
||||
getDailyEnabled,
|
||||
getEnabledSections,
|
||||
getGenerationPromptDaily,
|
||||
getGenerationPromptWeekly,
|
||||
getIncludePerAgentSections,
|
||||
getIncludeSystemSummary,
|
||||
getPublishTargets,
|
||||
getReviewBlockingMode,
|
||||
getReviewMinApprovals,
|
||||
getReviewPanelAgentIds,
|
||||
getReviewPrompt,
|
||||
getSectionOrder,
|
||||
getThemeMode,
|
||||
getTimezone,
|
||||
getWeeklyCron,
|
||||
getWeeklyEnabled,
|
||||
settingsSchema,
|
||||
} from "../settings.js";
|
||||
|
||||
const VALID_TYPES: PluginSettingType[] = ["string", "number", "boolean", "enum", "password", "array"];
|
||||
|
||||
describe("reports plugin settings schema", () => {
|
||||
it("uses only valid plugin setting types and labels", () => {
|
||||
for (const [key, schema] of Object.entries(settingsSchema)) {
|
||||
expect(VALID_TYPES).toContain(schema.type);
|
||||
expect(typeof schema.label).toBe("string");
|
||||
expect(schema.label?.trim().length).toBeGreaterThan(0);
|
||||
|
||||
if (schema.type === "enum") {
|
||||
expect(Array.isArray(schema.enumValues)).toBe(true);
|
||||
expect(schema.enumValues?.length ?? 0).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
if (schema.type === "array") {
|
||||
expect(schema.itemType).toBe("string");
|
||||
}
|
||||
|
||||
expect(key.length).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
it("uses documented literal defaults", () => {
|
||||
expect(settingsSchema.dailyCron.defaultValue).toBe("0 8 * * *");
|
||||
expect(settingsSchema.weeklyCron.defaultValue).toBe("0 8 * * 1");
|
||||
expect(settingsSchema.timezone.defaultValue).toBe("UTC");
|
||||
expect(settingsSchema.themeMode.defaultValue).toBe("auto");
|
||||
expect(settingsSchema.brandTitle.defaultValue).toBe("Fusion Activity Report");
|
||||
});
|
||||
|
||||
it("returns defaults for empty settings", () => {
|
||||
const empty = {};
|
||||
expect(getDailyEnabled(empty)).toBe(DEFAULT_DAILY_ENABLED);
|
||||
expect(getDailyCron(empty)).toBe(DEFAULT_DAILY_CRON);
|
||||
expect(getWeeklyEnabled(empty)).toBe(DEFAULT_WEEKLY_ENABLED);
|
||||
expect(getWeeklyCron(empty)).toBe(DEFAULT_WEEKLY_CRON);
|
||||
expect(getTimezone(empty)).toBe(DEFAULT_TIMEZONE);
|
||||
expect(getGenerationPromptDaily(empty)).toBe(DEFAULT_GENERATION_PROMPT_DAILY);
|
||||
expect(getGenerationPromptWeekly(empty)).toBe(DEFAULT_GENERATION_PROMPT_WEEKLY);
|
||||
expect(getReviewPrompt(empty)).toBe(DEFAULT_REVIEW_PROMPT);
|
||||
expect(getReviewPanelAgentIds(empty)).toEqual([]);
|
||||
expect(getReviewMinApprovals(empty)).toBe(DEFAULT_REVIEW_MIN_APPROVALS);
|
||||
expect(getReviewBlockingMode(empty)).toBe(DEFAULT_REVIEW_BLOCKING_MODE);
|
||||
expect(getSectionOrder(empty)).toEqual(DEFAULT_SECTION_ORDER);
|
||||
expect(getEnabledSections(empty)).toEqual(DEFAULT_ENABLED_SECTIONS);
|
||||
expect(getIncludeSystemSummary(empty)).toBe(DEFAULT_INCLUDE_SYSTEM_SUMMARY);
|
||||
expect(getIncludePerAgentSections(empty)).toBe(DEFAULT_INCLUDE_PER_AGENT_SECTIONS);
|
||||
expect(getBrandTitle(empty)).toBe(DEFAULT_BRAND_TITLE);
|
||||
expect(getBrandLogoUrl(empty)).toBeUndefined();
|
||||
expect(getThemeMode(empty)).toBe(DEFAULT_THEME_MODE);
|
||||
expect(getAccentColor(empty)).toBe(DEFAULT_ACCENT_COLOR);
|
||||
expect(getApprovalRequired(empty)).toBe(false);
|
||||
expect(getAutoPublishOnApproval(empty)).toBe(DEFAULT_AUTO_PUBLISH_ON_APPROVAL);
|
||||
expect(getApproverAgentIds(empty)).toEqual([]);
|
||||
expect(getPublishTargets(empty)).toEqual(DEFAULT_PUBLISH_TARGETS);
|
||||
});
|
||||
|
||||
it("returns configured values when provided", () => {
|
||||
const populated = {
|
||||
dailyEnabled: false,
|
||||
dailyCron: "5 9 * * *",
|
||||
weeklyEnabled: false,
|
||||
weeklyCron: "15 7 * * 2",
|
||||
timezone: "America/New_York",
|
||||
generationPromptDaily: "daily prompt",
|
||||
generationPromptWeekly: "weekly prompt",
|
||||
reviewPrompt: "review prompt",
|
||||
reviewPanelAgentIds: ["agent-a", "agent-b"],
|
||||
reviewMinApprovals: 3,
|
||||
reviewBlockingMode: "block",
|
||||
sectionOrder: ["highlights", "wins"],
|
||||
enabledSections: ["wins"],
|
||||
includeSystemSummary: false,
|
||||
includePerAgentSections: false,
|
||||
brandTitle: "Custom Report",
|
||||
brandLogoUrl: "https://example.com/logo.png",
|
||||
themeMode: "dark",
|
||||
accentColor: "#123456",
|
||||
approvalRequired: true,
|
||||
autoPublishOnApproval: false,
|
||||
approverAgentIds: ["approver-a"],
|
||||
publishTargets: ["dashboard", "html-export"],
|
||||
} satisfies Record<string, unknown>;
|
||||
|
||||
expect(getDailyEnabled(populated)).toBe(false);
|
||||
expect(getDailyCron(populated)).toBe("5 9 * * *");
|
||||
expect(getWeeklyEnabled(populated)).toBe(false);
|
||||
expect(getWeeklyCron(populated)).toBe("15 7 * * 2");
|
||||
expect(getTimezone(populated)).toBe("America/New_York");
|
||||
expect(getGenerationPromptDaily(populated)).toBe("daily prompt");
|
||||
expect(getGenerationPromptWeekly(populated)).toBe("weekly prompt");
|
||||
expect(getReviewPrompt(populated)).toBe("review prompt");
|
||||
expect(getReviewPanelAgentIds(populated)).toEqual(["agent-a", "agent-b"]);
|
||||
expect(getReviewMinApprovals(populated)).toBe(3);
|
||||
expect(getReviewBlockingMode(populated)).toBe("block");
|
||||
expect(getSectionOrder(populated)).toEqual(["highlights", "wins"]);
|
||||
expect(getEnabledSections(populated)).toEqual(["wins"]);
|
||||
expect(getIncludeSystemSummary(populated)).toBe(false);
|
||||
expect(getIncludePerAgentSections(populated)).toBe(false);
|
||||
expect(getBrandTitle(populated)).toBe("Custom Report");
|
||||
expect(getBrandLogoUrl(populated)).toBe("https://example.com/logo.png");
|
||||
expect(getThemeMode(populated)).toBe("dark");
|
||||
expect(getAccentColor(populated)).toBe("#123456");
|
||||
expect(getApprovalRequired(populated)).toBe(true);
|
||||
expect(getAutoPublishOnApproval(populated)).toBe(false);
|
||||
expect(getApproverAgentIds(populated)).toEqual(["approver-a"]);
|
||||
expect(getPublishTargets(populated)).toEqual(["dashboard", "html-export"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user