test: D1-13 cover DiscardPostChangesSideEffects FTS re-sync after discard
This commit is contained in:
@@ -127,7 +127,7 @@ All reconciled to follow code. Specs must be self-consistent and match code.
|
||||
| D1-10 | ~~TransformPipelineContinuation~~ | script.allium:247-249 | **Resolved:** added focused test in `transforms_test.exs` — a failing *first* transform (no prior valid state) does not halt the pipeline: the original input survives, a later enabled transform still runs against it, and every failure is captured per-script in pipeline order tagged with its slug |
|
||||
| D1-11 | ~~ChatContextTruncation invariant~~ | ai.allium:375-379 | **Resolved:** test added in `ai_test.exs` — a catalog model with a 2,000-token context window plus 40 large seeded turns forces truncation; the captured chat request keeps the system prompt as the first message, drops the oldest pairs first (surviving markers form a contiguous newest suffix, oldest absent), and always retains the newest user turn |
|
||||
| D1-12 | ~~BoundedToolLoop enforcement~~ | ai.allium:381-385 | **Resolved:** the round cap is now read from `config.chat_max_tool_rounds` (`config :bds, :chat, max_tool_rounds: 10`) via `chat_max_tool_rounds/0` in chat.ex instead of a hardcoded attribute, matching the spec wording; test added in `ai_test.exs` — a `LoopingToolRuntime` that always returns another tool call (never a final answer) with `max_tool_rounds: 3` ends with `{:error, %{kind: :tool_loop_exhausted}}` after exactly 3 runtime calls (the `rounds_left == 0` round short-circuits before contacting the runtime) |
|
||||
| D1-13 | DiscardPostChangesSideEffects | engine_side_effects.allium:99-104 | Write test: FTS updated after discard |
|
||||
| D1-13 | ~~DiscardPostChangesSideEffects~~ | engine_side_effects.allium:99-104 | **Resolved:** test added in `posts_test.exs` — a published post is dirtied with unsaved title/content edits (re-indexing the dirty text in FTS), then `discard_post_changes/1` restores the published file version (status=published, content=nil, original title) and re-syncs the FTS index so the published terms are searchable again and the discarded edits are gone |
|
||||
| D1-14 | ReplaceMediaFileSideEffects | engine_side_effects.allium:128-134 | Write test: file replaced, thumbnails regenerated |
|
||||
| D1-15 | Drag-and-drop image chain | action_patterns.allium:84-103 | Write integration test |
|
||||
| D1-16 | DebouncedPersistence (5s) | embedding.allium:204-208 | Write test: index persistence debounced |
|
||||
|
||||
@@ -446,6 +446,52 @@ defmodule BDS.PostsTest do
|
||||
assert {:error, :not_found} = BDS.Posts.unarchive_post(Ecto.UUID.generate())
|
||||
end
|
||||
|
||||
test "discard_post_changes restores the published version from file and updates the FTS index" do
|
||||
temp_dir =
|
||||
Path.join(System.tmp_dir!(), "bds-post-discard-#{System.unique_integer([:positive])}")
|
||||
|
||||
File.mkdir_p!(temp_dir)
|
||||
on_exit(fn -> File.rm_rf(temp_dir) end)
|
||||
|
||||
assert {:ok, project} =
|
||||
BDS.Projects.create_project(%{name: "Discard FTS", data_path: temp_dir})
|
||||
|
||||
assert {:ok, post} =
|
||||
BDS.Posts.create_post(%{
|
||||
project_id: project.id,
|
||||
title: "Pristine Headline",
|
||||
content: "pristine meadow body"
|
||||
})
|
||||
|
||||
assert {:ok, published} = BDS.Posts.publish_post(post.id)
|
||||
assert published.status == :published
|
||||
assert published.content == nil
|
||||
|
||||
# The published file is the source of truth; the FTS index reflects it.
|
||||
assert {:ok, %{posts: [%{id: post_id}]}} = BDS.Search.search_posts(project.id, "pristine")
|
||||
assert post_id == post.id
|
||||
|
||||
# Make the DB diverge from the file with unsaved edits, re-indexing the dirty text.
|
||||
assert {:ok, dirty} =
|
||||
BDS.Posts.update_post(post.id, %{
|
||||
title: "Tampered Headline",
|
||||
content: "tampered swamp body"
|
||||
})
|
||||
|
||||
assert dirty.content == "tampered swamp body"
|
||||
assert {:ok, %{posts: [%{id: ^post_id}]}} = BDS.Search.search_posts(project.id, "tampered")
|
||||
assert {:ok, %{posts: []}} = BDS.Search.search_posts(project.id, "pristine")
|
||||
|
||||
# Discarding restores the published file version and re-syncs the FTS index.
|
||||
assert {:ok, restored} = BDS.Posts.discard_post_changes(post.id)
|
||||
assert restored.status == :published
|
||||
assert restored.content == nil
|
||||
assert restored.title == "Pristine Headline"
|
||||
|
||||
assert {:ok, %{posts: [%{id: ^post_id}]}} = BDS.Search.search_posts(project.id, "pristine")
|
||||
assert {:ok, %{posts: []}} = BDS.Search.search_posts(project.id, "tampered")
|
||||
end
|
||||
|
||||
test "rebuild_posts_from_files recreates published posts from disk" do
|
||||
temp_dir =
|
||||
Path.join(System.tmp_dir!(), "bds-post-rebuild-#{System.unique_integer([:positive])}")
|
||||
|
||||
Reference in New Issue
Block a user