A Calabash custom step to Swipe to delete all cells in a Table View

While testing a "swipe to delete" feature in an app, I wrote a custom script for Calabash iOS that automates the deletion of all the cells in the Table View. This step definition is generic enough that it can be used in most apps. I hope you find it useful.

This step makes 2 assumptions:

1) The table view contains at least one cell that can be deleted via a swipe. It's up to you to create a step that populates the table.

2) When all cells are deleted, your app displays helpful text, such as "No Saved Articles," within a UITableViewCell. This requires additional logic since verifying that all cells were deleted is not as simple as checking that the total number of cells equals zero.

def check_cell(prefix)
  if @final_count[0] == 1
    final_cell = query "TableViewCell index:0"
    if final_cell.first["class"] == "UITableViewCell"
      sleep(STEP_PAUSE)
    else
      screenshot_and_raise "#{prefix} of the cells were deleted!"
    end
  else
    screenshot_and_raise "#{prefix} of the cells were deleted!"
  end
end

Then /^I swipe to delete all cells in "([^\"]*)"$/ do |orientation|
  total_rows = query("tableView index:0",numberOfRowsInSection:0)
  end_of_range = total_rows[0] - 1
  (0..end_of_range).each do
    scroll_to_row "tableView index:0", 0
    sleep(STEP_PAUSE)
    macro %Q[I swipe on cell number 1 in "#{orientation}"]
    sleep(STEP_PAUSE)
    touch "TableViewCellDeleteConfirmationControl"
  end
  @final_count = query("tableView index:0",numberOfRowsInSection:0)
  if @final_count[0] == total_rows[0]
    check_cell("None")
  else
    check_cell("Only some")
  end
end

If your app doesn't display any cells in the Table View after swiping to delete all cells (i.e. if you get [0] after running query("tableView index:0",numberOfRowsInSection:0)), then you can use this step definition instead:

Then /^I swipe to delete all cells in "([^\"]*)"$/ do |orientation|
  total_rows = query("tableView index:0",numberOfRowsInSection:0) #this returns an array
  end_of_range = total_rows[0] - 1
  (0..end_of_range).each do
    scroll_to_row "tableView index:0", 0
    sleep(STEP_PAUSE)
    macro %Q[I swipe on cell number 1 in "#{orientation}"] #requires this custom step definition: https://gist.github.com/3298026
    sleep(STEP_PAUSE)
    touch "TableViewCellDeleteConfirmationControl"
  end
  final_count = query("tableView index:0",numberOfRowsInSection:0)
  if final_count[0] == total_rows[0]
    screenshot_and_raise "None of the cells were deleted!"
  elsif final_count[0] != 0
    screenshot_and_raise "Some of the cells were not deleted!"
  end
end

Both of the steps above use a macro that is defined here:

Then /^I swipe on cell number (\d+) in "([^\"]*)"$/ do |index, orientation|
  index = index.to_i
  screenshot_and_raise "Index should be positive (was: #{index})" if (index<=0)
  if orientation == "landscape"
    swipe("up", {:query => "tableViewCell index:#{index-1}"})
  elsif orientation == "portrait"
    swipe("right", {:query => "tableViewCell index:#{index-1}"})
  end
  sleep(STEP_PAUSE)
end