calabash-cucumber 0.19.2 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/dylibs/libCalabashDyn.dylib +0 -0
  3. data/dylibs/libCalabashDynSim.dylib +0 -0
  4. data/lib/calabash-cucumber.rb +9 -2
  5. data/lib/calabash-cucumber/abstract.rb +23 -0
  6. data/lib/calabash-cucumber/automator/automator.rb +158 -0
  7. data/lib/calabash-cucumber/automator/coordinates.rb +401 -0
  8. data/lib/calabash-cucumber/automator/device_agent.rb +424 -0
  9. data/lib/calabash-cucumber/automator/instruments.rb +441 -0
  10. data/lib/calabash-cucumber/connection_helpers.rb +1 -0
  11. data/lib/calabash-cucumber/core.rb +632 -138
  12. data/lib/calabash-cucumber/device_agent.rb +346 -0
  13. data/lib/calabash-cucumber/dot_dir.rb +1 -0
  14. data/lib/calabash-cucumber/environment.rb +1 -0
  15. data/lib/calabash-cucumber/environment_helpers.rb +4 -3
  16. data/lib/calabash-cucumber/http/http.rb +6 -4
  17. data/lib/calabash-cucumber/keyboard_helpers.rb +97 -679
  18. data/lib/calabash-cucumber/launcher.rb +107 -31
  19. data/lib/calabash-cucumber/log_tailer.rb +46 -0
  20. data/lib/calabash-cucumber/map.rb +7 -1
  21. data/lib/calabash-cucumber/rotation_helpers.rb +47 -139
  22. data/lib/calabash-cucumber/status_bar_helpers.rb +51 -20
  23. data/lib/calabash-cucumber/store/preferences.rb +3 -0
  24. data/lib/calabash-cucumber/uia.rb +333 -2
  25. data/lib/calabash-cucumber/usage_tracker.rb +2 -0
  26. data/lib/calabash-cucumber/version.rb +2 -2
  27. data/lib/calabash-cucumber/wait_helpers.rb +2 -0
  28. data/lib/calabash/formatters/html.rb +6 -1
  29. data/lib/frank-calabash.rb +10 -4
  30. data/scripts/.irbrc +3 -0
  31. data/staticlib/calabash.framework.zip +0 -0
  32. data/staticlib/libFrankCalabash.a +0 -0
  33. metadata +11 -6
  34. data/lib/calabash-cucumber/actions/instruments_actions.rb +0 -155
@@ -4,7 +4,13 @@ module Calabash
4
4
  # Contains methods for interacting with the status bar.
5
5
  module StatusBarHelpers
6
6
 
7
- # Returns the device orientation as reported by `[[UIDevice currentDevice] orientation]`.
7
+ require "calabash-cucumber/map"
8
+
9
+ require "calabash-cucumber/connection_helpers"
10
+ include Calabash::Cucumber::ConnectionHelpers
11
+
12
+ # Returns the device orientation as reported by
13
+ # `[[UIDevice currentDevice] orientation]`.
8
14
  #
9
15
  # @note This method is not used internally by the gem. It is provided
10
16
  # as an alternative to `status_bar_orientation`. We recommend that you
@@ -16,25 +22,10 @@ module Calabash
16
22
  # @see #status_bar_orientation
17
23
  # @see Calabash::Cucumber::RotationHelpers#rotate_home_button_to
18
24
  #
19
- # @param [Boolean] force_down if true, do rotations until a down
20
- # orientation is achieved
21
25
  # @return [Symbol] Returns the device orientation as one of
22
- # `{:down, :up, :left, :right}`.
23
- def device_orientation(force_down=false)
24
- res = Map.map(nil, :orientation, :device).first
25
-
26
- if ['face up', 'face down'].include?(res)
27
- if force_down
28
- puts "WARN found orientation '#{res}' - will rotate to force orientation to 'down'"
29
- end
30
-
31
- return res unless force_down
32
- return rotate_home_button_to :down
33
- end
34
-
35
- return res unless res.eql?('unknown')
36
- return res unless force_down
37
- rotate_home_button_to(:down)
26
+ # `{'down', 'up', 'left', 'right', 'face up', 'face down', 'unknown'}`.
27
+ def device_orientation
28
+ Map.map(nil, :orientation, :device).first
38
29
  end
