module Avo::TestHelpers

def accept_custom_alert(&block)

def accept_custom_alert(&block)
  block.call
  find('#turbo-confirm button[value="confirm"]').click
end

def add_tag(field:, tag:)

add_tag(field: :tags, tag: "two")
expect(add_tag(field: :tags, tag: "one")).to eq ["one"]
Example usage:
def add_tag(field:, tag:)
  # Find the input field for the specified field and click it
  find("[data-field-id='#{field}'] [data-slot='value'] [role='textbox']").click
  # Enter the specified tag into the input field
  type tag, :return
  wait_for_tag_to_appear(tag)
  # Return an array of the current tags
  tags(field: field)
end

def check_select_all

def check_select_all
  find("input[type='checkbox'][name='Select all'][data-action='input->item-select-all#toggle']").set(true)
end

def click_global_search_input

def click_global_search_input
  page.find(:xpath, "//*[contains(@class, 'global-search')]").click
  wait_for_search_loaded
end

def click_on_sidebar_item(label)

def click_on_sidebar_item(label)
  within main_sidebar do
    click_on label
  end
end

def click_resource_search_input

}
write_in_search("Bob")
click_resource_search_input
within(has_and_belongs_to_many_field_wrapper(id: :users)) {
opens the search box for the "users" resource
click_resource_search_input # opens the first search box on the given page
Example usage:
def click_resource_search_input
  first("[data-search-resource]:not([data-search-resource='global'])").click
  wait_for_search_loaded
end

def click_tab(tab_name = "", within_target: nil, **args)

def click_tab(tab_name = "", within_target: nil, **args)
  if within_target.present?
    within within_target do
      within find('[data-controller="tabs"] [data-tabs-target="tabSwitcher"]') do
        find_link(tab_name).trigger("click")
      end
    end
  else
    within find('[data-controller="tabs"] [data-tabs-target="tabSwitcher"]') do
      find_link(tab_name).trigger("click")
    end
  end
  wait_for_loaded
end

def close_picker

def close_picker
  find('[data-target="title"]').trigger("click")
  sleep 0.3
end

def empty_dash

def empty_dash
  "—"
end

def first_tab_group

def first_tab_group
  tab_group 0
end

def grid_field_wrapper(record_id:)

grid_field_wrapper(record_id: 5)
Example usage:
Finds the wrapper element on the index grid view type for the given record id
def grid_field_wrapper(record_id:)
  find("[data-component-name='avo/index/grid_item_component'][data-resource-id='#{record_id}']")
end

def has_and_belongs_to_many_field_wrapper(id:, view: :show)

has_and_belongs_to_many_field_wrapper(id: :users, view: :edit)
has_and_belongs_to_many_field_wrapper(id: :users)
Example usage:
Finds the table on the show view for the given has_and_belongs_to_many field id and view
def has_and_belongs_to_many_field_wrapper(id:, view: :show)
  related_field_context(id: id, relation: :has_and_belongs_to_many, view: view)
end

def has_many_field_wrapper(id:, view: :show)

has_many_field_wrapper(id: :users, view: :edit)
has_many_field_wrapper(id: :users)
Example usage:
Finds the table on the show view for the given has_many field id and view
def has_many_field_wrapper(id:, view: :show)
  related_field_context(id: id, relation: :has_many, view: view)
end

def has_one_field_wrapper(id:, view: :show)

has_one_field_wrapper(id: :users, view: :edit)
has_one_field_wrapper(id: :users)
Example usage:
Finds the table on the show view for the given has_one field id and view
def has_one_field_wrapper(id:, view: :show)
  related_field_context(id: id, relation: :has_one, view: view)
end

def index_field_label(id:)

index_field_label(id: "name")
Example usage:
Finds the label element on the index view for the given field id
def index_field_label(id:)
  find("[data-component-name='avo/partials/table_header'] [data-table-header-field-id='#{id}']").text
end

def index_field_value(id:, record_id:, type: nil)

index_field_value(id: "name", record_id: 2)
Example usage:
Finds the value element on the index view for the given field id
def index_field_value(id:, record_id:, type: nil)
  index_field_wrapper(id: id, record_id: record_id, type: type).text
end

def index_field_wrapper(id:, record_id:, type: nil)

index_field_wrapper(id: "name", record_id: 2)
index_field_wrapper(id: "name", type: "text", record_id: 2)
Example usage:
Finds the wrapper element on the index view for the given field id and type, and associated with the given record id
def index_field_wrapper(id:, record_id:, type: nil)
  base_data = "#{row(record_id)} [data-field-id='#{id}']"
  if type.present?
    find("#{base_data}[data-resource-index-target='#{wrapper_name_for(id: id, type: type)}']")
  else
    find(base_data)
  end
end

def main_sidebar

def main_sidebar
  find('[data-sidebar-target="sidebar"]')
end

def open_action(action_name:, list:, context:, &block)

If no list is present, it will directly click on the action link.
and then find the specified action name within the panel.
Opens an action. If a list is provided, it will click on the list first
def open_action(action_name:, list:, context:, &block)
  within(context) do
    if list.present?
      sleep 0.1
      click_on list
      within("[data-toggle-target='panel']") do
        find("a[data-action-name='#{action_name}']").click
      end
    else
      click_link(action_name)
    end
  end
  expect(page).to have_selector(modal = "[role='dialog']")
  # Within the dialog, ensure that the action name is present
  within(find(modal)) do
    expect(page).to have_content(action_name)
  end
end

def open_panel_action(action_name:, list: "Actions")

open_panel_action(list: "Runnables", action_name: "Release fish")
open_panel_action(list: nil, action_name: "Release fish")
open_panel_action(action_name: "Dummy action")
Example usage:
Pass list: "List name" if list is not the default "Actions"
Pass list: nil to run an action outside of the list
Click on the action from the panel (index and show above the table)
def open_panel_action(action_name:, list: "Actions")
  open_action(action_name: action_name, list: list, context: first("[data-target='panel-tools']"))
end

def open_picker

def open_picker
  text_input.click
end

def open_row_action(record_id:, action_name:, list: "Actions")

open_row_action(list: "Runnables", action_name: "Release fish")
open_row_action(list: nil, action_name: "Release fish")
open_row_action(action_name: "Dummy action")
Example usage:
Pass list: "List name" if list is not the default "Actions"
Pass list: nil to run an action outside of the list
Open the action from the record_id row
def open_row_action(record_id:, action_name:, list: "Actions")
  open_action(action_name: action_name, list: list, context: row(record_id))
end

def related_field_context(id:, relation:, view: :show)

end
index_field_wrapper(id: "first_name", type: "text", record_id: 7)
first_name_wrapper = within has_and_belongs_to_many_users do
Now on the returend element you can do:
ex: has_and_belongs_to_many_users = related_field_context(id: :users, relation: :has_and_belongs_to_many)
Finds the context element for the related field with the given id, relation, and view
def related_field_context(id:, relation:, view: :show)
  turbo_frame = "#{relation}_field_#{view}_#{id}"
  find("[id='#{turbo_frame}']")
end

def remove_tag(field:, tag:)

remove_tag(field: :tags, tag: "one")
expect(remove_tag(field: :tags, tag: "one")).to eq ["three"]
Example usage:
def remove_tag(field:, tag:)
  # Within the specified field
  within("[data-field-id='#{field}'] [data-slot='value']") do
    # Find the tag with the specified text and click the remove button for the tag
    page.find(".tagify__tag", text: tag).find(".tagify__tag__removeBtn").click
    wait_for_tag_to_disappear(tag)
  end
  # Return an array of the current tags
  tags(field: field)
end

def row(id)

def row(id)
  "[data-component-name='avo/index/table_row_component'][data-resource-id='#{id}']"
end

def run_action

Click on submit action button if dialog is open
def run_action
  within(find("[role='dialog']")) do
    find("[data-target='submit_action']").click
  end
  wait_for_action_dialog_to_disappear
end

def save

Trigger can't be used by default because it breaks on some feature specs
Sometimes other element may be overlapping the button so the `.trigger("click")` solves the issue
For most cases `.click` works
Save a record and wait for the page to load
def save
  button = find("button.button-component", text: "Save")
  button.click
rescue Capybara::Cuprite::MouseEventFailed
  button.trigger("click")
ensure
  wait_for_loaded
end

def second_tab_group

def second_tab_group
  tab_group 1
end

def select_first_result_in_search

select_first_result_in_search
write_in_search("John Doe")
open_search_box(:users) # opens the search box for the "users" resource
Example usage:
Should use the click_global_search_input or click_resource_search_input method to open the search box first and optionaly write_in_search.
def select_first_result_in_search
  type :down, :enter
rescue
  find(".aa-Input").send_keys :arrow_down
  find(".aa-Input").send_keys :enter
ensure
  wait_for_search_loaded
end

def set_picker_day(date)

def set_picker_day(date)
  find(".flatpickr-day[aria-label=\"#{date}\"]").click
  sleep 0.2
end

def set_picker_hour(value)

def set_picker_hour(value)
  find(".flatpickr-hour").set(value)
end

def set_picker_minute(value)

def set_picker_minute(value)
  find(".flatpickr-minute").set(value)
end

def set_picker_second(value)

def set_picker_second(value)
  find(".flatpickr-second").set(value)
end

def show_field_label(id:)

show_field_label(id: "name")
Example usage:
Finds the label element on the show view for the given field id
def show_field_label(id:)
  within(show_field_wrapper(id: id)) { find("[data-slot='label']").text }
end

def show_field_value(id:, type: nil)

show_field_value(id: "name")
Example usage:
Finds the value element on the show view for the given field id
def show_field_value(id:, type: nil)
  within(show_field_wrapper(id: id, type: type)) { find("[data-slot='value']").text }
end

def show_field_wrapper(id:, type: nil)

show_field_wrapper(id: "name")
show_field_wrapper(id: "name", type: "text")
Example usage:
Finds the wrapper element on the show view for the given field id and type
def show_field_wrapper(id:, type: nil)
  base_data = "[data-panel-id='main'] [data-field-id='#{id}']"
  if type.present?
    find("#{base_data}[data-resource-show-target='#{wrapper_name_for(id: id, type: type)}']")
  else
    find(base_data)
  end
end

def tab_group(index = 0)

def tab_group(index = 0)
  find_all('[data-controller="tabs"]')[index]
end

def tag_suggestions(field:, input:)

expect(tag_suggestions(field: :tags, input: "t")).to eq ["two", "three"]
expect(tag_suggestions(field: :tags, input: "")).to eq ["one", "two", "three"]
Example usage:
def tag_suggestions(field:, input:)
  # Find the input field for the specified tag field
  input_area = find("[data-field-id='#{field}'] [data-slot='value'] [role='textbox']")
  # If the input argument is present, enter it into the input field
  # Else, set input to "open" than to " " to trigger dropdown
  if input.present?
    input_area.set(input)
  else
    input_area.set("open")
    input_area.set(" ")
  end
  wait_for_tag_suggestions_to_appear
  # Find all elements with class 'tagify_dropdown_item' within the dropdown
  # Map the elements to their 'label' attribute values and return the array of labels
  page.all(".tagify__dropdown__item").map { |element| element[:label] }
end

def tags(field:)

expect(tags(field: :tags)).to eq []
expect(tags(field: :tags)).to eq ["one", "two", "three"]
Example usage:
def tags(field:)
  # Find all elements with class 'tagify__tag'
  # Map the elements to text and return the array of texts
  page.all(".tagify__tag").map(&:text)
end

def third_tab_group

def third_tab_group
  tab_group 3
end

def toggle_collapsable(section)

def toggle_collapsable(section)
  find("[data-action='click->menu#triggerCollapse'][data-menu-key-param*='main_menu.#{section.underscore}'] svg").click
end

def type(...)

def type(...)
  if page.driver.browser.respond_to?(:keyboard)
    page.driver.browser.keyboard.type(...)
  else
    page.send_keys(...)
  end
end

def wrapper_name_for(id:, type:)

Returns the name of the wrapper element for the given field id and type
def wrapper_name_for(id:, type:)
  "#{id.camelize(:lower)}#{type.camelize}Wrapper"
end

def write_in_search(input)

}
write_in_search("Bob")
click_resource_search_input # opens the search box for the "users" resource
within(has_and_belongs_to_many_field_wrapper(id: :users)) {
open_search_box(:users)
Example usage:
Should use the click_global_search_input or click_resource_search_input method to open the search box first.
def write_in_search(input)
  # Use xpath to find outside of within context if any
  find(:xpath, "//input[@class='aa-Input']").set(input)
  wait_for_search_loaded
end