require 'rails_helper'

RSpec.describe NotesController, type: :controller do

  render_views

  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 "GET #new" do
    it "assigns a new note as @note" do
      get :new, params: {}, session: valid_session
      expect(assigns(:note)).to be_a_new(Note)
    end
  end

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

    it 'redirects if note is not owned' do
      note = create(:note)
      get :edit, params: {id: note.to_param}, session: valid_session
      expect(response).to redirect_to(root_path)
    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
        }.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 "redirects to the created note" do
        post :create, params: {note: valid_attributes}, session: valid_session
        expect(response).to redirect_to notes_path
      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 "re-renders the 'new' template" do
        post :create, params: {note: invalid_attributes}, session: valid_session
        expect(response).to render_template("new")
      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 "redirects to the note" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: valid_attributes}, session: valid_session
        expect(response).to redirect_to(notes_path)
      end

      it 'redirects if note is not owned' do
        note = create(:note)
        put :update, params: {id: note.to_param, note: valid_attributes}, session: valid_session
        expect(response).to redirect_to(root_path)
      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 "re-renders the 'edit' template" do
        note = create(:note, user: user)
        put :update, params: {id: note.to_param, note: invalid_attributes}, session: valid_session
        expect(response).to render_template("edit")
      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 "redirects to the notes list" do
      note = create(:note, user: user)
      delete :destroy, params: {id: note.to_param}, session: valid_session
      expect(response).to redirect_to(notes_url)
    end
  end

end