39
30
 
40
31
  # Returns the home button position relative to the status bar.
@@ -50,6 +41,47 @@ module Calabash
50
41
  Map.map(nil, :orientation, :status_bar).first
51
42
  end
52
43
 
44
+ # Returns details about the status bar like the frame, its visibility,
45
+ # and orientation.
46
+ #
47
+ # Requires calabash server 0.20.0.
48
+ def status_bar_details
49
+ result = http({:method => :get, :raw => true, :path => "statusBar"})
50
+ if result == ""
51
+ RunLoop::log_debug("status_bar_details is only available in Calabash iOS >= 0.20.0")
52
+ RunLoop::log_debug("Using default status bar details based on orientation.")
53
+
54
+ if portrait?
55
+ {
56
+ "frame" => {
57
+ "y" => 0,
58
+ "height" => 20,
59
+ "width" => 375,
60
+ "x" => 0
61
+ },
62
+ "hidden" => false,
63
+ "orientation" => status_bar_orientation,
64
+ "warning" => "These are default values. Update the server to 0.20.0"
65
+ }
66
+ else
67
+ {
68
+ "frame" => {
69
+ "y" => 0,
70
+ "height" => 10,
71
+ "width" => 375,
72
+ "x" => 0
73
+ },
74
+ "hidden" => false,
75
+ "orientation" => status_bar_orientation,
76
+ "warning" => "These are default values. Update the server to 0.20.0"
77
+ }
78
+ end
79
+ else
80
+ hash = JSON.parse(result)
81
+ hash["results"]
82
+ end
83
+ end
84
+
53
85
  # Is the device in the portrait orientation?
54
86
  #
55
87
  # @return [Boolean] Returns true if the device is in the 'up' or 'down'
@@ -67,7 +99,6 @@ module Calabash
67
99
  o = status_bar_orientation
68
100
  o.eql?('right') or o.eql?('left')
69
101
  end
70
-
71
102
  end
72
103
  end
73
104
  end
@@ -11,16 +11,19 @@ module Calabash
11
11
  class Preferences
12
12
  require "calabash-cucumber/dot_dir"
13
13
 
14
+ # @!visibility private
14
15
  def initialize
15
16
  dot_dir = Calabash::Cucumber::DotDir.directory
16
17
  @path = File.join(dot_dir, "preferences", "preferences.json")
17
18
  end
18
19
 
20
+ # @!visibility private
19
21
  def to_s
20
22
  puts "Preferences:"
21
23
  ap read
22
24
  end
23
25
 
26
+ # @!visibility private
24
27
  def inspect
25
28
  to_s
26
29
  end
@@ -16,7 +16,7 @@ module Calabash
16
16
 
17
17
  # UIA only makes sense if there is a run loop
18
18
  launcher = Calabash::Cucumber::Launcher.launcher_if_used
19
- run_loop = launcher && launcher.active? && launcher.run_loop
19
+ run_loop = launcher && launcher.attached_to_automator? && launcher.run_loop
20
20
 
21
21
  # Automatically attach in the calabash console
22
22
  if !run_loop && defined?(IRB)
@@ -307,6 +307,47 @@ module Calabash
307
307
  uia("target.setDeviceOrientation(#{uia_orientation})")
308
308
  end
309
309
 
310
+ # Used for detecting keyboards that are not normally visible to calabash;
311
+ # e.g. the keyboard on the `MFMailComposeViewController`
312
+ #
313
+ # @note
314
+ # IMPORTANT this should only be used when the app does not respond to
315
+ # `keyboard_visible?` and UIAutomation is being used.
316
+ #
317
+ # @see #keyboard_visible?
318
+ #
319
+ # @raise [RuntimeError] If the app was not launched with instruments
320
+ def uia_keyboard_visible?
321
+ res = uia_query_windows(:keyboard)
322
+ res != ":nil"
323
+ end
324
+
325
+ # Waits for a keyboard that is not normally visible to calabash;
326
+ # e.g. the keyboard on `MFMailComposeViewController`.
327
+ #
328
+ # @note
329
+ # IMPORTANT this should only be used when the app does not respond to
330
+ # `keyboard_visible?` and UIAutomation is being used.
331
+ #
332
+ # @see #keyboard_visible?
333
+ #
334
+ # @raise [RuntimeError] if the app was not launched with instruments
335
+ def uia_wait_for_keyboard(options={})
336
+ default_opts = {
337
+ :timeout => 10,
338
+ :retry_frequency => 0.1,
339
+ :post_timeout => 0.5,
340
+ :timeout_message => "Keyboard did not appear"
341
+ }
342
+
343
+ options = default_opts.merge(options)
344
+
345
+ wait_for(options) do
346
+ uia_keyboard_visible?
347
+ end
348
+ true
349
+ end
350
+
310
351
  # @!visibility private
