percy-appium-app 0.0.3 → 0.0.5.pre.beta.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a9d215b1a1e9daf04d5672a65a909db34bf2f9118e7551a72a83ba742e3dcbf
4
- data.tar.gz: d5bd4454dbb19e0f649025ebb21692a847b1e6f14a4bf85f67c16749ff462349
3
+ metadata.gz: f293168326d6bddeb11b1b5bdc1bb7beb7ec9c72d0fdd71b4a4122ca508ca7d0
4
+ data.tar.gz: 7145c22d760541bb741a251e58024e0f1027efc8b16fe25c760cd62c05ae6b6f
5
5
  SHA512:
6
- metadata.gz: 10f4a8d07bdc08deb1068025032f05cedacd3959244a1fbd5465ce9ed2eac0a502ab629abeb3087849ad62d9edf874dc298b49a8e14c9c2e36b2b4da71d9f1f6
7
- data.tar.gz: ef3897862dacf57e5b64b8026a0272415b7ea47a09cdd80e83bc8bcc51d7be02dc4243b4b3e99f268a841934b0131112d37610abef8c5801b21e0e208eb17c8d
6
+ metadata.gz: bd51272ede73d35decf0b7f143aa6345a5631401923981b5bd1b270fc51172c1779c5004b870f87a255a38e2bac0be434d11454eae3ebb7bcfc11131c65c7d3a
7
+ data.tar.gz: 8415678acd851a743154daaafb0b944c7c1dbf256764182637c51c8d47ea396665ff7a4a92d7ca930308e9b35bcb5aaf275ad6813bece2aa8311e566a6531909
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile CHANGED
@@ -3,7 +3,7 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'appium_console'
6
- gem 'appium_lib'
6
+ gem 'appium_lib', '>= 11.2.0'
7
7
  gem 'dotenv'
8
8
  gem 'minitest'
9
9
  gem 'rubocop', require: false
data/README.md CHANGED
@@ -93,6 +93,7 @@ $ percy app:exec -- [ruby test command]
93
93
  - `top_scrollview_offset`: (**optional**) - [Alpha] Offset from top of scrollview; int
94
94
  - `bottom_scrollview_offset` (**optional**) - [Alpha] Offset from bottom of scrollview; int
95
95
  - `full_screen` (**optional**) - Indicate whether app is full screen; boolean [ needs @percy/cli 1.20.2+ ];
96
+ - `sync` (**optional**) - Waits for screenshot to be processed and gives the processed result of screenshot [needs @percy/cli v1.28.0-beta.0+]; boolean
96
97
  - `scrollable_xpath` (**optional**) - [Alpha] Scrollable element xpath for fullpage [ needs @percy/cli 1.20.2+ ]; string
97
98
  - `scrollable_id` (**optional**) - [Alpha] Scrollable element accessibility id for fullpage [ needs @percy/cli 1.20.2+ ]; string
98
99
  - `ignore_regions_xpaths` (**optional**) - Elements xpaths that user want to ignore in visual diff [ needs @percy/cli 1.23.0+ ]; list of string
@@ -139,6 +140,7 @@ percy_screenshot_flutter(driver, name, **kwargs)
139
140
  - `driver` (**required**) - A appium driver instance
140
141
  - `name` (**required**) - The screenshot name; must be unique to each screenshot
141
142
  - `options` (**optional**) - There are various options supported by percy_screenshot to server further functionality.
143
+ - `sync` - Boolean value by default it falls back to `false`, Gives the processed result around screenshot [From CLI v1.28.0-beta.0+].
142
144
  - `freeze_animated_image` - Boolean value by default it falls back to `false`, you can pass `true` and percy will freeze image based animations.
143
145
  - `freeze_image_by_selectors` -List of selectors. Images will be freezed which are passed using selectors. For this to work `freeze_animated_image` must be set to true.
144
146
  - `freeze_image_by_xpaths` - List of xpaths. Images will be freezed which are passed using xpaths. For this to work `freeze_animated_image` must be set to true.
