calabash-android 0.5.0.pre2 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95f21eb2f0a76991155542d6963043ead614f372
4
- data.tar.gz: 879b905878e095cd1547dc808c6088d0815ef89c
3
+ metadata.gz: da10e47ee0890ecd2b419637e87e39c926689c9e
4
+ data.tar.gz: 3fb9435c2c925d99664b28b957a7ebcc64419da3
5
5
  SHA512:
6
- metadata.gz: b966369b4d9f8d27e46e1059466f54d809f93a6ad9ff76e1a2550497bf8797f27b4161e4795931a1c3e4f6253a49d1549bb456e099c9ca285577512645b5851d
7
- data.tar.gz: d095a2a9ef2a3a5ef7c473615f19b103760f4b0df831e8fe2a7b2f4afc32dc6361de05e05450a44b6b5cb1db6184893cc51476a4dba10b37c3cd2fd47d3ef212
6
+ metadata.gz: 7aed25ef751962b9f4396d3a323f0ff1a2234605e38ba88f72f96f05bb725b8edfdb52c9ab8c200dc7f7a41b69ee71f420fbf8d0ae72c0a3b0afb20191a35126
7
+ data.tar.gz: 82a7b377a02228b37d9fcc82cd3628666210b045c8bb50dee71ee9ec7ca220fa3e3a2681f9af67d37c63d115b40dfaca6c093c2d9ad8e32419eb8cc8069c2754
data/CHANGES.txt CHANGED
@@ -1,3 +1,23 @@
1
+ 0.5.0:
2
+ Removed many actions. They all have equivalent ruby wrappers/queries.
3
+
4
+ Added new ruby wrappers for scrolling and more complex gestures that would requre an action before.
5
+
6
+ Implemented flash method. It 'flashes' all found elements visually on the device to help the tester locate a view.
7
+ Its syntax is equivalent to query.
8
+
9
+ Added keyboard_enter_text/enter_text methods.
10
+
11
+ Updated all predefined steps. Their implementation is now more alike their naming.
12
+
13
+ Backoor method to invoke methods in the tested app.
14
+
15
+ Fixed visibility bugs:
16
+ - Views that were invisible were returned as visible in some cases.
17
+ - No visibility filtering on webviews.
18
+
19
+ Fixed various small bugs.
20
+
1
21
  0.3.7:
2
22
  Added calabash-android resign command
3
23
 
@@ -7,8 +7,9 @@ require 'json'
7
7
  require 'socket'
8
8
  require 'timeout'
9
9
  require 'calabash-android/helpers'
10
- require 'calabash-android/wait_helpers'
10
+ require 'calabash-android/text_helpers'
11
11
  require 'calabash-android/touch_helpers'
12
+ require 'calabash-android/wait_helpers'
12
13
  require 'calabash-android/version'
13
14
  require 'calabash-android/env'
14
15
  require 'retriable'
@@ -18,8 +19,9 @@ require 'cucumber'
18
19
  module Calabash module Android
19
20
 
20
21
  module Operations
21
- include Calabash::Android::WaitHelpers
22
+ include Calabash::Android::TextHelpers
22
23
  include Calabash::Android::TouchHelpers
24
+ include Calabash::Android::WaitHelpers
23
25
 
24
26
  def current_activity
25
27
  `#{default_device.adb_command} shell dumpsys window windows`.each_line.grep(/mFocusedApp.+[\.\/]([^.\s\/\}]+)/){$1}.first
@@ -59,8 +61,9 @@ module Operations
59
61
  @removed_actions.map! &:chomp
60
62
 
61
63
  if @removed_actions.include?(action)
62
- puts "Error: The action '#{action}' was removed in calabash-android x.x.x"
63
- puts 'For more information visit: https://github.com/calabash-android/foo/bar'
64
+ puts "\e[31mError: The action '#{action}' was removed in calabash-android 0.5\e[0m"
65
+ puts 'Solutions that do not require the removed action can be found on:'
66
+ puts "\e[36mhttps://github.com/calabash/calabash-android/blob/master/migrating_to_calabash_0.5.md\##{action}\e[0m"
64
67
  end
65
68
 
66
69
  default_device.perform_action(action, *arguments)
@@ -162,6 +165,10 @@ module Operations
162
165
  map(uiquery,:query,*converted_args)
163
166
  end
164
167
 
