Module: Avo::TestHelpers

Includes:
WaitForLoaded
Included in:
PrefixedTestHelpers
Defined in:
lib/avo/test_helpers.rb

Instance Method Summary collapse

Methods included from WaitForLoaded

#wait_for_action_dialog_to_disappear, #wait_for_body_class_missing, #wait_for_element_missing, #wait_for_element_present, #wait_for_loaded, #wait_for_path_to_be, #wait_for_route_loaded, #wait_for_route_loading, #wait_for_search_loaded, #wait_for_search_to_dissapear, #wait_for_tag_suggestions_to_appear, #wait_for_tag_to_appear, #wait_for_tag_to_disappear, #wait_for_turbo_frame_id, #wait_for_turbo_frame_src, #wait_for_turbo_loaded

Instance Method Details

#accept_custom_alert(&block) ⇒ Object



341
342
343
344
# File 'lib/avo/test_helpers.rb', line 341

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

#add_tag(field:, tag:) ⇒ Object

Example usage:

expect(add_tag(field: :tags, tag: "one")).to eq ["one"]
add_tag(field: :tags, tag: "two")


274
275
276
277
278
279
280
281
282
283
284
# File 'lib/avo/test_helpers.rb', line 274

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

#check_select_allObject



263
264
265
# File 'lib/avo/test_helpers.rb', line 263

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

#click_global_search_inputObject



96
97
98
# File 'lib/avo/test_helpers.rb', line 96

def click_global_search_input
  page.find("[data-global-search-target='input']").click
end

#click_on_sidebar_item(label) ⇒ Object



178
179
180
181
182
# File 'lib/avo/test_helpers.rb', line 178

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

#click_row_action(record, control:) ⇒ Object

Clicks a row control action (destroy, detach, edit, etc.) for a given record. Works for both grid view (actions behind a popover trigger) and table view (flat inline actions).



348
349
350
351
352
353
354
355
356
357
358
# File 'lib/avo/test_helpers.rb', line 348

def click_row_action(record, control:)
  row = find("[data-record-id='#{record.to_param}']")

  if row.has_css?(".grid-card__actions-row button[popovertarget]", wait: 0)
    row.find(".grid-card__actions-row button[popovertarget]").click
  end

  within(row) do
    find("a[data-control='#{control}'][data-resource-id='#{record.to_param}']").click
  end
end

#click_tab(tab_name = "", within_target: nil, **args) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/avo/test_helpers.rb', line 145

def click_tab(tab_name = "", within_target: nil, **args)
  tab_container_selector = '[data-controller="tabs"] [role="tablist"]'

  if within_target.present?
    within within_target do
      within find(tab_container_selector) do
        find_link(tab_name).trigger("click")
      end
    end
  else
    within find(tab_container_selector) do
      find_link(tab_name).trigger("click")
    end
  end
  wait_for_loaded
end

#close_pickerObject



227
228
229
230
# File 'lib/avo/test_helpers.rb', line 227

def close_picker
  all(".header__title").first.trigger("click")
  sleep 0.3
end

#empty_dashObject



92
93
94
# File 'lib/avo/test_helpers.rb', line 92

def empty_dash
  ""
end

#first_tab_groupObject



166
167
168
# File 'lib/avo/test_helpers.rb', line 166

def first_tab_group
  tab_group 0
end

#grid_field_wrapper(record_id:) ⇒ Object

Finds the wrapper element on the index grid view type for the given record id Example usage:

grid_field_wrapper(record_id: 5)


22
23
24
# File 'lib/avo/test_helpers.rb', line 22

def grid_field_wrapper(record_id:)
  find("[data-component-name='avo/index/grid_item_component'][data-resource-id='#{record_id}']")
end

#has_and_belongs_to_many_field_wrapper(id:, view: :show) ⇒ Object

Finds the table on the show view for the given has_and_belongs_to_many field id and view Example usage:

has_and_belongs_to_many_field_wrapper(id: :users)
has_and_belongs_to_many_field_wrapper(id: :users, view: :edit)


52
53
54
# File 'lib/avo/test_helpers.rb', line 52

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

#has_many_field_wrapper(id:, view: :show) ⇒ Object

Finds the table on the show view for the given has_many field id and view Example usage:

has_many_field_wrapper(id: :users)
has_many_field_wrapper(id: :users, view: :edit)


44
45
46
# File 'lib/avo/test_helpers.rb', line 44

def has_many_field_wrapper(id:, view: :show)
  related_field_context(id: id, relation: :has_many, view: view)