@@ -49,7 +49,6 @@ module Percy
49
49
  end
50
50
 
51
51
  @provider.screenshot(name, **kwargs)
52
- nil
53
52
  end
54
53
 
55
54
  attr_reader :percy_options
data/percy/lib/cache.rb CHANGED
@@ -50,5 +50,10 @@ module Percy
50
50
 
51
51
  session_ids.each { |session_id| @@cache.delete(session_id) }
52
52
  end
53
+
54
+ # Added only for tests
55
+ def self.force_cleanup_cache
56
+ @@cache = {}
57
+ end
53
58
  end
54
59
  end
@@ -49,13 +49,14 @@ module Percy
49
49
  end
50
50
 
51
51
  def post_screenshots(name, tag, tiles, external_debug_url = nil, ignored_elements_data = nil,
52
- considered_elements_data = nil)
53
- body = request_body(name, tag, tiles, external_debug_url, ignored_elements_data, considered_elements_data)
52
+ considered_elements_data = nil, sync = nil)
53
+ body = request_body(name, tag, tiles, external_debug_url, ignored_elements_data, considered_elements_data, sync)
54
54
  body['client_info'] = Percy::Environment.get_client_info
55
55
  body['environment_info'] = Percy::Environment.get_env_info
56
56
 
57
57
  uri = URI("#{PERCY_CLI_API}/percy/comparison")
58
58
  http = Net::HTTP.new(uri.host, uri.port)
59
+ http.read_timeout = 600 # seconds
59
60
  request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
60
61
  request.body = body.to_json
61
62
 
@@ -104,7 +105,11 @@ module Percy
104
105
  body['environment_info'] = Percy::Environment.get_env_info
105
106
 
106
107
  uri = URI("#{PERCY_CLI_API}/percy/automateScreenshot")
107
- response = Net::HTTP.post(uri, body.to_json, 'Content-Type' => 'application/json')
108
+ http = Net::HTTP.new(uri.host, uri.port)
109
+ http.read_timeout = 600 # seconds
110
+ request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
111
+ request.body = body.to_json
112
+ response = http.request(request)
108
113
 
109
114
  # Handle errors
110
115
  raise CLIException, "Error: #{response.message}" unless response.is_a?(Net::HTTPSuccess)
@@ -119,7 +124,7 @@ module Percy
119
124
  data
120
125
  end
121
126
 
122
- def request_body(name, tag, tiles, external_debug_url, ignored_elements_data, considered_elements_data)
127
+ def request_body(name, tag, tiles, external_debug_url, ignored_elements_data, considered_elements_data, sync)
123
128
  tiles = tiles.map(&:to_h)
124
129
  {
125
130
  'name' => name,
@@ -127,7 +132,8 @@ module Percy
127
132
  'tiles' => tiles,
128
133
  'ignored_elements_data' => ignored_elements_data,
129
134
  'external_debug_url' => external_debug_url,
130
- 'considered_elements_data' => considered_elements_data
135
+ 'considered_elements_data' => considered_elements_data,
136
+ 'sync' => sync
131
137
  }
132
138
  end
133
139
  end
@@ -43,7 +43,7 @@ module Percy
43
43
  'consider_region_elements' => consider_region_elements
44
44
  }
45
45
 