168
+ def flash(query_string)
169
+ map(query_string, :flash)
170
+ end
171
+
165
172
  def each_item(opts={:query => "android.widget.ListView", :post_scroll => 0.2}, &block)
166
173
  uiquery = opts[:query] || "android.widget.ListView"
167
174
  skip_if = opts[:skip_if] || lambda { |i| false }
@@ -501,7 +508,6 @@ module Operations
501
508
  env_options = {:target_package => package_name(@app_path),
502
509
  :main_activity => main_activity(@app_path),
503
510
  :test_server_port => @test_server_port,
504
- :debug => false,
505
511
  :class => "sh.calaba.instrumentationbackend.InstrumentationBackend"}
506
512
 
507
513
  env_options = env_options.merge(options)
@@ -724,81 +730,10 @@ module Operations
724
730
  raise(msg)
725
731
  end
726
732
 
727
- def has_text?(text)
728
- !query("* {text CONTAINS[c] '#{text}'}").empty?
729
- end
730
-
731
- def assert_text(text, should_find = true)
732
- raise "Text \"#{text}\" was #{should_find ? 'not ' : ''}found." if has_text?(text) ^ should_find
733
-
734
- true
735
- end
736
-
737
- def double_tap(uiquery, options = {})
738
- center_x, center_y = find_coordinate(uiquery)
739
-
740
- perform_action("double_tap_coordinate", center_x, center_y)
741
- end
742
-
743
- # Performs a "long press" operation on a selected view
744
- # Params:
745
- # +uiquery+: a uiquery identifying one view
746
- # +options[:length]+: the length of the long press in milliseconds (optional)
747
- #
748
- # Examples:
749
- # - long_press("* id:'my_id'")
750
- # - long_press("* id:'my_id'", {:length=>5000})
751
- def long_press(uiquery, options = {})
752
- center_x, center_y = find_coordinate(uiquery)
753
- length = options[:length]
754
- perform_action("long_press_coordinate", center_x, center_y, *(length unless length.nil?))
755
- end
756
-
757
- def touch(uiquery, options = {})
758
- center_x, center_y = find_coordinate(uiquery)
759
-
760
- perform_action("touch_coordinate", center_x, center_y)
761
- end
762
-
763
- def keyboard_enter_text(text, options = {})
764
- perform_action('keyboard_enter_text', text)
765
- end
766
-
767
- def keyboard_enter_char(character, options = {})
768
- keyboard_enter_text(character[0,1], options)
769
- end
770
-
771
- def enter_text(uiquery, text, options = {})
772
- tap_when_element_exists(uiquery, options)
773
- sleep 0.5
774
- keyboard_enter_text(text, options)
775
- end
776
-
777
- def clear_text(query_string, options={})
778
- result = query(query_string, setText: '')
779
-
780
- raise "No elements found. Query: #{query_string}" if result.empty?
781
-
782
- true
783
- end
784
-
785
733
  def hide_soft_keyboard
786
734
  perform_action('hide_soft_keyboard')
787
735
  end
788
736
 
789
- def find_coordinate(uiquery)
790
- raise "Cannot find nil" unless uiquery
791
-
792
- element = execute_uiquery(uiquery)
793
-
794
- raise "No elements found. Query: #{uiquery}" if element.nil?
795
-
796
- center_x = element["rect"]["center_x"]
797
- center_y = element["rect"]["center_y"]
798
-
799
- [center_x, center_y]
800
- end
801
-
802
737
  def execute_uiquery(uiquery)
803
738
  if uiquery.instance_of? String
804
739
  elements = query(uiquery)
@@ -854,26 +789,6 @@ module Operations
854
789
  touch(combined_query_string)
855
790
  end
856
791
 
857
- def tap_when_element_exists(query_string, options={})
858
- options.merge!({action: lambda {|q| touch(q)}})
859
-
860
- if options[:scroll] == true
861
- scroll_to(query_string, options)
862
- else
863
- when_element_exists(query_string, options)
864
- end
865
- end
866
-
867
- def long_press_when_element_exists(query_string, options={})
868
- options.merge!({action: lambda {|q| long_press(q)}})
869
-
870
- if options[:scroll] == true
871
- scroll_to(query_string, options)
872
- else
873
- when_element_exists(query_string, options)
874
- end
875
- end
876
-
877
792
  def swipe(dir,options={})
878
793
  ni
879
794
  end
@@ -943,7 +858,12 @@ module Operations
943
858
  raise "No elements found. Query: #{all_query_string}" if element.nil?
