require 'json' module Calabash module Cucumber # @!visibility private module Map # returns an array of views matched by the `query` or the result of # performing the Objective-C sequence defined by the `method_name` and # `method_args` on all the views matched by the `query` # # the query language is documented here: https://github.com/calabash/calabash-ios/wiki # # returns a JSON representation of each view that is matched # # when the `method_name` is a calabash operation, returns an array that # contains the result of calling the objc selector `description` on each # matched view. these are examples of calabash operations: `:flash`, # `:scrollToRowWithMark`, `:changeDatePickerDate`. def map(query, method_name, *method_args) #todo calabash operations should return 'views touched' in JSON format raw_map(query, method_name, *method_args)['results'] end # returns a JSON object the represents the result of performing an http # query against the calabash server. # # gem users should _not_ call this method directly; call `map` instead. # # raises an error and takes a screenshot if the value of the `outcome` key # is _not_ 'SUCCESS' # # the JSON object contains the following keys: # # `outcome` => indicates the success or failure of the query # # `status_bar_orientation` => the orientation of the status bar # # `results` => views matched by the `query` or the result of # performing the Objective-C selector sequence defined by # the `method_name` with arguments defined in # `method_args` on all views matched by the `query` # # the query language is documented here: https://github.com/calabash/calabash-ios/wiki # # here are some examples that clarify how the `method_name` and `method_args` # influence the value of the `results` key # # simple examples: # # raw_map('label')['result'] #=> [ all visible UILabels ] # raw_map('label', :text) #=> [ the 'text' of all visible UILabels ] # # example of calling a selector with arguments: # # raw_map("tableView marked:'cheeses'", {'numberOfRowsInSection' => 0})) => # [ the number of rows in the first section of the 'cheeses' table ] # # example of calling a selector on view to return an object and then calling # another selector on the returned object: # # raw_map("pickerView marked:'cheeses'", :delegate, [{pickerView:nil},{titleForRow:1},{forComponent:0}]) => # objc call: [[pickerView delegate] pickerView:nil titleForRow:1 forComponent:0] => # ['French'] def raw_map(query, method_name, *method_args) operation_map = { :method_name => method_name, :arguments => method_args } res = http({:method => :post, :path => 'map'}, {:query => query, :operation => operation_map}) res = JSON.parse(res) if res['outcome'] != 'SUCCESS' screenshot_and_raise "map #{query}, #{method_name} failed because: #{res['reason']}\n#{res['details']}" end res end # Asserts the result of a calabash `map` call and raises an error with # `msg` if no valid results are found. # # Casual gem users should never need to call this method; this is a # convenience method for gem maintainers. # # Raises an error if `map_results`: # # is an empty list #=> [] # contains a '' string #=> [ "" ] # contains '*****' string #=> [ "*****" ] # contains a single nil #=> [ nil ] # # When evaluating whether a `map` call is successful it is important to # note that sometimes a [ nil ] or [nil, , nil] is # a valid result. # # Consider a controller with 3 labels: # # label @ index 0 has text "foo" # label @ index 1 has text nil (the [label text] => nil) # label @ index 2 has text "bar" # # map('label', :text) => ['foo', nil, 'bar'] # map('label index:1', :text) => [nil] # # In other cases, [ nil ] should be treated as an invalid result # # # invalid # > mark = 'mark does not exist' # > map('tableView', :scrollToRowWithMark, mark, args) => [ nil ] # # Here a [ nil ] should be considered invalid because the # the operation could not be performed because there is not row that # matches `mark` def assert_map_results(map_results, msg) compact = map_results.compact if compact.empty? or compact.member? '' or compact.member? '*****' screenshot_and_raise msg end end end end end