46
- Percy::CLIWrapper.new.post_poa_screenshots(
46
+ response = Percy::CLIWrapper.new.post_poa_screenshots(
47
47
  name,
48
48
  metadata.session_id,
49
49
  metadata.command_executor_url,
@@ -51,11 +51,12 @@ module Percy
51
51
  metadata.session_capabilities,
52
52
  options.merge(additional_options)
53
53
  )
54
+
55
+ response['data']
54
56
  rescue StandardError => e
55
57
  log("Could not take Screenshot '#{name}'")
56
58
  log(e.message, on_debug: true)
57
59
  end
58
- nil
59
60
  end
60
61
  end
61
62
  end
@@ -45,7 +45,7 @@ module Percy
45
45
  def get_window_size
46
46
  @_window_size = Percy::Cache.get_cache(session_id, Percy::Cache::WINDOW_SIZE)
47
47
  unless @_window_size
48
- @_window_size = driver.get_window_size
48
+ @_window_size = driver.window_size
49
49
  Percy::Cache.set_cache(session_id, Percy::Cache::WINDOW_SIZE, @_window_size)
50
50
  end
51
51
  @_window_size
@@ -29,9 +29,10 @@ module Percy
29
29
  begin
30
30
  response = super(name, **kwargs)
31
31
  percy_screenshot_url = response.fetch('link', '')
32
- execute_percy_screenshot_end(name, percy_screenshot_url, 'success')
32
+ execute_percy_screenshot_end(name, percy_screenshot_url, 'success', kwargs.fetch('sync', nil))
33
+ response['data']
33
34
  rescue StandardError => e
34
- execute_percy_screenshot_end(name, percy_screenshot_url, 'failure', e.message)
35
+ execute_percy_screenshot_end(name, percy_screenshot_url, 'failure', kwargs.fetch('sync', nil), e.message)
35
36
  raise e
36
37
  end
37
38
  end
@@ -104,14 +105,15 @@ module Percy
104
105
  end
105
106
  end
106
107
 
107
- def execute_percy_screenshot_end(name, percy_screenshot_url, status, status_message = nil)
108
+ def execute_percy_screenshot_end(name, percy_screenshot_url, status, sync = nil, status_message = nil)
108
109
  request_body = {
109
110
  action: 'percyScreenshot',
110
111
  arguments: {
111
112
  state: 'end',
112
113
  percyScreenshotUrl: percy_screenshot_url,
113
114
  name: name,
114
- status: status
115
+ status: status,
116
+ sync: sync
115
117
  }
116
118
  }
117
119
  request_body[:arguments][:statusMessage] = status_message if status_message
@@ -158,4 +160,4 @@ module Percy
158
160
  end
159
161
  end
160
162
  end
161
- end
163
+ end
@@ -42,8 +42,9 @@ module Percy
42
42
  custom_locations: kwargs.fetch(:custom_consider_regions, [])
43
43
  )
44
44
  }
45
+ sync = kwargs.fetch(:sync, nil)
45
46
 
46
- _post_screenshots(name, tag, tiles, get_debug_url, ignore_regions, consider_regions)
47
+ _post_screenshots(name, tag, tiles, get_debug_url, ignore_regions, consider_regions, sync)
47
48
  end
48
49
 
49
50
  def _get_tag(**kwargs)
@@ -93,8 +94,8 @@ module Percy
93
94
  elements_array
94
95
  end
95
96
 
96
- def _post_screenshots(name, tag, tiles, debug_url, ignored_regions, considered_regions)
97
- Percy::CLIWrapper.new.post_screenshots(name, tag, tiles, debug_url, ignored_regions, considered_regions)
97
+ def _post_screenshots(name, tag, tiles, debug_url, ignored_regions, considered_regions, sync)
98
+ Percy::CLIWrapper.new.post_screenshots(name, tag, tiles, debug_url, ignored_regions, considered_regions, sync)
98
99
  end
99
100
 
100
101
  def _write_screenshot(png_bytes, directory)
data/percy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Percy
4
- VERSION = '0.0.3'.freeze
4
+ VERSION = '0.0.5-beta.0'.freeze
5
5
  end
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
26
  spec.require_paths = ['percy']
27
27
 
28
- spec.add_runtime_dependency 'appium_lib', '~> 12.0'
28
+ spec.add_runtime_dependency 'appium_lib', '~> 11.2.0'
29
29
  spec.add_runtime_dependency 'dotenv', '~> 2.8'
30
30
 
31
31
  spec.add_development_dependency 'bundler', '~> 2.4'
