module ReactOnRails::TestHelper

def self.configure_rspec_to_compile_assets(config, *metatags)

Default is :js, :server_rendering, :controller
metatags - metatags to add the ensure_assets_compiled check.
config - config for rspec
Params:

See docs/additional-reading/rspec-configuration.md for more info

to be running.
faster. The helper looks for these processes and will abort recompiling if it finds them
rendering) to have webpack recompile these files in the background, which will be *much*
run, you can call `yarn run build:client` (and `yarn run build:server` if doing server
If you do not want to be slowed down by re-compiling webpack assets from scratch every test

once per test run.
`server_rendering: true` (default). The helper will compile webpack files at most
if you want this helper to run on examples other than where `js: true` or
You can pass an RSpec metatag as an list of parameter to this helper method

ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
RSpec.configure do |config|

replacing any of the default components.
file, passing the config as an argument. You can customize this to your particular needs by
Call this method from inside of the `RSpec.configure` block in your `spec/rails_helper.rb`

JavaScript code.
Webpack assets, you will get invalid test results as your tests do not use the very latest
don't accidentally run tests on missing or stale webpack assets. If you did use stale
(typically, your integration/feature specs where `js: true`), you will want to ensure you
Because you will probably want to run RSpec tests that rely on compiled webpack assets
def self.configure_rspec_to_compile_assets(config, *metatags)
  metatags = %i[js server_rendering controller] if metatags.empty?
  # Supported since RSpec 3.5.0
  supports_first_matching_example = config.respond_to?(:when_first_matching_example_defined)
  metatags.each do |metatag|
    if supports_first_matching_example
      config.when_first_matching_example_defined(metatag) do
        ReactOnRails::TestHelper.ensure_assets_compiled
      end
    else
      config.before(:example, metatag) { ReactOnRails::TestHelper.ensure_assets_compiled }
    end
  end
end

def self.ensure_assets_compiled(webpack_assets_status_checker: nil,

rubocop:disable Metrics/CyclomaticComplexity
webpack_generated_files in your configuration
webpack_generated_files List of files to check for up-to-date-status, defaulting to
don't provide one.
source_path and generated_assets_full_path are passed into the default webpack_assets_status_checker if you
defaults to ReactOnRails::TestHelper::WebpackAssetsCompiler
webpack_assets_compiler: provide one method: `def compile`
defaults to ReactOnRails::TestHelper::WebpackAssetsStatusChecker
webpack_assets_status_checker: provide: `up_to_date?`, `whats_not_up_to_date`, `source_path`
Typical usage passes all params as nil defaults.

an example of usage.
Main entry point to ensuring assets are compiled. See `configure_rspec_to_compile_assets` for
def self.ensure_assets_compiled(webpack_assets_status_checker: nil,
                                webpack_assets_compiler: nil,
                                source_path: nil,
                                generated_assets_full_path: nil,
                                webpack_generated_files: nil)
  ReactOnRails::PackerUtils.check_manifest_not_cached
  if webpack_assets_status_checker.nil?
    source_path ||= ReactOnRails::Utils.source_path
    generated_assets_full_path ||= ReactOnRails::Utils.generated_assets_full_path
    webpack_generated_files ||= ReactOnRails.configuration.webpack_generated_files
    webpack_assets_status_checker ||=
      WebpackAssetsStatusChecker.new(source_path: source_path,
                                     generated_assets_full_path: generated_assets_full_path,
                                     webpack_generated_files: webpack_generated_files)
    unless @printed_once
      puts
      puts "====> React On Rails: Checking files in " \
           "#{webpack_assets_status_checker.generated_assets_full_path} for " \
           "outdated/missing bundles based on source_path #{source_path}"
      puts
      @printed_once = true
      if ReactOnRails::Utils.using_packer_source_path_is_not_defined_and_custom_node_modules?
        msg = <<-MSG.strip_heredoc
          WARNING: Define config/shakapacker.yml to include sourcePath to configure
          the location of your JavaScript source for React on Rails.
          Default location of #{source_path} is used.
        MSG
        puts ReactOnRails::Utils.wrap_message(msg, :orange)
      end
    end
  end
  webpack_assets_compiler ||= WebpackAssetsCompiler.new
  ReactOnRails::TestHelper::EnsureAssetsCompiled.new(
    webpack_assets_status_checker: webpack_assets_status_checker,
    webpack_assets_compiler: webpack_assets_compiler
  ).call
end