require 'rails_helper'

RSpec.describe Ppa::ObjetivosController, type: :controller do
	sign_in_admin
	set_ppa_id_na_sessao

	# Isso deve retornar o mínimo de atributos obrigatórios para criar um
	# Ppa::Objetivo válido.
	let(:atributos_validos) {
		FactoryBot.attributes_for(:ppa_objetivo)
	}

	let(:atributos_invalidos) {
		{ descricao: '' }
	}
	
	it{ is_expected.to use_before_action(:verifica_se_tem_ppa_na_sessao!) }

	describe "GET #show" do
		it "atribui a ppa_objetivo requisitado(a) à @ppa_objetivo" do
			objetivo = Ppa::Objetivo.create! atributos_validos
			get :show, params: {id: objetivo.to_param}
			expect(assigns(:ppa_objetivo)).to eq(objetivo)
		end
	end

	describe "GET #new" do
		let(:programa){
			FactoryBot.create(:ppa_objetivo).programa
		}

		it "atribui um(a) novo(a) ppa_objetivo à @ppa_objetivo" do
			get :new, programa_id: programa.id
			expect(assigns(:ppa_objetivo)).to be_a_new(Ppa::Objetivo)
		end

		it "@ppa_objetivo pertence ao programa requisitado nos params" do
			get :new, programa_id: programa.id
			expect(assigns(:ppa_objetivo).programa).to eq (programa)
		end
	end

	describe "GET #edit" do
		it "atribui o(a) ppa_objetivo requisitado à @ppa_objetivo" do
			objetivo = Ppa::Objetivo.create! atributos_validos
			get :edit, params: {id: objetivo.to_param}
			expect(assigns(:ppa_objetivo)).to eq(objetivo)
		end
	end

	describe "POST #create" do
		context "com parâmetros válidos" do
			it "cria um(a) novo(a) Ppa::Objetivo" do
				expect {
					post :create, params: {ppa_objetivo: atributos_validos}
				}.to change(Ppa::Objetivo, :count).by(1)
			end

			it "atribui o(a) ppa_objetivo recém criado(a) à @ppa_objetivo" do
				post :create, params: {ppa_objetivo: atributos_validos}

				expect(assigns(:ppa_objetivo)).to be_a(Ppa::Objetivo)
				expect(assigns(:ppa_objetivo)).to be_persisted
			end

			context "com o param 'mantem_form'" do
				it "redireciona para o form de cadastro" do
					post :create, params: {ppa_objetivo: atributos_validos, manter_form: true}
					expect(response).to redirect_to( action: :new, programa_id: assigns(:ppa_objetivo).programa.id)
				end
			end

			context "sem o param 'mantem_form'" do
				it "redireciona para o programa do objetivo criado" do

					post :create, params: {:ppa_objetivo => atributos_validos}
					expect(response).to redirect_to(Ppa::Objetivo.last.programa)
				end
			end
		end


		context "com parâmetros inválidos" do
			it "atribui um(a) ppa_objetivo recém criado(a), mas não salvo(a), à @ppa_objetivo" do
				post :create, params: {ppa_objetivo: atributos_invalidos}
				expect(assigns(:ppa_objetivo)).to be_a_new(Ppa::Objetivo)
			end

			it "re-renderiza o template 'new'" do
				post :create, params: {ppa_objetivo: atributos_invalidos}
				expect(response).to render_template("new")
			end
		end
	end

	describe "PUT #update" do
		context "com parâmetros válidos" do
			let(:novos_atributos) {
				{ descricao: 'nova descricao' }
			}

			it "atualiza o(a) ppa_objetivo requisitado(a)" do
				objetivo = Ppa::Objetivo.create! atributos_validos
				post :update, params: {id: objetivo.to_param, ppa_objetivo: novos_atributos}
				objetivo.reload
				expect( objetivo.descricao ).to eq 'nova descricao'
			end

			it "atribui o(a) ppa_objetivo requisitado(a) à @ppa_objetivo" do
				objetivo = Ppa::Objetivo.create! atributos_validos
				post :update, params: {id: objetivo.to_param, ppa_objetivo: atributos_validos}
				expect(assigns(:ppa_objetivo)).to eq(objetivo)
			end

			it "redireciona para o programa do objetivo atualizado" do
				objetivo = Ppa::Objetivo.create! atributos_validos
				post :update, params: {id: objetivo.to_param, ppa_objetivo: atributos_validos}
				expect(response).to redirect_to(objetivo.programa)
			end
		end

		context "com parâmetros inválidos" do
			it "atribui o(a) ppa_objetivo à @ppa_objetivo" do
				objetivo = Ppa::Objetivo.create! atributos_validos
				post :update, params: {id: objetivo.to_param, ppa_objetivo: atributos_invalidos}
				expect(assigns(:ppa_objetivo)).to eq(objetivo)
			end

			it "re-renderiza o template 'edit'" do
				objetivo = Ppa::Objetivo.create! atributos_validos
				post :update, params: {id: objetivo.to_param, ppa_objetivo: atributos_invalidos}
				expect(response).to render_template("edit")
			end
		end
	end

	describe "DELETE #destroy" do
		it "destrói o(a) ppa_objetivo requisitado(a)" do
			objetivo = Ppa::Objetivo.create! atributos_validos
			expect {
				delete :destroy, params: {:id => objetivo.to_param}
			}.to change(Ppa::Objetivo, :count).by(-1)
		end

		it "redireciona para o programa do objetivo excluído" do
			objetivo = Ppa::Objetivo.create! atributos_validos
			delete :destroy, params: {:id => objetivo.to_param}
			expect(response).to redirect_to(objetivo.programa)
		end
	end
end
