require 'rails_helper'

RSpec.describe NotesController, type: :controller do

  render_views

  before(:each) do
    request.accept = "application/json"
  end

  let(:user) {
    create(:user)
  }

  let(:valid_attributes) {
    {content: 'text'}
  }

  let(:invalid_attributes) {
    {content: ''}
  }

  let(:valid_session) { {user_id: user.id} }

  describe "GET #index" do
    it "assigns all user notes as @notes" do
      note = create(:note, user: user)
      create(:note)
      get :index, params: {}, session: valid_session
      expect(assigns(:notes)).to eq([note])
    end
  end

  describe "GET #show" do
    it "assigns the requested note as @note" do
      note = create(:note, user: user)
      get :show, params: {id: note.to_param}, session: valid_session
      expect(assigns(:note)).to eq(note)
    end
  end

  describe "POST #create" do
    context "with valid params" do
      it "creates a new Note" do
        expect {
          post :create, params: {note: valid_attributes}, session: valid_session, as: :json
        }.to change(Note, :count).by(1)
      end

      it "assigns a newly created note as @note" do
        post :create, params: {note: valid_attributes}, session: valid_session
        expect(assigns(:note)).to be_a(Note)
        expect(assigns(:note)).to be_persisted
      end

      it "returns a 201" do
        post :create, params: {note: valid_attributes}, session: valid_session
        expect(response).to have_http_status 201
      end
    end

    context "with invalid params" do
      it "assigns a newly created but unsaved note as @note" do
        post :create, params: {note: invalid_attributes}, session: valid_session
        expect(assigns(:note)).to be_a_new(Note)
      end

      it "returns a 422" do
        post :create, params: {note: invalid_attributes}, session: valid_session
        expect(response).to have_http_status 422
      end
    end
  end

  describe "PUT #update" do
    context "with valid params" do
      let(:new_attributes) {
        {content: 'new stuff'}
      }

      it "updates the requested note" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: new_attributes}, session: valid_session
        note.reload
        expect(note.content).to eq 'new stuff'
      end

      it "assigns the requested note as @note" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: valid_attributes}, session: valid_session
        expect(assigns(:note)).to eq(note)
      end

      it "returns a 201" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: valid_attributes}, session: valid_session
        expect(response).to have_http_status 200
      end

      it 'redirects if note is not owned' do
        note = create(:note)
        put :update, params: {id: note.to_param, note: valid_attributes, format: :html}, session: valid_session
        expect(response).to redirect_to(root_path)
      end

      it 'returns a 403 if note is not owned for json requests' do
        note = create(:note)
        put :update, params: {id: note.to_param, note: valid_attributes, format: :json}, session: valid_session
        expect(response).to have_http_status 403
      end
    end

    context "with invalid params" do
      it "assigns the note as @note" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: invalid_attributes}, session: valid_session
        expect(assigns(:note)).to eq(note)
      end

      it "returns a 422" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: invalid_attributes}, session: valid_session
        expect(response).to have_http_status 422
      end
    end
  end

  describe "DELETE #destroy" do
    it "destroys the requested note" do
      note = create(:note, user: user)
      expect {
        delete :destroy, params: {id: note.to_param}, session: valid_session
      }.to change(Note, :count).by(-1)
    end

    it "returns a 204" do
      note = create(:note, user: user)
      delete :destroy, params: {id: note.to_param}, session: valid_session
      expect(response).to have_http_status 204
    end
  end

end
