calabash-page-objects 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 53ca9ca6d996a039a9b1e1d04675267a889a3f2a
4
+ data.tar.gz: 9ef0111bb7e576a8bd1331d3da57cc4a58bdb7e2
5
+ SHA512:
6
+ metadata.gz: 4fea84b0b3c128459cdbbf9bff64a27d92a50f546ea17c080dc3a23da79bd168e66718715c3478636fb4e4a943888c97c602fa5277b4a13857b7b72b5e639ba7
7
+ data.tar.gz: 95aa7fa23b22f133189adf2c19b48e8b41bc2c7e64ade82e9110787674ac845d03c4a5622560a7572e09d7c01e229c2812659015550c7165503d7982d8beda4a
@@ -0,0 +1,16 @@
1
+ # Created by .gitignore support plugin (hsz.mobi)
2
+ /.bundle/
3
+ /.yardoc
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.gem
16
+ .idea
@@ -0,0 +1,8 @@
1
+ Metrics/LineLength:
2
+ Enabled: false
3
+
4
+ MethodLength:
5
+ Enabled: false
6
+
7
+ FileName:
8
+ Enabled: false
@@ -0,0 +1,37 @@
1
+ # Contributing to calabash-page-objects
2
+
3
+ ♥ calabash-page-objects and want to get involved?
4
+ Great! There are plenty of ways you can help!
5
+
6
+ If you find a bug, have a feature request or even want to contribute an enhancement or fix, please follow the below guidelines so that we can help you out and/or get your code merged quickly.
7
+
8
+ ## If you find what looks like a bug:
9
+
10
+ * Check the [GitHub issue tracker](http://github.com/justeat/CalabashPageObjects/issues/) to see if anyone else has reported the issue.
11
+ * Make sure you are using the latest version of calabash-page-objects
12
+ * If you are still having an issue, create an issue including:
13
+ * Information you will need to reproduce and diagnose the problem
14
+
15
+ ## If you want to contribute an enhancement or a fix:
16
+
17
+ 0. Discuss any major enhancement with the project moderator.
18
+ 0. Write your Spec and/or Functional tests.
19
+ 0. Write or modify any accompanying documentation.
20
+ 0. Ensure that your tests work and your documentation is complete.
21
+
22
+
23
+ ### General Contribution Guidelines:
24
+ We follow the standard GitHub fork & pull request approach to open source collaboration.
25
+ You can find an awesome description on how this works on the [gun.io blog](https://gun.io/blog/how-to-github-fork-branch-and-pull-request/).
26
+
27
+ In a nutshell:
28
+
29
+ 0. Fork it.
30
+ 0. Create your feature branch (`git checkout -b feature/my-new-feature`).
31
+ 0. Commit your changes (`git commit -am 'Add some feature'`) and [reference any issues](https://github.com/blog/831-issues-2-0-the-next-generation).
32
+ 0. Push to your branch (`git push origin my-new-feature`).
33
+ 0. Send a new Pull Request describing what you have done and why, in detail.
34
+
35
+ **IMPORTANT**: By submitting a patch, you agree to allow the project owners to
36
+ license your work under the the terms of the Apache 2.0 license. A copy of this
37
+ license is provided in the root of the repository.
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'CalabashPageObjects/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'calabash-page-objects'
8
+ spec.version = CalabashPageObjects::VERSION
9
+ spec.authors = ['Alan Nichols and Andrew Barnett']
10
+ spec.email = ['alan.nichols@outlook.com']
11
+ spec.summary = 'Page Object framework for calabash'
12
+ spec.description = 'Page Object frameworks for calabash on iOS and Android'
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.6'
22
+ spec.add_development_dependency 'calabash-android', '>=0.5.14'
23
+ spec.add_development_dependency 'calabash-cucumber'
24
+ spec.add_development_dependency 'geminabox'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'rspec-expectations'
27
+ end
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in calabash-page-objects.gemspec
4
+ gemspec
@@ -0,0 +1,108 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ CalabashPageObjects (0.5.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ CFPropertyList (2.3.1)
10
+ awesome_print (1.6.1)
11
+ builder (3.2.2)
12
+ calabash-android (0.5.14)
13
+ awesome_print (~> 1.2)
14
+ cucumber (~> 1.3.17)
15
+ escape (~> 0.0.4)
16
+ httpclient (>= 2.3.2, < 3.0)
17
+ json (~> 1.8)
18
+ retriable (>= 1.3.3.1, < 1.5)
19
+ rubyzip (~> 1.1)
20
+ slowhandcuke (~> 0.0.3)
21
+ calabash-common (0.0.1)
22
+ cucumber (~> 1.3.0)
23
+ calabash-cucumber (0.13.0)
24
+ CFPropertyList
25
+ awesome_print
26
+ bundler (~> 1.3)
27
+ calabash-common (~> 0.0.1)
28
+ cucumber (~> 1.3.17)
29
+ edn (>= 1.0.6, < 2.0)
30
+ geocoder (>= 1.1.8, < 2.0)
31
+ httpclient (>= 2.3.2, < 3.0)
32
+ json
33
+ run_loop (~> 1.2.7)
34
+ sim_launcher (~> 0.4.13)
35
+ slowhandcuke (~> 0.0.3)
36
+ cucumber (1.3.19)
37
+ builder (>= 2.1.2)
38
+ diff-lcs (>= 1.1.3)
39
+ gherkin (~> 2.12)
40
+ multi_json (>= 1.7.5, < 2.0)
41
+ multi_test (>= 0.1.2)
42
+ diff-lcs (1.2.5)
43
+ edn (1.0.6)
44
+ escape (0.0.4)
45
+ faraday (0.9.1)
46
+ multipart-post (>= 1.2, < 3)
47
+ geminabox (0.12.4)
48
+ builder
49
+ faraday
50
+ httpclient (>= 2.2.7)
51
+ nesty
52
+ sinatra (>= 1.2.7)
53
+ geocoder (1.2.8)
54
+ gherkin (2.12.2)
55
+ multi_json (~> 1.3)
56
+ httpclient (2.6.0.1)
57
+ json (1.8.3)
58
+ multi_json (1.11.0)
59
+ multi_test (0.1.2)
60
+ multipart-post (2.0.0)
61
+ nesty (1.0.2)
62
+ rack (1.6.0)
63
+ rack-protection (1.5.3)
64
+ rack
65
+ retriable (1.4.1)
66
+ rspec (3.3.0)
67
+ rspec-core (~> 3.3.0)
68
+ rspec-expectations (~> 3.3.0)
69
+ rspec-mocks (~> 3.3.0)
70
+ rspec-core (3.3.2)
71
+ rspec-support (~> 3.3.0)
72
+ rspec-expectations (3.3.1)
73
+ diff-lcs (>= 1.2.0, < 2.0)
74
+ rspec-support (~> 3.3.0)
75
+ rspec-mocks (3.3.2)
76
+ diff-lcs (>= 1.2.0, < 2.0)
77
+ rspec-support (~> 3.3.0)
78
+ rspec-support (3.3.0)
79
+ rubyzip (1.1.7)
80
+ run_loop (1.2.9)
81
+ CFPropertyList (~> 2.2)
82
+ awesome_print (~> 1.2)
83
+ json (~> 1.8)
84
+ retriable (>= 1.3.3.1, < 2.0)
85
+ sim_launcher (0.4.13)
86
+ sinatra
87
+ sinatra (1.4.5)
88
+ rack (~> 1.4)
89
+ rack-protection (~> 1.4)
90
+ tilt (~> 1.3, >= 1.3.4)
91
+ slowhandcuke (0.0.3)
92
+ cucumber
93
+ tilt (1.4.1)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ CalabashPageObjects!
100
+ bundler (~> 1.6)
101
+ calabash-android (>= 0.5.14)
102
+ calabash-cucumber
103
+ geminabox
104
+ rspec
105
+ rspec-expectations
106
+
107
+ BUNDLED WITH
108
+ 1.10.6
@@ -0,0 +1,7 @@
1
+ Copyright 2015 JUST EAT plc
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
@@ -0,0 +1,244 @@
1
+ #CalabashPageObjects
2
+ =====================
3
+
4
+ The Calabash Page Object ruby gem provides a way to define on-screen elements in your application. These elements then have methods defined to make interacting with them in a Calabash test framework easier and more consistent across iOS and Android.
5
+
6
+ The methods can be used whether the application is on iOS or Android.
7
+
8
+ Defining an element in Android `AElement.new` (or `IElement.new` for iOS) will provide you with methods to wait for that element, find it with or without scrolling, click it, retrieve properties etc. Using the gem takes away the headache of having cater for scrolling depending on screen size, dealing with several scrollviews and interacting with elements inside webviews.
9
+
10
+ #Getting Started
11
+
12
+ ##Installing the gem
13
+ ```
14
+ gem install 'CalabashPageObjects'
15
+ ```
16
+ or add the following to your Gemfile if you use Bundler:
17
+ ```
18
+ gem 'CalabashPageObjects'
19
+ ```
20
+ Then require it in your page object class:
21
+ ```
22
+ require 'CalabashPageObjects'
23
+ ```
24
+
25
+ ##Defining Elements
26
+
27
+ There are two different types of element made available in the gem, IElement (for iOS apps) and AElement (for Android apps). These two classes provide exactly the same functionality, but abstract away slight differences in implementation between the platforms.
28
+
29
+ The constructors of both classes take a Calabash query string as their only argument. More information about the Calabash query syntax can be found [here](https://github.com/calabash/calabash-android/wiki/05-Query-Syntax).
30
+
31
+ ###For Android:
32
+ To define elements for an Android app:
33
+ ```
34
+ require 'CalabashPageObjects'
35
+ class HomeScreen
36
+
37
+ def initialize
38
+ @my_element = AElement.new("* id:'search_button'")
39
+ end
40
+ ...
41
+ ```
42
+
43
+ ###iOS
44
+ To define elements for an iOS app:
45
+ ```
46
+ require 'CalabashPageObjects'
47
+ class HomeScreen
48
+
49
+ def initialize
50
+ @my_element = IElement.new("* id:'search_button'")
51
+ end
52
+ ...
53
+ ```
54
+
55
+ #Methods (for iOS and Android)
56
+
57
+ Both AElement and IElement have the same methods. All of the methods take options as a hash. However, many of the methods have defaults set for some of their arguments and in many cases these won't need to be changed.
58
+
59
+ ###screen_query
60
+ Queries the current screen using the elements locator.
61
+ This will return an array of hashes of each element on the screen that matches your locator. This is useful for counting objects with @my_element.screen_query.size, or you can delve further into an element's attributes.
62
+
63
+ #####Example
64
+ ```
65
+ @my_element.screen_query
66
+ ```
67
+
68
+ ###when_visible
69
+ Waits a number of seconds for the element to be present. As soon as it is, the method will return.
70
+ #####Args
71
+ ```
72
+ Can take an argument for timeout. Default is 10 seconds.
73
+ ```
74
+
75
+ #####Example
76
+ ```
77
+ @my_element.when_visible(30)
78
+ ```
79
+ Use this method to make sure a particular screen/element has loaded before continuing the test run. See 'present?' if you want to assert on the presence of an element.
80
+
81
+ ###when_not_visible
82
+ Will wait a full amount of seconds for the element to not be on the screen.
83
+ #####Args
84
+ ```
85
+ Can take an argument for timeout. Default is 10 seconds.
86
+ ```
87
+
88
+ #####Example
89
+ ```
90
+ @my_element.when_not_visible(30)
91
+ ```
92
+
93
+ ###present?
94
+ Checks to see if the element is present. Returns a boolean. Can optionally scroll in search of the element.
95
+ #####Args
96
+ ```
97
+ Can take an argument for timeout. Default is 0.1.
98
+ Can take an argument for parent. Default is nil
99
+ Can take an argument for webview. Default is false
100
+ Can take an argument for scroll. Default is false.
101
+ ```
102
+
103
+ #####Example
104
+ ```
105
+ @my_element.present?(timeout: 2, scroll: true)
106
+ ```
107
+ The method will wait 'timeout' seconds for the element to be present on the screen. If 'scroll' is set to true, the method will wait 'timeout' seconds for the element to be present, and if it is not, it will automatically start scrolling to find it. It will return true if the element is found during this time and it will return false if it has reached the bottom of the screen and it hasn't found the element anywhere.
108
+
109
+ ###prod
110
+ This is probably the method you'll use the most. It is our method for tapping the element. We made sure that we used new methods names so that you can still use the regular Calabash Operations methods as well as ours.
111
+ #####Args
112
+ ```
113
+ Can take an argument for timeout. Default is 1 second.
114
+ Can take an argument for parent. Default is nil.
115
+ Can take an argument for webview. Default is false.
116
+ ```
117
+
118
+ ```
119
+ @my_element.prod
120
+ ```
121
+ It will wait 'timeout' seconds for an element to be present before scrolling to find it. The beauty of this method is you can now both wait for an element to be present and tap it using the same method. Just include an integer or float for however long you want to wait for it as the timeout!
122
+
123
+ ###input
124
+ Clears the text in an element and then enters the text that is passed in.
125
+ #####Args
126
+ ```
127
+ Always takes a string argument for 'value'.
128
+ Can take an argument for timeout. Default is 1 second. Works in the same way as the 'prod' method.
129
+ Can take an argument for parent. Default is nil.
130
+ Can take an argument for webview. Default is false.
131
+ ```
132
+ Value is is the text you want to enter. It should be the first parameter passed in.
133
+
134
+ #####Example
135
+ ```
136
+ @my_element.input('email@email.com', parent: @form_scrollview)
137
+ ```
138
+
139
+ ###check
140
+ Sets a checkbox element to 'checked' state.
141
+ #####Args
142
+ ```
143
+ Can take an argument for timeout. Default is 1 second.
144
+ Can take an argument for parent. Default is nil.
145
+ Can take an argument for webview. Default is false.
146
+ ```
147
+
148
+ #####Example
149
+ ```
150
+ @my_checkbox.check
151
+ ```
152
+ Will scroll to find the element after the timeout has elapsed.
153
+
154
+ ###uncheck
155
+ Works in the same way as 'check' except sets the state of the checkbox to 'unchecked'.
156
+ #####Args
157
+ ```
158
+ Can take an argument for timeout. Default is 1 second.
159
+ Can take an argument for parent. Default is nil.
160
+ Can take an argument for webview. Default is false.
161
+ ```
162
+
163
+ #####Example
164
+ ```
165
+ @my_checkbox.uncheck
166
+ ```
167
+ Will scroll to find the element after the timeout has elapsed.
168
+
169
+ ###checked?
170
+ Finds the checked status of a checkbox element. Returns true if it's checked and false if it's unchecked.
171
+
172
+ #####Args
173
+ ```
174
+ Can take an argument for timeout. Default is 1 second.
175
+ Can take an argument for parent. Default is nil.
176
+ Can take an argument for webview. Default is false.
177
+ ```
178
+
179
+ #####Example
180
+ ```
181
+ @my_checkbox.checked?
182
+ ```
183
+ Will scroll to find the element after the timeout has elapsed.
184
+
185
+ ###text
186
+ Retrieves the text attribute of an element and returns it as a string.
187
+
188
+ #####Args
189
+ ```
190
+ Can take an argument for timeout. Default is 1 second.
191
+ Can take an argument for parent. Default is nil.
192
+ Can take an argument for webview. Default is false.
193
+ ```
194
+
195
+ #####Example
196
+ ```
197
+ @my_element.text
198
+ ```
199
+ Will scroll to find the element after the timeout has elapsed.
200
+
201
+ #Parameter usage
202
+ ###Some examples:
203
+
204
+ The AElement @my_element has a method called 'prod' which will tap it. It can accept values for the timeout for the element to appear, a secondary 'parent' element that your element lives inside, and whether the element is in a webview. The defaults for these values are as follows:
205
+ ```
206
+ timeout: 1
207
+ parent: nil
208
+ webview: false
209
+ ```
210
+ so if the defaults are suitable then the prod method can be called with no arguments:
211
+ `@my_element.prod`
212
+
213
+ but to run the method in a situation where the defaults are not suitable, you can override as many as you like. In this example we override timeout and webview, but not parent:
214
+ `@my_element.prod(timeout: 10, webview: true)`
215
+
216
+ ###Shorthand for timeout
217
+ As in most cases, the only default that will be overridden is the timeout. There is a shorthand implemented especially for doing this. If the only argument passed in is an integer or float, then it is assumed that it is a timeout and all other arguments are left as default:
218
+ `@my_element.prod(10)`
219
+
220
+ ###Parent elements
221
+ Most of the generated methods contain optional functionality to search the screen for your element. This is useful in cases where your element may not be visible on the screen. By default, Calabash scrolls down the first scrollable view in the hierarchy to look for your element, which isn't always the required behaviour. In these cases, it is necessary to specify the parent element that you want to scroll through to find your element.
222
+
223
+ For example the 'prod' method will scroll through the screen to find your element and then tap it. To make Calabash scroll through a specific scrollable view you can pass a Calabash query string locator for that scroll view element as an argument.
224
+
225
+ `@my_element.prod(parent: "* id:'my_list_container'")`
226
+
227
+ However, it is not good practice to use hardcoded strings any more than necessary. To assist with this, a 'locator' attritute is provided to return the Calabash query string for an element. This means that the parent element that you want to scroll through can be defined in the same way as all of your other elements.
228
+
229
+ e.g.
230
+ ```
231
+ require 'CalabashPageObjects'
232
+ class PageObjectClass
233
+
234
+ def initialize
235
+ @my_element = IElement.new("* id:'search_button'")
236
+ @my_parent_element = IElement.new("* id:'my_list_container'")
237
+ end
238
+
239
+ def tap_my_element
240
+ @my_element.prod(parent: @my_parent_element.locator)
241
+ end
242
+ ...
243
+ ```
244
+ Note: passing in an element for 'parent' rather than its locator will not work at present.
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'geminabox'
3
+
4
+ task :build do
5
+ system 'gem build CalabashPageObjects.gemspec'
6
+ end
7
+
8
+ task upload_to_internal_server: :build do
9
+ system "gem inabox pkg/CalabashPageObjects-#{CalabashPageObjects::VERSION}.gem -g http://gems.ict.je-labs.com:8808"
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'calabash-android'
2
+ require 'calabash-cucumber'
3
+ require 'CalabashPageObjects/version'
4
+ require 'CalabashPageObjects/element_base'
5
+ require 'CalabashPageObjects/aelement'
6
+ require 'CalabashPageObjects/ielement'
7
+ # Calabash Page Objects module.
8
+ module CalabashPageObjects
9
+ end
@@ -0,0 +1,11 @@
1
+ # The android specific implementation of ElementBase.
2
+ class AElement < ElementBase
3
+ include Calabash::Android::WaitHelpers
4
+ include Calabash::Android::Operations
5
+ include Calabash::Android::TextHelpers
6
+
7
+ def initialize(*args)
8
+ @wait_error = Calabash::Android::WaitHelpers::WaitError
9
+ super(*args)
10
+ end
11
+ end
@@ -0,0 +1,141 @@
1
+ require_relative 'element_base_option_parser'
2
+ require_relative 'element_finder'
3
+ # The main class for functionality for defined elements.
4
+ class ElementBase
5
+ include ElementBaseOptionParser
6
+ include ElementFinder
7
+
8
+ attr_reader :locator
9
+
10
+ CPO_LOGGING ||= false
11
+
12
+ # Constructor for ElementBase.
13
+ # Takes an argument for the Calabash Query that locates the object.
14
+ def initialize(locator)
15
+ @locator = locator
16
+ end
17
+
18
+ # Queries the current screen using the elements locator.
19
+ def screen_query
20
+ query("#{@locator}")
21
+ end
22
+
23
+ # Waits for an element to be visible on the current screen.
24
+ # Can take an argument for timeout. Default is 10 seconds.
25
+ def when_visible(options = {})
26
+ opts = options_parser(options, timeout: 10)
27
+ puts "Waiting for element with locator #{@locator} to appear..." if CPO_LOGGING
28
+ wait_for_element_exists(@locator, timeout: opts[:timeout], screenshot_on_error: false)
29
+ end
30
+
31
+ # Waits for an element to not be visible on the current screen.
32
+ # Can take an argument for timeout. Default is 10 seconds.
33
+ def when_not_visible(options = {})
34
+ opts = options_parser(options, timeout: 10)
35
+ puts "Waiting for element with locator #{@locator} to not be present..." if CPO_LOGGING
36
+ wait_for_element_does_not_exist(@locator, timeout: opts[:timeout], screenshot_on_error: false)
37
+ end
38
+
39
+ # Checks to see if the element is present. Can optionally scroll down to try and find the element.
40
+ # Can take an argument for timeout. Default is 0.5 as 0 can cause calabash to hang.
41
+ # Can take an argument for parent. Default is nil
42
+ # Can take an argument for webview. Default is false
43
+ # Can take an argument for scroll. Default is false
44
+ def present?(options = {})
45
+ opts = options_parser(options, timeout: 0.5, parent: nil, webview: false, scroll: false)
46
+ if opts[:scroll]
47
+ find(opts[:timeout], opts[:parent], opts[:webview])
48
+ else
49
+ puts "Checking for the presence of an element with locator #{@locator} after #{opts[:timeout]} seconds..." if CPO_LOGGING
50
+ begin
51
+ wait_for_element_exists(@locator, timeout: opts[:timeout], screenshot_on_error: false)
52
+ true
53
+ rescue
54
+ false
55
+ end
56
+ end
57
+ end
58
+
59
+ # Taps the element.
60
+ # Can take an argument for timeout. Default is 1 second
61
+ # Can take an argument for parent. Default is nil.
62
+ # Can take an argument for webview. Default is false.
63
+ def prod(options = {})
64
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
65
+ find(opts[:timeout], opts[:parent], opts[:webview])
66
+ sleep 0.1
67
+ puts "Touching an element with locator #{@locator}." if CPO_LOGGING
68
+ touch(@locator)
69
+ end
70
+
71
+ # Clears the text in an element and then enters the text that is passed into the method.
72
+ # Always takes an argument for 'value'.
73
+ # Can take an argument for timeout. Default is 1 second.
74
+ # Can take an argument for parent. Default is nil.
75
+ # Can take an argument for webview. Default is false.
76
+ def input(value, options = {})
77
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
78
+ find(opts[:timeout], opts[:parent], opts[:webview])
79
+ puts "Clearing text from element with locator #{@locator}..." if CPO_LOGGING
80
+ clear_text_in(@locator)
81
+ puts "Entering text in element with locator #{@locator}..." if CPO_LOGGING
82
+ enter_text(@locator, value)
83
+ end
84
+
85
+ # Set a checkbox element to 'checked' state.
86
+ # Can take an argument for timeout. Default is 1 second.
87
+ # Can take an argument for parent. Default is nil.
88
+ # Can take an argument for webview. Default is false.
89
+ def check(options = {})
90
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
91
+
92
+ find(opts[:timeout], opts[:parent], opts[:webview])
93
+ puts "Setting checkbox with locator #{@locator} to checked..." if CPO_LOGGING
94
+ query("#{@locator}", setChecked: true)
95
+ end
96
+
97
+ # Set a checkbox element to 'unchecked' state.
98
+ # Can take an argument for timeout. Default is 1 second.
99
+ # Can take an argument for parent. Default is nil.
100
+ # Can take an argument for webview. Default is false.
101
+ def uncheck(options = {})
102
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
103
+
104
+ find(opts[:timeout], opts[:parent], opts[:webview])
105
+ puts "Setting checkbox with locator #{@locator} to unchecked..." if CPO_LOGGING
106
+ query("#{@locator}", setChecked: false)
107
+ end
108
+
109
+ # Find the checked status of a checkbox element.
110
+ # Can take an argument for timeout. Default is 1 second.
111
+ # Can take an argument for parent. Default is nil.
112
+ # Can take an argument for webview. Default is false.
113
+ def checked?(options = {})
114
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
115
+
116
+ find(opts[:timeout], opts[:parent], opts[:webview])
117
+ puts "Checking status of checkbox element with locator #{@locator}." if CPO_LOGGING
118
+ query("#{@locator}", :isChecked)
119
+ end
120
+
121
+ # Retrieve the text attribute of an element.
122
+ # Can take an argument for timeout. Default is 1 second.
123
+ # Can take an argument for parent. Default is nil.
124
+ # Can take an argument for webview. Default is false.
125
+ def text(options = {})
126
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
127
+
128
+ find(opts[:timeout], opts[:parent], opts[:webview])
129
+ puts "Retrieving text from element with locator #{@locator}..." if CPO_LOGGING
130
+ query("#{@locator}", :text)[0]
131
+ end
132
+
133
+ # Search the whole screen for an element, scrolling down if it doesn't find it after the timeout.
134
+ # Can take an argument for timeout. Default is 1 second.
135
+ # Can take an argument for parent. Default is nil.
136
+ # Can take an argument for webview. Default is false.
137
+ def look_for(options = {})
138
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
139
+ fail @wait_error, "Timeout waiting for element with locator #{@locator}" unless find(opts[:timeout], opts[:parent], opts[:webview])
140
+ end
141
+ end
@@ -0,0 +1,15 @@
1
+ # A class that handles merging of default options.
2
+ module ElementBaseOptionParser
3
+ # Merges provided options with defaults.
4
+ def options_parser(input_options, defaults = {})
5
+ if input_options.is_a?(Integer) || input_options.is_a?(Float)
6
+ timeout_only_output_options = {}
7
+ timeout_only_output_options[:timeout] = input_options
8
+ timeout_only_output_options
9
+ else
10
+ defaults.merge(input_options)
11
+ end
12
+ end
13
+
14
+ private :options_parser
15
+ end
@@ -0,0 +1,49 @@
1
+ # Provides a method that searches the screen for an element.
2
+ module ElementFinder
3
+ CPO_LOGGING ||= false
4
+
5
+ # Searches the screen for an element if it isn't visible after an initial delay.
6
+ def find(initial_delay, parent, webview)
7
+ puts "Looking for element with locator #{@locator} and an initial delay of #{initial_delay} seconds." if CPO_LOGGING
8
+ return true if present?(initial_delay)
9
+
10
+ puts 'Element has not been found within initial_delay.' if CPO_LOGGING
11
+ element_present = false
12
+ current_screen_state = query_screen(webview)
13
+ prev_screen_state = []
14
+
15
+ while !element_present && current_screen_state != prev_screen_state
16
+ puts 'Element not found. Scrolling...' if CPO_LOGGING
17
+ prev_screen_state = current_screen_state
18
+ scroll_down_the_screen(parent, webview)
19
+ current_screen_state = query_screen(webview)
20
+ element_present = present?(0.4)
21
+ end
22
+
23
+ element_present
24
+ end
25
+
26
+ def query_screen(webview)
27
+ webview ? current_screen_state = query("webview css:'*'") : current_screen_state = query('*')
28
+ current_screen_state
29
+ end
30
+
31
+ def scroll_down_the_screen(parent, webview)
32
+ if !parent.nil?
33
+ puts "Scrolling down parent element - #{parent.locator}." if CPO_LOGGING
34
+ scroll(parent.locator, :down)
35
+ elsif webview
36
+ puts "Scrolling down the default webview." if CPO_LOGGING
37
+ scroll('webview', :down)
38
+ else
39
+ begin
40
+ puts 'Scrolling down the default element.' if CPO_LOGGING
41
+ scroll_down
42
+ rescue
43
+ puts 'View is not currently scrollable.'
44
+ end
45
+ end
46
+ end
47
+
48
+ private :find, :query_screen, :scroll_down_the_screen
49
+ end
@@ -0,0 +1,30 @@
1
+ # The ios specific implementation of ElementBase.
2
+ class IElement < ElementBase
3
+ include Calabash::Cucumber::Core
4
+ include Calabash::Cucumber::WaitHelpers
5
+ include Calabash::Cucumber::KeyboardHelpers
6
+
7
+ def initialize(*args)
8
+ @wait_error = Calabash::Cucumber::WaitHelpers::WaitError
9
+ super(*args)
10
+ end
11
+
12
+ # Need to override the method in the Element class as this one has a different name in the iOS libs.
13
+ # Waits for an element to not be present.
14
+ # Can take an argument for timeout. Default is 10 seconds.
15
+ def when_not_visible(options = {})
16
+ opts = options_parser(options, timeout: 10)
17
+ puts "Waiting for element with locator #{@locator} to not be present..." if CPO_LOGGING
18
+ wait_for_element_does_not_exists(@locator, timeout: opts[:timeout], screenshot_on_error: false)
19
+ end
20
+
21
+ # The ios libs have a different name for the method to clear the test from a field.
22
+ def input(value, options = {})
23
+ opts = options_parser(options, timeout: 1, parent: nil, webview: false)
24
+ find(opts[:timeout], opts[:parent], opts[:webview])
25
+ puts "Clearing text from element with locator #{@locator}..." if CPO_LOGGING
26
+ clear_text(@locator)
27
+ puts "Entering text in element with locator #{@locator}..." if CPO_LOGGING
28
+ enter_text(@locator, value)
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ # Version information.
2
+ module CalabashPageObjects
3
+ VERSION = '0.5.2'
4
+ end
@@ -0,0 +1,70 @@
1
+ require 'calabash-page-objects'
2
+ # Page object for tests.
3
+ class AndroidPageObjectClass
4
+ # rubocop:disable CyclomaticComplexity
5
+ # rubocop:disable PerceivedComplexity
6
+ # rubocop:disable AbcSize
7
+ def initialize
8
+ @my_element = AElement.new("* text:'ggg'")
9
+ end
10
+
11
+ def try_all_methods
12
+ begin
13
+ @my_element.screen_query
14
+ @my_element.touch('asdf')
15
+
16
+ rescue RuntimeError => e
17
+ raise unless e.message == 'No connected devices'
18
+ end
19
+ begin
20
+ @my_element.when_visible
21
+ rescue RuntimeError => e
22
+ raise unless e.message == 'No connected devices'
23
+ end
24
+ begin
25
+ @my_element.when_not_visible
26
+ rescue RuntimeError => e
27
+ raise unless e.message == 'No connected devices'
28
+ end
29
+ begin
30
+ @my_element.present?
31
+ rescue RuntimeError => e
32
+ raise unless e.message == 'No connected devices'
33
+ end
34
+ begin
35
+ @my_element.prod
36
+ rescue RuntimeError => e
37
+ raise unless e.message == 'No connected devices'
38
+ end
39
+ begin
40
+ @my_element.input('test_string')
41
+ rescue RuntimeError => e
42
+ raise unless e.message == 'No connected devices'
43
+ end
44
+ begin
45
+ @my_element.check
46
+ rescue RuntimeError => e
47
+ raise unless e.message == 'No connected devices'
48
+ end
49
+ begin
50
+ @my_element.uncheck
51
+ rescue RuntimeError => e
52
+ raise unless e.message == 'No connected devices'
53
+ end
54
+ begin
55
+ @my_element.checked?
56
+ rescue RuntimeError => e
57
+ raise unless e.message == 'No connected devices'
58
+ end
59
+ begin
60
+ @my_element.text
61
+ rescue RuntimeError => e
62
+ raise unless e.message == 'No connected devices'
63
+ end
64
+ begin
65
+ @my_element.look_for
66
+ rescue RuntimeError => e
67
+ raise unless e.message == 'No connected devices'
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,68 @@
1
+ require 'calabash-page-objects'
2
+ # Page object for tests.
3
+ class IosPageObjectClass
4
+ # rubocop:disable CyclomaticComplexity
5
+ # rubocop:disable PerceivedComplexity
6
+ # rubocop:disable AbcSize
7
+ def initialize
8
+ @my_element = IElement.new("* text:'ggg'")
9
+ end
10
+
11
+ def try_all_methods
12
+ begin
13
+ @my_element.screen_query
14
+ rescue Errno::ECONNREFUSED => e
15
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
16
+ end
17
+ begin
18
+ @my_element.when_visible
19
+ rescue RuntimeError => e
20
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265) (Errno::ECONNREFUSED)'
21
+ end
22
+ begin
23
+ @my_element.when_not_visible
24
+ rescue RuntimeError => e
25
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265) (Errno::ECONNREFUSED)'
26
+ end
27
+ begin
28
+ @my_element.present?
29
+ rescue Errno::ECONNREFUSED => e
30
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
31
+ end
32
+ begin
33
+ @my_element.prod
34
+ rescue Errno::ECONNREFUSED => e
35
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
36
+ end
37
+ begin
38
+ @my_element.input('test_string')
39
+ rescue Errno::ECONNREFUSED => e
40
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
41
+ end
42
+ begin
43
+ @my_element.check
44
+ rescue Errno::ECONNREFUSED => e
45
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
46
+ end
47
+ begin
48
+ @my_element.uncheck
49
+ rescue Errno::ECONNREFUSED => e
50
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
51
+ end
52
+ begin
53
+ @my_element.checked?
54
+ rescue Errno::ECONNREFUSED => e
55
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
56
+ end
57
+ begin
58
+ @my_element.text
59
+ rescue Errno::ECONNREFUSED => e
60
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
61
+ end
62
+ begin
63
+ @my_element.look_for
64
+ rescue Errno::ECONNREFUSED => e
65
+ raise unless e.message == 'Connection refused - connect(2) (http://localhost:37265)'
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ require 'rspec'
2
+ require 'rspec/expectations'
3
+ require_relative 'android_page_object'
4
+ require_relative 'ios_page_object'
5
+ include RSpec
6
+ extend RSpec::Matchers
7
+
8
+ RSpec.describe calabash-page-objects do
9
+ it 'android has inherited methods' do
10
+ android_page_object = AndroidPageObjectClass.new
11
+ android_page_object.try_all_methods
12
+ end
13
+
14
+ it 'ios has inherited methods' do
15
+ ios_page_object = IosPageObjectClass.new
16
+ ios_page_object.try_all_methods
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calabash-page-objects
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - Alan Nichols and Andrew Barnett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: calabash-android
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.14
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.14
41
+ - !ruby/object:Gem::Dependency
42
+ name: calabash-cucumber
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: geminabox
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-expectations
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Page Object frameworks for calabash on iOS and Android
98
+ email:
99
+ - alan.nichols@outlook.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rubocop.yml"
106
+ - CONTRIBUTING.md
107
+ - CalabashPageObjects.gemspec
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - LICENSE.MD
111
+ - README.md
112
+ - Rakefile
113
+ - lib/CalabashPageObjects.rb
114
+ - lib/CalabashPageObjects/aelement.rb
115
+ - lib/CalabashPageObjects/element_base.rb
116
+ - lib/CalabashPageObjects/element_base_option_parser.rb
117
+ - lib/CalabashPageObjects/element_finder.rb
118
+ - lib/CalabashPageObjects/ielement.rb
119
+ - lib/CalabashPageObjects/version.rb
120
+ - specs/android_page_object.rb
121
+ - specs/ios_page_object.rb
122
+ - specs/test_spec.rb
123
+ homepage: ''
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.4.6
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Page Object framework for calabash
147
+ test_files: []