Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- `0, 1, 2, 3, 4` or `NOT_INSTALLED, NOT_RUNNING, RUNNING_IN_BACKGROUND_SUSPENDED, RUNNING_IN_BACKGROUND, RUNNING_IN_FOREGROUND`
- After: Symbol.
- `:not_installed, :not_running, :running_in_background_suspended, :running_in_background, :running_in_foreground`
- add `battery_info` to get battery information
- add `is_keyboard_shown` for iOS ( see also https://github.com/appium/appium-xcuitest-driver/pull/664/files )

### Bug fixes
Expand Down
1 change: 1 addition & 0 deletions lib/appium_lib_core/android/uiautomator2/bridge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Bridge
def self.for(target)
target.extend Appium::Android::Device
Core::Android::SearchContext.extend
target.extend Appium::Core::Android::Uiautomator2::Device
end
end
end
Expand Down
50 changes: 50 additions & 0 deletions lib/appium_lib_core/android/uiautomator2/device.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module Appium
module Core
module Android
module Uiautomator2
module Device
extend Forwardable

# @since 1.6.0
# @!method battery_info
#
# Get battery information.
#
# @return [Hash] Return battery level and battery state.
# Battery level in range [0.0, 1.0], where 1.0 means 100% charge. -1 is returned
# if the actual value cannot be retrieved from the system.
# Battery state. The following symbols are possible
# `:unknown, :charging, :discharging, :not_charging, :full`
#
# @example
#
# @driver.battery_info #=> { state: :charging, level: 0.7 }
#

####
## class << self
####

class << self
def extended(_mod)
::Appium::Core::Device.add_endpoint_method(:battery_info) do
def battery_info
response = execute_script 'mobile: batteryInfo', {}

state = case response['state']
when 2, 3, 4, 5
::Appium::Core::Device::BatteryStatus::ANDROID[response['state']]
else
Appium::Logger.warn("The state is unknown or undefined: #{response['state']}")
::Appium::Core::Device::BatteryStatus::ANDROID[1] # :unknown
end
{ state: state, level: response['level'] }
end
end
end
end # class << self
end # module Device
end # module Uiautomator2
end # module Android
end # module Core
end # module Appium
2 changes: 2 additions & 0 deletions lib/appium_lib_core/android_uiautomator2.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# loaded in common/driver.rb
require_relative 'android/search_context'
require_relative 'android/device'

require_relative 'android/uiautomator2/bridge'
require_relative 'android/uiautomator2/device'
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
module Appium
# Perform a series of gestures, one after another. Gestures are chained
# together and only performed when `perform()` is called. Default is conducted by global driver.
#
# Each method returns the object itself, so calls can be chained.
#
# Consider to use W3C spec touch action like the followings.
# https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/android/webdriver/w3c_actions_test.rb
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/ios/webdriver/w3c_actions_test.rb
#
# @example
#
# @driver = Appium::Core.for(self, opts).start_driver
# action = TouchAction.new(@driver).press(x: 45, y: 100).wait(5).release
# action.perform
# action = TouchAction.new(@driver).swipe(....)
# action.perform
#
module Core
# Perform a series of gestures, one after another. Gestures are chained
# together and only performed when `perform()` is called. Default is conducted by global driver.
#
# Each method returns the object itself, so calls can be chained.
#
# Consider to use W3C spec touch action like the followings.
# https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/W3CActionBuilder.html
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/android/webdriver/w3c_actions_test.rb
# https://github.com/appium/ruby_lib_core/blob/master/test/functional/ios/webdriver/w3c_actions_test.rb
#
# @example
#
# @driver = Appium::Core.for(self, opts).start_driver
# action = TouchAction.new(@driver).press(x: 45, y: 100).wait(5).release
# action.perform
# action = TouchAction.new(@driver).swipe(....)
# action.perform
#
class TouchAction
ACTIONS = %i(move_to long_press double_tap two_finger_tap press release tap wait perform).freeze
COMPLEX_ACTIONS = %i(swipe).freeze
Expand Down
4 changes: 2 additions & 2 deletions lib/appium_lib_core/device.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require_relative 'device/touch_actions'
require_relative 'device/multi_touch'
require_relative 'common/touch_action/touch_actions'
require_relative 'common/touch_action/multi_touch'
require_relative 'device/screen_record'
require_relative 'device/app_state'
require_relative 'device/clipboard_content_type'
Expand Down
23 changes: 23 additions & 0 deletions lib/appium_lib_core/device/battery_status.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Appium
module Core
module Device
module BatteryStatus
ANDROID = [
:undefined, # 0, dummy
:unknown, # 1
:charging, # 2
:discharging, # 3
:not_charging, # 4
:full # 5
].freeze

IOS = [
:unknown, # 0
:unplugged, # 1
:charging, # 2
:full # 3
].freeze
end
end
end
end
37 changes: 35 additions & 2 deletions lib/appium_lib_core/ios/xcuitest/device.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ module Device
# @driver.get_performance_record
# @driver.get_performance_record(save_file_path: './performance', profile_name: 'Activity Monitor')

# @since 1.6.0
# @!method battery_info
#
# Get battery information.
#
# @return [Hash] Return battery level and battery state from the target real device. (Simulator has no battery.)
# https://developer.apple.com/documentation/uikit/uidevice/ 's `batteryLevel` and `batteryState`.
# Battery level in range [0.0, 1.0], where 1.0 means 100% charge. -1 is returned
# if the actual value cannot be retrieved from the system.
# Battery state. The following symbols are possible
# `:unplugged, :charging, :full`
#
# @example
#
# @driver.battery_info #=> { state: :full, level: 0.7 }
#

# rubocop:enable Metrics/LineLength

####
Expand All @@ -117,8 +134,6 @@ module Device

class << self
def extended(_mod)
::Appium::Core::Device.extend_webdriver_with_forwardable

# Override
::Appium::Core::Device.add_endpoint_method(:hide_keyboard) do
def hide_keyboard(close_key = nil, strategy = nil)
Expand All @@ -143,10 +158,28 @@ def background_app(duration = 0)

add_performance
add_screen_recording
add_battery_info
end

private

def add_battery_info
Appium::Core::Device.add_endpoint_method(:battery_info) do
def battery_info
response = execute_script 'mobile: batteryInfo', {}

state = case response['state']
when 1, 2, 3
::Appium::Core::Device::BatteryStatus::IOS[response['state']]
else
Appium::Logger.warn("The state is unknown or undefined: #{response['state']}")
::Appium::Core::Device::BatteryStatus::IOS[0] # :unknown
end
{ state: state, level: response['level'] }
end
end
end

def add_performance
Appium::Core::Device.add_endpoint_method(:start_performance_record) do
def start_performance_record(timeout: 300_000, profile_name: 'Activity Monitor', pid: nil)
Expand Down
2 changes: 2 additions & 0 deletions lib/appium_lib_core/ios_xcuitest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
require_relative 'ios/xcuitest/search_context'
require_relative 'ios/xcuitest/device'
require_relative 'ios/xcuitest/bridge'

require_relative 'device/battery_status'
7 changes: 7 additions & 0 deletions test/functional/android/android/device_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,13 @@ def test_image_comparison_get_images_result
File.delete 'get_images_result_visual.png'
end

def test_battery_info
result = @@driver.battery_info

assert !result[:state].nil?
assert !result[:level].nil?
end

private

def scroll_to(text)
Expand Down
13 changes: 10 additions & 3 deletions test/functional/ios/ios/device_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ def test_close_and_launch_app
end

def test_lock_unlock
@@driver.lock 5
assert @@driver.device_locked?
@@driver.lock
@@core.wait { assert @@driver.device_locked? }

@@driver.unlock
assert !@@driver.device_locked?
@@core.wait { assert !@@driver.device_locked? }
end

def test_background_reset
Expand Down Expand Up @@ -301,6 +301,13 @@ def test_image_comparison_get_images_result

File.delete 'get_images_result_visual.png'
end

def test_battery_info
result = @@driver.battery_info

assert !result[:state].nil?
assert !result[:level].nil?
end
end
end
end
12 changes: 12 additions & 0 deletions test/unit/android/device_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,18 @@ def test_image_comparison_get_images_similarity

assert_requested(:post, "#{SESSION}/appium/compare_images", times: 1)
end

def test_get_battery_info
stub_request(:post, "#{SESSION}/execute")
.with(body: { script: 'mobile: batteryInfo', args: [{}] }.to_json)
.to_return(headers: HEADER, status: 200, body: { value: { state: 2, level: 1.0 } }.to_json)

info = @driver.battery_info

assert_requested(:post, "#{SESSION}/execute", times: 1)
assert_equal :charging, info[:state]
assert_equal 1.0, info[:level]
end
end
end
end
12 changes: 12 additions & 0 deletions test/unit/android/device_w3c_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,18 @@ def test_image_comparison_get_images_similarity

assert_requested(:post, "#{SESSION}/appium/compare_images", times: 1)
end

def test_get_battery_info
stub_request(:post, "#{SESSION}/execute/sync")
.with(body: { script: 'mobile: batteryInfo', args: [{}] }.to_json)
.to_return(headers: HEADER, status: 200, body: { value: { state: 5, level: 0.5 } }.to_json)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the value has status, then Ruby client raise parse response error.
I guess the implementation is https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#responses 's one.

  test_get_battery_info                                          ERROR (0.02s)
Selenium::WebDriver::Error::NoCollectionError:         Selenium::WebDriver::Error::NoCollectionError: unknown error, status=2: nil
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/response.rb:32:in `initialize'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/http/common.rb:81:in `new'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/http/common.rb:81:in `create_response'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/http/default.rb:104:in `request'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/bridge.rb:164:in `execute'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/oss/bridge.rb:579:in `execute'
            /Users/kazuaki/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.11.0/lib/selenium/webdriver/remote/oss/bridge.rb:267:in `execute_script'
            /Users/kazuaki/GitHub/ruby_lib_core/lib/appium_lib_core/android/uiautomator2/device.rb:15:in `battery_info'
            /Users/kazuaki/GitHub/ruby_lib_core/test/unit/android/device_test.rb:763:in `test_get_battery_info'


info = @driver.battery_info

assert_requested(:post, "#{SESSION}/execute/sync", times: 1)
assert_equal :full, info[:state]
assert_equal 0.5, info[:level]
end
end
end
end
12 changes: 12 additions & 0 deletions test/unit/ios/device_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ def test_stop_recording_screen_custom

assert_requested(:post, "#{SESSION}/appium/stop_recording_screen", times: 1)
end

def test_get_battery_info
stub_request(:post, "#{SESSION}/execute")
.with(body: { script: 'mobile: batteryInfo', args: [{}] }.to_json)
.to_return(headers: HEADER, status: 200, body: { value: { state: 3, level: 1.0 } }.to_json)

info = @driver.battery_info

assert_requested(:post, "#{SESSION}/execute", times: 1)
assert_equal :full, info[:state]
assert_equal 1.0, info[:level]
end
end
end
end
12 changes: 12 additions & 0 deletions test/unit/ios/device_w3c_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ def test_stop_recording_screen_custom

assert_requested(:post, "#{SESSION}/appium/stop_recording_screen", times: 1)
end

def test_get_battery_info
stub_request(:post, "#{SESSION}/execute/sync")
.with(body: { script: 'mobile: batteryInfo', args: [{}] }.to_json)
.to_return(headers: HEADER, status: 200, body: { value: { state: 1, level: 0.5 } }.to_json)

info = @driver.battery_info

assert_requested(:post, "#{SESSION}/execute/sync", times: 1)
assert_equal :unplugged, info[:state]
assert_equal 0.5, info[:level]
end
end
end
end