integration-tests-rails 1.1.4 → 1.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3020cc3bc2a7fdcda72ea6b7fd12bb5786b4f26b1be3ff1c8533ff6a3046de3a
4
- data.tar.gz: 3603ab4f58a7b508879fda0c91901142f22c39df3894013a54e4e88e8809b396
3
+ metadata.gz: 1668370843b5697395c5716bfd2442188ab3dc44381b65d9442b3df2d8a77db7
4
+ data.tar.gz: c55dbc2cc27128a3858e72a16ba1ea14b09069a84f0d154993c6c6423a752a9b
5
5
  SHA512:
6
- metadata.gz: '032484b408cd1cfc672d6e0dfa379b1e3d01866546a750cb98d7d45d3e098941c79f77621f5431e41a2008ed1a45e0b299f38a18fe78a1a39496c2d5a00ddba7'
7
- data.tar.gz: 8612c1eb1ac54ba15c2f63f236b85d07e93783f57d0fbbcdd39e2ddc6dd8521d9402bd15d53e600210f44009a7f923103a97153e6b88dbeb4a6aeee5eb745978
6
+ metadata.gz: 5c8b64492f395681aa22d9e64a3c3a23adca9a9088a48c5e9ec427d36e1ef326efd549f6a96890087aee5be6d03fac63b2d4321ddedade93027876d340977bee
7
+ data.tar.gz: 6f836c2525fa07283f1270c98ddbc9a52815a26b2c5452f2d50408cdbdcc10c2547b1ca2834064b9e5dc53cb17c61cf78cbadc6194c973c942c8fd26b2d28410
data/README.md CHANGED
@@ -62,6 +62,7 @@ The `IntegrationTestsRails.setup` method accepts an optional block for further c
62
62
 
63
63
  ```ruby
64
64
  IntegrationTestsRails.setup do |config|
65
+ config.auto_retry = false # Whether to automatically wrap all examples inside retry_on_fail block.
65
66
  config.chrome_url = nil # Used for remote Chrome instances. Needs remote to be true.
66
67
  config.js_coverage = true # Whether to enable JavaScript coverage using Istanbul.
67
68
  config.max_server_retries = 1000 # Before running the tests, Cuprite starts a server to communicate with Chrome. This sets the maximum number of retries to connect to that server.
@@ -253,6 +254,20 @@ retry_on_fail(retry_attempts: 3, retry_sleep_duration: 1, capture_exceptions: [S
253
254
  end
254
255
  ```
255
256
 
257
+ ### Auto Retry
258
+
259
+ If you want to automatically retry all examples in a test suite without having to wrap them in `retry_on_fail`, you can set the `auto_retry` configuration option to `true`. This will automatically wrap all examples in a `retry_on_fail` block with the configured number of retries, exceptions to capture and sleep duration between retries.
260
+
261
+ It is possible to pass custom arguments with `auto_retry` enabled through example metadata:
262
+
263
+ ```ruby
264
+ it 'is a flaky test', auto_retry: { retry_attempts: 3, retry_sleep_duration: 2, capture_exceptions: [StandardError] } do
265
+ expect(page).to have_css('div#popover', visible: :visible, wait: 8)
266
+ end
267
+ ```
268
+
269
+ If no metadata is passed, it will use the default configuration values.
270
+
256
271
  ## JavaScript Coverage Reports
257
272
 
258
273
  After the tests (successful, failed or cancelled), coverage reports will be generated in `coverage/javascript` by default. This can be disabled in the configuration by setting `js_coverage` to `false`. Be sure to uninstall Istanbul packages through the rake task `rake integration_tests_rails:istanbul:uninstall` if you do not need this feature.
@@ -15,7 +15,7 @@ module IntegrationTestsRails
15
15
  yield
16
16
  rescue *capture_exceptions => e
17
17
  counter += 1
18
- Util.log("Attempt #{counter} for #{RSpec.current_example.full_description} failed!")
18
+ Util.log("Inline Retry Attempt #{counter} for #{RSpec.current_example.full_description} failed!")
19
19
  raise e if counter > attempts
20
20
 
21
21
  sleep(sleep_duration) if sleep_duration.positive?
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IntegrationTestsRails
4
+ module Capybara
5
+ # Handles auto-retry logic for RSpec feature examples.
6
+ module Retry
7
+ class << self
8
+ def run(example, context)
9
+ description = example.full_description
10
+ attempts, sleep_duration, capture_exceptions = retry_config(example)
11
+
12
+ (attempts + 1).times do |attempt_number|
13
+ reset_example_state(context)
14
+ example.run
15
+ ex = RSpec.current_example.exception
16
+ break unless ex
17
+ break unless capture_exceptions.any? { |klass| ex.is_a?(klass) }
18
+
19
+ Util.log "Auto Retry Attempt #{attempt_number + 1} failed for: #{description}"
20
+ sleep(sleep_duration) if attempt_number < attempts && sleep_duration.positive?
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def retry_config(example)
27
+ kwargs = example.metadata.fetch(:auto_retry, {})
28
+ config_obj = IntegrationTestsRails.configuration
29
+ attempts = kwargs.fetch(:attempts, config_obj.retry_attempts)
30
+ sleep_duration = kwargs.fetch(:sleep_duration, config_obj.retry_sleep_duration)
31
+ capture_exceptions = constantize_exceptions(config_obj)
32
+ [attempts, sleep_duration, capture_exceptions]
33
+ end
34
+
35
+ def constantize_exceptions(config)
36
+ config.retry_capture_exceptions.filter_map { |e| e.constantize if e.is_a?(String) }
37
+ end
38
+
39
+ def reset_example_state(context)
40
+ RSpec.current_example.instance_variable_set(:@exception, nil)
41
+ memoized_class = begin
42
+ RSpec::Core::MemoizedHelpers::ThreadsafeMemoized
43
+ rescue StandardError
44
+ RSpec::Core::MemoizedHelpers::NonThreadSafeMemoized
45
+ end
46
+ context.instance_variable_set(:@__memoized, memoized_class.new)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'helpers'
4
4
  require_relative 'dsl'