944
859
  element_center_y = element['rect']['center_y']
945
860
 
946
- scroll_view_query_string = "#{all_query_string} parent android.widget.ScrollView index:0"
861
+ if element.has_key?('html')
862
+ scroll_view_query_string = element['webView']
863
+ else
864
+ scroll_view_query_string = "#{all_query_string} parent android.widget.ScrollView index:0"
865
+ end
866
+
947
867
  scroll_element = query(scroll_view_query_string).first
948
868
 
949
869
  raise "Could not find parent scroll view. Query: #{scroll_view_query_string}" if element.nil?
@@ -1067,7 +987,6 @@ module Operations
1067
987
  def make_http_request(options)
1068
988
  default_device.make_http_request(options)
1069
989
  end
1070
-
1071
990
  end
1072
991
 
1073
992
 
@@ -1,5 +1,5 @@
1
1
  Then /^I wait for progress$/ do
2
- wait_for_element_do_not_exist("android.widget.ProgressBar")
2
+ wait_for_element_does_not_exist("android.widget.ProgressBar")
3
3
  end
4
4
 
5
5
  Then /^I wait$/ do
@@ -0,0 +1,41 @@
1
+ module Calabash
2
+ module Android
3
+ module TextHelpers
4
+ def has_text?(text)
5
+ !query("* {text CONTAINS[c] '#{text}'}").empty?
6
+ end
7
+
8
+ def assert_text(text, should_find = true)
9
+ raise "Text \"#{text}\" was #{should_find ? 'not ' : ''}found." if has_text?(text) ^ should_find
10
+
11
+ true
12
+ end
13
+
14
+ def keyboard_enter_text(text, options = {})
15
+ perform_action('keyboard_enter_text', text)
16
+ end
17
+
18
+ def keyboard_enter_char(character, options = {})
19
+ keyboard_enter_text(character[0,1], options)
20
+ end
21
+
22
+ def enter_text(uiquery, text, options = {})
23
+ tap_when_element_exists(uiquery, options)
24
+ sleep 0.5
25
+ keyboard_enter_text(text, options)
26
+ end
27
+
28
+ def clear_text(query_string, options={})
29
+ result = query(query_string, setText: '')
30
+
31
+ raise "No elements found. Query: #{query_string}" if result.empty?
32
+
33
+ true
34
+ end
35
+
36
+ def escape_quotes(str)
37
+ str.gsub("'", "\\\\'")
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,6 +4,70 @@ module Calabash
4
4
  def tap(mark, *args)
5
5
  touch("* marked:'#{mark}'", *args)
6
6
  end
7
+
8
+ def double_tap(uiquery, options = {})
9
+ center_x, center_y = find_coordinate(uiquery, options)
10
+
11
+ perform_action("double_tap_coordinate", center_x, center_y)
12
+ end
13
+
14
+ # Performs a "long press" operation on a selected view
15
+ # Params:
16
+ # +uiquery+: a uiquery identifying one view
17
+ # +options[:length]+: the length of the long press in milliseconds (optional)
18
+ #
19
+ # Examples:
20
+ # - long_press("* id:'my_id'")
21
+ # - long_press("* id:'my_id'", {:length=>5000})
22
+ def long_press(uiquery, options = {})
23
+ center_x, center_y = find_coordinate(uiquery, options)
24
+ length = options[:length]
25
+ perform_action("long_press_coordinate", center_x, center_y, *(length unless length.nil?))
26
+ end
27
+
28
+ def touch(uiquery, options = {})
29
+ center_x, center_y = find_coordinate(uiquery, options)
30
+
31
+ perform_action("touch_coordinate", center_x, center_y)
32
+ end
33
+
34
+ def find_coordinate(uiquery, options={})
35
+ raise "Cannot find nil" unless uiquery
36
+
37
+ element = execute_uiquery(uiquery)
38
+
39
+ raise "No elements found. Query: #{uiquery}" if element.nil?
40
+
41
+ x = element["rect"]["center_x"]
42
+ y = element["rect"]["center_y"]
43
+
44
+ if options[:offset]
45
+ x += options[:offset][:x] || 0
46
+ y += options[:offset][:y] || 0
47
+ end
48
+
49
+ [x, y]
50
+ end
51
+
52
+ def tap_when_element_exists(query_string, options={})
53
+ options.merge!({action: lambda {|q| touch(q, options)}})
54
+
55
+ if options[:scroll] == true
56
+ scroll_to(query_string, options)
57
+ else
58
+ when_element_exists(query_string, options)
59
+ end
60
+ end
61
+
62
+ def long_press_when_element_exists(query_string, options={})
63
+ options.merge!({action: lambda {|q| long_press(q, options)}})
64
+
65
+ if options[:scroll] == true
66
+ scroll_to(query_string, options)
67
+ else
68
+ when_element_exists(query_string, options)
69
+ end
70
+ end
7
71
  end
