214 lines
6.7 KiB
TypeScript
214 lines
6.7 KiB
TypeScript
/**
|
|
* Unit tests for settings.ts pure functions.
|
|
* Tests migrateToGroupedFormat which converts legacy flat settings to grouped format.
|
|
*/
|
|
|
|
import { expect, test, describe } from "bun:test";
|
|
import { migrateToGroupedFormat } from "../src/core/settings.ts";
|
|
|
|
// =============================================================================
|
|
// migrateToGroupedFormat
|
|
// =============================================================================
|
|
|
|
describe("migrateToGroupedFormat", () => {
|
|
test("migrates legacy auto_invite fields to grouped format", () => {
|
|
const legacy = {
|
|
name: "my-workspace",
|
|
auto_invite_enabled: true,
|
|
auto_invite_as: "operator",
|
|
auto_invite_mode: "add",
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.auto_invite).toEqual({
|
|
enabled: true,
|
|
operator: true,
|
|
mode: "add",
|
|
});
|
|
});
|
|
|
|
test("migrates legacy auto_invite with non-operator role", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
auto_invite_enabled: true,
|
|
auto_invite_as: "developer",
|
|
auto_invite_mode: "invite",
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.auto_invite).toEqual({
|
|
enabled: true,
|
|
operator: false,
|
|
mode: "invite",
|
|
});
|
|
});
|
|
|
|
test("migrates legacy auto_invite when disabled", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
auto_invite_enabled: false,
|
|
auto_invite_as: "operator",
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.auto_invite!.enabled).toBe(false);
|
|
});
|
|
|
|
test("preserves already-grouped auto_invite", () => {
|
|
const grouped = {
|
|
name: "ws",
|
|
auto_invite: { enabled: true, operator: false, mode: "invite" as const },
|
|
};
|
|
const result = migrateToGroupedFormat(grouped);
|
|
expect(result.auto_invite).toEqual({
|
|
enabled: true,
|
|
operator: false,
|
|
mode: "invite",
|
|
});
|
|
});
|
|
|
|
test("migrates legacy error_handler string to grouped format", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
error_handler: "u/admin/error_handler",
|
|
error_handler_extra_args: { notify: true },
|
|
error_handler_muted_on_cancel: true,
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.error_handler).toEqual({
|
|
path: "u/admin/error_handler",
|
|
extra_args: { notify: true },
|
|
muted_on_cancel: true,
|
|
});
|
|
});
|
|
|
|
test("preserves already-grouped error_handler", () => {
|
|
const grouped = {
|
|
name: "ws",
|
|
error_handler: {
|
|
path: "u/admin/handler",
|
|
extra_args: {},
|
|
muted_on_cancel: false,
|
|
},
|
|
};
|
|
const result = migrateToGroupedFormat(grouped);
|
|
expect(result.error_handler).toEqual({
|
|
path: "u/admin/handler",
|
|
extra_args: {},
|
|
muted_on_cancel: false,
|
|
});
|
|
});
|
|
|
|
test("migrates legacy success_handler string to grouped format", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
success_handler: "u/admin/on_success",
|
|
success_handler_extra_args: { channel: "#deploys" },
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.success_handler).toEqual({
|
|
path: "u/admin/on_success",
|
|
extra_args: { channel: "#deploys" },
|
|
});
|
|
});
|
|
|
|
test("preserves already-grouped success_handler", () => {
|
|
const grouped = {
|
|
name: "ws",
|
|
success_handler: { path: "u/admin/handler", extra_args: {} },
|
|
};
|
|
const result = migrateToGroupedFormat(grouped);
|
|
expect(result.success_handler).toEqual({
|
|
path: "u/admin/handler",
|
|
extra_args: {},
|
|
});
|
|
});
|
|
|
|
test("copies non-legacy fields through", () => {
|
|
const settings = {
|
|
name: "my-workspace",
|
|
webhook: "https://example.com/hook",
|
|
deploy_to: "staging",
|
|
default_app: "u/admin/dashboard",
|
|
mute_critical_alerts: true,
|
|
color: "#ff0000",
|
|
};
|
|
const result = migrateToGroupedFormat(settings);
|
|
expect(result.name).toBe("my-workspace");
|
|
expect(result.webhook).toBe("https://example.com/hook");
|
|
expect(result.deploy_to).toBe("staging");
|
|
expect(result.default_app).toBe("u/admin/dashboard");
|
|
expect(result.mute_critical_alerts).toBe(true);
|
|
expect(result.color).toBe("#ff0000");
|
|
});
|
|
|
|
test("handles minimal settings with only name", () => {
|
|
const result = migrateToGroupedFormat({ name: "ws" });
|
|
expect(result.name).toBe("ws");
|
|
expect(result.auto_invite).toBeUndefined();
|
|
expect(result.error_handler).toBeUndefined();
|
|
expect(result.success_handler).toBeUndefined();
|
|
});
|
|
|
|
test("defaults name to empty string when missing", () => {
|
|
const result = migrateToGroupedFormat({});
|
|
expect(result.name).toBe("");
|
|
});
|
|
|
|
test("defaults auto_invite_mode to invite when missing", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
auto_invite_enabled: true,
|
|
auto_invite_as: "operator",
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.auto_invite!.mode).toBe("invite");
|
|
});
|
|
|
|
test("defaults error_handler_muted_on_cancel to false when missing", () => {
|
|
const legacy = {
|
|
name: "ws",
|
|
error_handler: "u/admin/handler",
|
|
};
|
|
const result = migrateToGroupedFormat(legacy);
|
|
expect(result.error_handler!.muted_on_cancel).toBe(false);
|
|
});
|
|
|
|
test("preserves ai_config, large_file_storage, git_sync, default_scripts, operator_settings", () => {
|
|
const settings = {
|
|
name: "ws",
|
|
ai_config: { provider: "openai" },
|
|
large_file_storage: { type: "s3" },
|
|
git_sync: { enabled: true },
|
|
default_scripts: { python: "template.py" },
|
|
operator_settings: { hideCode: true },
|
|
};
|
|
const result = migrateToGroupedFormat(settings);
|
|
expect(result.ai_config).toEqual({ provider: "openai" });
|
|
expect(result.large_file_storage).toEqual({ type: "s3" });
|
|
expect(result.git_sync).toEqual({ enabled: true });
|
|
expect(result.default_scripts).toEqual({ python: "template.py" });
|
|
expect(result.operator_settings).toEqual({ hideCode: true });
|
|
});
|
|
|
|
test("does not include undefined fields in result", () => {
|
|
const result = migrateToGroupedFormat({ name: "ws" });
|
|
expect("webhook" in result).toBe(false);
|
|
expect("deploy_to" in result).toBe(false);
|
|
expect("color" in result).toBe(false);
|
|
expect("slack_team_id" in result).toBe(false);
|
|
expect("slack_name" in result).toBe(false);
|
|
expect("slack_command_script" in result).toBe(false);
|
|
});
|
|
|
|
test("copies slack fields through", () => {
|
|
const settings = {
|
|
name: "ws",
|
|
slack_team_id: "T12345",
|
|
slack_name: "my-team",
|
|
slack_command_script: "u/admin/slack_handler",
|
|
};
|
|
const result = migrateToGroupedFormat(settings);
|
|
expect(result.slack_team_id).toBe("T12345");
|
|
expect(result.slack_name).toBe("my-team");
|
|
expect(result.slack_command_script).toBe("u/admin/slack_handler");
|
|
});
|
|
});
|