5
+ require_relative 'retry'
5
6
  require_relative 'tests_controller'
6
7
 
7
8
  module IntegrationTestsRails
@@ -14,6 +15,28 @@ module IntegrationTestsRails
14
15
  log 'WebMock configured to allow localhost connections'
15
16
  end
16
17
 
18
+ def configure_routes
19
+ return unless IntegrationTestsRails.configuration.experimental_features
20
+
21
+ app = Rails.application
22
+ routes = app.routes
23
+ # Use append and let Rails handle finalization automatically
24
+ routes.append do
25
+ get '/tests', to: 'tests#index', as: :tests
26
+ end
27
+ routes.instance_variable_set(:@finalized, false)
28
+ routes.finalize!
29
+ log 'Routes appended.'
30
+ end
31
+
32
+ def verbose?
33
+ IntegrationTestsRails.configuration.verbose
34
+ end
35
+
36
+ def log(message)
37
+ puts "[CAPYBARA] #{message}" if verbose?
38
+ end
39
+
17
40
  def ensure_server_ready(context)
18
41
  return if @server_ready
19
42
 
@@ -38,37 +61,32 @@ module IntegrationTestsRails
38
61
  def configure_rspec
39
62
  RSpec.configure do |config|
40
63
  config.include Dsl, type: :feature
41
- config.before(:each, type: :feature) do
42
- ::Capybara.current_driver = ::Capybara.javascript_driver
43
- IntegrationTestsRails::Capybara::Util.ensure_server_ready(self)
44
- end
45
-
64
+ configure_before_hook(config)
65
+ configure_around_hook(config)
46
66
  if IntegrationTestsRails.configuration.experimental_features
47
- config.include(Helper, type: :feature, unit: true)
67
+ config.include(Helper, type: :feature,
68
+ unit: true)
48
69
  end
49
70
  end
50
71
  end
51
72
 
52
- def configure_routes
53
- return unless IntegrationTestsRails.configuration.experimental_features
73
+ private
54
74
 
55
- app = Rails.application
56
- routes = app.routes
57
- # Use append and let Rails handle finalization automatically
58
- routes.append do
59
- get '/tests', to: 'tests#index', as: :tests
75
+ def configure_before_hook(config)
76
+ config.before(:each, type: :feature) do
77
+ ::Capybara.current_driver = ::Capybara.javascript_driver
78
+ IntegrationTestsRails::Capybara::Util.ensure_server_ready(self)
60
79
  end
61
- routes.instance_variable_set(:@finalized, false)
62
- routes.finalize!
63
- log 'Routes appended.'
64
- end
65
-
66
- def verbose?
67
- IntegrationTestsRails.configuration.verbose
68
80
  end
69
81
 
70
- def log(message)
71
- puts "[CAPYBARA] #{message}" if verbose?
82
+ def configure_around_hook(config)
83
+ config.around(:each, type: :feature) do |example|
84
+ if IntegrationTestsRails.configuration.auto_retry
85
+ Retry.run(example, self)
86
+ else
87
+ example.run
88
+ end
89
+ end
72
90
  end
73
91
  end
74
92
  end
@@ -38,11 +38,12 @@ module IntegrationTestsRails
38
38
  HTML
39
39
 
40
40
  attr_accessor :source_dir, :output_dir, :backup_dir, :coverage_path, :wait_time, :remote, :chrome_url, :window_size,
41
- :tests_page_html, :max_server_retries, :verbose, :js_coverage,
41
+ :tests_page_html, :max_server_retries, :verbose, :js_coverage, :auto_retry,
42
42
  :timeout, :server_host, :server_port, :puma_threads, :experimental_features,
43
43
  :retry_attempts, :retry_sleep_duration, :retry_capture_exceptions
44
44
 
45
- def initialize
45
+ def initialize # rubocop:disable Metrics/MethodLength
46
+ @auto_retry = false
46
47
  @backup_dir = 'tmp/js_backup'
47
48
  @chrome_url = nil
48
49
  @coverage_path = 'coverage/nyc'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IntegrationTestsRails
4
- VERSION = '1.1.4'
4
+ VERSION = '1.1.7'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: integration-tests-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tien
@@ -94,6 +94,7 @@ files:
94
94
  - lib/integration_tests_rails/capybara/helpers.rb
95
95
  - lib/integration_tests_rails/capybara/local.rb
96
96
  - lib/integration_tests_rails/capybara/remote.rb
97
+ - lib/integration_tests_rails/capybara/retry.rb
97
98
  - lib/integration_tests_rails/capybara/tests_controller.rb
98
99
  - lib/integration_tests_rails/capybara/util.rb
99
100
  - lib/integration_tests_rails/configuration.rb