8
72
  end
9
73
  end
@@ -1,5 +1,5 @@
1
1
  module Calabash
2
2
  module Android
3
- VERSION = "0.5.0.pre2"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -100,7 +100,7 @@ module Calabash
100
100
  end
101
101
 
102
102
  #options for wait_for apply
103
- def wait_for_element_do_not_exist(uiquery, options={})
103
+ def wait_for_element_does_not_exist(uiquery, options={})
104
104
  wait_for_elements_do_not_exist([uiquery], options)
105
105
  end
106
106
 
@@ -176,7 +176,7 @@ module Calabash
176
176
  # Example usage: when_element_exists("Button", :timeout => 10)
177
177
  def when_element_exists(uiquery, opts = {})
178
178
  action = { :action => lambda { touch uiquery } }
179
- opts = DEFAULT_OPTS.merge(action).merge(opts)
179
+ opts = action.merge(opts)
180
180
  wait_for_elements_exist([uiquery], opts)
181
181
 
182
182
  if opts[:action].parameters.length == 0
@@ -191,7 +191,7 @@ module Calabash
191
191
  end
192
192
 
193
193
  def wait_for_text_to_disappear(text, options={})
194
- wait_for_element_do_not_exist("* {text CONTAINS[c] '#{text}'}", options)
194
+ wait_for_element_does_not_exist("* {text CONTAINS[c] '#{text}'}", options)
195
195
  end
196
196
 
197
197
  def wait_for_activity(activity_name, options={})
@@ -26,7 +26,18 @@ public class CalabashInstrumentationTestRunner extends InstrumentationTestRunner
26
26
  HttpServer.instantiate(Integer.parseInt(arguments.getString("test_server_port")));
27
27
 
28
28
  InstrumentationBackend.testPackage = arguments.getString("target_package");
29
- InstrumentationBackend.extras = arguments;
29
+
30
+ Bundle extras = (Bundle)arguments.clone();
31
+ extras.remove("target_package");
32
+ extras.remove("main_activity");
33
+ extras.remove("test_server_port");
34
+ extras.remove("class");
35
+
36
+ if (extras.isEmpty()) {
37
+ extras = null;
38
+ }
39
+
40
+ InstrumentationBackend.extras = extras;
30
41
 