data/specs/cli_wrapper.rb CHANGED
@@ -104,14 +104,16 @@ class TestCLIWrapper < Minitest::Test
104
104
  tag = { 'name' => 'Tag' }
105
105
  name = 'some-name'
106
106
  debug_url = 'debug-url'
107
+ sync = false
107
108
  response = @cli_wrapper.request_body(name, tag, [tile], debug_url, @ignored_elements_data,
108
- @considered_elements_data)
109
+ @considered_elements_data, sync)
109
110
  assert_equal response['name'], name
110
111
  assert_equal response['external_debug_url'], debug_url
111
112
  assert_equal response['tag'], tag
112
113
  assert_equal response['tiles'], [tile.to_h]
113
114
  assert_equal response['ignored_elements_data'], @ignored_elements_data
114
115
  assert_equal response['considered_elements_data'], @considered_elements_data
116
+ assert_equal response['sync'], sync
115
117
  end
116
118
 
117
119
  def test_request_body_when_optional_values_are_null
@@ -121,13 +123,15 @@ class TestCLIWrapper < Minitest::Test
121
123
  debug_url = nil
122
124
  ignored_elements_data = nil
123
125
  considered_elements_data = nil
126
+ sync = nil
124
127
  response = @cli_wrapper.send(:request_body, name, tag, [tile], debug_url, ignored_elements_data,
125
- considered_elements_data)
128
+ considered_elements_data, sync)
126
129
  assert_equal response['name'], name
127
130
  assert_equal response['external_debug_url'], debug_url
128
131
  assert_equal response['tag'], tag
129
132
  assert_equal response['tiles'], [tile.to_h]
130
133
  assert_nil response['ignored_elements_data']
131
134
  assert_nil response['considered_elements_data']
135
+ assert_nil response['sync']
132
136
  end
133
137
  end
@@ -15,6 +15,7 @@ class TestGenericProvider < Minitest::Test
15
15
 
16
16
  def setup
17
17
  @existing_dir = 'existing-dir'
18
+ teardown
18
19
  Dir.mkdir(@existing_dir)
19
20
 
20
21
  @mock_webdriver = Minitest::Mock.new
@@ -33,7 +34,9 @@ class TestGenericProvider < Minitest::Test
33
34
  end
34
35
 
35
36
  def teardown
36
- FileUtils.remove_entry_secure(@existing_dir)
37
+ if Dir.exist?(@existing_dir)
38
+ FileUtils.remove_dir(@existing_dir, force: true)
39
+ end
37
40
  end
38
41
 
39
42
  def test_get_dir_without_env_variable
@@ -37,7 +37,7 @@ class TestIOSMetadata < Minitest::Test
37
37
  height = 100
38
38
  width = 100
39
39
  window_size = { 'height' => height, 'width' => width }
40
- @mock_webdriver.expect(:get_window_size, window_size)
40
+ @mock_webdriver.expect(:window_size, window_size)
41
41
  session_id = 'session_id_123'
42
42
  @mock_webdriver.expect(:session_id, session_id)
43
43
  @mock_webdriver.expect(:session_id, session_id)
@@ -48,12 +48,13 @@ class TestIOSMetadata < Minitest::Test
48
48
  end
49
49
 
50
50
  def test_device_screen_size
51
+ Percy::Cache.force_cleanup_cache
51
52
  session_id = 'session_id_123'
52
53
  5.times do
53
54
  @mock_webdriver.expect(:session_id, session_id)
54
55
  end
55
56
  @mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 6' })
56
- @mock_webdriver.expect(:get_window_size, { 'height' => 100, 'width' => 100 })
57
+ @mock_webdriver.expect(:window_size, { 'height' => 100, 'width' => 100 })
57
58
  device_screen_size = @ios_metadata.device_screen_size
58
59
  assert_equal({ 'height' => 200, 'width' => 200 }, device_screen_size)
59
60
  end
