calabash-cucumber 0.19.2 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
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