1

I have difficulty understanding the Rspec logic of creating data to use in tests.

I have a couple of scenarios and all result in errors except for the first scenario. Error meaning that when i print the page, the record is not rendered in the HTML, meaning that the variable is not created.

Here are my factories:

article:

FactoryGirl.define do   
  factory :article do
    title "First test article"
    summary "Summary of first article"
    description "This is the first test article."
    user
  end  
end

comment:

FactoryGirl.define do
  factory :comment do
    sequence(:content) { |n| "comment text #{n}" }
    article
    user
  end
end

spec/features/article_spec.rb

1) Explicitly create the comment variable within the rspec test.

require 'rails_helper'

describe "Comments on article" do

let!(:user) { FactoryGirl.create(:user) }
let!(:article) { FactoryGirl.create(:article) }
let!(:comment) {Comment.create(content:"Some comments", article_id: article.id, user_id: user.id)}

before do
    login_as(user, :scope => :user)
    visit article_path(article)
end

describe 'edit', js: true do

let!(:comment) {Comment.create(content:"Some comments", article_id: article.id, user_id: user.id)}

  it 'a comment can be edited through ajax' do
    print page.html
    find("a[href = '/articles/#{article.friendly_id}/comments/#{comment.id}/edit']").click
    expect(page).to have_css('#comment-content', text: "Some comments")
    within('.card-block') do
       fill_in 'comment[content]', with: "Edited comments"
       click_on "Save"
    end
    expect(page).to have_css('#comment-content', text: "Edited comments")
  end

end

end

2) Replacing let!(:comment) {Comment.create(content:"Some comments", article_id: article.id, user_id: user.id)} with below:

let!(:comment) { FactoryGirl.create(:comment) }

3) Place the let! statement before the first 'it' block

describe 'edit', js: true do

let!(:comment) {Comment.create(content:"Some comments", article_id: article.id, user_id: user.id)}

  it 'a comment can be edited through ajax' do
    print page.html
    find("a[href = '/articles/#{article.friendly_id}/comments/#{comment.id}/edit']").click
    expect(page).to have_css('#comment-content', text: "Some comments")
    within('.card-block') do
       fill_in 'comment[content]', with: "Edited comments"
       click_on "Save"
    end
    expect(page).to have_css('#comment-content', text: "Edited comments")
  end

end

UPDATE:

I find setting up test data/variables to be a big pain/stumbling block for me as a Rspec newbie. Here are some references i found that helped me:

1) When is using instance variables more advantageous than using let()?

2) https://www.ombulabs.com/blog/rails/rspec/ruby/let-vs-instance.html

doyz
  • 887
  • 2
  • 18
  • 43

1 Answers1

0
let!(:comment) {Comment.create(content:"Some comments", article_id: article.id, user_id: user.id)}

let!(:comment) { FactoryGirl.create(:comment) }

These are not going to create the same comments - in the second case, the comment that is created will not be associated with user or article (but a new user and a new article).

Are you inspecting the variable and it is nil, or are you just going by what you see on the page? If you're going by what's on the page, is it possible it is only showing you comments associated with the given article/user?

As for the other issue, the before block is executed before the comment variable created inside the describe - so the comment does not exist until after you've navigated to the page.

oowowaee
  • 1,635
  • 3
  • 16
  • 24