# Generators are not automatically loaded by Rails
require 'generators/rspec/install/install_generator'
require 'support/generators'

RSpec.describe Rspec::Generators::InstallGenerator, type: :generator do
  def use_active_record_migration
    match(/ActiveRecord::Migration\./m)
  end

  def content_for(file_name)
    File.read(file(file_name))
  end

  def have_a_fixture_path
    match(/^  config\.fixture_path = /m)
  end

  def have_fixture_paths
    match(/^  config\.fixture_paths = /m)
  end

  def maintain_test_schema
    match(/ActiveRecord::Migration\.maintain_test_schema!/m)
  end

  def require_rails_environment
    match(/^require_relative '\.\.\/config\/environment'$/m)
  end

  def require_rspec_rails
    match(/^require 'rspec\/rails'$/m)
  end

  def have_active_record_enabled
    match(/^\  # config\.use_active_record = false/m)
  end

  def have_active_record_disabled
    match(/^\  config\.use_active_record = false/m)
  end

  def have_transactional_fixtures_enabled
    match(/^  config\.use_transactional_fixtures = true/m)
  end

  def filter_rails_from_backtrace
    match(/config\.filter_rails_from_backtrace!/m)
  end

  setup_default_destination

  let(:rails_helper) { content_for('spec/rails_helper.rb') }
  let(:spec_helper) { content_for('spec/spec_helper.rb') }
  let(:developmentrb) { content_for('config/environments/development.rb')  }

  it "generates .rspec" do
    run_generator
    expect(File.exist?(file('.rspec'))).to be true
  end

  it "generates spec/spec_helper.rb" do
    generator_command_notice = / This file was generated by the `rails generate rspec:install` command./m
    run_generator
    expect(spec_helper).to match(generator_command_notice)
  end

  it "does not configure warnings in the spec/spec_helper.rb" do
    run_generator
    expect(spec_helper).not_to match(/\bconfig.warnings\b/m)
  end

  context "generates spec/rails_helper.rb" do
    specify "requiring Rails environment" do
      run_generator
      expect(rails_helper).to require_rails_environment
    end

    specify "requiring rspec/rails" do
      run_generator
      expect(rails_helper).to require_rspec_rails
    end

    specify "with ActiveRecord" do
      run_generator
      expect(rails_helper).to have_active_record_enabled
      expect(rails_helper).not_to have_active_record_disabled
    end

    specify "with default fixture path" do
      run_generator
      if ::Rails::VERSION::STRING < "7.1.0"
        expect(rails_helper).to have_a_fixture_path
      else
        expect(rails_helper).to have_fixture_paths
      end
    end

    specify "with transactional fixtures" do
      run_generator
      expect(rails_helper).to have_transactional_fixtures_enabled
    end

    specify "excluding rails gems from the backtrace" do
      run_generator
      expect(rails_helper).to filter_rails_from_backtrace
    end

    specify "checking for maintaining the schema" do
      run_generator
      expect(rails_helper).to maintain_test_schema
    end
  end

  context "generates spec/rails_helper.rb", "without ActiveRecord available" do
    before do
      hide_const("ActiveRecord")
    end

    specify "requiring Rails environment" do
      run_generator
      expect(rails_helper).to require_rails_environment
    end

    specify "requiring rspec/rails" do
      run_generator
      expect(rails_helper).to require_rspec_rails
    end

    specify "without ActiveRecord" do
      run_generator
      expect(rails_helper).not_to have_active_record_enabled
      expect(rails_helper).to have_active_record_disabled
    end

    specify "without fixture path" do
      run_generator
      expect(rails_helper).not_to have_a_fixture_path
      expect(rails_helper).not_to have_fixture_paths
    end

    specify "without transactional fixtures" do
      run_generator
      expect(rails_helper).not_to have_transactional_fixtures_enabled
    end

    specify "without schema maintenance checks" do
      run_generator
      expect(rails_helper).not_to use_active_record_migration
      expect(rails_helper).not_to maintain_test_schema
    end
  end
end