end

#has_one_field_wrapper(id:, view: :show) ⇒ Object

Finds the table on the show view for the given has_one field id and view Example usage:

has_one_field_wrapper(id: :users)
has_one_field_wrapper(id: :users, view: :edit)


60
61
62
# File 'lib/avo/test_helpers.rb', line 60

def has_one_field_wrapper(id:, view: :show)
  related_field_context(id: id, relation: :has_one, view: view)
end

#index_field_label(id:) ⇒ Object

Finds the label element on the index view for the given field id Example usage:

index_field_label(id: "name")


67
68
69
# File 'lib/avo/test_helpers.rb', line 67

def index_field_label(id:)
  find("[data-component-name='avo/partials/table_header'] [data-table-header-field-id='#{id}']").text
end

#index_field_value(id:, record_id:, type: nil) ⇒ Object

Finds the value element on the index view for the given field id Example usage:

index_field_value(id: "name", record_id: 2)


81
82
83
# File 'lib/avo/test_helpers.rb', line 81

def index_field_value(id:, record_id:, type: nil)
  index_field_wrapper(id: id, record_id: record_id, type: type).text
end

#index_field_wrapper(id:, record_id:, type: nil) ⇒ Object

Finds the wrapper element on the index view for the given field id and type, and associated with the given record id Example usage:

index_field_wrapper(id: "name", type: "text", record_id: 2)
index_field_wrapper(id: "name", record_id: 2)


9
10
11
12
13
14
15
16
17
# File 'lib/avo/test_helpers.rb', line 9

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

#open_panel_action(action_name:, list: "Actions") ⇒ Object

Click on the action from the panel (index and show above the table) Pass list: nil to run a standalone action (found by data-action-name / action name, not link text) Pass list: "List name" if list is not the default "Actions" Example usage:

open_panel_action(action_name: "Dummy action")
open_panel_action(list: nil, action_name: "Release fish")
open_panel_action(list: "Runnables", action_name: "Release fish")


239
240
241
# File 'lib/avo/test_helpers.rb', line 239

def open_panel_action(action_name:, list: "Actions")
  open_action(action_name: action_name, list: list, context: first(".header__controls"))
end

#open_pickerObject



223
224
225
# File 'lib/avo/test_helpers.rb', line 223

def open_picker
  text_input.click
end

#open_row_action(record_id:, action_name:, list: "Actions") ⇒ Object

Open the action from the record_id row Pass list: nil to run a standalone row action (matched by action name, not visible label) Pass list: "List name" if list is not the default "Actions" Example usage:

open_row_action(action_name: "Dummy action")
open_row_action(list: nil, action_name: "Release fish")
open_row_action(list: "Runnables", action_name: "Release fish")


250
251
252
# File 'lib/avo/test_helpers.rb', line 250

def open_row_action(record_id:, action_name:, list: "Actions")
  open_action(action_name: action_name, list: list, context: row(record_id))
end

#remove_tag(field:, tag:) ⇒ Object

Example usage:

expect(remove_tag(field: :tags, tag: "one")).to eq ["three"]
remove_tag(field: :tags, tag: "one")


289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/avo/test_helpers.rb', line 289

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

#run_actionObject

Click on submit action button if dialog is open



255
256
257
258
259
260
261
# File 'lib/avo/test_helpers.rb', line 255

def run_action
  within(find("[role='dialog']")) do
    find("[data-target='submit_action']").click
  end

  wait_for_action_dialog_to_disappear
end

#saveObject

Save a record and wait for the page to load For most cases .click works Sometimes other element may be overlapping the button so the .trigger("click") solves the issue Trigger can't be used by default because it breaks on some feature specs



136
137
138
139
140
141
142
143
# File 'lib/avo/test_helpers.rb', line 136

def save
  button = find("button.button", text: "Save")
  button.click
rescue Capybara::Cuprite::MouseEventFailed
  button.trigger("click")
ensure
  wait_for_loaded
end

#second_tab_groupObject



170
171
172
# File 'lib/avo/test_helpers.rb', line 170

def second_tab_group
  tab_group 1
end

#select_first_result_in_searchObject

TODO: this will make sense only on global search Should use the click_global_search_input or click_resource_search_input method to open the search box first and optionaly write_in_search. Example usage:

open_search_box(:users) # opens the search box for the "users" resource
write_in_search("John Doe")
select_first_result_in_search


123
124
125
126
127
128
129
130
# File 'lib/avo/test_helpers.rb', line 123

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

