Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/features/admin/meeting_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

visit edit_admin_meeting_path(meeting)
fill_in 'Name', with: 'March Meeting'
remove_from_tom_select(permissions.members.first.full_name)
remove_from_tom_select(permissions.members.first.full_name, from: 'meeting_organisers')

click_on 'Save'

Expand Down
43 changes: 26 additions & 17 deletions spec/support/select_from_tom_select.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,56 @@
module SelectFromTomSelect
# Select an item from a TomSelect dropdown
# @param item_text [String] The text to select
# @param from [String, Symbol] The field ID (for documentation purposes)
def select_from_tom_select(item_text, from: nil)
# Wait for TomSelect to initialize - the real initialization runs via the
# jQuery DOMContentLoaded handler in application.js, which fires after the
# CDN script (loaded in the page head) defines the TomSelect global.
expect(page).to have_css('.ts-wrapper', wait: 15)
# @param from [String, Symbol] The original select element ID
def select_from_tom_select(item_text, from:)
# Wait for the specific TomSelect to initialize - the real initialization
# runs via the jQuery DOMContentLoaded handler in application.js, which
# fires after the CDN script (loaded in the page head) defines the TomSelect
# global.
select = find("##{from}", visible: false)
wrapper = select.find(:xpath, '..')
expect(wrapper).to have_css('.ts-control', wait: 15)

# Open dropdown and focus the input. The click on .ts-control opens the
# dropdown; a second click on the input guarantees focus before typing.
find('.ts-control').click
input = find('.ts-control input')
# dropdown; a second click on the input focuses it, and the explicit JS
# focus call guards against headless CI drivers where Capybara's click alone
# does not reliably focus the field before keys are sent.
wrapper.find('.ts-control').click
input = wrapper.find('.ts-control input')
input.click
page.execute_script('arguments[0].focus();', input.native)

# Type first 3 characters to trigger search (shouldLoad requires >= 3)
input.send_keys(item_text[0, 3])

# Wait for the initial search results to load after the debounce and AJAX.
# Uses Capybara's adaptive wait instead of a blind sleep so slow CI environments
# get enough time while fast environments don't waste a fixed wait.
expect(page).to have_css('.ts-dropdown .option', wait: 15)
expect(wrapper).to have_css('.ts-dropdown .option', wait: 15)

# Type the rest if item_text is longer than 3 characters
input.send_keys(item_text[3..]) if item_text.length > 3

# Wait for updated results after the refined search
expect(page).to have_css('.ts-dropdown .option', text: item_text, wait: 10)
expect(wrapper).to have_css('.ts-dropdown .option', text: item_text, wait: 10)

# Click the matching option
# Use JavaScript click to avoid element interception issues
option = find('.ts-dropdown .option', text: item_text, match: :prefer_exact)
option = wrapper.find('.ts-dropdown .option', text: item_text, match: :prefer_exact)
page.execute_script("arguments[0].click();", option.native)
end

# Remove an item from a TomSelect multi-select
# @param item_text [String] The text of the item to remove (must match exactly)
def remove_from_tom_select(item_text)
# Wait for TomSelect to initialize and items to be present
expect(page).to have_css('.ts-wrapper', wait: 15)
expect(page).to have_css('.ts-wrapper .item', text: item_text, wait: 5)
# @param from [String, Symbol] The original select element ID
def remove_from_tom_select(item_text, from:)
# Wait for the specific TomSelect to initialize and items to be present
select = find("##{from}", visible: false)
wrapper = select.find(:xpath, '..')
expect(wrapper).to have_css('.ts-wrapper', wait: 15)
expect(wrapper).to have_css('.ts-wrapper .item', text: item_text, wait: 5)

within '.ts-wrapper' do
within wrapper do
find('.item', text: item_text, match: :prefer_exact).find('.remove').click
end
end
Expand Down