Files
bDS2/test/bds/ui/settings_form_test.exs

201 lines
6.5 KiB
Elixir

defmodule BDS.UI.SettingsFormTest do
use ExUnit.Case, async: false
alias BDS.UI.SettingsForm
setup do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(BDS.Repo)
Ecto.Adapters.SQL.Sandbox.mode(BDS.Repo, {:shared, self()})
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.mode(BDS.Repo, :manual) end)
temp_dir = Path.join(System.tmp_dir!(), "bds-settings-form-#{System.unique_integer([:positive])}")
File.mkdir_p!(temp_dir)
on_exit(fn -> File.rm_rf(temp_dir) end)
{:ok, project} = BDS.Projects.create_project(%{name: "Prefs", data_path: temp_dir})
{:ok, _} = BDS.Projects.set_active_project(project.id)
%{project: project}
end
defp field(form, key), do: Enum.find(form.fields, &(&1.key == key))
defp values(form, overrides) do
form.fields
|> Map.new(fn f -> {f.key, f.value} end)
|> Map.merge(overrides)
end
describe "project" do
test "load exposes the project metadata as typed fields", %{project: project} do
form = SettingsForm.load("project", project.id)
assert field(form, "name").value == "Prefs"
assert field(form, "name").type == :text
assert field(form, "main_language").type == :enum
assert "de" in field(form, "main_language").options
assert field(form, "semantic_similarity_enabled").type == :bool
end
test "save writes through Metadata and keeps untouched values", %{project: project} do
{:ok, _} = BDS.Metadata.update_project_metadata(project.id, %{pico_theme: "jade"})
form = SettingsForm.load("project", project.id)
:ok =
SettingsForm.save(
"project",
project.id,
values(form, %{
"name" => "Renamed",
"max_posts_per_page" => "25",
"blog_languages" => "en, de",
"semantic_similarity_enabled" => true
})
)
{:ok, metadata} = BDS.Metadata.get_project_metadata(project.id)
assert metadata.name == "Renamed"
assert metadata.max_posts_per_page == 25
assert metadata.blog_languages == ["en", "de"]
assert metadata.semantic_similarity_enabled
assert metadata.pico_theme == "jade"
end
end
describe "editor" do
test "round-trips the global editor settings", %{project: project} do
form = SettingsForm.load("editor", project.id)
assert field(form, "default_mode").type == :enum
:ok =
SettingsForm.save(
"editor",
project.id,
values(form, %{"default_mode" => "preview", "wrap_long_lines" => true})
)
assert BDS.Settings.get_global_setting("ui.preferred_editor_mode") == "preview"
assert BDS.Settings.get_global_setting("ui.git_diff_word_wrap") == "true"
reloaded = SettingsForm.load("editor", project.id)
assert field(reloaded, "default_mode").value == "preview"
assert field(reloaded, "wrap_long_lines").value == true
end
end
describe "content" do
test "edits category settings and adds new categories", %{project: project} do
form = SettingsForm.load("content", project.id)
assert field(form, "cat:aside:show_title").type == :bool
:ok =
SettingsForm.save(
"content",
project.id,
values(form, %{
"new_category" => "linkroll",
"cat:article:render_in_lists" => false,
"cat:article:title" => "Articles"
})
)
{:ok, metadata} = BDS.Metadata.get_project_metadata(project.id)
assert "linkroll" in metadata.categories
assert metadata.category_settings["article"]["render_in_lists"] == false
assert metadata.category_settings["article"]["title"] == "Articles"
end
end
describe "technology" do
test "toggles semantic similarity without wiping the project", %{project: project} do
form = SettingsForm.load("technology", project.id)
refute field(form, "semantic_similarity_enabled").value
:ok =
SettingsForm.save(
"technology",
project.id,
values(form, %{"semantic_similarity_enabled" => true})
)
{:ok, metadata} = BDS.Metadata.get_project_metadata(project.id)
assert metadata.semantic_similarity_enabled
assert metadata.name == "Prefs"
end
end
describe "publishing" do
test "saves the SSH preferences", %{project: project} do
form = SettingsForm.load("publishing", project.id)
assert field(form, "ssh_mode").options == ["scp", "rsync"]
:ok =
SettingsForm.save(
"publishing",
project.id,
values(form, %{"ssh_host" => "example.org", "ssh_mode" => "rsync"})
)
{:ok, metadata} = BDS.Metadata.get_project_metadata(project.id)
assert metadata.publishing_preferences["ssh_host"] == "example.org"
assert metadata.publishing_preferences["ssh_mode"] == "rsync"
end
end
describe "ai" do
test "loads the AI form and saves prompt plus airplane mode", %{project: project} do
form = SettingsForm.load("ai", project.id)
assert field(form, "offline_mode").type == :bool
assert field(form, "system_prompt").type == :text
:ok =
SettingsForm.save(
"ai",
project.id,
values(form, %{"system_prompt" => "be terse", "offline_mode" => true})
)
assert BDS.Settings.get_global_setting("ai.system_prompt") == "be terse"
assert BDS.AI.airplane_mode?()
end
end
describe "style" do
test "applies a theme without wiping other metadata", %{project: project} do
form = SettingsForm.load("style", project.id)
assert "jade" in field(form, "pico_theme").options
:ok = SettingsForm.save("style", project.id, values(form, %{"pico_theme" => "jade"}))
{:ok, metadata} = BDS.Metadata.get_project_metadata(project.id)
assert metadata.pico_theme == "jade"
assert metadata.name == "Prefs"
end
end
describe "data" do
test "shows the data folder read-only and save is a no-op", %{project: project} do
form = SettingsForm.load("data", project.id)
data_field = field(form, "data_path")
assert data_field.type == :info
assert data_field.value =~ "bds-settings-form"
assert SettingsForm.save("data", project.id, %{}) == :ok
end
end
describe "mcp" do
test "lists the agents with supported ones as toggles", %{project: project} do
form = SettingsForm.load("mcp", project.id)
claude = field(form, "mcp:claude_code")
assert claude.type == :bool
assert is_boolean(claude.value)
gemini = field(form, "mcp:gemini_cli")
assert gemini.type == :info
end
end
end