import { beforeEach, describe, expect, it, vi } from "vitest" ;
import {
makeCatalogEntry,
makeChannelSetupEntries,
makeMeta,
} from "./channel-setup.test-helpers.js" ;
type ListChatChannels = typeof import ("../channels/chat-meta.js" ).listChatChannels;
type ResolveChannelSetupEntries =
typeof import ("../commands/channel-setup/discovery.js" ).resolveChannelSetupEntries;
type FormatChannelPrimerLine = typeof import ("../channels/registry.js" ).formatChannelPrimerLine;
type FormatChannelSelectionLine =
typeof import ("../channels/registry.js" ).formatChannelSelectionLine;
type IsChannelConfigured = typeof import ("../config/channel-configured.js" ).isChannelConfigured;
type NoteChannelPrimerChannels = Parameters<
typeof import ("./channel-setup.status.js" ).noteChannelPrimer
>[1 ];
const listChatChannels = vi.hoisted(() => vi.fn<ListChatChannels>(() => []));
const resolveChannelSetupEntries = vi.hoisted(() =>
vi.fn<ResolveChannelSetupEntries>(() => ({
entries: [],
installedCatalogEntries: [],
installableCatalogEntries: [],
installedCatalogById: new Map(),
installableCatalogById: new Map(),
})),
);
const formatChannelPrimerLine = vi.hoisted(() =>
vi.fn<FormatChannelPrimerLine>((meta) => `${meta.label}: ${meta.blurb}`),
);
const formatChannelSelectionLine = vi.hoisted(() =>
vi.fn<FormatChannelSelectionLine>((meta) => `${meta.label} — ${meta.blurb}`),
);
const isChannelConfigured = vi.hoisted(() => vi.fn<IsChannelConfigured>(() => false ));
vi.mock("../channels/chat-meta.js" , () => ({
listChatChannels: () => listChatChannels(),
}));
vi.mock("../channels/registry.js" , () => ({
formatChannelPrimerLine: (meta: Parameters<FormatChannelPrimerLine>[0 ]) =>
formatChannelPrimerLine(meta),
formatChannelSelectionLine: (
meta: Parameters<FormatChannelSelectionLine>[0 ],
docsLink: Parameters<FormatChannelSelectionLine>[1 ],
) => formatChannelSelectionLine(meta, docsLink),
}));
vi.mock("../commands/channel-setup/discovery.js" , () => ({
resolveChannelSetupEntries: (params: Parameters<ResolveChannelSetupEntries>[0 ]) =>
resolveChannelSetupEntries(params),
shouldShowChannelInSetup: (meta: { exposure?: { setup?: boolean }; showInSetup?: boolean }) =>
meta.showInSetup !== false && meta.exposure?.setup !== false ,
}));
vi.mock("../config/channel-configured.js" , () => ({
isChannelConfigured: (
cfg: Parameters<IsChannelConfigured>[0 ],
channelId: Parameters<IsChannelConfigured>[1 ],
) => isChannelConfigured(cfg, channelId),
}));
import {
collectChannelStatus,
noteChannelPrimer,
resolveChannelSelectionNoteLines,
resolveChannelSetupSelectionContributions,
} from "./channel-setup.status.js" ;
describe("resolveChannelSetupSelectionContributions" , () => {
beforeEach(() => {
vi.clearAllMocks();
listChatChannels.mockReturnValue([
makeMeta("discord" , "Discord" ),
makeMeta("bluebubbles" , "BlueBubbles" ),
]);
resolveChannelSetupEntries.mockReturnValue(makeChannelSetupEntries());
formatChannelPrimerLine.mockImplementation(
(meta: { label: string; blurb: string }) => `${meta.label}: ${meta.blurb}`,
);
formatChannelSelectionLine.mockImplementation((meta) => `${meta.label} — ${meta.blurb}`);
isChannelConfigured.mockReturnValue(false );
});
it("sorts channels alphabetically by picker label" , () => {
const contributions = resolveChannelSetupSelectionContributions({
entries: [
{
id: "zalo" ,
meta: {
id: "zalo" ,
label: "Zalo" ,
selectionLabel: "Zalo (Bot API)" ,
},
},
{
id: "discord" ,
meta: {
id: "discord" ,
label: "Discord" ,
selectionLabel: "Discord (Bot API)" ,
},
},
{
id: "bluebubbles" ,
meta: {
id: "bluebubbles" ,
label: "BlueBubbles" ,
selectionLabel: "BlueBubbles (macOS app)" ,
},
},
],
statusByChannel: new Map(),
resolveDisabledHint: () => undefined,
});
expect(contributions.map((contribution) => contribution.option.label)).toEqual([
"BlueBubbles (macOS app)" ,
"Discord (Bot API)" ,
"Zalo (Bot API)" ,
]);
});
it("does not invent hints before status has been collected" , () => {
const contributions = resolveChannelSetupSelectionContributions({
entries: [
{
id: "zalo" ,
meta: {
id: "zalo" ,
label: "Zalo" ,
selectionLabel: "Zalo (Bot API)" ,
},
},
],
statusByChannel: new Map(),
resolveDisabledHint: () => undefined,
});
expect(contributions.map((contribution) => contribution.option)).toEqual([
{
value: "zalo" ,
label: "Zalo (Bot API)" ,
},
]);
});
it("combines real status and disabled hints when available" , () => {
const contributions = resolveChannelSetupSelectionContributions({
entries: [
{
id: "zalo" ,
meta: {
id: "zalo" ,
label: "Zalo" ,
selectionLabel: "Zalo (Bot API)" ,
},
},
],
statusByChannel: new Map([["zalo" , { selectionHint: "configured" }]]),
resolveDisabledHint: () => "disabled" ,
});
expect(contributions[0 ]?.option).toEqual({
value: "zalo" ,
label: "Zalo (Bot API)" ,
hint: "configured · disabled" ,
});
});
it("sanitizes picker labels and hints before terminal rendering" , () => {
const contributions = resolveChannelSetupSelectionContributions({
entries: [
{
id: "zalo" ,
meta: {
id: "zalo" ,
label: "Zalo\u001B[31m\nBot\u0007" ,
},
},
],
statusByChannel: new Map([["zalo" , { selectionHint: "configured\u001B[2K\nnow" }]]),
resolveDisabledHint: () => "disabled\u0007" ,
});
expect(contributions[0 ]?.option).toEqual({
value: "zalo" ,
label: "Zalo\\nBot" ,
hint: "configured\\nnow · disabled" ,
});
});
it("sanitizes the picker fallback label when metadata sanitizes to empty" , () => {
const contributions = resolveChannelSetupSelectionContributions({
entries: [
{
id: "bad\u001B[31m\nid" ,
meta: {
id: "bad\u001B[31m\nid" ,
label: "\u001B[31m\u0007" ,
},
},
],
statusByChannel: new Map(),
resolveDisabledHint: () => undefined,
});
expect(contributions[0 ]?.option).toEqual({
value: "bad\u001B[31m\nid" ,
label: "bad\\nid" ,
});
});
it("sanitizes channel labels in status note lines" , async () => {
listChatChannels.mockReturnValue([makeMeta("discord" , "Discord\u001B[31m\nCore\u0007" )]);
resolveChannelSetupEntries.mockReturnValue(
makeChannelSetupEntries({
installedCatalogEntries: [makeCatalogEntry("matrix" , "Matrix\u001B[2K\nPlugin\u0007" )],
installableCatalogEntries: [makeCatalogEntry("zalo" , "Zalo\u001B[2K\nPlugin\u0007" )],
}),
);
const summary = await collectChannelStatus({
cfg: {} as never,
accountOverrides: {},
installedPlugins: [],
});
expect(summary.statusLines).toEqual([
"Discord\\nCore: not configured" ,
"Matrix\\nPlugin: installed" ,
"Zalo\\nPlugin: install plugin to enable" ,
]);
});
it("sanitizes channel metadata before primer notes" , async () => {
const note = vi.fn(async () => undefined);
await noteChannelPrimer(
{ note } as never,
[
{
id: "bad\u001B[31m\nid" ,
label: "\u001B[31m\u0007" ,
blurb: "Blurb\u001B[2K\nline\u0007" ,
} satisfies NoteChannelPrimerChannels[number],
] as NoteChannelPrimerChannels,
);
expect(formatChannelPrimerLine).toHaveBeenCalledWith(
expect.objectContaining({
id: "bad\\nid" ,
label: "bad\\nid" ,
selectionLabel: "bad\\nid" ,
blurb: "Blurb\\nline" ,
}),
);
expect(note).toHaveBeenCalledWith(
expect.stringContaining("bad\\nid: Blurb\\nline" ),
"How channels work" ,
);
});
it("sanitizes channel metadata before selection notes" , () => {
resolveChannelSetupEntries.mockReturnValue(
makeChannelSetupEntries({
entries: [
{
id: "zalo" ,
meta: {
id: "zalo" ,
label: "Zalo\u001B[31m\nBot\u0007" ,
selectionLabel: "Zalo" ,
docsPath: "/channels/zalo" ,
docsLabel: "Docs\u001B[2K\nLabel" ,
blurb: "Setup\u001B[2K\nhelp\u0007" ,
selectionDocsPrefix: "Docs\u001B[2K\nPrefix" ,
selectionExtras: ["Extra\u001B[2K\nOne" , "\u001B[31m\u0007" ],
},
},
],
}),
);
const lines = resolveChannelSelectionNoteLines({
cfg: {} as never,
installedPlugins: [],
selection: ["zalo" ],
});
expect(formatChannelSelectionLine).toHaveBeenCalledWith(
expect.objectContaining({
label: "Zalo\\nBot" ,
blurb: "Setup\\nhelp" ,
docsLabel: "Docs\\nLabel" ,
selectionDocsPrefix: "Docs\\nPrefix" ,
selectionExtras: ["Extra\\nOne" ],
}),
expect.any(Function ),
);
expect(lines).toEqual(["Zalo\\nBot — Setup\\nhelp" ]);
});
});
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-09)
¤
*© Formatika GbR, Deutschland