percy-appium-app 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +55 -0
- data/.github/dependabot.yml +14 -0
- data/.github/release-drafter.yml +28 -0
- data/.github/workflows/Semgrep.yml +48 -0
- data/.github/workflows/changelog.yml +11 -0
- data/.github/workflows/release.yml +22 -0
- data/.github/workflows/stale.yml +30 -0
- data/.github/workflows/test.yml +40 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/Makefile +3 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/percy/common/common.rb +19 -0
- data/percy/configs/devices.json +232 -0
- data/percy/environment.rb +25 -0
- data/percy/exceptions/exceptions.rb +13 -0
- data/percy/lib/app_percy.rb +55 -0
- data/percy/lib/cache.rb +53 -0
- data/percy/lib/cli_wrapper.rb +132 -0
- data/percy/lib/ignore_region.rb +8 -0
- data/percy/lib/percy_automate.rb +59 -0
- data/percy/lib/percy_options.rb +37 -0
- data/percy/lib/region.rb +22 -0
- data/percy/lib/tile.rb +28 -0
- data/percy/metadata/android_metadata.rb +79 -0
- data/percy/metadata/driver_metadata.rb +40 -0
- data/percy/metadata/ios_metadata.rb +83 -0
- data/percy/metadata/metadata.rb +108 -0
- data/percy/metadata/metadata_resolver.rb +21 -0
- data/percy/providers/app_automate.rb +159 -0
- data/percy/providers/generic_provider.rb +205 -0
- data/percy/providers/provider_resolver.rb +17 -0
- data/percy/screenshot.rb +23 -0
- data/percy/version.rb +5 -0
- data/percy-appium-app.gemspec +37 -0
- data/specs/android_metadata.rb +79 -0
- data/specs/app_automate.rb +124 -0
- data/specs/app_percy.rb +175 -0
- data/specs/cache.rb +56 -0
- data/specs/cli_wrapper.rb +135 -0
- data/specs/driver_metadata.rb +71 -0
- data/specs/generic_providers.rb +370 -0
- data/specs/ignore_regions.rb +51 -0
- data/specs/ios_metadata.rb +88 -0
- data/specs/metadata.rb +105 -0
- data/specs/metadata_resolver.rb +41 -0
- data/specs/mocks/mock_methods.rb +147 -0
- data/specs/percy_options.rb +114 -0
- data/specs/screenshot.rb +342 -0
- data/specs/tile.rb +33 -0
- metadata +194 -0
@@ -0,0 +1,370 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/MethodLength
|
4
|
+
# rubocop:disable Metrics/AbcSize
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require 'securerandom'
|
8
|
+
require 'appium_lib'
|
9
|
+
require_relative '../percy/providers/generic_provider'
|
10
|
+
require_relative '../percy/metadata/android_metadata'
|
11
|
+
require_relative '../percy/lib/region'
|
12
|
+
require_relative 'mocks/mock_methods'
|
13
|
+
|
14
|
+
# Test suite for the GenericProvider class
|
15
|
+
class TestGenericProvider < Minitest::Test
|
16
|
+
include Appium
|
17
|
+
COMPARISON_RESPONSE = { 'comparison' => { 'id' => 123, 'url' => 'https://percy-build-url' } }.freeze
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@existing_dir = 'existing-dir'
|
21
|
+
Dir.mkdir(@existing_dir)
|
22
|
+
|
23
|
+
@mock_webdriver = Minitest::Mock.new
|
24
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
25
|
+
@mock_webdriver.expect(:orientation, 'PorTrait')
|
26
|
+
@mock_webdriver.expect(:get_system_bars, {
|
27
|
+
'statusBar' => { 'height' => 10, 'width' => 20 },
|
28
|
+
'navigationBar' => { 'height' => 10, 'width' => 20 }
|
29
|
+
})
|
30
|
+
|
31
|
+
png_bytes = 'some random bytes'
|
32
|
+
@mock_webdriver.expect(:screenshot_as, png_bytes, [:png])
|
33
|
+
|
34
|
+
@android_metadata = AndroidMetadata.new(@mock_webdriver)
|
35
|
+
@generic_provider = GenericProvider.new(@mock_webdriver, @android_metadata)
|
36
|
+
end
|
37
|
+
|
38
|
+
def teardown
|
39
|
+
FileUtils.remove_entry_secure(@existing_dir)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_get_dir_without_env_variable
|
43
|
+
ENV.delete('PERCY_TMP_DIR')
|
44
|
+
result = @generic_provider._get_dir
|
45
|
+
assert File.directory?(result), 'Directory should exist'
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_get_dir_with_env_variable
|
49
|
+
ENV['PERCY_TMP_DIR'] = '/tmp/percy-apps'
|
50
|
+
result = @generic_provider._get_dir
|
51
|
+
assert_equal '/tmp/percy-apps', result
|
52
|
+
assert File.directory?(result), 'Directory should exist'
|
53
|
+
Dir.rmdir(result)
|
54
|
+
ENV.delete('PERCY_TMP_DIR')
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_get_path
|
58
|
+
count = 1000
|
59
|
+
png_paths = Array.new(count) { @generic_provider._get_path(@existing_dir) }
|
60
|
+
assert_equal png_paths.uniq.length, count
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_write_screenshot
|
64
|
+
png_bytes = 'some random bytes'
|
65
|
+
filepath = @generic_provider._write_screenshot(png_bytes, @existing_dir)
|
66
|
+
assert(File.exist?(filepath))
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_get_debug_url
|
70
|
+
assert_equal @generic_provider.get_debug_url, ''
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_get_tag
|
74
|
+
10.times do
|
75
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
76
|
+
end
|
77
|
+
tag = @generic_provider._get_tag
|
78
|
+
assert_includes tag, 'name'
|
79
|
+
assert_equal tag['name'], @android_metadata.device_name
|
80
|
+
assert_includes tag, 'os_name'
|
81
|
+
assert_equal tag['os_name'], @android_metadata.os_name
|
82
|
+
assert_includes tag, 'os_version'
|
83
|
+
assert_equal tag['os_version'], @android_metadata.os_version
|
84
|
+
assert_includes tag, 'width'
|
85
|
+
assert_equal tag['width'], @android_metadata.device_screen_size['width']
|
86
|
+
assert_includes tag, 'height'
|
87
|
+
assert_equal tag['height'], @android_metadata.device_screen_size['height']
|
88
|
+
assert_includes tag, 'orientation'
|
89
|
+
assert_equal tag['orientation'], @android_metadata.get_orientation.downcase
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_get_tag_kwargs
|
93
|
+
10.times do
|
94
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
95
|
+
end
|
96
|
+
device_name = 'some-device-name'
|
97
|
+
tag = @generic_provider._get_tag(device_name: device_name)
|
98
|
+
assert_includes tag, 'name'
|
99
|
+
assert_equal tag['name'], device_name
|
100
|
+
|
101
|
+
orientation = 'Some-Orientation'
|
102
|
+
tag = @generic_provider._get_tag(orientation: orientation)
|
103
|
+
assert_includes tag, 'orientation'
|
104
|
+
assert_equal tag['orientation'], orientation.downcase
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_get_tiles
|
108
|
+
session_id = 'session_id_123'
|
109
|
+
10.times do
|
110
|
+
@mock_webdriver.expect(:session_id, session_id)
|
111
|
+
end
|
112
|
+
10.times do
|
113
|
+
@mock_webdriver.expect(:get_system_bars, {
|
114
|
+
'statusBar' => { 'height' => 10, 'width' => 20 },
|
115
|
+
'navigationBar' => { 'height' => 10, 'width' => 20 }
|
116
|
+
})
|
117
|
+
end
|
118
|
+
tile = @generic_provider._get_tiles[0]
|
119
|
+
dict_tile = tile.to_h
|
120
|
+
assert_includes dict_tile, 'filepath'
|
121
|
+
assert_instance_of String, dict_tile['filepath']
|
122
|
+
assert(File.exist?(dict_tile['filepath']))
|
123
|
+
assert_includes dict_tile, 'status_bar_height'
|
124
|
+
assert_equal dict_tile['status_bar_height'], @android_metadata.status_bar_height
|
125
|
+
assert_includes dict_tile, 'nav_bar_height'
|
126
|
+
assert_equal dict_tile['nav_bar_height'], @android_metadata.navigation_bar_height
|
127
|
+
assert_includes dict_tile, 'header_height'
|
128
|
+
assert_equal dict_tile['header_height'], 0
|
129
|
+
assert_includes dict_tile, 'footer_height'
|
130
|
+
assert_equal dict_tile['footer_height'], 0
|
131
|
+
assert_includes dict_tile, 'fullscreen'
|
132
|
+
assert_equal dict_tile['fullscreen'], false
|
133
|
+
File.delete(tile.filepath)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_get_tiles_kwargs
|
137
|
+
status_bar_height = 135
|
138
|
+
nav_bar_height = 246
|
139
|
+
tile = @generic_provider._get_tiles(
|
140
|
+
status_bar_height: status_bar_height,
|
141
|
+
nav_bar_height: nav_bar_height,
|
142
|
+
full_screen: true
|
143
|
+
)[0]
|
144
|
+
dict_tile = tile.to_h
|
145
|
+
assert_includes dict_tile, 'status_bar_height'
|
146
|
+
assert_equal dict_tile['status_bar_height'], status_bar_height
|
147
|
+
assert_includes dict_tile, 'nav_bar_height'
|
148
|
+
assert_equal dict_tile['nav_bar_height'], nav_bar_height
|
149
|
+
assert_includes dict_tile, 'fullscreen'
|
150
|
+
assert_equal dict_tile['fullscreen'], true
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_post_screenshots
|
154
|
+
session_id = 'session_id_123'
|
155
|
+
|
156
|
+
mock = Minitest::Mock.new
|
157
|
+
mock.expect(:post_screenshots, COMPARISON_RESPONSE, [String, Hash, Hash, String, Array, Array])
|
158
|
+
mock.expect(:session_id, session_id)
|
159
|
+
10.times do
|
160
|
+
mock.expect(:get_system_bars, {
|
161
|
+
'statusBar' => { 'height' => 10, 'width' => 20 },
|
162
|
+
'navigationBar' => { 'height' => 10, 'width' => 20 }
|
163
|
+
})
|
164
|
+
end
|
165
|
+
6.times do
|
166
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
167
|
+
end
|
168
|
+
|
169
|
+
Metadata.class_eval do
|
170
|
+
define_method(:session_id) do
|
171
|
+
mock.session_id
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
AndroidMetadata.class_eval do
|
176
|
+
6.times do
|
177
|
+
define_method(:get_system_bars) do
|
178
|
+
mock.get_system_bars
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
tag = @generic_provider._get_tag
|
184
|
+
tiles = @generic_provider._get_tiles
|
185
|
+
|
186
|
+
@generic_provider.stub(:_post_screenshots, COMPARISON_RESPONSE) do
|
187
|
+
response = @generic_provider._post_screenshots(
|
188
|
+
'screenshot 1', tag, tiles, '', [], []
|
189
|
+
)
|
190
|
+
assert_equal response, COMPARISON_RESPONSE
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_supports
|
195
|
+
assert GenericProvider.supports('some-dummy-url')
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_non_app_automate
|
199
|
+
session_id = 'session_id_123'
|
200
|
+
mock = Minitest::Mock.new
|
201
|
+
4.times do
|
202
|
+
mock.expect(:session_id, session_id)
|
203
|
+
end
|
204
|
+
|
205
|
+
Metadata.class_eval do
|
206
|
+
4.times do
|
207
|
+
define_method(:session_id) do
|
208
|
+
mock.session_id
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
7.times do
|
214
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
215
|
+
end
|
216
|
+
6.times do
|
217
|
+
@mock_webdriver.expect(:get_system_bars, {
|
218
|
+
'statusBar' => { 'height' => 10, 'width' => 20 },
|
219
|
+
'navigationBar' => { 'height' => 10, 'width' => 20 }
|
220
|
+
})
|
221
|
+
end
|
222
|
+
|
223
|
+
@generic_provider.stub(:_post_screenshots, COMPARISON_RESPONSE) do
|
224
|
+
response = @generic_provider.screenshot('screenshot 1')
|
225
|
+
assert_equal response, COMPARISON_RESPONSE
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_get_device_name
|
230
|
+
device_name = @generic_provider.get_device_name
|
231
|
+
assert_equal device_name, ''
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_get_region_object
|
235
|
+
mock_element = Minitest::Mock.new
|
236
|
+
mock_element.expect(:location, { 'x' => 10, 'y' => 20 })
|
237
|
+
mock_element.expect(:size, { 'width' => 100, 'height' => 200 })
|
238
|
+
|
239
|
+
result = @generic_provider.get_region_object('my-selector', mock_element)
|
240
|
+
expected_result = {
|
241
|
+
'selector' => 'my-selector',
|
242
|
+
'coOrdinates' => { 'top' => 20, 'bottom' => 220, 'left' => 10, 'right' => 110 }
|
243
|
+
}
|
244
|
+
|
245
|
+
assert_equal result, expected_result
|
246
|
+
mock_element.verify
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_get_regions_by_xpath
|
250
|
+
mock_element = Minitest::Mock.new
|
251
|
+
mock_element.expect(:location, { 'x' => 10, 'y' => 20 })
|
252
|
+
mock_element.expect(:size, { 'width' => 100, 'height' => 200 })
|
253
|
+
|
254
|
+
@mock_webdriver.expect(:find_element, mock_element,
|
255
|
+
[Appium::Core::Base::SearchContext::FINDERS[:xpath], '//path/to/element'])
|
256
|
+
|
257
|
+
elements_array = []
|
258
|
+
xpaths = ['//path/to/element']
|
259
|
+
@generic_provider.get_regions_by_xpath(elements_array, xpaths)
|
260
|
+
|
261
|
+
expected_elements_array = [{
|
262
|
+
'selector' => 'xpath: //path/to/element',
|
263
|
+
'coOrdinates' => { 'top' => 20, 'bottom' => 220, 'left' => 10, 'right' => 110 }
|
264
|
+
}]
|
265
|
+
|
266
|
+
assert_equal elements_array, expected_elements_array
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_get_regions_by_xpath_with_non_existing_element
|
270
|
+
@mock_webdriver.expect(:find_element, [Appium::Core::Base::SearchContext::FINDERS[:xpath], '//path/to/element']) do
|
271
|
+
raise Appium::Core::Error::NoSuchElementError, 'Test error'
|
272
|
+
end
|
273
|
+
elements_array = []
|
274
|
+
xpaths = ['//path/to/element']
|
275
|
+
@generic_provider.get_regions_by_xpath(elements_array, xpaths)
|
276
|
+
|
277
|
+
assert_empty elements_array
|
278
|
+
end
|
279
|
+
|
280
|
+
def test_get_regions_by_ids
|
281
|
+
mock_element = Minitest::Mock.new
|
282
|
+
mock_element.expect(:location, { 'x' => 10, 'y' => 20 })
|
283
|
+
mock_element.expect(:size, { 'width' => 100, 'height' => 200 })
|
284
|
+
|
285
|
+
@mock_webdriver.expect(:find_element, mock_element,
|
286
|
+
[Appium::Core::Base::SearchContext::FINDERS[:accessibility_id], 'some_id'])
|
287
|
+
|
288
|
+
elements_array = []
|
289
|
+
ids = ['some_id']
|
290
|
+
@generic_provider.get_regions_by_ids(elements_array, ids)
|
291
|
+
|
292
|
+
expected_elements_array = [{
|
293
|
+
'selector' => 'id: some_id',
|
294
|
+
'coOrdinates' => { 'top' => 20, 'bottom' => 220, 'left' => 10, 'right' => 110 }
|
295
|
+
}]
|
296
|
+
|
297
|
+
assert_equal elements_array, expected_elements_array
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_get_regions_by_ids_with_non_existing_element
|
301
|
+
mock_element = Minitest::Mock.new
|
302
|
+
mock_element.expect(:location, { 'x' => 10, 'y' => 20 })
|
303
|
+
mock_element.expect(:size, { 'width' => 100, 'height' => 200 })
|
304
|
+
|
305
|
+
@mock_webdriver.expect(:find_element, [Appium::Core::Base::SearchContext::FINDERS[:accessibility_id], 'id1']) do
|
306
|
+
raise Appium::Core::Error::NoSuchElementError, 'Test error'
|
307
|
+
end
|
308
|
+
|
309
|
+
elements_array = []
|
310
|
+
ids = ['id1']
|
311
|
+
@generic_provider.get_regions_by_ids(elements_array, ids)
|
312
|
+
|
313
|
+
assert_empty elements_array
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_get_regions_by_elements
|
317
|
+
mock_element = Minitest::Mock.new
|
318
|
+
mock_element.expect(:location, { 'x' => 10, 'y' => 20 })
|
319
|
+
mock_element.expect(:size, { 'width' => 100, 'height' => 200 })
|
320
|
+
mock_element.expect(:attribute, 'textView', ['class'])
|
321
|
+
|
322
|
+
elements_array = []
|
323
|
+
elements = [mock_element]
|
324
|
+
@generic_provider.get_regions_by_elements(elements_array, elements)
|
325
|
+
|
326
|
+
expected_elements_array = [{
|
327
|
+
'selector' => 'element: 0 textView',
|
328
|
+
'coOrdinates' => { 'top' => 20, 'bottom' => 220, 'left' => 10, 'right' => 110 }
|
329
|
+
}]
|
330
|
+
|
331
|
+
assert_equal elements_array, expected_elements_array
|
332
|
+
mock_element.verify
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_get_regions_by_elements_with_non_existing_element
|
336
|
+
element_mock = Minitest::Mock.new
|
337
|
+
element_mock.expect(:attribute, 'class') do
|
338
|
+
raise Appium::Core::Error::NoSuchElementError, 'Test error'
|
339
|
+
end
|
340
|
+
|
341
|
+
elements_array = []
|
342
|
+
elements = [element_mock]
|
343
|
+
|
344
|
+
@generic_provider.get_regions_by_elements(elements_array, elements)
|
345
|
+
|
346
|
+
assert_equal 0, elements_array.length
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_get_regions_by_location
|
350
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
351
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
352
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
353
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
354
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
355
|
+
@mock_webdriver.expect(:capabilities, get_android_capabilities)
|
356
|
+
valid_ignore_region = Region.new(100, 200, 200, 300)
|
357
|
+
invalid_ignore_region = Region.new(100, 2390, 200, 300)
|
358
|
+
|
359
|
+
elements_array = []
|
360
|
+
custom_locations = [valid_ignore_region, invalid_ignore_region]
|
361
|
+
@generic_provider.get_regions_by_location(elements_array, custom_locations)
|
362
|
+
|
363
|
+
expected_elements_array = [{
|
364
|
+
selector: 'custom ignore region: 0',
|
365
|
+
coOrdinates: { top: 100, bottom: 200, left: 200, right: 300 }
|
366
|
+
}]
|
367
|
+
|
368
|
+
assert_equal elements_array, expected_elements_array
|
369
|
+
end
|
370
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/MethodLength
|
4
|
+
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require_relative '../percy/lib/ignore_region'
|
7
|
+
|
8
|
+
# Test suite for the IgnoreRegions class
|
9
|
+
class TestIgnoreRegion < Minitest::Test
|
10
|
+
def test_ignore_region_valid_input
|
11
|
+
top = 10
|
12
|
+
bottom = 20
|
13
|
+
left = 30
|
14
|
+
right = 40
|
15
|
+
ignore_region = IgnoreRegion.new(top, bottom, left, right)
|
16
|
+
|
17
|
+
assert_equal ignore_region.top, top
|
18
|
+
assert_equal ignore_region.bottom, bottom
|
19
|
+
assert_equal ignore_region.left, left
|
20
|
+
assert_equal ignore_region.right, right
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_ignore_region_negative_input
|
24
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(-10, 20, 30, 40) }
|
25
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(10, 20, -30, 40) }
|
26
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(10, 20, 30, -40) }
|
27
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(-10, -20, -30, -40) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_ignore_region_invalid_input
|
31
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(20, 10, 30, 40) } # bottom < top
|
32
|
+
assert_raises(ArgumentError) { IgnoreRegion.new(10, 20, 40, 30) } # right < left
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_ignore_region_is_valid
|
36
|
+
ignore_region = IgnoreRegion.new(10, 20, 30, 40)
|
37
|
+
screen_height = 100
|
38
|
+
screen_width = 200
|
39
|
+
assert_equal true, ignore_region.valid?(screen_height, screen_width)
|
40
|
+
|
41
|
+
ignore_region = IgnoreRegion.new(10, 200, 30, 400)
|
42
|
+
height = 100
|
43
|
+
width = 200
|
44
|
+
assert_equal false, ignore_region.valid?(height, width)
|
45
|
+
|
46
|
+
ignore_region = IgnoreRegion.new(10, 20, 30, 40)
|
47
|
+
screen_height = 5
|
48
|
+
screen_width = 10
|
49
|
+
assert_equal false, ignore_region.valid?(screen_height, screen_width)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/mock'
|
5
|
+
require_relative 'mocks/mock_methods'
|
6
|
+
require_relative '../percy/metadata/ios_metadata'
|
7
|
+
|
8
|
+
# Test suite for the IOSMetadata class
|
9
|
+
class TestIOSMetadata < Minitest::Test
|
10
|
+
def setup
|
11
|
+
@mock_webdriver = Minitest::Mock.new
|
12
|
+
@bridge = Minitest::Mock.new
|
13
|
+
@http = Minitest::Mock.new
|
14
|
+
@server_url = Minitest::Mock.new
|
15
|
+
@ios_metadata = IOSMetadata.new(@mock_webdriver)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_ios_execute_script
|
19
|
+
command = 'some dummy command'
|
20
|
+
output = 'some output'
|
21
|
+
@mock_webdriver.expect(:execute_script, output, [command])
|
22
|
+
|
23
|
+
response = @ios_metadata.execute_script(command)
|
24
|
+
assert_equal(output, response)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_remote_url
|
28
|
+
@mock_webdriver.expect(:instance_variable_get, @bridge, [:@bridge])
|
29
|
+
@http.expect(:instance_variable_get, @server_url, [:@server_url])
|
30
|
+
@bridge.expect(:instance_variable_get, @http, [:@http])
|
31
|
+
@server_url.expect(:to_s, 'some-remote-url')
|
32
|
+
|
33
|
+
assert_equal('some-remote-url', @ios_metadata.remote_url)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_get_window_size
|
37
|
+
height = 100
|
38
|
+
width = 100
|
39
|
+
window_size = { 'height' => height, 'width' => width }
|
40
|
+
@mock_webdriver.expect(:get_window_size, window_size)
|
41
|
+
session_id = 'session_id_123'
|
42
|
+
@mock_webdriver.expect(:session_id, session_id)
|
43
|
+
@mock_webdriver.expect(:session_id, session_id)
|
44
|
+
|
45
|
+
assert_equal({}, @ios_metadata._window_size)
|
46
|
+
fetched_window_size = @ios_metadata.get_window_size
|
47
|
+
assert_equal(window_size, fetched_window_size)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_device_screen_size
|
51
|
+
session_id = 'session_id_123'
|
52
|
+
5.times do
|
53
|
+
@mock_webdriver.expect(:session_id, session_id)
|
54
|
+
end
|
55
|
+
@mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 6' })
|
56
|
+
@mock_webdriver.expect(:get_window_size, { 'height' => 100, 'width' => 100 })
|
57
|
+
device_screen_size = @ios_metadata.device_screen_size
|
58
|
+
assert_equal({ 'height' => 200, 'width' => 200 }, device_screen_size)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_status_bar
|
62
|
+
@mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 6' })
|
63
|
+
session_id = 'session_id_123'
|
64
|
+
@mock_webdriver.expect(:session_id, session_id)
|
65
|
+
@mock_webdriver.expect(:session_id, session_id)
|
66
|
+
|
67
|
+
status_bar = @ios_metadata.status_bar
|
68
|
+
assert_equal({ 'height' => 40 }, status_bar)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_scale_factor_present_in_devices_json
|
72
|
+
@mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 6' })
|
73
|
+
assert_equal(2, @ios_metadata.scale_factor)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_scale_factor_not_present_in_devices_json
|
77
|
+
window_size = { 'height' => 100, 'width' => 100 }
|
78
|
+
session_id = 'session_id_123'
|
79
|
+
4.times do
|
80
|
+
@mock_webdriver.expect(:session_id, session_id)
|
81
|
+
end
|
82
|
+
@mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 14' })
|
83
|
+
@mock_webdriver.expect(:get_window_size, window_size)
|
84
|
+
@mock_webdriver.expect(:execute_script, { 'height' => 100, 'width' => 200 }, ['mobile: viewportRect'])
|
85
|
+
|
86
|
+
assert_equal(2, @ios_metadata.scale_factor)
|
87
|
+
end
|
88
|
+
end
|
data/specs/metadata.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Metrics/MethodLength
|
4
|
+
# rubocop:disable Metrics/AbcSize
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require_relative '../percy/metadata/metadata'
|
8
|
+
|
9
|
+
# Test suite for the Metadata class
|
10
|
+
class TestMetadata < Minitest::Test
|
11
|
+
def setup
|
12
|
+
@mock_webdriver = Minitest::Mock.new
|
13
|
+
@metadata = Metadata.new(@mock_webdriver)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_metadata_properties
|
17
|
+
assert_raises(NotImplementedError) { @metadata._device_name }
|
18
|
+
assert_raises(NotImplementedError) { @metadata.device_screen_size }
|
19
|
+
assert_raises(NotImplementedError) { @metadata.navigation_bar }
|
20
|
+
assert_raises(NotImplementedError) { @metadata.navigation_bar_height }
|
21
|
+
assert_raises(NotImplementedError) { @metadata.status_bar }
|
22
|
+
assert_raises(NotImplementedError) { @metadata.status_bar_height }
|
23
|
+
assert_raises(NotImplementedError) { @metadata.viewport }
|
24
|
+
|
25
|
+
assert_equal({}, @metadata.device_info)
|
26
|
+
|
27
|
+
device_config = @metadata.get_device_info('iPhone 6')
|
28
|
+
refute_equal({}, @metadata.device_info)
|
29
|
+
assert_equal(device_config, @metadata.get_device_info('iPhone 6'))
|
30
|
+
|
31
|
+
ENV['PERCY_LOGLEVEL'] = 'debug'
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_get_device_info_device_not_present
|
35
|
+
device_name = 'Some Phone 123'
|
36
|
+
assert_output(/#{Regexp.escape(device_name.downcase)} does not exist in config\./) do
|
37
|
+
@metadata.get_device_info(device_name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_metadata_get_orientation
|
42
|
+
orientation = 'PRTRT'
|
43
|
+
@mock_webdriver.expect(:get_orientation, orientation, [{ "orientation": orientation }])
|
44
|
+
assert(orientation, @metadata.get_orientation(orientation: orientation))
|
45
|
+
|
46
|
+
orientation = 'prtrt'
|
47
|
+
@mock_webdriver.expect(:get_orientation, orientation, [{ "orientation": orientation }])
|
48
|
+
assert_equal(orientation.upcase, @metadata.get_orientation(orientation: orientation))
|
49
|
+
|
50
|
+
orientation = 'OriENTation'
|
51
|
+
@mock_webdriver.expect(:get_orientation, orientation, [{ "orientation": 'AUTO' }])
|
52
|
+
|
53
|
+
@mock_webdriver.expect(:orientation, orientation)
|
54
|
+
assert(orientation.upcase, @metadata.get_orientation(orientation: 'AUTO'))
|
55
|
+
|
56
|
+
@mock_webdriver.expect(:orientation, orientation)
|
57
|
+
assert(orientation.upcase, @metadata.get_orientation(orientation: 'auto'))
|
58
|
+
|
59
|
+
@mock_webdriver.expect(:orientation, orientation)
|
60
|
+
assert(orientation.upcase, @metadata.get_orientation(orientation: 'Auto'))
|
61
|
+
|
62
|
+
orientation = 'OriEntaTion'
|
63
|
+
@mock_webdriver.expect(:capabilities, { 'orientation' => orientation })
|
64
|
+
assert_equal(orientation.upcase, @metadata.get_orientation)
|
65
|
+
|
66
|
+
@mock_webdriver.expect(:capabilities, {})
|
67
|
+
assert_equal('PORTRAIT', @metadata.get_orientation)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_metadata_session_id
|
71
|
+
session_id = 'Some Totally random session ID'
|
72
|
+
@mock_webdriver.expect(:session_id, session_id)
|
73
|
+
assert_equal(session_id, @metadata.session_id)
|
74
|
+
@mock_webdriver.verify
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_metadata_os_version
|
78
|
+
capabilities = { 'os_version' => '10' }
|
79
|
+
@mock_webdriver.expect(:capabilities, capabilities)
|
80
|
+
@mock_webdriver.expect(:capabilities, capabilities)
|
81
|
+
@mock_webdriver.expect(:capabilities, capabilities)
|
82
|
+
os_ver = @metadata.os_version
|
83
|
+
assert_equal('10', os_ver)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_metadata_value_from_devices_info_for_android
|
87
|
+
android_device = 'google pixel 7'
|
88
|
+
android_device_info = { '13' => { 'status_bar' => '118', 'nav_bar' => '63' } }
|
89
|
+
|
90
|
+
@metadata.instance_variable_set(:@device_name, nil)
|
91
|
+
assert_equal(android_device_info['13']['status_bar'].to_i,
|
92
|
+
@metadata.value_from_devices_info('status_bar', android_device, '13'))
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_metadata_value_from_devices_info_for_ios
|
96
|
+
ios_device = 'iphone 12 pro max'
|
97
|
+
ios_device_info = { 'scale_factor' => '3', 'status_bar' => '47' }
|
98
|
+
|
99
|
+
@metadata.instance_variable_set(:@device_name, nil)
|
100
|
+
assert_equal(
|
101
|
+
ios_device_info['scale_factor'].to_i,
|
102
|
+
@metadata.value_from_devices_info('scale_factor', ios_device)
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/mock'
|
5
|
+
require_relative '../percy/metadata/android_metadata'
|
6
|
+
require_relative '../percy/metadata/ios_metadata'
|
7
|
+
require_relative '../percy/metadata/metadata_resolver'
|
8
|
+
|
9
|
+
# Test suite for the MetadataResolver class
|
10
|
+
class MetadataResolverTestCase < Minitest::Test
|
11
|
+
def setup
|
12
|
+
@mock_webdriver = Minitest::Mock.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_android_resolved
|
16
|
+
@mock_webdriver.expect(:capabilities, { 'platformName' => 'Android' })
|
17
|
+
@mock_webdriver.expect(:capabilities, { 'platformName' => 'Android' })
|
18
|
+
resolved_metadata = MetadataResolver.resolve(@mock_webdriver)
|
19
|
+
|
20
|
+
assert_instance_of(AndroidMetadata, resolved_metadata)
|
21
|
+
@mock_webdriver.verify
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_ios_resolved
|
25
|
+
@mock_webdriver.expect(:capabilities, { 'platformName' => 'iOS' })
|
26
|
+
resolved_metadata = MetadataResolver.resolve(@mock_webdriver)
|
27
|
+
|
28
|
+
assert_instance_of(IOSMetadata, resolved_metadata)
|
29
|
+
@mock_webdriver.verify
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_unknown_platform_exception
|
33
|
+
@mock_webdriver.expect(:capabilities, { 'platformName' => 'Something Random' })
|
34
|
+
|
35
|
+
assert_raises(Exception) do
|
36
|
+
MetadataResolver.resolve(@mock_webdriver)
|
37
|
+
end
|
38
|
+
|
39
|
+
@mock_webdriver.verify
|
40
|
+
end
|
41
|
+
end
|