calabash-android 0.5.0.pre2 → 0.5.0

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