Files
sure/test/components/DS/icon_picker_test.rb
T
Victor Dusart c8252ed15e feat(icons): add search field for icon selection (#2862)
* feat(icons): add search field for icon selection

* fix(icons): address review suggestions on the icon picker

* fix(goals): prevent the icon picker popover from collapsing

`updatePopupPosition` sets `bottom: 0px` when the popover would run past
the fold,
but never clears Tailwind's `top-full`.
With both offsets set and `height: auto`, CSS derives the height from
the offsets
instead of the content, collapsing the popover to 26px.

This PR is what makes it reachable: the search row (42px plus an 8px gap)
and the grid going max-h-40 -> max-h-52 grow the popover ~98px, moving the
overflow trigger point far enough to hit standalone /goals/new at 1280x800.

`h-fit` makes the height non-auto, so the over-constraint resolves by
ignoring `bottom`,
which is why categories, already carrying it, was never affected.
2026-08-11 23:44:24 +02:00

66 lines
2.4 KiB
Ruby

require "test_helper"
class DS::IconPickerTest < ViewComponent::TestCase
test "renders one filterable label per icon, keyed by icon code" do
render_icon_picker(icons: %w[pizza coffee dog])
assert_selector "label.filterable-item", count: 3
assert_selector "label.filterable-item[data-filter-name='pizza']"
assert_selector "label.filterable-item[data-filter-name='coffee']"
assert_selector "label.filterable-item[data-filter-name='dog']"
end
test "wires the list-filter controller with a search input and empty message" do
render_icon_picker(icons: %w[pizza])
assert_selector "[data-controller='list-filter']"
assert_selector "input[type='search'][data-list-filter-target='input']"
assert_selector "[data-list-filter-target='list']"
assert_selector "[data-list-filter-target='emptyMessage']", text: "No matching icons", visible: :all
end
test "prevents Enter in the search field from submitting the form" do
render_icon_picker(icons: %w[pizza])
action = page.find("input[type='search']")["data-action"]
assert_includes action, "input->list-filter#filter"
assert_includes action, "keydown.enter->list-filter#filter:prevent"
end
test "preserves the color-icon-picker contract on each radio" do
render_icon_picker(icons: %w[pizza])
radio = page.find("input[type='radio']", visible: :all)
assert_equal "icon", radio["data-color-icon-picker-target"]
assert_includes radio["data-action"], "change->color-icon-picker#handleIconChange"
assert_includes radio["data-action"], "change->color-icon-picker#handleIconColorChange"
assert_selector "label.filterable-item > input[type='radio'] + div > svg", visible: :all
end
test "binds radios to the method it was given" do
render_icon_picker(icons: %w[pizza])
assert_selector "input[name='category[lucide_icon]']", visible: :all
render_inline DS::IconPicker.new(
form: form_builder_for(Goal.new, "goal"),
method: :icon,
icons: %w[pizza]
)
assert_selector "input[name='goal[icon]']", visible: :all
end
private
def render_icon_picker(icons:)
render_inline DS::IconPicker.new(
form: form_builder_for(Category.new, "category"),
method: :lucide_icon,
icons: icons
)
end
def form_builder_for(object, name)
StyledFormBuilder.new(name, object, vc_test_controller.view_context, {})
end
end