Files
sure/test/system/categories_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

122 lines
3.9 KiB
Ruby

require "application_system_test_case"
class CategoriesTest < ApplicationSystemTestCase
setup do
sign_in @user = users(:family_admin)
end
test "can create category" do
visit categories_url
click_link I18n.t("categories.new.new_category")
fill_in "Name", with: "My Shiny New Category"
click_button "Create Category"
visit categories_url
assert_text "My Shiny New Category"
end
test "trying to create a duplicate category fails" do
visit categories_url
click_link I18n.t("categories.new.new_category")
fill_in "Name", with: categories(:food_and_drink).name
click_button "Create Category"
assert_text "Name has already been taken"
end
test "can search the icon picker and save the icon it finds" do
visit categories_url
click_link I18n.t("categories.new.new_category")
fill_in "Name", with: "Takeout"
picker = find("summary[aria-label='#{I18n.t("categories.form.trigger_label")}']")
picker.click
# Exact-match on `data-controller` so this can't pick up the parent-category
# `DS::Select`, whose own search field lives under "select list-filter ...".
within "[data-controller='list-filter']" do
search = find("input[type='search']")
search.set("zzzz")
assert_text I18n.t("ds.icon_picker.no_matching_icons")
search.set("pizza")
assert_selector "label[data-filter-name='pizza']"
assert_no_selector "label[data-filter-name='coffee']"
find("label[data-filter-name='pizza']").click
end
picker.click
click_button "Create Category"
# Wait for the redirect back to the list before reading the record —
# `click_button` returns before the Turbo round-trip finishes.
assert_text "Takeout"
assert_equal "pizza", @user.family.categories.find_by!(name: "Takeout").lucide_icon
end
test "reopening the icon picker clears the previous search" do
visit categories_url
click_link I18n.t("categories.new.new_category")
picker = find("summary[aria-label='#{I18n.t("categories.form.trigger_label")}']")
picker.click
within "[data-controller='list-filter']" do
find("input[type='search']").set("pizza")
assert_no_selector "label[data-filter-name='coffee']"
end
picker.click
picker.click
within "[data-controller='list-filter']" do
assert_selector "label[data-filter-name='coffee']"
assert_equal "", find("input[type='search']").value
end
end
test "pressing enter in the icon search does not submit the category form" do
visit categories_url
click_link I18n.t("categories.new.new_category")
fill_in "Name", with: "Not Saved Yet"
find("summary[aria-label='#{I18n.t("categories.form.trigger_label")}']").click
within "[data-controller='list-filter']" do
search = find("input[type='search']")
search.set("pizza")
search.send_keys(:enter)
end
# Round-trip to the index before reading the record. Capybara's negative
# matchers return as soon as they hold, so asserting straight after the
# keypress would pass while an accidental POST was still in flight.
visit categories_url
assert_no_text "Not Saved Yet"
assert_nil @user.family.categories.find_by(name: "Not Saved Yet")
end
test "long category names truncate before the actions menu on mobile" do
category = categories(:food_and_drink)
category.update!(name: "Super Long Category Name That Should Stop Before The Menu Button On Mobile")
page.current_window.resize_to(315, 643)
visit categories_url
row = find("##{ActionView::RecordIdentifier.dom_id(category)}")
actions = row.find("[data-testid='category-actions'] button", visible: true)
assert actions.visible?
viewport_width = page.evaluate_script("window.innerWidth")
page_scroll_width = page.evaluate_script("document.documentElement.scrollWidth")
assert_operator page_scroll_width, :<=, viewport_width
end
end