# Generators are not automatically loaded by Rails
require 'generators/rspec/controller/controller_generator'
require 'support/generators'

RSpec.describe Rspec::Generators::ControllerGenerator, type: :generator do
  setup_default_destination

  describe 'request specs' do
    subject(:filename) { file('spec/requests/posts_spec.rb') }

    describe 'generated by default' do
      before do
        run_generator %w[posts]
      end

      it 'includes the standard boilerplate' do
        expect(filename).to contain(/require 'rails_helper'/)
                              .and(contain(/^RSpec.describe "Posts", #{type_metatag(:request)}/))
                              .and(contain('pending'))
      end
    end

    describe 'skipped with a flag' do
      before do
        run_generator %w[posts --no-request_specs]
      end

      it 'skips the file' do
        expect(File.exist?(filename)).to be false
      end
    end

    describe 'with actions' do
      before do
        run_generator %w[posts index custom_action]
      end

      it 'includes the standard boilerplate' do
        expect(filename).to contain('get "/posts/index"')
                             .and(contain('get "/posts/custom_action"'))
      end
    end

    describe 'with namespace and actions' do
      subject(:filename) { file('spec/requests/admin/external/users_spec.rb') }

      before do
        run_generator %w[admin::external::users index custom_action]
      end

      it 'includes the standard boilerplate' do
        expect(filename).to contain(/^RSpec.describe "Admin::External::Users", #{type_metatag(:request)}/)
                             .and(contain('get "/admin/external/users/index"'))
                             .and(contain('get "/admin/external/users/custom_action"'))
      end
    end
  end

  describe 'view specs' do
    describe 'are not generated' do
      describe 'with no-view-spec flag' do
        before do
          run_generator %w[posts index show --no-view-specs]
        end

        describe 'index.html.erb' do
          subject(:filename) { file('spec/views/posts/index.html.erb_spec.rb') }

          it 'skips the file' do
            expect(File.exist?(filename)).to be false
          end
        end
      end

      describe 'with no actions' do
        before do
          run_generator %w[posts]
        end

        describe 'index.html.erb' do
          subject(:filename) { file('spec/views/posts/index.html.erb_spec.rb') }

          it 'skips the file' do
            expect(File.exist?(filename)).to be false
          end
        end
      end

      describe 'with --no-template-engine' do
        before do
          run_generator %w[posts index --no-template-engine]
        end

        describe 'index.html.erb' do
          subject(:filename) { file('spec/views/posts/index.html._spec.rb') }

          it 'skips the file' do
            expect(File.exist?(filename)).to be false
          end
        end
      end
    end

    describe 'are generated' do
      describe 'with default template engine' do
        before do
          run_generator %w[posts index show]
        end

        describe 'index.html.erb' do
          subject(:filename) { file('spec/views/posts/index.html.erb_spec.rb') }

          it 'includes the standard boilerplate' do
            expect(filename).to contain(/require 'rails_helper'/)
                                 .and(contain(/^RSpec.describe "posts\/index.html.erb", #{type_metatag(:view)}/))
          end
        end

        describe 'show.html.erb' do
          subject(:filename) { file('spec/views/posts/show.html.erb_spec.rb') }

          it 'includes the standard boilerplate' do
            expect(filename).to contain(/require 'rails_helper'/)
                                 .and(contain(/^RSpec.describe "posts\/show.html.erb", #{type_metatag(:view)}/))
          end
        end
      end

      describe 'with haml' do
        before do
          run_generator %w[posts index --template_engine haml]
        end

        describe 'index.html.haml' do
          subject(:filename) { file('spec/views/posts/index.html.haml_spec.rb') }

          it 'includes the standard boilerplate' do
            expect(filename).to contain(/require 'rails_helper'/)
                                 .and(contain(/^RSpec.describe "posts\/index.html.haml", #{type_metatag(:view)}/))
          end
        end
      end
    end

    describe 'are removed' do
      subject(:output) { run_generator %w[posts], behavior: :revoke }

      it 'will remove the file' do
        expect(output).to match('remove  spec/views/posts')
      end
    end
  end

  describe 'routing spec' do
    subject(:filename) { file('spec/routing/posts_routing_spec.rb') }

    describe 'with no flag' do
      before do
        run_generator %w[posts seek and destroy]
      end

      it 'skips the file' do
        expect(File.exist?(filename)).to be false
      end
    end

    describe 'with --routing-specs  flag' do
      describe 'without action parameter' do
        before do
          run_generator %w[posts --routing-specs]
        end

        it 'skips the file' do
          expect(File.exist?(filename)).to be false
        end
      end

      describe 'with action parameter' do
        before { run_generator %w[posts seek --routing-specs] }

        it 'includes the standard boilerplate' do
          expect(filename).to contain(/require 'rails_helper'/)
                                .and(contain(/^RSpec.describe 'PostsController', #{type_metatag(:routing)}/))
                                .and(contain(/describe 'routing'/))
                                .and(contain(/it 'routes to #seek'/))
                                .and(contain(/expect\(get: "\/posts\/seek"\).to route_to\("posts#seek"\)/))
        end
      end
    end

    describe 'with --no-routing-specs flag' do
      before do
        run_generator %w[posts seek and destroy --no-routing_specs]
      end

      it 'skips the file' do
        expect(File.exist?(filename)).to be false
      end
    end
  end

  describe 'controller specs' do
    subject(:filename) { file('spec/controllers/posts_controller_spec.rb') }

    it 'are not generated' do
      expect(File.exist?(filename)).to be false
    end

    describe 'with --controller-specs flag' do
      before do
        run_generator %w[posts --controller-specs]
      end

      describe 'the spec' do
        it 'includes the standard boilerplate' do
          expect(filename).to contain(/require 'rails_helper'/)
                               .and(contain(/^RSpec.describe PostsController, #{type_metatag(:controller)}/))
        end
      end
    end

    describe 'with --no-controller_specs flag' do
      before do
        run_generator %w[posts --no-controller-specs]
      end

      it 'are skipped' do
        expect(File.exist?(filename)).to be false
      end
    end
  end
end
