discourse/spec/system/page_objects/modals/sidebar_section_form.rb
Régis Hanol 630c295cdb
FIX: Allow typing inside float-kit menus rendered from within a modal (#39370)
`DModal` listens for `keydown` on `documentElement` in the capture phase
and cancels events whose `activeElement` is not inside the modal
wrapper, to prevent keyboard shortcuts from leaking to the page behind
the modal.

Since `DIconGridPicker` replaced the select-kit `IconPicker` in the
custom sidebar section modal (#38943), the picker's filter input renders
inside the `#d-menu-portal-outlet` portal — outside the modal DOM — so
every keystroke was cancelled and typing silently failed.

Allow keydown through when `activeElement` is inside a float-kit portal
(`.fk-d-menu`, `.fk-d-menu-modal`, `.fk-d-tooltip`), which covers any
menu/tooltip opened from within a modal without weakening the leak guard
for elements actually behind the modal.

Also adds a system spec that catches this with real keyboard typing (the
existing `icon_picker.filter` helper used `fill_in` + clicked the target
icon which was already visible without filtering, so the bug slipped
past the suite).

https://meta.discourse.org/t/400945
2026-04-21 15:08:50 +02:00

84 lines
1.8 KiB
Ruby

# frozen_string_literal: true
module PageObjects
module Modals
class SidebarSectionForm < PageObjects::Modals::Base
def fill_name(name)
fill_in "section-name", with: name
end
def fill_link(name, url, icon = "link")
fill_in("link-name", with: name, match: :first)
fill_in("link-url", with: url, match: :first)
icon_picker = first_link_icon_picker
icon_picker.expand
icon_picker.filter(icon)
icon_picker.select_icon(icon)
end
def first_link_icon_picker
PageObjects::Components::DIconGridPicker.new(
find(".sidebar-section-form-link", match: :first),
)
end
def mark_as_public
find(".modal .mark-public").click
end
def remove_last_link
all(".delete-link").last.click
end
def delete
find("#delete-section").click
end
def confirm_delete
find(".dialog-container .btn-danger").click
closed?
end
def confirm_update
find(".dialog-container .btn-primary").click
closed?
end
def reset
find(".reset-link").click
find(".dialog-footer .btn-primary").click
closed?
self
end
def save
find("#save-section").click
self
end
def visible?
page.has_css?(".sidebar-section-form-modal")
end
def closed?
page.has_no_css?(".sidebar-section-form-modal")
end
def has_disabled_save?
find_button("Save", disabled: true)
end
def has_enabled_save?
find_button("Save", disabled: false)
end
def topics_link
find(".draggable[data-link-name='Topics']")
end
def review_link
find(".draggable[data-link-name='Review']")
end
end
end
end