shakacode/react_on_rails

View on GitHub
lib/react_on_rails/test_helper/webpack_assets_status_checker.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

require "rake"
require "fileutils"
require "react_on_rails/utils"

# You can replace this implementation with your own for use by the
# ReactOnRails::TestHelper.ensure_assets_compiled helper
module ReactOnRails
  module TestHelper
    class WebpackAssetsStatusChecker
      include Utils::Required
      # source_path is typically configured in the webpacker.yml file
      # for `source_path`
      # or for legacy React on Rails, it's /client, where all client files go
      attr_reader :source_path, :generated_assets_full_path

      def initialize(
        generated_assets_full_path: required("generated_assets_full_path"),
        source_path: required("source_path"),
        webpack_generated_files: required("webpack_generated_files")
      )
        @generated_assets_full_path = generated_assets_full_path
        @source_path = source_path
        @webpack_generated_files = webpack_generated_files
      end

      def stale_generated_webpack_files
        stale_generated_files(client_files)
      end

      def stale_generated_files(files)
        manifest_needed = ReactOnRails::WebpackerUtils.using_webpacker? &&
                          !ReactOnRails::WebpackerUtils.manifest_exists?

        return ["manifest.json"] if manifest_needed

        most_recent_mtime = Utils.find_most_recent_mtime(files)
        all_compiled_assets.each_with_object([]) do |webpack_generated_file, stale_gen_list|
          if !File.exist?(webpack_generated_file) ||
             File.mtime(webpack_generated_file) < most_recent_mtime
            stale_gen_list << webpack_generated_file
          end
          stale_gen_list
        end
      end

      private

      def all_compiled_assets
        @all_compiled_assets ||= begin
          webpack_generated_files = @webpack_generated_files.map do |bundle_name|
            if bundle_name == ReactOnRails.configuration.server_bundle_js_file
              ReactOnRails::Utils.server_bundle_js_file_path
            else
              ReactOnRails::Utils.bundle_js_file_path(bundle_name)
            end
          end

          if webpack_generated_files.present?
            webpack_generated_files
          else
            file_list = make_file_list(make_globs(generated_assets_full_path)).to_ary
            puts "V" * 80
            puts "Please define config.webpack_generated_files (array) so the test helper knows " \
                 "which files are required. If you are using webpacker, you typically need to only " \
                 "include 'manifest.json'."
            puts "Detected the possible following files to check for webpack compilation in " \
                 "#{generated_assets_full_path}"
            puts file_list.join("\n")
            puts "^" * 80
            file_list
          end
        end
      end

      def client_files
        @client_files ||= make_file_list(make_globs(source_path)).to_ary
      end

      def make_globs(dirs)
        Array(dirs).map { |dir| File.join(dir, "**", "*") }
      end

      def assets_exist?
        !all_compiled_assets.empty?
      end

      def make_file_list(glob)
        FileList.new(glob) do |fl|
          fl.exclude(%r{/node_modules})
          fl.exclude(".DS_Store")
          fl.exclude(".keep")
          fl.exclude("thumbs.db")
          fl.exclude(".")
          fl.exclude("..")
        end
      end
    end
  end
end