Skip to content

Commit b0cd235

Browse files
authored
feat: append screenshot in element module as well (#297)
* feat: append screenshot in element module as well * switch tests * add screenshot * update * add screenshot
1 parent c01f4f1 commit b0cd235

File tree

7 files changed

+80
-4
lines changed

7 files changed

+80
-4
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ Read `release_notes.md` for commit level details.
55
## [Unreleased]
66

77
### Enhancements
8+
- Add `Element#screenshot`, `Element#screenshot_as` and `Element#save_screenshot` in Element module
9+
- `Element#screenshot_as` and `Element#save_screenshot` are same as `Driver#element_screenshot_as` and `Driver#save_element_screenshot`
10+
- `Element#screenshot` is same as `Element#screenshot_as(:base64)`
811

912
### Bug fixes
1013

lib/appium_lib_core/common/base/driver.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Driver < ::Selenium::WebDriver::Driver
2727
include ::Selenium::WebDriver::DriverExtensions::HasWebStorage
2828

2929
include ::Appium::Core::Base::SearchContext
30-
include ::Appium::Core::Base::TakeScreenshot
30+
include ::Appium::Core::Base::TakesScreenshot
3131

3232
# Private API.
3333
# Do not use this for general use. Used by flutter driver to get bridge for creating a new element

lib/appium_lib_core/common/base/screenshot.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
module Appium
1616
module Core
1717
class Base
18-
module TakeScreenshot
18+
module TakesScreenshot
1919
#
2020
# Save a PNG screenshot to the given path
2121
#

lib/appium_lib_core/patch.rb

+53
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class Selenium::WebDriver::Element
2121
# To extend Appium related SearchContext into ::Selenium::WebDriver::Element
2222
include ::Appium::Core::Base::SearchContext
2323

24+
# TODO: Probably can remove own TakesScreenshot since Selenium 4
25+
include ::Appium::Core::Base::TakesScreenshot
26+
2427
# Returns the value of attributes like below. Read each platform to know more details.
2528
#
2629
# uiautomator2: https://github.com/appium/appium-uiautomator2-server/blob/203cc7e57ce477f3cff5d95b135d1b3450a6033a/app/src/main/java/io/appium/uiautomator2/utils/Attribute.java#L19
@@ -99,6 +102,56 @@ def location_rel(driver)
99102
w = driver.window_size
100103
::Selenium::WebDriver::Point.new "#{center_x} / #{w.width.to_f}", "#{center_y} / #{w.height.to_f}"
101104
end
105+
106+
# Return an element screenshot as base64
107+
#
108+
# @return String Base 64 encoded string
109+
#
110+
# @example
111+
#
112+
# element.screenshot #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
113+
#
114+
def screenshot
115+
bridge.take_element_screenshot(self)
116+
end
117+
118+
# Return an element screenshot in the given format
119+
#
120+
# @param [:base64, :png] format
121+
# @return String screenshot
122+
#
123+
# @example
124+
#
125+
# element.screenshot_as :base64 #=> "iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX"
126+
#
127+
def screenshot_as(format)
128+
case format
129+
when :base64
130+
bridge.take_element_screenshot(self)
131+
when :png
132+
bridge.take_element_screenshot(self).unpack('m')[0]
133+
else
134+
raise Core::Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
135+
end
136+
end
137+
138+
# Save an element screenshot to the given path
139+
#
140+
# @param [String] png_path A path to save the screenshot
141+
# @return [File] Path to the element screenshot.
142+
#
143+
# @example
144+
#
145+
# element.save_screenshot("fine_name.png")
146+
#
147+
def save_screenshot(png_path)
148+
extension = File.extname(png_path).downcase
149+
if extension != '.png'
150+
::Appium::Logger.warn 'name used for saved screenshot does not match file type. '\
151+
'It should end with .png extension'
152+
end
153+
File.open(png_path, 'wb') { |f| f << screenshot_as(:png) }
154+
end
102155
end
103156
end # module Core
104157
end # module Appium

test/functional/android/android/image_comparison_test.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def test_template_scale_ratio
176176
@driver.rotation = :portrait
177177

178178
el = @driver.find_element :accessibility_id, 'NFC'
179-
@driver.save_element_screenshot el, 'test/functional/data/test_android_nfc.png'
179+
el.save_screenshot 'test/functional/data/test_android_nfc.png'
180180

181181
@driver.update_settings({ defaultImageTemplateScale: 4 })
182182

test/functional/ios/ios/image_comparison_test.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def test_image_elements
139139
@@driver.update_settings({ fixImageTemplateScale: true })
140140

141141
el = @@driver.find_element :accessibility_id, 'Buttons'
142-
@@driver.save_element_screenshot el, 'test/functional/data/test_ios_button.png'
142+
el.save_screenshot 'test/functional/data/test_ios_button.png'
143143

144144
image_elements = @@driver.find_elements_by_image AppiumLibCoreTest.path_of('test/functional/data/test_ios_button.png')
145145
image_element = image_elements[0]

test/unit/common/element_test.rb

+20
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,25 @@ def test_replace
7575

7676
assert_requested(:post, "#{SESSION}/appium/element/id/replace_value", times: 1)
7777
end
78+
79+
def test_element_screenshot_as
80+
stub_request(:get, "#{SESSION}/element/id/screenshot")
81+
.to_return(headers: HEADER, status: 200,
82+
body: { value: 'iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX' }.to_json)
83+
84+
e = ::Selenium::WebDriver::Element.new(@driver.send(:bridge), 'id')
85+
assert_equal 'iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX', e.screenshot_as(:base64)
86+
assert_requested(:get, "#{SESSION}/element/id/screenshot", times: 1)
87+
end
88+
89+
def test_element_screenshot
90+
stub_request(:get, "#{SESSION}/element/id/screenshot")
91+
.to_return(headers: HEADER, status: 200,
92+
body: { value: 'iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX' }.to_json)
93+
94+
e = ::Selenium::WebDriver::Element.new(@driver.send(:bridge), 'id')
95+
assert_equal 'iVBORw0KGgoAAAANSUhEUgAABDgAAAB+CAIAAABOPDa6AAAAAX', e.screenshot
96+
assert_requested(:get, "#{SESSION}/element/id/screenshot", times: 1)
97+
end
7898
end
7999
end

0 commit comments

Comments
 (0)