How to use mongoid-rspec gem properly? - ruby

Following instructions I have installed mongoid-rspec and configured it in spec_helper.rb
RSpec.configure do |config|
config.include Mongoid::Matchers, type: :model
end
But came across an issue with the simplest test
describe City do
it { should have_many(:locations) }
end
City should have many :locations
Failure/Error: it { should have_many(:locations) }
NoMethodError:
undefined method `has_many?' for
Seems I'm doing it wrong, but can't figure out what's exactly wrong.
The models are pretty simple
class City
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Paranoia
include Mongoid::Versioning
max_versions 10
has_many :locations
end
class Location
include Mongoid::Document
belongs_to :city
field :name, type: String
end
One last thing, I don't use Rails.

I came across similar issue but whilst working on rails, solution for both rails and none rails I believe are very similar:
gem 'mongoid-rspec', '~> 2.2.0'
Without rails
Add to your spec_helper.rb file:
require 'mongoid-rspec'
RSpec.configure do |config|
config.include Mongoid::Matchers
end
With rails
Add to your rails_helper.rb
require 'mongoid-rspec'
RSpec.configure do |config|
config.include Mongoid::Matchers, type: :model
end

In my spec_helper file i removed the option type: :model and it now works
RSpec.configure do |config|
config.include Mongoid::Matchers
end

Related

“including Capybara::DSL in the global scope is not recommended!” want to remove it. console warning

To resolve the error visit is not found. I have included include Capybara::DSL in one of my helper module like this:
I am using ruby 2.7.0
include Capybara::DSL
module LoginHelper
def self.login_user
visit 'https://staging.have2have.it/login'
within(".container-fluid") do
fill_in("email", with: 'shinsaurab#gmail.com', :match => :prefer_exact)
fill_in("password", with: '123', :match => :prefer_exact)
end
click_button('Log In')
end
end
spec_helper.rb
require 'capybara'
require 'capybara/dsl'
require 'capybara/rspec'
require './spec/helpers/login_helper'
Capybara.default_driver = :selenium
RSpec.configure do |config|
config.include Capybara::DSL
config.include LoginHelper
end
Can anyone please suggest if I am doing something wrong. I have tried some suggestion but didn't work for me
I was having a similar issue tried many things but what worked for me is to remove config.include Capybara::DSL from spec_helper and include the LoginHelper in a Helpers module. In your case, they may look like this:
login_helper.rb
module Helpers
module LoginHelper
def login_user
visit 'https://staging.have2have.it/login'
within(".container-fluid") do
fill_in("email", with: 'shinsaurab#gmail.com', :match => :prefer_exact)
fill_in("password", with: '123', :match => :prefer_exact)
end
click_button('Log In')
end
end
end
And spec_helper will look like this:
require 'capybara'
require 'capybara/dsl'
require 'capybara/rspec'
require './spec/helpers/login_helper.rb'
Capybara.default_driver = :selenium
RSpec.configure do |config|
config.include Helpers::LoginHelper
end
Thanks!
Please let me know if you have any doubts

uninitialized constant User::PhotoUploader

Iam trying to use mini_magick,but after following the git guide i still recieve uninitialized constant. i have another project working just fine using the same syntax.. however must be missing something ..
photo_uploader.rb
class PhotoUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def default_url
"photo.jpg"
end
#right orientation
def right_orientation
manipulate! do |img|
img.auto_orient
img
end
end
def filename
"photo.jpg" if original_filename
end
end
user.rb
require 'bcrypt'
require 'carrierwave'
require 'carrierwave/orm/activerecord'
class User < ActiveRecord::Base
belongs_to :pakars
has_many :courses
scoped_search on: [:name1, :name2]
mount_uploader :photo, PhotoUploader
attr_accessor :password, :password_confirmation
def self.authenticate(email, pass)
u=where("email =?", email).first
return nil if u.nil?
return u if BCrypt::Password.new(u.hashed_password) == pass
nil
end
def password=(pass)
self.hashed_password = BCrypt::Password.create(pass)
end
end
Here is the error
uninitialized constant User::PhotoUploader
Rails.root: C:/Users/User/Desktop/Ruby_training/Project/Pakar_my
and yes i already installed the gems
Gemfile
#carrier wave
gem 'carrierwave'
#mini_magick
gem 'mini_magick' , '3.7.0'
I think you need to add carrierwave to your application.rb file like this:
require File.expand_path('../boot', __FILE__)
require 'rails/all'
require 'carrierwave'
if defined?(Bundler)
# Bundler stuff
end
Try this may be it's work for you
Or sometime just restart rails server and after it everything worked
fine. :)

Rspec + Factory girl (without rails!)

I am using Rspec with selenium-webdriver gem to test a web app. And I wanted to unclude factories in my tests to emulate users and not to create a user manually each time.
So, I made gem install factory_girl, added required lined in my spec_helper, created a factory and included some lines in my spec file. And when running the test I get an error
Failure/Error: FactoryGirl.build(:user)
NameError:
uninitialized constant User
Here is my spec_helper.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
My factories.rb file:
FactoryGirl.define do
factory :user do
name "testuser"
password "freestyle"
inventory true
end
end
And my test_spec file:
require "json"
require "selenium-webdriver"
require "rspec"
require "factory_girl"
FactoryGirl.find_definitions
include RSpec::Expectations
describe "MallSpec" do
before(:all) do
FactoryGirl.build(:user)
#driver = Selenium::WebDriver.for :firefox
#base_url = "http://localhost:9000/"
#accept_next_alert = true
#driver.manage.timeouts.implicit_wait = 30
#driver.manage.window.resize_to(1301, 744)
#verification_errors = []
end
My spec_file is in the root dir of the project. my factories.rb file is in /spec dir as well as the test_spec.rb itself.
Can anyone help me with this issue or point what i am doing wrong?
If you don't actually have a User class but you want to use FactoryGirl to generate the attributes, you can override the class:
require "ostruct"
FactoryGirl.define do
factory :user, class: OpenStruct do
name "testuser"
password "freestyle"
inventory true
# This isn't necessary, but it will prevent FactoryGirl from trying
# to call #save on the built instance.
to_create {}
end
end
You can then use attributes_for if you just want a Hash, or create if you want an object that responds to methods like name.
You can use a library like Hashie::Mash if you want to generate JSON for use in your API:
factory :user, class: Hashie::Mash do
# ...
end
# In your tests:
user_json = create(:user).to_json
And when running the test I get an error Failure/Error:
FactoryGirl.build(:user) NameError: uninitialized constant User
Your User class has to be defined. The following is a test with no User class defined:
require 'factory_girl'
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
FactoryGirl.define do
factory :user do
name 'Alice'
age 10
end
end
describe "MallSpec" do
let(:test_user) { FactoryGirl.build(:user) }
describe "user's name" do
it "equals 'Alice'" do
expect(test_user.name).to eq('Alice')
end
end
end
--output:--
$ rspec 1.rb
F
Failures:
1) MallSpec user's name equals 'Alice'
Failure/Error: let(:user) { FactoryGirl.build(:user) }
NameError:
uninitialized constant User
...
Adding a definition for the User class:
require 'factory_girl'
#====NEW CODE=====
class User
attr_accessor :name, :age
end
#=================
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
FactoryGirl.define do
factory :user do
name 'Alice'
age 10
end
end
describe "MallSpec" do
let(:test_user) { FactoryGirl.build(:user) }
describe "user's name" do
it "equals 'Alice'" do
expect(test_user.name).to eq('Alice')
end
end
end
--output:--
$ rspec 1.rb
.
Finished in 0.0024 seconds (files took 0.35197 seconds to load)
1 example, 0 failures
I expect that the factory() method here:
factory :user do
name 'Alice'
age 10
end
...does something like this:
def factory(model_name)
target_class = constant_get(model_name.capitalize)
...in order to construct a real instance of the User class. In other words, factory_girl constructs instances of classes that already exist in your app--factory_girl does not mock a class.

Why am I getting FactoryGirl wrong number of arguments error?

Having strange behavior from FactoryGirl in non-rails app. getting wrong number of arguments error...don't know why.
gideon#thefonso ~/Sites/testing (master)$ rspec spec
/Users/gideon/.rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/syntax/default.rb:6:in `define': wrong number of arguments (1 for 0) (ArgumentError)
from /Users/gideon/Sites/testing/spec/factories.rb:1:in `<top (required)>'
Here are the files involved...
login_user_spec.rb
require_relative '../spec_helper'
require_relative '../lib/login_user'
describe "Existing User Log in Scenario", :type => :request do
before :all do
#user = FactoryGirl(:user)
end
xit "should allow user to select login from top nav" do
visit "/"
within("#main-header")do
click_link 'Log In'
end
page.should have_content('Log in to your account')
end
it "and fill in login form" do
visit "/login"
within("#login-form")do
fill_in 'user-email', :with => #user.email
fill_in 'user-password', :with => #user.password
end
#FIXME - the design crew will make this go away
within("#login-form") do
click_link '#login-link' #this gives false failing test...geek query...why?
end
page.should have_content('Manage courses')
end
end
Factories.rb
FactoryGirl.define :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
user.rb
class User
attr_accessor :email, :password
end
spec_helper.rb
require 'rubygems'
require 'bundler/setup'
require 'capybara'
require 'rspec'
require 'capybara/rspec'
require 'json'
require 'capybara/dsl'
# Capybara configuration
Capybara.default_driver = :selenium
Capybara.app_host = "http://www.website.com"
require 'factory_girl'
# give me ma stuff
FactoryGirl.find_definitions
require "rspec/expectations"
include Capybara::DSL
include RSpec::Matchers
ANSWER: :user is a reserved word..changed it to :stuff...works fine now.
Try to use new syntax from readme
FactoryGirl.define do
factory :user do
email "joe#website.com"
password "joe009"
end
end
If this is a non-rails app you will have to create a Userclass first. I'm not sure if you have to have instance vars with name, password and email but you definitely will have to have that class defined somewhere.
See the Getting Started file on Github for more on that.
Try this
FactoryGirl.define do
factory :user do |u|
u.email "joe#website.com"
u.password "joe009"
end
end

Automatically share context in RSpec

I want to share a memoized method between my specs. So I tried to use shared context like this
RSpec.configure do |spec|
spec.shared_context :specs do
let(:response) { request.execute! }
end
end
describe 'something' do
include_context :specs
end
It works ok. But I have about 60 spec files, so I'm forced to explicitly include context in each of them. Is there an way to automatically include shared context (or at least let definition) for all example groups in spec_helper.rb?
Something like this
RSpec.configure do |spec|
spec.include_context :specs
end
You can set up global before hooks using RSpec.configure via configure-class-methods and Configuration:
RSpec.configure {|c| c.before(:all) { do_stuff }}
let is not supported in RSpec.configure, but you can set up a global let by including it in a SharedContext module and including that module using config.before:
module MyLetDeclarations
extend RSpec::Core::SharedContext
let(:foo) { Foo.new }
end
RSpec.configure { |c| c.include MyLetDeclarations }
In RSpec 3+, this can be achieved as follows - based on Jeremy Peterson's answer.
# spec/supprt/users.rb
module SpecUsers
extend RSpec::SharedContext
let(:admin_user) do
create(:user, email: 'admin#example.org')
end
end
RSpec.configure do |config|
config.include SpecUsers
end
You can do it almost like that: there's a mechanism for including a module, and module inclusion has its own callback mechanism.
Suppose for example that we have a disconnected shared context that we want to use to run all our model specs without a database connection.
shared_context "disconnected" do
before :all do
ActiveRecord::Base.establish_connection(adapter: :nulldb)
end
after :all do
ActiveRecord::Base.establish_connection(:test)
end
end
You can now create a module that will include that context on inclusion.
module Disconnected
def self.included(scope)
scope.include_context "disconnected"
end
end
Finally, you can include that module into all specs in the normal manner (I've demonstrated doing it only for models, just to show that you can), which is almost exactly what you asked for.
RSpec.configure do |config|
config.include Disconnected, type: :model
end
That works with rspec-core 2.13.0 and rspec-rails 2.13.0.
Another way to go is to automatically share examples via metadata. So:
shared_context 'a shared context', a: :b do
let(:foo) { 'bar' }
end
describe 'an example group', a: :b do
# I have access to 'foo' variable
end
The most common way I use it is in rspec-rails, with some shared context depending on the example group type. So if you have config.infer_spec_type_from_file_location!, you can simply do:
shared_context 'a shared context', type: :controller do
let(:foo) { 'bar' }
end
describe SomeController do
# I have access to 'foo' variable
end
Also if you need ability to use shared data in before blocks inside specs, as me, try to include this (if its Rails project):
module SettingsHelper
extend ActiveSupport::Concern
included do
attr_reader :default_headers
before :all do
#default_headers = Hash[
'HTTP_HOST' => 'test.lvh.me'
]
end
after :all do
#default_headers = nil
end
end
end
RSpec.configure do |config|
config.include SettingsHelper
end
Or try something similar, look at #threedaymonk answer.

Resources