1
votes
RSpec.describe 'Book', :type => :request do
  describe 'List Books' do
    let(:book) { FactoryGirl.create :book }
    before(:each) do
      visit root_path
    end
    context 'when book is created' do
      let(:book) { FactoryGirl.create :book, title: 'My Book Title' }
      it 'should list books' do
        post books_path({book: book})        
        expect(page).to have_content 'My Book Title'
      end
    end
    context 'when no book is created' do
      it 'should not list books' do
        expect(page).to have_content 'No books found'
      end
    end
  end
end

Failure/Error: params.require(:book).permit(:title, :abstract, :author, :pages, :price, :image_file_name, :genre, :published_on)

 ActionController::ParameterMissing:
   param is missing or the value is empty: book
3

3 Answers

0
votes

This error is caused by post books_path(book). The correct implementation is:

RSpec.describe 'Book', :type => :request do
  describe 'List Books' do
    let(:book) { FactoryGirl.create :book }
    before(:each) do
      visit root_path
    end
    context 'when book is created' do
      let!(:book) { FactoryGirl.create :book, title: 'My Book Title' }
      it 'should list books' do
        expect(page).to have_content 'Displaying 1 book'
        expect(page).not_to have_content 'No books found'
      end
    end
    context 'when no book is created' do
      it 'should not list books' do
        expect(page).to have_content 'No books found'
      end
    end
  end
end
0
votes

Try this

RSpec.describe 'Book', :type => :request do
  describe 'List Books' do
    let(:book) { FactoryGirl.create :book }
    before(:each) do
      visit root_path
    end
    context 'when book is created' do
      let(:book) { FactoryGirl.create :book, title: 'My Book Title' }
      it 'should list books' do
        post books_path({book: book})
        #visit root_path(book)
        #expect(page).to have_content 'Displaying 1 book'
        expect(page).to have_content 'No books found'
      end
    end
    context 'when no book is created' do
      it 'should not list books' do
        expect(page).to have_content 'No books found'
      end
    end
  end
end

In your controller you can change

params.require(:book).permit(:title, :abstract, :author, :pages, :price, :image_file_name, :genre, :published_on)

to

params.require(:book)
params.permit(:title, :abstract, :author, :pages, :price, :image_file_name, :genre, :published_on)

The issue is that you are saying I want to permit these values to be passed into the book parameter. Unless book is a hash like the {book => {'title' => 'Cat and the Hat', 'auther' => 'Me'}} the permit method won't work correctly on it. So either change the structure of your params, or white list them in two steps

0
votes

In the below example i am using Let to create an instance variable. Using let the variable lazy loads only when it is used the first time in the test and get cached until that specific test is finished. therefore i will have book instance created for one example and no books created for anther example to test

RSpec.describe 'Book', :type => :request do
  describe 'List Books' do
    before(:each) do
      visit books_path
    end
    context 'when book is created' do
      let!(:book) { FactoryGirl.create :book, title: 'My Book Title' }
      it 'should list books' do
        expect(page).to have_content 'Displaying all 2   book'
        expect(page).to have_content 'My Book Title'
      end
    end
    context 'when no book is created' do
      it 'should not list books' do
        expect(page).to have_content 'No books found'
      end
    end
  end
end

does this test full fills the need to test list of book