@@ -80,7 +81,7 @@ class TestIOSMetadata < Minitest::Test
80
81
  @mock_webdriver.expect(:session_id, session_id)
81
82
  end
82
83
  @mock_webdriver.expect(:capabilities, { 'deviceName' => 'iPhone 14' })
83
- @mock_webdriver.expect(:get_window_size, window_size)
84
+ @mock_webdriver.expect(:window_size, window_size)
84
85
  @mock_webdriver.expect(:execute_script, { 'height' => 100, 'width' => 200 }, ['mobile: viewportRect'])
85
86
 
86
87
  assert_equal(2, @ios_metadata.scale_factor)
data/specs/screenshot.rb CHANGED
@@ -6,7 +6,7 @@ require 'webmock/minitest'
6
6
  require 'appium_lib'
7
7
  require 'webrick'
8
8
 
9
- require_relative '../percy/screenshot'
9
+ require_relative '../percy/percy-appium-app'
10
10
  require_relative '../percy/lib/app_percy'
11
11
  require_relative 'mocks/mock_methods'
12
12
 
@@ -54,14 +54,14 @@ def mock_healthcheck(fail: false, fail_how: 'error', type: 'Percy::AppPercy')
54
54
  .to_return(status: health_status, body: health_body, headers: health_headers)
55
55
  end
56
56
 
57
- def mock_screenshot(fail: false)
57
+ def mock_screenshot(fail: false, data: false)
58
58
  stub_request(:post, 'http://localhost:5338/percy/comparison')
59
- .to_return(body: "{\"success\": #{fail ? 'false, "error": "test"' : 'true'}}", status: (fail ? 500 : 200))
59
+ .to_return(body: "{\"success\": #{fail ? 'false, "error": "test"' : 'true'} #{data ? ',"data": "sync-data"' : ""}}", status: (fail ? 500 : 200))
60
60
  end
61
61
 
62
- def mock_poa_screenshot(fail: false)
62
+ def mock_poa_screenshot(fail: false, data: false)
63
63
  stub_request(:post, 'http://localhost:5338/percy/automateScreenshot')
64
- .to_return(body: "{\"success\": #{fail ? 'false, "error": "test"' : 'true'}}", status: (fail ? 500 : 200))
64
+ .to_return(body: "{\"success\": #{fail ? 'false, "error": "test"' : 'true'} #{data ? ',"data": "sync-data"' : ""}}", status: (fail ? 500 : 200))
65
65
  end
66
66
 
67
67
  def mock_session_request
@@ -204,6 +204,37 @@ class TestPercyScreenshot < Minitest::Test
204
204
  assert_equal(['Consider_Dummy_id'], s2['options']['consider_region_elements'])
205
205
  end
206
206
 
207
+ def test_posts_screenshot_poa_with_sync
208
+ mock_healthcheck(type: 'automate')
209
+ mock_poa_screenshot(data: true)
210
+ mock_session_request
211
+
212
+ driver = Minitest::Mock.new
213
+ @bridge = Minitest::Mock.new
214
+ @http = Minitest::Mock.new
215
+ @server_url = Minitest::Mock.new
216
+
217
+ driver.expect(:is_a?, true, [Appium::Core::Base::Driver])
218
+ driver.expect(:desired_capabilities, { 'key' => 'value' })
219
+ driver.expect(:instance_variable_get, @bridge, [:@bridge])
220
+ @http.expect(:instance_variable_get, @server_url, [:@server_url])
221
+ @bridge.expect(:instance_variable_get, @http, [:@http])
222
+ @server_url.expect(:to_s, 'https://hub-cloud.browserstack.com/wd/hub')
223
+
224
+ 10.times do
225
+ driver.expect(:session_id, 'Dummy_session_id')
226
+ end
227
+ 2.times do
228
+ driver.expect(:capabilities, { 'key' => 'value' })
229
+ end
230
+ @mock_webdriver.expect(:capabilities, { 'key' => 'value' })
231
+
232
+ res = percy_screenshot(driver, 'Snapshot 1', options: { sync: true })
233
+
234
+ assert_equal('sync-data', res)
235
+ assert_equal('/percy/automateScreenshot', @requests.last.uri.path)
236
+ end
237
+
207
238
  def test_posts_multiple_screenshots_to_the_local_percy_server
