feat: step 5 claimed done
This commit is contained in:
@@ -51,13 +51,7 @@ defmodule BDS.Desktop.ShellCommandsTest do
|
||||
assert result.project_id == project.id
|
||||
end
|
||||
|
||||
test "validate_translations returns an editor payload with current translation gaps", %{project: project} do
|
||||
assert {:ok, _metadata} =
|
||||
BDS.Metadata.update_project_metadata(project.id, %{
|
||||
main_language: "en",
|
||||
blog_languages: ["en", "de"]
|
||||
})
|
||||
|
||||
test "validate_translations returns an editor payload with current translation gaps", %{project: project, temp_dir: temp_dir} do
|
||||
assert {:ok, post} =
|
||||
BDS.Posts.create_post(%{
|
||||
project_id: project.id,
|
||||
@@ -66,7 +60,37 @@ defmodule BDS.Desktop.ShellCommandsTest do
|
||||
language: "en"
|
||||
})
|
||||
|
||||
assert {:ok, _published_post} = BDS.Posts.publish_post(post.id)
|
||||
assert {:ok, published_post} = BDS.Posts.publish_post(post.id)
|
||||
|
||||
assert {:ok, translation} =
|
||||
BDS.Posts.upsert_post_translation(post.id, "de", %{
|
||||
title: "Hallo",
|
||||
content: "Welt",
|
||||
status: :published
|
||||
})
|
||||
|
||||
translation_id = translation.id
|
||||
|
||||
invalid_file_path =
|
||||
Path.join([
|
||||
temp_dir,
|
||||
Path.dirname(published_post.file_path),
|
||||
"#{published_post.slug}.en.md"
|
||||
])
|
||||
|
||||
File.write!(
|
||||
invalid_file_path,
|
||||
[
|
||||
"---",
|
||||
"translationFor: #{post.id}",
|
||||
"language: en",
|
||||
"title: Wrong Language",
|
||||
"---",
|
||||
"Invalid translation",
|
||||
""
|
||||
]
|
||||
|> Enum.join("\n")
|
||||
)
|
||||
|
||||
assert {:ok, result} = ShellCommands.execute("validate_translations")
|
||||
|
||||
@@ -79,9 +103,28 @@ defmodule BDS.Desktop.ShellCommandsTest do
|
||||
assert completed.group_name == "Validation"
|
||||
assert completed.result.kind == "open_editor"
|
||||
assert completed.result.route == "translation_validation"
|
||||
assert completed.result.payload.summary.missing_count == 1
|
||||
assert completed.result.payload.checked_database_row_count == 1
|
||||
assert completed.result.payload.checked_filesystem_file_count == 1
|
||||
|
||||
post_id = post.id
|
||||
assert [%{"language" => "de", "post_id" => ^post_id}] = completed.result.payload.missing
|
||||
|
||||
assert [
|
||||
%{
|
||||
"issue" => "content-in-database",
|
||||
"translation_for" => ^post_id,
|
||||
"translation_id" => ^translation_id,
|
||||
"translation_language" => "de"
|
||||
}
|
||||
] = completed.result.payload.invalid_database_rows
|
||||
|
||||
assert [
|
||||
%{
|
||||
"issue" => "same-language-as-canonical",
|
||||
"translation_for" => ^post_id,
|
||||
"translation_language" => "en",
|
||||
"file_path" => ^invalid_file_path
|
||||
}
|
||||
] = completed.result.payload.invalid_filesystem_files
|
||||
end
|
||||
|
||||
test "validate_site queues a tracked validation task and returns the report as an editor payload" do
|
||||
|
||||
@@ -1736,6 +1736,160 @@ defmodule BDS.Desktop.ShellLiveTest do
|
||||
refute chat_html =~ "Desktop workbench content routed through the Elixir shell."
|
||||
end
|
||||
|
||||
test "chat editor renders legacy model controls, tool markers, and structured tool surfaces" do
|
||||
assert {:ok, conversation} = AI.start_chat(%{title: "Editor Chat", model: "gpt-4.1"})
|
||||
|
||||
now = Persistence.now_ms()
|
||||
|
||||
Repo.insert!(
|
||||
BDS.AI.ChatMessage.changeset(%BDS.AI.ChatMessage{}, %{
|
||||
conversation_id: conversation.id,
|
||||
role: :user,
|
||||
content: "Show me a table",
|
||||
created_at: now
|
||||
})
|
||||
)
|
||||
|
||||
Repo.insert!(
|
||||
BDS.AI.ChatMessage.changeset(%BDS.AI.ChatMessage{}, %{
|
||||
conversation_id: conversation.id,
|
||||
role: :assistant,
|
||||
content: "Here is the current summary.",
|
||||
tool_calls:
|
||||
Jason.encode!([
|
||||
%{
|
||||
"id" => "call-table",
|
||||
"name" => "render_table",
|
||||
"arguments" => %{"title" => "Blog Stats", "columns" => ["Metric", "Value"]}
|
||||
}
|
||||
]),
|
||||
created_at: now + 1
|
||||
})
|
||||
)
|
||||
|
||||
Repo.insert!(
|
||||
BDS.AI.ChatMessage.changeset(%BDS.AI.ChatMessage{}, %{
|
||||
conversation_id: conversation.id,
|
||||
role: :tool,
|
||||
tool_call_id: "call-table",
|
||||
content:
|
||||
Jason.encode!(%{
|
||||
"type" => "table",
|
||||
"title" => "Blog Stats",
|
||||
"columns" => ["Metric", "Value"],
|
||||
"rows" => [["Posts", "1"], ["Media", "0"]]
|
||||
}),
|
||||
created_at: now + 2
|
||||
})
|
||||
)
|
||||
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
html =
|
||||
render_click(view, "pin_sidebar_item", %{
|
||||
"route" => "chat",
|
||||
"id" => conversation.id,
|
||||
"title" => conversation.title,
|
||||
"subtitle" => conversation.model || "chat"
|
||||
})
|
||||
|
||||
assert html =~ ~s(data-testid="chat-model-selector-button")
|
||||
assert html =~ "gpt-4.1"
|
||||
assert html =~ ~s(data-testid="chat-tool-marker")
|
||||
assert html =~ "render_table"
|
||||
assert html =~ ~s(data-testid="chat-tool-surface")
|
||||
assert html =~ "Blog Stats"
|
||||
assert html =~ "Metric"
|
||||
assert html =~ "Posts"
|
||||
end
|
||||
|
||||
test "translation validation route renders dedicated cards and fix controls", %{project: project, temp_dir: temp_dir} do
|
||||
assert {:ok, _metadata} =
|
||||
BDS.Metadata.update_project_metadata(project.id, %{
|
||||
main_language: "en",
|
||||
blog_languages: ["en", "de"]
|
||||
})
|
||||
|
||||
assert {:ok, post} =
|
||||
Posts.create_post(%{
|
||||
project_id: project.id,
|
||||
title: "Hello",
|
||||
content: "World",
|
||||
language: "en"
|
||||
})
|
||||
|
||||
assert {:ok, published_post} = Posts.publish_post(post.id)
|
||||
|
||||
assert {:ok, _translation} =
|
||||
Posts.upsert_post_translation(post.id, "de", %{
|
||||
title: "Hallo",
|
||||
content: "Welt",
|
||||
status: :published
|
||||
})
|
||||
|
||||
invalid_file_path =
|
||||
Path.join([
|
||||
temp_dir,
|
||||
Path.dirname(published_post.file_path),
|
||||
"#{published_post.slug}.en.md"
|
||||
])
|
||||
|
||||
File.write!(
|
||||
invalid_file_path,
|
||||
[
|
||||
"---",
|
||||
"translationFor: #{post.id}",
|
||||
"language: en",
|
||||
"title: Wrong Language",
|
||||
"---",
|
||||
"Invalid translation",
|
||||
""
|
||||
]
|
||||
|> Enum.join("\n")
|
||||
)
|
||||
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
assert {:ok, queued} = BDS.Desktop.ShellCommands.execute("validate_translations")
|
||||
completed_task!(queued.task_id)
|
||||
send(view.pid, :refresh_task_status)
|
||||
|
||||
html = render(view)
|
||||
|
||||
assert html =~ ~s(class="translation-validation-view")
|
||||
assert html =~ ~s(data-testid="translation-validation-revalidate")
|
||||
assert html =~ ~s(data-testid="translation-validation-fix")
|
||||
assert html =~ ~s(data-testid="translation-validation-card")
|
||||
assert html =~ invalid_file_path
|
||||
end
|
||||
|
||||
test "git diff route renders a structured Monaco diff surface for working tree changes", %{temp_dir: temp_dir} do
|
||||
posts_dir = Path.join(temp_dir, "posts")
|
||||
File.mkdir_p!(posts_dir)
|
||||
|
||||
file_path = Path.join(posts_dir, "first.md")
|
||||
File.write!(file_path, "Old content\n")
|
||||
|
||||
init_git_repo!(temp_dir, "initial")
|
||||
File.write!(file_path, "New content\n")
|
||||
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
html =
|
||||
render_click(view, "pin_sidebar_item", %{
|
||||
"route" => "git_diff",
|
||||
"id" => "git-working-tree",
|
||||
"title" => "Working tree",
|
||||
"subtitle" => "Working tree and history"
|
||||
})
|
||||
|
||||
assert html =~ ~s(class="git-diff-view")
|
||||
assert html =~ ~s(data-testid="git-diff-file-select")
|
||||
assert html =~ "posts/first.md"
|
||||
assert html =~ ~s(phx-hook="MonacoDiffEditor")
|
||||
refute html =~ ~s(<pre><code>)
|
||||
end
|
||||
|
||||
test "settings sidebar categories render the full old-app section model and target the requested section" do
|
||||
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user