311
352
  def uia_type_string(string, opt_text_before='', escape=true)
312
353
  result = uia_handle_command(:typeString, string, opt_text_before)
@@ -337,6 +378,7 @@ module Calabash
337
378
  end
338
379
  end
339
380
 
381
+ # @!visibility private
340
382
  def uia_type_string_raw(str)
341
383
  uia("uia.keyboard().typeString('#{str}')")
342
384
  end
@@ -404,7 +446,6 @@ module Calabash
404
446
  end
405
447
 
406
448
  uia_result(uia(command))
407
-
408
449
  end
409
450
 
410
451
  # @!visibility private
@@ -459,6 +500,7 @@ module Calabash
459
500
  end
460
501
 
461
502
  private
503
+
462
504
  def validate_hash_is_location!(options)
463
505
  return if options[:latitude] and options[:longitude]
464
506
  if (options[:latitude] and not options[:longitude]) ||
@@ -483,3 +525,292 @@ module Calabash
483
525
  end
484
526
  end
485
527
  end
528
+
529
+ module Calabash::Cucumber::UIA
530
+
531
+ # @!visibility private
532
+ def self.redefine_instance_methods_if_necessary(xcode, automator=nil)
533
+ return if Calabash::Cucumber::Environment.xtc?
534
+
535
+ if xcode.version_gte_8?
536
+ reason = "UIAutomation is not available in Xcode >= 8.0."
537
+ return self.redefine_instance_methods_to_raise(reason)
538
+ end
539
+
540
+ if automator && automator.name == :device_agent
541
+ reason = "UIAutomation is not available when testing with DeviceAgent."
542
+ return self.redefine_instance_methods_to_raise(reason)
543
+ end
544
+ end
545
+
546
+ # @!visibility private
547
+ def self.redefine_instance_methods_to_raise(reason)
548
+ methods = Calabash::Cucumber::UIA.instance_methods
549
+ methods.each do |method_name|
550
+ Calabash::Cucumber::UIA.send(:remove_method, method_name)
551
+
552
+ Calabash::Cucumber::UIA.send(:define_method, method_name) do |*args|
553
+
554
+ case method_name
555
+ when :uia
556
+ raise RuntimeError, %Q[
557
+
558
+ #{reason}
559
+
560
+ #{method_name} has been removed from the Calabash API.
561
+
562
+ It is not possible to make raw UIAutomation JavaScript calls.
563
+
564
+ If you are trying to make query, use the DeviceAgent query API.
565
+
566
+ device_agent.query({type: "TextField", index:1})
567
+ device_agent.query({marked: "Cancel"})
568
+
569
+ If you are trying to perform a gesture or enter text, in most cases the normal
570
+ Core method will work. If a normal Core method does work, try the DeviceAgent
571
+ Gesture API.
572
+
573
+ device_agent.touch({type: "TextField", index:1})
574
+ device_agent.touch({marked: "Button"})
575
+
576
+ If you cannot find an equivalent DeviceAgent workaround, please create an issue
577
+ and include:
578
+
579
+ 1. At a high level, what you are trying to do.
580
+ 2. The JavaScript you are trying to invoke.
581
+
582
+ Links:
583
+
584
+ * http://calabashapi.xamarin.com/ios/Calabash/Cucumber/DeviceAgent.html
585
+ * https://github.com/calabash/calabash-ios/issues
586
+ ]
587
+ when :uia_call, :uia_call_windows, :uia_call_method, :uia_names
588
+ raise RuntimeError, %Q[
589
+
590
+ #{reason}
591
+
592
+ #{method_name} has been removed from the Calabash API.
593
+
594
+ There is no suggested workaround for this method. Please review the DeviceAgent
595
+ API for a replacement. If you can find no replacement, please create an issue
596
+ and include:
597
+
598
+ If you are trying to make query, use the DeviceAgent query API.
599
+
600
+ device_agent.query({type: "TextField", index:1})
601
+ device_agent.query({marked: "Cancel"})
602
+
603
+ If you are trying to perform a gesture or enter text, in most cases the normal
604
+ Core method will work. If a normal Core method does work, try the DeviceAgent
605
+ Gesture API.
606
+
607
+ device_agent.touch({type: "TextField", index:1})
608
+ device_agent.touch({marked: "Button"})
609
+
610
+ If you cannot find an equivalent DeviceAgent workaround, please create an issue
611
+ and include:
612
+
613
+ 1. At a high level, what you are trying to do.
614
+ 2. The method you are invoking with the arguments.
615
+
616
+ Links:
617
+
618
+ * http://calabashapi.xamarin.com/ios/Calabash/Cucumber/DeviceAgent.html
619
+ * https://github.com/calabash/calabash-ios/issues
620
+ ]
621
+ when :uia_element_exists?, :uia_element_does_not_exist?
622
+ raise RuntimeError, %Q[
623
+
624
+ #{reason}
625
+
626
+ #{method_name} has been removed from the Calabash API.
627
+
628
+ Use the DeviceAgent wait API.
629
+
630
+ device_agent.wait_for_view({marked: "Cancel"})
631
+ device_agent.wait_for_no_view({marked: "Cancel"})
632
+
633
+ ]
634
+ when :uia_query, :uia_query_el
635
+ raise RuntimeError, %Q[
636
+
637
+ #{reason}
638
+
639
+ #{method_name} has been removed from the Calabash API.
640
+
641
+ Use the DeviceAgent query API.
642
+
643
+ device_agent.query({marked: "Cancel"})
644
+ device_agent.query({type: "TextField", index:1})
645
+
646
+ ]
647
+
648
+ when :uia_query_windows
649
+
650
+ raise RuntimeError, %Q[
651
+
652
+ #{reason}
653
+
654
+ #{method_name} has been removed from the Calabash API.
655
+
656
+ Try to use the DeviceAgent query API.
657
+
658
+ device_agent.query({marked: "Cancel"})
659
+ device_agent.query({type: "TextField", index:1})
660
+
661
+ If the DeviceAgent query API does not find the correct views, please create an
662
+ issue and include:
663
+
664
+ 1. At a high level, what you are trying to do.
665
+ 2. The method you are invoking with the arguments.
666
+
667
+ ]
668
+ when :uia_screenshot
669
+ raise RuntimeError, %Q[
670
+
671
+ #{reason}
672
+
673
+ #{method_name} has been removed from the Calabash API.
674
+
675
+ There is no replacement for this method.
676
+
677
+ Please create an issue and include:
678
+
679
+ 1. At a high level, what you are trying to do.
680
+ 2. A screenshot of the view you are trying capture.
681
+
682
+ ]
683
+ when :uia_orientation, :uia_rotate_home_button_to, :uia_rotate
684
+ raise RuntimeError, %Q[
685
+
686
+ #{reason}
687
+
688
+ #{method_name} has been removed from the Calabash API.
689
+
690
+ You should not be calling this method. Always call the orientation methods
691
+ defined in the Core API.
692
+
693
+ ]
694
+ when :uia_type_string, :uia_type_string_raw, :uia_enter, :uia_set_responder_value
695
+ raise RuntimeError, %Q[
696
+
697
+ #{reason}
698
+
699
+ #{method_name} has been removed from the Calabash API.
700
+
701
+ In general, you should use the the text input methods defined in Core.
702
+
703
+ In some cases you will need to use the DeviceAgent query and keyboard API.
704
+
705
+ device_agent.touch({type: "TextField", index: 1})
706
+ wait_for_keyboard
707
+ keyboard_enter_text("Hello")
708
+
709
+ It is important to note that the DeviceAgent implementations of:
710
+
711
+ * keyboard_enter_text
712
+ * keyboard_enter_char
713
+ * enter_text_in
714
+ * enter_text
715
+ * fast_enter_text
716
+
717
+ have exactly the same performance.
718
+
719
+ You should prefer `enter_text` or `enter_text_in` because it matches the
720
+ Calabash 2.0 API.
721
+
722
+ ]
723
+ when :uia_set_location
724
+ raise RuntimeError, %Q[
725
+
726
+ #{reason}
727
+
728
+ #{method_name} has been removed from the Calabash API.
729
+
730
+ This method has been broken for various iOS versions and device combinations
731
+ for years.
732
+
733
+ At the moment, we do not have replacement for location spoofing with DeviceAgent.
734
+
735
+ ]
736
+ when :uia_send_app_to_background
737
+ raise RuntimeError, %Q[
738
+
739
+ #{reason}
740
+
741
+ #{method_name} has been removed from the Calabash API.
742
+
743
+ You should not use this method. If the Core send_app_to_background is not
744
+ working under UIAutomation, please create a GitHub issue.
745
+
746
+ https://github.com/calabash/calabash-ios/issues
747
+
748
+ ]
749
+ when :uia_keyboard_visible?, :uia_wait_for_keyboard
750
+ raise RuntimeError, %Q[
751
+
752
+ #{reason}
753
+
754
+ #{method_name} has been removed from the Calabash API.
755
+
756
+ We have not found a case (yet) where the the Core keyboard_visible? and
757
+ wait_for_keyboard methods do not work when using DeviceAgent. If you find a
758
+ case where the Core methods do not work, please create a GitHub issue.
759
+
760
+ The current DeviceAgent keyboard API is scheduled for removal. It is crucial
761
+ that you report workflows that require the DeviceAgent keyboard API.
762
+
763
+ device_agent.keyboard_visible?
764
+ wait_for { device_agent.keyboard_visible? }
765
+
766
+ https://github.com/calabash/calabash-ios/issues
767
+
768
+ ]
769
+ when :uia_handle_command, :uia_serialize_command,
770
+ :uia_serialize_arguments, :uia_serialize_argument,
771
+ :escape_uia_string, :send_uia_command
772
+ raise RuntimeError, %Q[
773
+
774
+ #{reason}
775
+
776
+ #{method_name} has been removed from the Calabash API.
777
+
778
+ There is no replacement.
779
+
780
+ ]
781
+ when :uia_tap, :uia_tap_mark, :uia_tap_offset,
782
+ :uia_double_tap, :uia_double_tap_mark, :uia_double_tap_offset,
783
+ :uia_two_finger_tap, :uia_two_finger_tap_offset,
784
+ :uia_touch_hold, :uia_touch_hold_offset,
785
+ :uia_pan, :uia_pan_offset,
786
+ :uia_swipe, :uia_swipe_offset, :uia_flick_offset,
787
+ :uia_drag_inside, :uia_drag_inside_mark,
788
+ :uia_pinch, :uia_pinch_offset, :uia_scroll_to
789
+ raise RuntimeError, %Q[
790
+
791
+ #{reason}
792
+
793
+ #{method_name} has been removed from the Calabash API.
794
+
795
+ DeviceAgent is our replacement for UIAutomation. In most cases, you will not
796
+ need to use a special DeviceAgent gesture method like you did with UIAutomation.
797
+
798
+ If a Core gesture method does not work, there is a DeviceAgent gesture API.
799
+
800
+ device_agent.touch({type: "Button", marked: "Back"})
801
+
802
+ For UIA pan gestures (flick, swipe, pan) use pan_coordinates.
803
+
804
+ from_point = device_agent.query_for_coordinate({marked: "From"})
805
+ to_point = device_agent.query_for_coordinate({marked: "To"})
806
+ pan_coordinates(from_point, to_point)
807
+
808
+ ]
809
+ else
810
+ raise ArgumentError, "This #{method_name} has not been handled"
811
+ end
812
+ end
813
+ end
814
+ true
815
+ end
816
+ end