208
239
  mock_healthcheck
209
240
  mock_screenshot
@@ -256,6 +287,53 @@ class TestPercyScreenshot < Minitest::Test
256
287
  assert_match(%r{ruby/\d+\.\d+\.\d+}, body['environment_info'][1])
257
288
  end
258
289
 
290
+ def test_post_screenshot_with_sync
291
+ mock_healthcheck
292
+ mock_screenshot(data: true)
293
+
294
+ driver = Minitest::Mock.new
295
+
296
+ driver.expect(:is_a?, true, [Appium::Core::Base::Driver])
297
+ driver.expect(:instance_variable_get, @bridge, [:@bridge])
298
+ @http.expect(:instance_variable_get, @server_url, [:@server_url])
299
+ @bridge.expect(:instance_variable_get, @http, [:@http])
300
+ @server_url.expect(:to_s, 'https://hub-cloud.browserstack.com/wd/hub')
301
+
302
+ 5.times do
303
+ driver.expect(:session_id, 'Dummy_session_id')
304
+ end
305
+
306
+ 13.times do
307
+ driver.expect(:capabilities, get_android_capabilities)
308
+ end
309
+
310
+ 3.times do
311
+ driver.expect(
312
+ :execute_script,
313
+ '{"success":true,"result":"[{\"sha\":\"sha-something\",\"status_bar\":null'\
314
+ ',\"nav_bar\":null,\"header_height\":0,\"footer_height\":0,\"index\":0}]"}',
315
+ [String]
316
+ )
317
+ end
318
+
319
+ 2.times do
320
+ driver.expect(:get_system_bars, {
321
+ 'statusBar' => { 'height' => 10, 'width' => 20 },
322
+ 'navigationBar' => { 'height' => 10, 'width' => 20 }
323
+ })
324
+ end
325
+
326
+ res = percy_screenshot(driver, 'screenshot 2', sync: true)
327
+
328
+ assert_equal('sync-data', res)
329
+ assert_equal('/percy/comparison', @requests.last.uri.path)
330
+
331
+ body = JSON.parse(@requests[-1].body)
332
+ assert_match(%r{percy-appium-app/\d+}, body['client_info'])
333
+ assert_match(%r{appium/\d+}, body['environment_info'][0])
334
+ assert_match(%r{ruby/\d+\.\d+\.\d+}, body['environment_info'][1])
335
+ end
336
+
259
337
  def test_ignore_region_screenshots_to_the_local_percy_server
260
338
  mock_healthcheck
261
339
  mock_screenshot
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percy-appium-app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5.pre.beta.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BroswerStack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appium_lib
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '12.0'
19
+ version: 11.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '12.0'
26
+ version: 11.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dotenv
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -137,6 +137,7 @@ files:
137
137
  - ".github/workflows/release.yml"
138
138
  - ".github/workflows/stale.yml"
139
139
  - ".github/workflows/test.yml"
140
+ - ".gitignore"
140
141
  - Gemfile
141
142
  - LICENSE
142
143
  - Makefile
@@ -197,11 +198,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
197
198
  version: 2.6.0
198
199
  required_rubygems_version: !ruby/object:Gem::Requirement
199
200
  requirements:
200
- - - ">="
201
+ - - ">"
201
202
  - !ruby/object:Gem::Version
202
- version: '0'
203
+ version: 1.3.1
203
204
  requirements: []
204
- rubygems_version: 3.2.3
205
+ rubygems_version: 3.1.6
205
206
  signing_key:
206
207
  specification_version: 4
207
208
  summary: Percy visual testing for Ruby Appium Mobile Apps