fix(ui): handle slack config snapshot
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
- Heartbeat: make HEARTBEAT_OK ack padding configurable across heartbeat and cron delivery. (#238) — thanks @jalehman
|
- Heartbeat: make HEARTBEAT_OK ack padding configurable across heartbeat and cron delivery. (#238) — thanks @jalehman
|
||||||
- WhatsApp: set sender E.164 for direct chats so owner commands work in DMs.
|
- WhatsApp: set sender E.164 for direct chats so owner commands work in DMs.
|
||||||
- Slack: keep auto-replies in the original thread when responding to thread messages. Thanks @scald for PR #251.
|
- Slack: keep auto-replies in the original thread when responding to thread messages. Thanks @scald for PR #251.
|
||||||
|
- Control UI: avoid Slack config ReferenceError by reading slack config snapshots. Thanks @sreekaransrinath for PR #249.
|
||||||
|
|
||||||
### Maintenance
|
### Maintenance
|
||||||
- Deps: bump pi-* stack, Slack SDK, discord-api-types, file-type, zod, and Biome.
|
- Deps: bump pi-* stack, Slack SDK, discord-api-types, file-type, zod, and Biome.
|
||||||
|
|||||||
139
ui/src/ui/controllers/config.test.ts
Normal file
139
ui/src/ui/controllers/config.test.ts
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { applyConfigSnapshot, type ConfigState } from "./config";
|
||||||
|
import {
|
||||||
|
defaultDiscordActions,
|
||||||
|
defaultSlackActions,
|
||||||
|
type DiscordForm,
|
||||||
|
type IMessageForm,
|
||||||
|
type SignalForm,
|
||||||
|
type SlackForm,
|
||||||
|
type TelegramForm,
|
||||||
|
} from "../ui-types";
|
||||||
|
|
||||||
|
const baseTelegramForm: TelegramForm = {
|
||||||
|
token: "",
|
||||||
|
requireMention: true,
|
||||||
|
allowFrom: "",
|
||||||
|
proxy: "",
|
||||||
|
webhookUrl: "",
|
||||||
|
webhookSecret: "",
|
||||||
|
webhookPath: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseDiscordForm: DiscordForm = {
|
||||||
|
enabled: true,
|
||||||
|
token: "",
|
||||||
|
dmEnabled: true,
|
||||||
|
allowFrom: "",
|
||||||
|
groupEnabled: false,
|
||||||
|
groupChannels: "",
|
||||||
|
mediaMaxMb: "",
|
||||||
|
historyLimit: "",
|
||||||
|
textChunkLimit: "",
|
||||||
|
replyToMode: "off",
|
||||||
|
guilds: [],
|
||||||
|
actions: { ...defaultDiscordActions },
|
||||||
|
slashEnabled: false,
|
||||||
|
slashName: "",
|
||||||
|
slashSessionPrefix: "",
|
||||||
|
slashEphemeral: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseSlackForm: SlackForm = {
|
||||||
|
enabled: true,
|
||||||
|
botToken: "",
|
||||||
|
appToken: "",
|
||||||
|
dmEnabled: true,
|
||||||
|
allowFrom: "",
|
||||||
|
groupEnabled: false,
|
||||||
|
groupChannels: "",
|
||||||
|
mediaMaxMb: "",
|
||||||
|
textChunkLimit: "",
|
||||||
|
reactionNotifications: "own",
|
||||||
|
reactionAllowlist: "",
|
||||||
|
slashEnabled: false,
|
||||||
|
slashName: "",
|
||||||
|
slashSessionPrefix: "",
|
||||||
|
slashEphemeral: true,
|
||||||
|
actions: { ...defaultSlackActions },
|
||||||
|
channels: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseSignalForm: SignalForm = {
|
||||||
|
enabled: true,
|
||||||
|
account: "",
|
||||||
|
httpUrl: "",
|
||||||
|
httpHost: "",
|
||||||
|
httpPort: "",
|
||||||
|
cliPath: "",
|
||||||
|
autoStart: true,
|
||||||
|
receiveMode: "",
|
||||||
|
ignoreAttachments: false,
|
||||||
|
ignoreStories: false,
|
||||||
|
sendReadReceipts: false,
|
||||||
|
allowFrom: "",
|
||||||
|
mediaMaxMb: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseIMessageForm: IMessageForm = {
|
||||||
|
enabled: true,
|
||||||
|
cliPath: "",
|
||||||
|
dbPath: "",
|
||||||
|
service: "auto",
|
||||||
|
region: "",
|
||||||
|
allowFrom: "",
|
||||||
|
includeAttachments: false,
|
||||||
|
mediaMaxMb: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
function createState(): ConfigState {
|
||||||
|
return {
|
||||||
|
client: null,
|
||||||
|
connected: false,
|
||||||
|
configLoading: false,
|
||||||
|
configRaw: "",
|
||||||
|
configValid: null,
|
||||||
|
configIssues: [],
|
||||||
|
configSaving: false,
|
||||||
|
configSnapshot: null,
|
||||||
|
configSchema: null,
|
||||||
|
configSchemaVersion: null,
|
||||||
|
configSchemaLoading: false,
|
||||||
|
configUiHints: {},
|
||||||
|
configForm: null,
|
||||||
|
configFormDirty: false,
|
||||||
|
configFormMode: "form",
|
||||||
|
lastError: null,
|
||||||
|
telegramForm: { ...baseTelegramForm },
|
||||||
|
discordForm: { ...baseDiscordForm },
|
||||||
|
slackForm: { ...baseSlackForm },
|
||||||
|
signalForm: { ...baseSignalForm },
|
||||||
|
imessageForm: { ...baseIMessageForm },
|
||||||
|
telegramConfigStatus: null,
|
||||||
|
discordConfigStatus: null,
|
||||||
|
slackConfigStatus: null,
|
||||||
|
signalConfigStatus: null,
|
||||||
|
imessageConfigStatus: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("applyConfigSnapshot", () => {
|
||||||
|
it("handles missing slack config without throwing", () => {
|
||||||
|
const state = createState();
|
||||||
|
applyConfigSnapshot(state, {
|
||||||
|
config: {
|
||||||
|
telegram: {},
|
||||||
|
discord: {},
|
||||||
|
signal: {},
|
||||||
|
imessage: {},
|
||||||
|
},
|
||||||
|
valid: true,
|
||||||
|
issues: [],
|
||||||
|
raw: "{}",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(state.slackForm.botToken).toBe("");
|
||||||
|
expect(state.slackForm.actions).toEqual(defaultSlackActions);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -100,6 +100,7 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot
|
|||||||
const config = snapshot.config ?? {};
|
const config = snapshot.config ?? {};
|
||||||
const telegram = (config.telegram ?? {}) as Record<string, unknown>;
|
const telegram = (config.telegram ?? {}) as Record<string, unknown>;
|
||||||
const discord = (config.discord ?? {}) as Record<string, unknown>;
|
const discord = (config.discord ?? {}) as Record<string, unknown>;
|
||||||
|
const slack = (config.slack ?? {}) as Record<string, unknown>;
|
||||||
const signal = (config.signal ?? {}) as Record<string, unknown>;
|
const signal = (config.signal ?? {}) as Record<string, unknown>;
|
||||||
const imessage = (config.imessage ?? {}) as Record<string, unknown>;
|
const imessage = (config.imessage ?? {}) as Record<string, unknown>;
|
||||||
const toList = (value: unknown) =>
|
const toList = (value: unknown) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user