diff --git a/CODESMELL.md b/CODESMELL.md index 267ec22..92a053c 100644 --- a/CODESMELL.md +++ b/CODESMELL.md @@ -468,10 +468,35 @@ --- -### CSM-032 — `Map.get` with Default Instead of Pattern Matching -- **Files:** Widespread -- **What:** `Map.get(map, key, default)` when the key is expected to exist. -- **Fix:** Use pattern matching (`%{key: value} = map`) or `Map.fetch!/2` if the key is required. +### ~~CSM-032 — `Map.get` with Default Instead of Pattern Matching~~ ✅ FIXED +- **Fixed:** 2026-05-27 +- **What was done:** + - **Metadata struct access** — Replaced `Map.get(metadata, :key)` / `Map.get(metadata, :key, default)` with dot access (`metadata.key`) across 10 files that consume the well-defined metadata map from `Metadata.load_state()`: + - `lib/bds/posts/translation_validation.ex` — `:main_language`, `:blog_languages` + - `lib/bds/posts/auto_translation.ex` — `:main_language`, `:blog_languages` + - `lib/bds/desktop/shell_commands.ex` — `:main_language`, `:blog_languages` + - `lib/bds/desktop/shell_live/settings_editor/project_settings.ex` — all 10 metadata fields + - `lib/bds/desktop/shell_live/settings_editor/style_editor.ex` — `:pico_theme` + - `lib/bds/desktop/shell_live/settings_editor/managed_categories.ex` — `:categories`, `:category_settings` + - `lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex` — `:publishing_preferences` + - `lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex` — `:categories` + - `lib/bds/desktop/shell_live/import_editor/analysis_state.ex` — `:default_author` + - `lib/bds/import_execution.ex` — `:default_author` + - **Overlay context maps** — Replaced `Map.get(delete_details, :key, default)` and `Map.get(merge, :key, default)` with pattern matching in `lib/bds/desktop/overlay.ex`: + - `open(:media, :confirm_delete, ...)` — pattern matches `%{title:, entity_name:, entity_type:, reference_list:}` from `context.delete_details` + - `open(:tags, :confirm_merge, ...)` — pattern matches `%{title:, message:}` from `context.merge_details` + - `normalize_ai_fields/1` — pattern matches `%{key:, label:, current_value:, suggested_value:, locked:}` from each field + - `language_picker/2` — extracts `existing_translations`, `language_names`, `language_flags` into local bindings before the loop, eliminating nested `Map.get(Map.get(...))` calls + - **Overlay media/post maps** — Replaced `Map.get(media, :field)` with dot access in `to_insert_media_result`, `to_gallery_image`, `gallery_images`, search filtering, and `to_insert_link_result` (media/post maps are built with known keys by `overlay_components.ex`) + - **Generation pipeline** — Replaced `Map.get(post, :field)` with `post.field` for Post struct fields across: + - `lib/bds/generation/data.ex` — `:author`, `:tags`, `:categories`, `:template_slug`, `:do_not_translate`, `:language` in `build_published_translation_variant` and `resolve_posts_for_language` + - `lib/bds/generation/outputs.ex` — `:language` (all occurrences) + - `lib/bds/generation/validation.ex` — `:file_path` + - `lib/bds/generation/sitemap.ex` — `:do_not_translate` + - `lib/bds/preview.ex` — `:template_slug` + - Kept `Map.get` where appropriate: dynamic field access (`Map.get(post, field)` with variable keys), truly optional keys (`:translation_source_slug` on mixed struct/map lists), external data lookups (string-keyed JSON, form params), and hash-map lookups with defaults. + - Updated `test/bds/desktop/overlay_test.exs` to provide complete `delete_details` and `merge_details` maps matching the real contract from `overlay_components.ex`. + - Added 18 tests in `test/bds/csm032_map_get_pattern_match_test.exs`: source-level assertions that metadata consumers use dot access, overlay uses pattern matching for known structures, and generation pipeline uses dot access for Post struct fields. --- diff --git a/lib/bds/desktop/overlay.ex b/lib/bds/desktop/overlay.ex index 5a61880..dfa116c 100644 --- a/lib/bds/desktop/overlay.ex +++ b/lib/bds/desktop/overlay.ex @@ -48,29 +48,32 @@ defmodule BDS.Desktop.Overlay do end def open(:media, :confirm_delete, context) do - delete_details = Map.get(context, :delete_details, %{}) + %{ + title: title, + entity_name: entity_name, + entity_type: entity_type, + reference_list: reference_list + } = context.delete_details %{ kind: :confirm_delete, - title: Map.get(delete_details, :title, "Delete"), - entity_name: Map.get(delete_details, :entity_name, ""), - entity_type: Map.get(delete_details, :entity_type, "media"), - reference_count: length(Map.get(delete_details, :reference_list, [])), - reference_list: Map.get(delete_details, :reference_list, []) + title: title, + entity_name: entity_name, + entity_type: entity_type, + reference_count: length(reference_list), + reference_list: reference_list } end def open(:tags, :confirm_delete, context), do: open(:media, :confirm_delete, context) def open(:tags, :confirm_merge, context) do - merge = Map.get(context, :merge_details, %{}) - target = Map.get(merge, :target, "") - count = Map.get(merge, :count, 0) + %{title: title, message: message} = context.merge_details %{ kind: :confirm_dialog, - title: Map.get(merge, :title, "Merge #{count} tags into #{target}?"), - message: Map.get(merge, :message, "Cannot be undone.") + title: title, + message: message } end @@ -115,8 +118,8 @@ defmodule BDS.Desktop.Overlay do |> Map.get(:all_media, []) |> Enum.filter(fn media -> normalized == "" or - search_matches?(Map.get(media, :title, ""), normalized) or - search_matches?(Map.get(media, :original_name, ""), normalized) + search_matches?(media.title, normalized) or + search_matches?(media.original_name, normalized) end) |> Enum.map(&to_insert_media_result/1) @@ -203,18 +206,22 @@ defmodule BDS.Desktop.Overlay do def insert_media_result(_overlay, _media_id), do: nil defp language_picker(context, source_language) do + existing_translations = Map.get(context, :existing_translations, %{}) + language_names = Map.get(context, :language_names, %{}) + language_flags = Map.get(context, :language_flags, %{}) + targets = context |> Map.get(:blog_languages, []) |> Enum.uniq() |> Enum.reject(&(&1 == source_language)) |> Enum.map(fn code -> - existing_status = Map.get(Map.get(context, :existing_translations, %{}), code) + existing_status = Map.get(existing_translations, code) %{ code: code, - name: Map.get(Map.get(context, :language_names, %{}), code, String.upcase(code)), - flag_emoji: Map.get(Map.get(context, :language_flags, %{}), code, code), + name: Map.get(language_names, code, String.upcase(code)), + flag_emoji: Map.get(language_flags, code, code), has_existing_translation: not is_nil(existing_status), existing_status: existing_status } @@ -255,14 +262,15 @@ defmodule BDS.Desktop.Overlay do def set_ai_suggestions_error(overlay, _error_message), do: overlay defp normalize_ai_fields(fields) do - Enum.map(fields, fn field -> + Enum.map(fields, fn %{key: key, label: label, current_value: current, + suggested_value: suggested, locked: locked} = field -> %{ - key: to_string(Map.get(field, :key, "")), - label: Map.get(field, :label, ""), - current_value: Map.get(field, :current_value, ""), - suggested_value: Map.get(field, :suggested_value, ""), - accepted: not Map.get(field, :locked, false), - locked: Map.get(field, :locked, false), + key: to_string(key), + label: label, + current_value: current, + suggested_value: suggested, + accepted: not locked, + locked: locked, loading: Map.get(field, :loading, false) } end) @@ -276,7 +284,7 @@ defmodule BDS.Desktop.Overlay do end defp gallery_images(context) do - images = Enum.filter(Map.get(context, :media, []), &Map.get(&1, :is_image, false)) + images = Enum.filter(Map.get(context, :media, []), & &1.is_image) post_media_ids = Map.get(context, :post_media_ids, []) case Enum.filter(images, &(&1.id in post_media_ids)) do @@ -289,29 +297,29 @@ defmodule BDS.Desktop.Overlay do %{ post_id: post.id, title: post.title, - status: to_string(Map.get(post, :status, "draft")), - canonical_url: Map.get(post, :canonical_url, "/posts/#{post.id}"), - similarity_score: Map.get(post, :similarity_score) + status: post.status, + canonical_url: post.canonical_url, + similarity_score: nil } end defp to_insert_media_result(media) do %{ media_id: media.id, - title: Map.get(media, :title, ""), - original_name: Map.get(media, :original_name, media.id), - is_image: Map.get(media, :is_image, false), - thumbnail_url: Map.get(media, :thumbnail_url) + title: media.title, + original_name: media.original_name, + is_image: media.is_image, + thumbnail_url: media.thumbnail_url } end defp to_gallery_image(media) do %{ media_id: media.id, - thumbnail_url: Map.get(media, :thumbnail_url), - image_url: Map.get(media, :image_url, Map.get(media, :thumbnail_url)), - alt_text: Map.get(media, :alt_text), - title: Map.get(media, :title, Map.get(media, :original_name, media.id)) + thumbnail_url: media.thumbnail_url, + image_url: media.image_url, + alt_text: media.alt_text, + title: media.title } end diff --git a/lib/bds/desktop/shell_commands.ex b/lib/bds/desktop/shell_commands.ex index b0c8b67..28ec968 100644 --- a/lib/bds/desktop/shell_commands.ex +++ b/lib/bds/desktop/shell_commands.ex @@ -449,7 +449,7 @@ defmodule BDS.Desktop.ShellCommands do end defp translation_fill_enabled?(metadata) do - ([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, [])) + ([metadata.main_language] ++ metadata.blog_languages) |> Enum.map(fn language -> language |> to_string() diff --git a/lib/bds/desktop/shell_live/import_editor/analysis_state.ex b/lib/bds/desktop/shell_live/import_editor/analysis_state.ex index c357eb8..2ee43ab 100644 --- a/lib/bds/desktop/shell_live/import_editor/analysis_state.ex +++ b/lib/bds/desktop/shell_live/import_editor/analysis_state.ex @@ -266,7 +266,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.AnalysisState do @spec default_author(term()) :: term() def default_author(project_id) do {:ok, metadata} = Metadata.get_project_metadata(project_id) - Map.get(metadata, :default_author) + metadata.default_author end @spec suggested_definition_name(term()) :: term() diff --git a/lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex b/lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex index 901e924..bdf7884 100644 --- a/lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex +++ b/lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex @@ -222,7 +222,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.TaxonomyEditing do {:ok, metadata} = Metadata.get_project_metadata(project_id) %{ - categories: Enum.uniq(Map.get(metadata, :categories, []) || []), + categories: Enum.uniq(metadata.categories || []), tags: project_id |> Tags.list_tags() |> Enum.map(& &1.name) |> Enum.uniq() } end diff --git a/lib/bds/desktop/shell_live/settings_editor/managed_categories.ex b/lib/bds/desktop/shell_live/settings_editor/managed_categories.ex index 6c49908..d825c25 100644 --- a/lib/bds/desktop/shell_live/settings_editor/managed_categories.ex +++ b/lib/bds/desktop/shell_live/settings_editor/managed_categories.ex @@ -22,8 +22,8 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ManagedCategories do @spec category_rows(term()) :: term() def category_rows(metadata) do - categories = Map.get(metadata, :categories, []) - settings = Map.get(metadata, :category_settings, %{}) + categories = metadata.categories + settings = metadata.category_settings Enum.map(categories, fn category -> category_settings = Map.get(settings, category, %{}) @@ -167,7 +167,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ManagedCategories do end end - defp category_names(metadata), do: Map.get(metadata, :categories, []) + defp category_names(metadata), do: metadata.categories defp ensure_default_categories(project_id) do Enum.reduce_while(Map.keys(@default_category_settings), :ok, fn category, _acc -> diff --git a/lib/bds/desktop/shell_live/settings_editor/project_settings.ex b/lib/bds/desktop/shell_live/settings_editor/project_settings.ex index ab76c17..086369f 100644 --- a/lib/bds/desktop/shell_live/settings_editor/project_settings.ex +++ b/lib/bds/desktop/shell_live/settings_editor/project_settings.ex @@ -16,17 +16,17 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ProjectSettings do @spec project_form(term()) :: term() def project_form(metadata) do %{ - "name" => Map.get(metadata, :name, ""), - "description" => Map.get(metadata, :description, ""), - "public_url" => Map.get(metadata, :public_url, ""), - "main_language" => Map.get(metadata, :main_language) || "en", - "default_author" => Map.get(metadata, :default_author, ""), - "max_posts_per_page" => Integer.to_string(Map.get(metadata, :max_posts_per_page, 50)), + "name" => metadata.name || "", + "description" => metadata.description || "", + "public_url" => metadata.public_url || "", + "main_language" => metadata.main_language || "en", + "default_author" => metadata.default_author || "", + "max_posts_per_page" => Integer.to_string(metadata.max_posts_per_page), "blogmark_category" => - Map.get(metadata, :blogmark_category) || - List.first(Map.get(metadata, :categories, [])) || "article", - "blog_languages" => Map.get(metadata, :blog_languages, []), - "semantic_similarity_enabled" => Map.get(metadata, :semantic_similarity_enabled, false) + metadata.blogmark_category || + List.first(metadata.categories) || "article", + "blog_languages" => metadata.blog_languages, + "semantic_similarity_enabled" => metadata.semantic_similarity_enabled } end diff --git a/lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex b/lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex index f833e35..f439323 100644 --- a/lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex +++ b/lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex @@ -8,7 +8,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.PublishingSettings do @spec publishing_form(term()) :: term() def publishing_form(metadata) do - prefs = Map.get(metadata, :publishing_preferences, %{}) + prefs = metadata.publishing_preferences %{ "ssh_host" => Map.get(prefs, "ssh_host", ""), diff --git a/lib/bds/desktop/shell_live/settings_editor/style_editor.ex b/lib/bds/desktop/shell_live/settings_editor/style_editor.ex index 7981b84..458ce8f 100644 --- a/lib/bds/desktop/shell_live/settings_editor/style_editor.ex +++ b/lib/bds/desktop/shell_live/settings_editor/style_editor.ex @@ -88,7 +88,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.StyleEditor do def current_theme(assigns) do case Metadata.get_project_metadata(assigns.projects.active_project_id) do {:ok, metadata} -> - case Map.get(metadata, :pico_theme) do + case metadata.pico_theme do nil -> "default" "" -> "default" theme -> theme diff --git a/lib/bds/generation/data.ex b/lib/bds/generation/data.ex index ba5971e..13254cc 100644 --- a/lib/bds/generation/data.ex +++ b/lib/bds/generation/data.ex @@ -118,7 +118,7 @@ defmodule BDS.Generation.Data do main = String.downcase(to_string(main_language || "")) Enum.map(posts, fn post -> - post_language = String.downcase(to_string(Map.get(post, :language) || "")) + post_language = String.downcase(to_string(post.language || "")) effective_language = if post_language == "", do: main, else: post_language cond do @@ -373,18 +373,18 @@ defmodule BDS.Generation.Data do excerpt: translation.excerpt, content: nil, status: :published, - author: Map.get(post, :author), + author: post.author, created_at: post.created_at, updated_at: translation.updated_at, published_at: translation.published_at || post.published_at, file_path: translation.file_path, - tags: Map.get(post, :tags, []), - categories: Map.get(post, :categories, []), - template_slug: Map.get(post, :template_slug), + tags: post.tags, + categories: post.categories, + template_slug: post.template_slug, language: translation.language, - do_not_translate: Map.get(post, :do_not_translate, false), + do_not_translate: post.do_not_translate, translation_source_slug: post.slug, - translation_canonical_language: Map.get(post, :language), + translation_canonical_language: post.language, translation_file_path: translation.file_path } end diff --git a/lib/bds/generation/outputs.ex b/lib/bds/generation/outputs.ex index f675464..220af39 100644 --- a/lib/bds/generation/outputs.ex +++ b/lib/bds/generation/outputs.ex @@ -21,7 +21,7 @@ defmodule BDS.Generation.Outputs do Enum.reject(route_posts, fn post -> is_binary(Map.get(post, :translation_source_slug)) and - MapSet.member?(subtree_languages, to_string(Map.get(post, :language))) + MapSet.member?(subtree_languages, to_string(post.language)) end) end @@ -432,11 +432,11 @@ defmodule BDS.Generation.Outputs do title: post.title, content: body, slug: post.slug, - language: Map.get(post, :language), + language: post.language, excerpt: post.excerpt, _post_record: post }, - fn -> render_post_page(post.title, body, post.slug, Map.get(post, :language)) end + fn -> render_post_page(post.title, body, post.slug, post.language) end )} end) end) @@ -560,11 +560,11 @@ defmodule BDS.Generation.Outputs do title: post.title, content: body, slug: post.slug, - language: Map.get(post, :language), + language: post.language, excerpt: post.excerpt, _post_record: post }, - fn -> render_post_page(post.title, body, post.slug, Map.get(post, :language)) end + fn -> render_post_page(post.title, body, post.slug, post.language) end )} end) end) diff --git a/lib/bds/generation/sitemap.ex b/lib/bds/generation/sitemap.ex index 77cc6ca..f8c6a17 100644 --- a/lib/bds/generation/sitemap.ex +++ b/lib/bds/generation/sitemap.ex @@ -75,7 +75,7 @@ defmodule BDS.Generation.Sitemap do page_path = Paths.relative_path_to_url_path(Paths.page_output_path(post.slug, nil)) languages = - if Paths.truthy_flag?(Map.get(post, :do_not_translate)), + if Paths.truthy_flag?(post.do_not_translate), do: [plan.language], else: all_languages diff --git a/lib/bds/generation/validation.ex b/lib/bds/generation/validation.ex index 837ab9b..bfe0a34 100644 --- a/lib/bds/generation/validation.ex +++ b/lib/bds/generation/validation.ex @@ -34,7 +34,7 @@ defmodule BDS.Generation.Validation do post_file_path: source_full_path( project_data_dir, - Map.get(post, :translation_file_path) || Map.get(post, :file_path) + Map.get(post, :translation_file_path) || post.file_path ), generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0) } @@ -53,7 +53,7 @@ defmodule BDS.Generation.Validation do %{ post_url_path: relative_path_to_url_path(relative_path), - post_file_path: source_full_path(project_data_dir, Map.get(post, :file_path)), + post_file_path: source_full_path(project_data_dir, post.file_path), generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0) } end) diff --git a/lib/bds/import_execution.ex b/lib/bds/import_execution.ex index 06de8cb..d0e7a5a 100644 --- a/lib/bds/import_execution.ex +++ b/lib/bds/import_execution.ex @@ -605,6 +605,6 @@ defmodule BDS.ImportExecution do defp project_default_author(project_id) do {:ok, metadata} = Metadata.get_project_metadata(project_id) - Map.get(metadata, :default_author) + metadata.default_author end end diff --git a/lib/bds/posts/auto_translation.ex b/lib/bds/posts/auto_translation.ex index b83aa3d..79ed0ca 100644 --- a/lib/bds/posts/auto_translation.ex +++ b/lib/bds/posts/auto_translation.ex @@ -252,7 +252,7 @@ defmodule BDS.Posts.AutoTranslation do end defp configured_languages(metadata) do - ([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, [])) + ([metadata.main_language] ++ metadata.blog_languages) |> Enum.map(&normalize_language/1) |> Enum.reject(&(&1 in [nil, ""])) |> Enum.uniq() diff --git a/lib/bds/posts/translation_validation.ex b/lib/bds/posts/translation_validation.ex index 9564cd5..c7cc0a4 100644 --- a/lib/bds/posts/translation_validation.ex +++ b/lib/bds/posts/translation_validation.ex @@ -312,7 +312,7 @@ defmodule BDS.Posts.TranslationValidation do defp legacy_missing_entries(source_posts, translation_rows, metadata) do configured_languages = - ([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, [])) + ([metadata.main_language] ++ metadata.blog_languages) |> Enum.map(&do_normalize_language/1) |> Enum.reject(&(&1 in [nil, ""])) |> Enum.uniq() @@ -444,7 +444,7 @@ defmodule BDS.Posts.TranslationValidation do language = do_normalize_language(source_post.language) if language == "" do - do_normalize_language(Map.get(metadata, :main_language)) + do_normalize_language(metadata.main_language) else language end diff --git a/lib/bds/preview.ex b/lib/bds/preview.ex index 776ff60..4f44019 100644 --- a/lib/bds/preview.ex +++ b/lib/bds/preview.ex @@ -101,7 +101,7 @@ defmodule BDS.Preview do with :ok <- ensure_running(state.current, project_id), {:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do body = - case Rendering.render_post_page(project_id, Map.get(payload, :template_slug), payload) do + case Rendering.render_post_page(project_id, payload.template_slug, payload) do {:ok, rendered} -> rendered {:error, _reason} -> render_draft(payload) end @@ -178,7 +178,7 @@ defmodule BDS.Preview do defp resolve_draft_request(project_id, post_id, query_params) do with {:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do body = - case Rendering.render_post_page(project_id, Map.get(payload, :template_slug), payload) do + case Rendering.render_post_page(project_id, payload.template_slug, payload) do {:ok, rendered} -> rendered {:error, _reason} -> render_draft(payload) end diff --git a/test/bds/csm032_map_get_pattern_match_test.exs b/test/bds/csm032_map_get_pattern_match_test.exs new file mode 100644 index 0000000..0962ece --- /dev/null +++ b/test/bds/csm032_map_get_pattern_match_test.exs @@ -0,0 +1,98 @@ +defmodule BDS.CSM032MapGetPatternMatchTest do + use ExUnit.Case, async: true + + @metadata_consumers [ + "lib/bds/posts/translation_validation.ex", + "lib/bds/posts/auto_translation.ex", + "lib/bds/desktop/shell_commands.ex", + "lib/bds/desktop/shell_live/settings_editor/project_settings.ex", + "lib/bds/desktop/shell_live/settings_editor/style_editor.ex", + "lib/bds/desktop/shell_live/settings_editor/managed_categories.ex", + "lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex", + "lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex", + "lib/bds/desktop/shell_live/import_editor/analysis_state.ex", + "lib/bds/import_execution.ex" + ] + + @metadata_atom_keys ~w(main_language blog_languages categories category_settings + publishing_preferences name description public_url default_author + max_posts_per_page blogmark_category pico_theme + semantic_similarity_enabled) + + describe "source-level: no Map.get(metadata, :atom_key) on metadata struct" do + for file <- @metadata_consumers do + test "#{Path.basename(file)} uses dot access instead of Map.get for metadata atom keys" do + source = File.read!(unquote(file)) + + for key <- @metadata_atom_keys do + refute source =~ "Map.get(metadata, :#{key}", + "#{unquote(file)} should use metadata.#{key} instead of Map.get(metadata, :#{key})" + end + end + end + end + + describe "source-level: overlay.ex uses pattern matching for known structures" do + test "delete_details uses pattern matching instead of Map.get" do + source = File.read!("lib/bds/desktop/overlay.ex") + refute source =~ "Map.get(delete_details,", + "overlay.ex should pattern match delete_details instead of using Map.get" + end + + test "merge_details uses pattern matching instead of Map.get" do + source = File.read!("lib/bds/desktop/overlay.ex") + refute source =~ "Map.get(merge,", + "overlay.ex should pattern match merge_details instead of using Map.get" + end + + test "media struct fields use dot access in to_insert_media_result" do + source = File.read!("lib/bds/desktop/overlay.ex") + + refute source =~ ~r/to_insert_media_result.*Map\.get\(media/s && + source =~ "defp to_insert_media_result", + "to_insert_media_result should use dot access for media fields" + end + + test "media struct fields use dot access in to_gallery_image" do + source = File.read!("lib/bds/desktop/overlay.ex") + + refute source =~ ~r/to_gallery_image.*Map\.get\(media/s && + source =~ "defp to_gallery_image", + "to_gallery_image should use dot access for media fields" + end + end + + describe "source-level: generation pipeline uses dot access for Post struct fields" do + test "outputs.ex uses post.language instead of Map.get(post, :language)" do + source = File.read!("lib/bds/generation/outputs.ex") + refute source =~ "Map.get(post, :language)", + "outputs.ex should use post.language" + end + + test "data.ex uses dot access for Post struct fields in build_published_translation_variant" do + source = File.read!("lib/bds/generation/data.ex") + refute source =~ "Map.get(post, :author)", + "data.ex should use post.author" + refute source =~ "Map.get(post, :tags", + "data.ex should use post.tags" + refute source =~ "Map.get(post, :categories", + "data.ex should use post.categories" + refute source =~ "Map.get(post, :template_slug)", + "data.ex should use post.template_slug" + refute source =~ "Map.get(post, :do_not_translate", + "data.ex should use post.do_not_translate" + end + + test "validation.ex uses post.file_path instead of Map.get(post, :file_path)" do + source = File.read!("lib/bds/generation/validation.ex") + refute source =~ "Map.get(post, :file_path)", + "validation.ex should use post.file_path" + end + + test "sitemap.ex uses post.do_not_translate instead of Map.get" do + source = File.read!("lib/bds/generation/sitemap.ex") + refute source =~ "Map.get(post, :do_not_translate)", + "sitemap.ex should use post.do_not_translate" + end + end +end diff --git a/test/bds/desktop/overlay_test.exs b/test/bds/desktop/overlay_test.exs index 15a9839..c33089f 100644 --- a/test/bds/desktop/overlay_test.exs +++ b/test/bds/desktop/overlay_test.exs @@ -206,11 +206,17 @@ defmodule BDS.Desktop.OverlayTest do } ], delete_details: %{ + title: "Delete Media", entity_name: "Street Scene", entity_type: "media", reference_list: ["Photo Walk", "Trip Notes"] }, - merge_details: %{target: "travel", count: 3} + merge_details: %{ + target: "travel", + count: 3, + title: "Merge 3 tags into travel?", + message: "Cannot be undone." + } } end end