31
42
  try {
32
43
  InstrumentationBackend.mainActivityName = arguments.getString("main_activity");
@@ -69,7 +69,12 @@ public class InstrumentationBackend extends ActivityInstrumentationTestCase2<Act
69
69
  Intent i = new Intent(Intent.ACTION_MAIN);
70
70
  i.setClassName(testPackage, mainActivityName);
71
71
  i.addCategory("android.intent.category.LAUNCHER");
72
- i.putExtras(extras);
72
+ i.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
73
+
74
+ if (extras != null) {
75
+ i.putExtras(extras);
76
+ }
77
+
73
78
  setActivityIntent(i);
74
79
 
75
80
  actions = new Actions(getInstrumentation(), this);
@@ -6,9 +6,13 @@ import java.io.File;
6
6
  import java.io.IOException;
7
7
  import java.io.PrintWriter;
8
8
  import java.io.StringWriter;
9
+ import java.lang.InterruptedException;
10
+ import java.lang.Override;
11
+ import java.lang.Runnable;
9
12
  import java.util.Enumeration;
10
13
  import java.util.List;
11
14
  import java.util.Map;
15
+ import java.util.HashMap;
12
16
  import java.util.Properties;
13
17
  import java.util.concurrent.locks.Condition;
14
18
  import java.util.concurrent.locks.Lock;
@@ -22,9 +26,12 @@ import sh.calaba.instrumentationbackend.json.JSONUtils;
22
26
  import sh.calaba.instrumentationbackend.query.Query;
23
27
  import sh.calaba.instrumentationbackend.query.QueryResult;
24
28
  import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
29
+
25
30
  import android.graphics.Bitmap;
26
31
  import android.util.Log;
27
32
  import android.view.View;
33
+ import android.view.animation.Animation;
34
+ import android.view.animation.AlphaAnimation;
28
35
 
29
36
  public class HttpServer extends NanoHTTPD {
30
37
  private static final String TAG = "InstrumentationBackend";
@@ -127,17 +134,53 @@ public class HttpServer extends NanoHTTPD {
127
134
  String uiQuery = (String) command.get("query");
128
135
  uiQuery = uiQuery.trim();
129
136
  Map op = (Map) command.get("operation");
130
- @SuppressWarnings("unused") //TODO: support other methods, e.g., flash
131
- String methodName = (String) op.get("method_name");
132
- List arguments = (List) op.get("arguments");
133
-
134
- //For now we only support query
135
-
136
-
137
- QueryResult queryResult = new Query(uiQuery,arguments).executeQuery();
137
+ String methodName = (String) op.get("method_name");
138
+ List arguments = (List) op.get("arguments");
139
+
140
+ if (methodName.equals("flash")) {
141
+ QueryResult queryResult = new Query(uiQuery, java.util.Collections.emptyList()).executeQuery();
142
+ List<View> views = queryResult.getResult();
143
+
144
+ if (views.isEmpty()) {
145
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
146
+ FranklyResult.failedResult("Could not find view to flash", "").asJson());
147
+ }
148
+
149
+ final Object firstItem = views.get(0);
150
+
151
+ if (!(firstItem instanceof View)) {
152
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
153
+ FranklyResult.failedResult("Only views can be flashed", "").asJson());
154
+ }
155
+
156
+ for (final View view : views) {
157
+ InstrumentationBackend.solo.runOnMainSync(new Runnable() {
158
+ @Override
159
+ public void run() {
160
+ Animation animation = new AlphaAnimation(1, 0);
161
+ animation.setRepeatMode(Animation.REVERSE);
162
+ animation.setDuration(200);
163
+ animation.setRepeatCount(5);
164
+ view.startAnimation(animation);
165
+ }
166
+ });
167
+
168
+ try {
169
+ Thread.sleep(1200);
170
+ } catch (InterruptedException e) {
171
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
172
+ FranklyResult.failedResult("Interrupted while flashing", "").asJson());
173
+ }
174
+ }
175
+
176
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
177
+ FranklyResult.successResult(queryResult).asJson());
178
+ } else {
179
+ QueryResult queryResult = new Query(uiQuery,arguments).executeQuery();
138
180
 
139
- return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
140
- FranklyResult.successResult(queryResult).asJson());
181
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8",
182
+ FranklyResult.successResult(queryResult).asJson());
183
+ }
141
184
  } catch (Exception e ) {
142
185
  e.printStackTrace();
143
186
  errorResult = FranklyResult.fromThrowable(e);
@@ -22,6 +22,10 @@ public class KeyboardEnterText implements Action {
22
22
 
23
23
  final InputConnection inputConnection = getInputConnection();
24
24
 
25
+ if (inputConnection == null) {
26
+ return Result.failedResult("Could not enter text. No element has focus.");
27
+ }
28
+
25
29
  final String textToEnter = args[0];
26
30
  InstrumentationBackend.solo.runOnMainSync(new Runnable() {
27
31
  @Override
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calabash-android
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.pre2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Maturana Larsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-18 00:00:00.000000000 Z
11
+ date: 2014-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -198,6 +198,7 @@ files:
198
198
  - lib/calabash-android/steps/search_steps.rb
199
199
  - lib/calabash-android/steps/spinner_steps.rb
200
200
  - lib/calabash-android/steps/time_picker_steps.rb
201
+ - lib/calabash-android/text_helpers.rb
201
202
  - lib/calabash-android/touch_helpers.rb
202
203
  - lib/calabash-android/version.rb
203
204
  - lib/calabash-android/wait_helpers.rb
@@ -839,9 +840,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
839
840
  version: '0'
840
841
  required_rubygems_version: !ruby/object:Gem::Requirement
841
842
  requirements:
842
- - - '>'
843
+ - - '>='
843
844
  - !ruby/object:Gem::Version
844
- version: 1.3.1
845
+ version: '0'
845
846
  requirements: []
846
847
  rubyforge_project:
847
848
  rubygems_version: 2.1.10