|
| 1 | +#### Documentation |
| 2 | + |
| 3 | +- find_elements returns an empty array [] when no elements are found. |
| 4 | + |
| 5 | +##### [app_lib on rubydoc.info](http://www.rubydoc.info/github/appium/ruby_lib/master/toplevel) |
| 6 | + |
| 7 | +- [iOS UI Automation](http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html) Example use `@driver.execute_script "UIATarget.localTarget().frontMostApp().mainWindow().rect()" |
| 8 | +` |
| 9 | +- [Android UIAutomator](http://developer.android.com/tools/help/uiautomator/index.html) |
| 10 | +- [UiSelector.java](https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator/library/src/com/android/uiautomator/core/UiSelector.java) |
| 11 | +- [Ruby selenium-webdriver](http://selenium.googlecode.com/svn/trunk/docs/api/rb/index.html) |
| 12 | +- [Appium](https://github.com/appium/appium/blob/master/README.md) |
| 13 | +- [Appium extension](https://github.com/appium/appium/wiki/Automating-mobile-gestures) |
| 14 | +- [mechanic names of elements](https://github.com/jaykz52/mechanic/blob/8c490e1d225f384847e47ffdafb47cc2248bb96c/src/mechanic-core.js#L28) |
| 15 | +- [All methods supported by Appium](https://github.com/appium/appium/wiki/JSON-Wire-Protocol:-Supported-Methods) |
| 16 | +- [Appium's mobile gesture docs](https://github.com/appium/appium/wiki/Automating-mobile-gestures) |
| 17 | +- |
| 18 | +Example use of Appium's mobile gesture. |
| 19 | + |
| 20 | +> @driver.execute_script 'mobile: tap', :x => 0, :y => 500 |
| 21 | +
|
| 22 | +`console.rb` uses some code from [simple_test.rb]( |
| 23 | +https://github.com/appium/appium/blob/82995f47408530c80c3376f4e07a1f649d96ba22/sample-code/examples/ruby/simple_test.rb) and is released under the [same license](https://github.com/appium/appium/blob/c58eeb66f2d6fa3b9a89d188a2e657cca7cb300f/LICENSE) as Appium. The [Accessibility Inspector](https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/iPhoneAccessibility/Testing_Accessibility/Testing_Accessibility.html) is helpful for discovering button names and textfield values. |
| 24 | + |
| 25 | +-- |
| 26 | + |
| 27 | +Tag Name | UIA |
| 28 | + --:|:-- |
| 29 | +button | UIAButton |
| 30 | +textfield | UIATextField |
| 31 | +secure | UIASecureTextField |
| 32 | +text | UIAStaticText |
| 33 | + |
| 34 | + |
| 35 | +-- |
| 36 | + |
| 37 | +#### generic |
| 38 | + |
| 39 | +- `source` Prints a JSON view of the current page. |
| 40 | +- `page` Prints the content descriptions and text values on the current page. |
| 41 | +- `(Element) name(name)` Returns the first element matching name. Android name is the content description. |
| 42 | +iOS uses accessibility label with a fallback to text. |
| 43 | +- `(Array<Element>) names(name)` Returns all elements matching name. |
| 44 | + |
| 45 | +-- |
| 46 | + |
| 47 | +#### alert |
| 48 | +0. `(void) alert_accept` Accept the alert. |
| 49 | +0. `(String) alert_accept_text` Get the text of the alert's accept button. |
| 50 | +0. `(void) alert_click(value)` iOS only Tap the alert button identified by value. |
| 51 | +0. `(void) alert_dismiss` Dismiss the alert. |
| 52 | +0. `(String) alert_dismiss_text` Get the text of the alert's dismiss button. |
| 53 | +0. `(String) alert_text` Get the alert message text. |
| 54 | + |
| 55 | +#### button |
| 56 | +0. `(Button) button(index)` Find a button by index. |
| 57 | +0. `(Button) button(text, number = 0)` Find a button by text and optionally number. |
| 58 | +0. `(Button) button_include(text)` Get the first button that includes text. |
| 59 | +0. `(Array<String>, Array<Buttons>) buttons(text = nil)` Get an array of button texts or button elements if text is provided. |
| 60 | +0. `(Array<Button>) buttons_include(text)` Get all buttons that include text. |
| 61 | +0. `(Button) first_button` Get the first button element. |
| 62 | +0. `(Button) last_button` Get the last button element. |
| 63 | + |
| 64 | +#### textfield |
| 65 | +0. `(Textfield) textfield(index)` Find a textfield by index. |
| 66 | +0. `(Array<Textfield>) e_textfields` Get an array of textfield elements. |
| 67 | +0. `(Textfield) first_textfield` Get the first textfield element. |
| 68 | +0. `(Textfield) last_textfield` Get the last textfield element. |
| 69 | +0. `(Textfield) textfield(text)` Get the first textfield that matches text. |
| 70 | +0. `(Textfield) textfield_include(text)` Get the first textfield that includes text. |
| 71 | +0. `(Array<String>) textfields` Get an array of textfield texts. |
| 72 | + |
| 73 | +#### text |
| 74 | +0. `(Text) text(index)` Find a text by index. |
| 75 | +0. `(Array<Text>) e_texts` Get an array of text elements. |
| 76 | +0. `(Text) first_text` Get the first text element. |
| 77 | +0. `(Text) last_text` Get the last text element. |
| 78 | +0. `(Text) text(text)` Get the first element that matches text. |
| 79 | +0. `(Text) text_include(text)` Get the first textfield that includes text. |
| 80 | +0. `(Array<String>) texts` Get an array of text texts. |
| 81 | + |
| 82 | +#### window |
| 83 | +0. `(Object) window_size` Get the window's size. |
| 84 | + |
| 85 | +-- |
| 86 | + |
| 87 | +```ruby |
| 88 | +e.name # button, text |
| 89 | +e.value # secure, textfield |
| 90 | +e.type |
| 91 | +e.tag_name # calls .type (patch.rb) |
| 92 | +e.text |
| 93 | +e.size |
| 94 | +e.location |
| 95 | +e.rel_location |
| 96 | +e.click |
| 97 | +e.send_keys 'keys to send' |
| 98 | +e.set_value 'value to set' # ruby_console specific |
| 99 | + |
| 100 | +# alert example without helper methods |
| 101 | +alert = $driver.switch_to.alert |
| 102 | +alert.text |
| 103 | +alert.accept |
| 104 | +alert.dismiss |
| 105 | + |
| 106 | +# Secure textfield example. |
| 107 | +# |
| 108 | +# Find using default value |
| 109 | +s = secure 'Password' |
| 110 | +# Enter password |
| 111 | +s.send_keys 'hello' |
| 112 | +# Check value |
| 113 | +s.value == password('hello'.length) |
| 114 | +``` |
| 115 | + |
| 116 | +[routing.js](https://github.com/appium/appium/blob/master/app/routing.js#L69) lists not yet implemented end points. |
| 117 | + |
| 118 | +-- |
| 119 | + |
| 120 | +#### Driver |
| 121 | + |
| 122 | +`start_driver` will restart the driver. |
| 123 | + |
| 124 | +`x` will quit the driver and exit Pry. |
| 125 | + |
| 126 | +`execute_script` calls `$driver.execute_script` |
| 127 | + |
| 128 | +`find_element` calls `$driver.find_element` |
| 129 | + |
| 130 | +`find_elements` calls `$driver.find_elements` |
| 131 | + |
| 132 | +`mobile :swipe, endX: 100, endY: 100, duration: 0.01` calls `$driver.execute_script 'mobile: swipe', endX: 100, endY: 100, duration: 0.01` |
| 133 | + |
| 134 | +`no_wait` will set implicit wait to 0. `$driver.manage.timeouts.implicit_wait = 0` |
| 135 | + |
| 136 | +`set_wait` will set implicit wait to default 30 seconds. `$driver.manage.timeouts.implicit_wait = 30` |
| 137 | + |
| 138 | +`set_wait(timeout_seconds)` will set implicit wait to desired timeout. `$driver.manage.timeouts.implicit_wait = timeout` |
| 139 | + |
| 140 | +.click to tap an element. |
| 141 | +.send_keys to type on an element. |
| 142 | + |
| 143 | +#### Raw UIAutomation |
| 144 | + |
| 145 | +`execute_script "au.lookup('button')[0].tap()"` is the same as |
| 146 | +`execute_script 'UIATarget.localTarget().frontMostApp().buttons()[0].tap()'` |
| 147 | + |
| 148 | +See [app.js](https://github.com/appium/appium/blob/master/app/uiauto/appium/app.js#L3) for more au methods. |
| 149 | +Note that raw UIAutomation commands are not offically supported. |
| 150 | + |
| 151 | +Advanced au. |
| 152 | + |
| 153 | +In this example we lookup two tags, combine the results, wrap with $, and then return the elements. |
| 154 | + |
| 155 | +```ruby |
| 156 | +s = %( |
| 157 | +var t = au.lookup('textfield'); |
| 158 | +var s = au.lookup('secure'); |
| 159 | +var r = $(t.concat(s)); |
| 160 | +au._returnElems(r); |
| 161 | +) |
| 162 | + |
| 163 | +execute_script s |
| 164 | +``` |
| 165 | + |
| 166 | +#### XPath |
| 167 | + |
| 168 | +See [#194](https://github.com/appium/appium/pull/194/files) for details. |
| 169 | + |
| 170 | +```ruby |
| 171 | +find_element :xpath, 'button' |
| 172 | +find_elements :xpath, 'button' |
| 173 | + |
| 174 | +find_element :xpath, 'button[@name="Sign In"]' |
| 175 | +find_elements :xpath, 'button[@name="Sign In"]' |
| 176 | + |
| 177 | +find_element :xpath, 'button[contains(@name, "Sign In")]' |
| 178 | +find_elements :xpath, 'button[contains(@name, "Sign")]' |
| 179 | + |
| 180 | +find_element :xpath, 'textfield[@value="Email"]' |
| 181 | +find_element :xpath, 'textfield[contains(@value, "Email")]' |
| 182 | + |
| 183 | +find_element :xpath, 'text[contains(@name, "Reset")]' |
| 184 | +find_elements :xpath, 'text[contains(@name, "agree")]' |
| 185 | +``` |
| 186 | + |
| 187 | +#### Cucumber Sauce Integration |
| 188 | + |
| 189 | +Reset after each test and when done report the result to Sauce after quiting the driver. |
| 190 | + |
| 191 | +```ruby |
| 192 | +require 'rest_client' # https://github.com/archiloque/rest-client |
| 193 | +require 'json' # for .to_json |
| 194 | + |
| 195 | +$passed = true |
| 196 | + |
| 197 | +After do |scenario| |
| 198 | + # Reset scenario unless the feature was tagged @keep |
| 199 | + $driver.execute_script 'mobile: reset' unless scenario.feature.source_tag_names.include? '@keep' |
| 200 | + |
| 201 | + if $passed |
| 202 | + $passed = false if scenario.failed? |
| 203 | + end |
| 204 | +end |
| 205 | + |
| 206 | +at_exit do |
| 207 | + ID = $driver.send(:bridge).session_id |
| 208 | + $driver.quit |
| 209 | + |
| 210 | + if !SAUCE_USERNAME.nil? && !SAUCE_ACCESS_KEY.nil? |
| 211 | + URL = "https://#{SAUCE_USERNAME}:#{SAUCE_ACCESS_KEY}@saucelabs.com/rest/v1/#{SAUCE_USERNAME}/jobs/#{ID}" |
| 212 | + |
| 213 | + # Keep trying until passed is set correctly. Give up after 30 seconds. |
| 214 | + wait do |
| 215 | + response = RestClient.put URL, { 'passed' => $passed }.to_json, :content_type => :json, :accept => :json |
| 216 | + response = JSON.parse(response) |
| 217 | + |
| 218 | + # Check that the server responded with the right value. |
| 219 | + response['passed'] == $passed |
| 220 | + end |
| 221 | + end |
| 222 | +end |
| 223 | +``` |
0 commit comments