discourse/spec/system/page_objects/pages/admin_email_templates.rb
Régis Hanol 5f6e69f64f
UX: Display interpolation keys as interactive pills in admin editors (#37254)
When editing site texts or email templates, admins need to know which
interpolation keys are available and whether they're being used
correctly.
Previously there was no UI for this.

Show interpolation keys as clickable pill buttons below the editor:
- Unused keys are dimmed — clicking inserts %{key} at the last cursor
position
- Used keys are highlighted green to confirm they're present in the text
- Invalid keys (typos or unknown keys) appear in red as non-clickable
pills

Implementation:
- New `<AdminInterpolationKeys>` template-only component renders the
pills
- New `interpolationKeysWithStatus()` utility in admin/lib centralizes
the
logic for computing key statuses (used/unused/invalid) across both
editors
- Controllers track textarea focus and cursor position via private
fields
  (no @Tracked — these are only read imperatively on pill click)
- Uses document.execCommand("insertText") for native undo/redo support
- Fix duplicate keys in backend by using Array#| (set union) instead of
Array#+

<img width="1662" height="1355" alt="2026-02-26 @ 17 09 32"
src="https://github.com/user-attachments/assets/05497832-4e17-4eb2-b4c1-e9e0e036304a"
/>

<img width="1662" height="1355" alt="2026-02-26 @ 17 09 19"
src="https://github.com/user-attachments/assets/f13271ad-511e-4fa1-9bec-eb6fbc7a66d8"
/>


Ref - t/172375
2026-02-27 21:21:26 +01:00

73 lines
1.9 KiB
Ruby

# frozen_string_literal: true
module PageObjects
module Pages
class AdminEmailTemplates < PageObjects::Pages::AdminBase
def visit
page.visit("/admin/email/templates")
self
end
def visit_template(template_id)
page.visit("/admin/email/templates/#{template_id}")
self
end
def has_template?(template_name)
has_css?("td", text: template_name)
end
def click_template(template_name)
find("td", text: template_name).click
self
end
def edit_subject(text)
find("input.email-template__subject").fill_in(with: text)
self
end
def has_subject_value?(value)
expect(find("input.email-template__subject").value).to eq(value)
end
def edit_body(text)
find(".d-editor-input").fill_in(with: text)
self
end
def has_preview_content?(text)
has_css?(".d-editor-preview", text: text)
end
def save_changes
find(".save-changes").click
self
end
def has_multiple_subjects_link?(href)
link = find(".email-template__has-multiple-subjects")
expect(link[:href]).to eq(href)
expect(link.text).to eq(
I18n.t("admin_js.admin.customize.email_templates.multiple_subjects"),
)
end
def has_multiple_bodies_link?(href)
link = find(".email-template__has-multiple-bodies")
expect(link[:href]).to eq(href)
expect(link.text).to eq(I18n.t("admin_js.admin.customize.email_templates.multiple_bodies"))
end
def has_interpolation_keys?(keys)
container = find(".email-template .interpolation-keys")
keys.each { |key| expect(container).to have_css("button", text: key) }
true
end
def has_no_interpolation_keys?
has_no_css?(".email-template .interpolation-keys")
end
end
end
end