I am trying to test a carrierwave image upload to a model, using RSpec / capybara / Factory girl for Rails.
This specific test tests the validation that an image should be present.
At the moment, I have this code:
it "should accept a spotlight record with spotlight info" do
feature = create :feature, spotlight: true, spotlight_description: "description", spotlight_image: File.open(Rails.root.join "/app/assets/shopstar_logo_stamp.png")
expect(feature).to be_valid
end
But somehow the image isn't detected, and I get this error:
Failures:
1) Feature validations should accept a spotlight record with spotlight info
Failure/Error: feature = create :feature, spotlight: true, spotlight_description: "description", spotlight_image: File.open(Rails.root.join "/app/assets/shopstar_logo_stamp.png")
Errno::ENOENT:
No such file or directory - /app/assets/shopstar_logo_stamp.png
# ./spec/models/feature_spec.rb:32:in `initialize'
# ./spec/models/feature_spec.rb:32:in `open'
# ./spec/models/feature_spec.rb:32:in `block (3 levels) in <top (required)>'
How can I specify a path to an image in assets and use it for testing?
Or alternatively, what is a better way of testing a carrierwave image upload?
If this is an acceptance test/integration test you'll actually want to do it from the users perspective using capybara like this:
feature 'user uploads image' do
scenario '#Image' do
count = ImageModel.count
visit new_image_path
attach_file('css_selector_here', File.join(Rails.root, '/spec/support/herst.jpg'))
click_button('Submit')
expect(page).to have_content('Image uploaded successfully!')
expect(ImageModel.count).to eq(count + 1)
end
end
If you're after a unit test, do something like this with FactoryGirl in spec/factories/factory.rb
Factory.define :feature do |f|
f.spotlight true
f.spotlight_description "description"
f.spotlight_image { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec', 'support', 'feature', 'images', 'shopstar_logo_stamp.jpg')) }
end
now in your unit test you can run your test:
it "should accept a spotlight record with spotlight info" do
feature = create :feature
expect(feature).to be_valid
end
Related
I can't figure out how to give a file in one of my Factories. I'm using the default test suite of rails 5, Factory Bot, and Paperclip. This is the test I'm running:
require 'test_helper'
class AttachmentTest < ActiveSupport::TestCase
test "should be valid" do
p "should look into: #{ActionController::TestCase.fixture_path}"
ressource = build(:attachment)
assert ressource.valid?
end
end
This is my fixture:
include ActionDispatch::TestProcess
FactoryBot.define do
factory :attachment do
file { fixture_file_upload('files/invoice.pdf', 'application/pdf') }
association :attachable, factory: :mission
end
end
I've invoice.pdf in /Users/Daniel/GitHub/haeapua-rails/test/fixtures/files (both values copy / pasted here directly from terminal)
The trace I get
# Running:
"should look into: /Users/Daniel/GitHub/haeapua-rails/test/fixtures/"
E
Error:
AttachmentTest#test_should_be_valid:
RuntimeError: files/invoice.pdf file does not exist
test/factories/attachments.rb:5:in `block (3 levels) in <top (required)>'
test/models/attachment_test.rb:7:in `block in <class:AttachmentTest>'
bin/rails test test/models/attachment_test.rb:5
I'm missing something but can't figure out what. As I'm using FactoryBot, does it change the fixtures/files path? How could I know it?
Edit
Try to move the invoice to this places:
/Users/Daniel/GitHub/haeapua-rails/test/fixtures/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/factories/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/test/files/invoice.pdf
/Users/Daniel/GitHub/haeapua-rails/files/invoice.pdf
I have started to test my app via Rspec (Capybara). This is how I am doing it:
require 'rails_helper'
RSpec.describe "Homepages", type: :request do
describe "GET / without login" , js: true do
before(:all) do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
it "works!" do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Because of env namely "TEST-ENV" I have to create an employee at first.
the problem is, if I run 'rake spec:requests', I get this errors:
1) Homepages GET / without login works!
Got 0 failures and 2 other errors:
1.1) Failure/Error:
def initialize(template, original_exception)
super(original_exception.message)
#template, #original_exception = template, original_exception
#sub_templates = nil
set_backtrace(original_exception.backtrace)
end
ArgumentError:
wrong number of arguments (1 for 2)
#/.rvm/gems/ruby-2.1.1/gems/actionview-4.2.7/lib/action_view/template/error.rb:64:in `initialize'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `exception'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `raise'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `rescue in raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:125:in `raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:113:in `reset!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `block in reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reverse_each'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/rspec.rb:21:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Capybara::CapybaraError:
# Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:126:in `raise_server_error!'
I'm not sure but I think better if type = feature
Sample
require "rails_helper"
RSpec.feature "Homepages", type: :feature do
before do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
context "GET / without login" do
scenario "works!", js: true do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Please make sure your input name is correct by inspect element to get the input name
I think
fill_in "loginname", with: "username"
maybe be
fill_in "user[loginname]", with: "username"
As others have stated, Capybara tests should be of type 'feature' not 'request', however that's not the primary cause of your error. Your apps code is raising an exception during template rendering, and then you're running into a bug in the current version of Capybara with handling exceptions whose initializers take multiple parameters. As long as you're not using jRuby you can lock your Capybara version to 2.10.0 and you should see the correct error your app is raising. If you are using jRuby, or if you prefer to not lock to an older version, you can specify to use the master branch of Capybara
gem 'capybara', github: 'teamcapybara/capybara'
which has the bug fixed.
As a side-note, you've tagged this question with capybara-webkit when you're not actually using the capybara-webkit driver (since it only supports up to Capybara 2.7.1 currently), so you might want to change the tag to just capybara.
So, for some reason my routes increment by 11 when I run my comment feature test.
Exhibit A: I hit save on my comment_spec.rb
RSpec.feature "Adding comments to movies" do
before do
#kyle = Admin.create(email: "kyle#example.com", password: "password")
#jill = Member.create(email: "jill#example.com", password: "password")
#movie = Movie.create!(title: "First movie", synopsis: "Synopsis of first movie", year_released: '2000', admin: #kyle)
end
scenario "permits a signed in member to write a comment" do
login_as(#jill, scope: :member)
visit "/"
click_link #movie.title
fill_in "New Review", with: "An awesome movie"
click_button "Add Review"
expect(page).to have_content("Review has been created")
expect(page).to have_content("An awesome movie")
# must implement a nested route in order for this to work.
expect(current_path).to eq(movie_path(#movie.comments.last.id))
end
end
Then the test passes
moviesmoviesmovies/spec/features/comments_spec.rb:3)
Finished in 0.99879 seconds (files took 2.4 seconds to load) 1
example, 0 failures
Now, I hit enter in the terminal and get this:
Adding comments to movies permits a signed in member to write a comment
Failure/Error: expect(current_path).to eq(movie_path(#movie.comments.last.id))
expected: "/movies/2"
got: "/movies/4"
(compared using ==)
# ./spec/features/comments_spec.rb:26:in `block (2 levels) in <top (required)>'
Then I save the comment_spec.rb again and get this:
Adding comments to movies permits a signed in member to write a comment
Failure/Error: expect(current_path).to eq(movie_path(#movie.comments.last.id))
expected: "/movies/3"
got: "/movies/15"
(compared using ==)
# ./spec/features/comments_spec.rb:26:in `block (2 levels) in <top (required)>'
After this happens, I run:
bundle exec rails db:test:prepare
Then the tests pass again, but the above repeats. What in the world is making this happen? haha, but really?
My GitHub if needed.
The issue you're having is that your database isn't being reset after each feature test, as you likely expect it is. Specifically, the problem is with Capybara and the config.use_transactional_fixtures = true line which is set in your spec config.
Capybara effectively tests your application as an external process using a virtual browser. This means that your capybara tests only have visibility into the client-side behavior of your app (i.e. the page variable). In other words, from Capybara's perspective your app is a "Black box". Therefore, capaybara doesn't see controller objects like your session, params, or request variables, nor can it see or control the specific database transactions which occur during testing.
Rather than relying on transactional fixtures, consider using database cleaner, which manually resets the database after each feature test. You can find the gem here: https://github.com/DatabaseCleaner/database_cleaner. Make sure you follow the directions on integrating with Capybara: https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example.
I followed a few tutorials and docs of FactoryGirl to use with RSpec. Currently I get one error when trying to use FactoryGirl.create:
describe "GenericRecipesController" do
describe "GET 'index'" do
it "displays list of generic recipes" do
generic_recipe = FactoryGirl.create(:generic_recipe)
visit '/recipe'
response.should be_success
end
end
end
And the error:
GenericRecipesController GET 'index' displays list of generic recipes
Failure/Error: generic_recipe = FactoryGirl.create(:generic_recipe)
NameError:
uninitialized constant GenericRecipe
# ./spec/integration/generic_recipes_spec.rb:8:in `block (3 levels) in <top (required)>'
The rest of code is there.
You can try this:
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
# ...
end
I think problem in a nesting model in module
Upd: delete file /spec/factories.rb, in file /spec/support/factories.rb make
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
When you will run tests, probably will see 'can not load table'. Make
rake db:migrate RAILS_ENV=test
and try again.
You don't seem to have a GenericRecipe model in your app. Factory Girl is looking for a Model called GenericReciper and can't find it.
I'm following this tutorial to get started with TDD on rails with factory girl, rspec and i ran into this issue i can't get my head around.
Here's my "factory".rb (events.rb)
require 'faker'
FactoryGirl.define do
factory :event do
name "HIGH"
genre "house, techno, idb"
venue_name "Westbourne Studios"
venue_address "4-6 Chamberlayne Road"
venue_postcode "NW103JD"
begin_time "10pm"
end_time "2am"
user_id 2
description "A Super massive party with loads of everything you would want around."
status true
venue_id nil
end
end
and here's the event_spec.rb:
require 'spec_helper'
require 'factory_girl_rails'
describe Event do
it "has a valid factory" do
Factory.create(:event).should be_valid
end
it "is invalid without a name"
it "is invalid without a genre"
it "is invalid without a venue_name"
it "is invalid without a venue_address"
it "is invalid without a venue_postcode"
...
end
I have setup the model, migrated etc.. and when i run "rspec spec/models/event_spec.rb" i get the following error:
Failures:
1) Event has a valid factory
Failure/Error: Factory.create(:event).should be_valid
NameError:
uninitialized constant Factory
# ./spec/models/event_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.1682 seconds
13 examples, 1 failure, 12 pending
Failed examples:
rspec ./spec/models/event_spec.rb:6 # Event has a valid factory
Randomized with seed 64582
Try to use it in this way:
FactoryGirl.create(:event).should be_valid
I think, I can remember, that it was only "Factory" in old versions of the gem. If you take a look in the recent "Getting started" guide of Factory Girl, there are only calls with "FactoryGirl".
If you create file spec/support/factory_girl.rb with content:
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
Then you can simply use:
create(:event)
build(:book)
Instead of:
FactogyGirl.create(:event)
FactogyGirl.build(:book)
I had the same error with factory bot, and to supplement Stefan's answer I came across this little cheat sheet.
https://devhints.io/factory_bot