#set_picker_dates(input, *dates) ⇒ Object



189
190
191
192
193
194
195
# File 'lib/avo/test_helpers.rb', line 189

def set_picker_dates(input, *dates)
  page.execute_script(
    "arguments[0]._flatpickr.setDate(arguments[1], true)",
    input.native,
    (dates.length == 1) ? dates.first : dates
  )
end

#set_picker_day(date) ⇒ Object



184
185
186
187
# File 'lib/avo/test_helpers.rb', line 184

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

#set_picker_hour(value) ⇒ Object



205
206
207
# File 'lib/avo/test_helpers.rb', line 205

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

#set_picker_minute(value) ⇒ Object



209
210
211
# File 'lib/avo/test_helpers.rb', line 209

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

#set_picker_second(value) ⇒ Object



213
214
215
# File 'lib/avo/test_helpers.rb', line 213

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

#set_picker_text_input(value) ⇒ Object



217
218
219
220
221
# File 'lib/avo/test_helpers.rb', line 217

def set_picker_text_input(value)
  element = find("input.form-control[type='text']")
  # Set value without firing input/change events
  page.execute_script("arguments[0].value = arguments[1]", element.native, value)
end

#set_picker_time(input, hour:, minute: 0, second: 0) ⇒ Object



197
198
199
200
201
202
203
# File 'lib/avo/test_helpers.rb', line 197

def set_picker_time(input, hour:, minute: 0, second: 0)
  page.execute_script(
    "arguments[0]._flatpickr.setDate(arguments[1], true)",
    input.native,
    "#{hour}:#{minute}:#{second}"
  )
end

#show_field_label(id:) ⇒ Object

Finds the label element on the show view for the given field id Example usage:

show_field_label(id: "name")


74
75
76
# File 'lib/avo/test_helpers.rb', line 74

def show_field_label(id:)
  within(show_field_wrapper(id: id)) { find("[data-slot='label']").text }
end

#show_field_value(id:, type: nil) ⇒ Object

Finds the value element on the show view for the given field id Example usage:

show_field_value(id: "name")


88
89
90
# File 'lib/avo/test_helpers.rb', line 88

def show_field_value(id:, type: nil)
  within(show_field_wrapper(id: id, type: type)) { find("[data-slot='value']").text }
end

#show_field_wrapper(id:, type: nil) ⇒ Object

Finds the wrapper element on the show view for the given field id and type Example usage:

show_field_wrapper(id: "name", type: "text")
show_field_wrapper(id: "name")


30
31
32
33
34
35
36
37
38
# File 'lib/avo/test_helpers.rb', line 30

def show_field_wrapper(id:, type: nil)
  base_data = "[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

#tab_group(index = 0) ⇒ Object



162
163
164
# File 'lib/avo/test_helpers.rb', line 162

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

#tag_suggestions(field:, input:) ⇒ Object

Example usage:

expect(tag_suggestions(field: :tags, input: "")).to eq ["one", "two", "three"]
expect(tag_suggestions(field: :tags, input: "t")).to eq ["two", "three"]


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/avo/test_helpers.rb', line 314

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

#tags(field:) ⇒ Object

Example usage:

expect(tags(field: :tags)).to eq ["one", "two", "three"]
expect(tags(field: :tags)).to eq []


305
306
307
308
309
# File 'lib/avo/test_helpers.rb', line 305

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

#third_tab_groupObject



174
175
176
# File 'lib/avo/test_helpers.rb', line 174

def third_tab_group
  tab_group 3
end

#toggle_collapsable(section) ⇒ Object



267
268
269
# File 'lib/avo/test_helpers.rb', line 267

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

#typeObject



333
334
335
336
337
338
339
# File 'lib/avo/test_helpers.rb', line 333

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

#write_in_global_search(input) ⇒ Object



113
114
115
# File 'lib/avo/test_helpers.rb', line 113

def write_in_global_search(input)
  page.find("[data-global-search-target='input']").set(input)
end

#write_in_search(input) ⇒ Object

Should use the click_global_search_input or click_resource_search_input method to open the search box first. Example usage:

open_search_box(:users)
within(has_and_belongs_to_many_field_wrapper(id: :users)) {
click_resource_search_input # opens the search box for the "users" resource
write_in_search("Bob")
}


107
108
109
110
111
# File 'lib/avo/test_helpers.rb', line 107

def write_in_search(input)
  # Use xpath to find outside of within context if any
  find('[data-resource-search-target="input"]').set(input)
  wait_for_search_loaded
end