Rails MailForm Gem captcha validation not passing test - ruby-on-rails-5

I am using the
MailForm Gem
to create a contact form for my app and everything seems to be working just fine so I decided to write some tests to make sure it stays that way.
class ContactsControllerTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
end
test "should send contact email" do
get contact_path
post contacts_path, params: { contact: {
name: "interested customer",
email: "interested#customer.com",
subject: "we are interested!",
message: "we are so interested!!!"
}}
assert_equal 1, ActionMailer::Base.deliveries.size
assert_redirected_to root_path
end
test "should not send invalid contact email" do
get contact_path
post contacts_path, params: { contact: {
name: "",
email: "",
subject: "",
message: ""
}}
assert_equal 0, ActionMailer::Base.deliveries.size
assert_template 'contacts/new'
end
test "should not send contact email with captcha filled" do
get contact_path
post contacts_path, params: { contact: {
name: "interested customer",
email: "interested#customer.com",
subject: "we are interested!",
message: "we are so interested!!!",
nickname: "not_blank"
}}
assert_equal 0, ActionMailer::Base.deliveries.size
assert_template 'contacts/new'
end
the first two tests pass while the third fails with the message
FAIL["test_should_not_send_contact_email_with_captcha_filled", ContactsControllerTest, 5.2574800989968935]
test_should_not_send_contact_email_with_captcha_filled#ContactsControllerTest (5.26s)
Expected: 0
Actual: 1
test/controllers/contacts_controller_test.rb:35:in `block in <class:ContactsControllerTest>'
My model looks like this.
class Contact < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+ ([\w]{2,})\z/i
attribute :subject
attribute :message
attribute :nickname, :captcha => true
def headers
{
:subject => "Contact: #{subject}" ,
:to => "myemail#mail.com",
:from => %("#{name}" <#{email}>)
}
end
end
My first thought was that the captcha validation is not stopping the mail from being sent. If someone could point out what I am missing I would appreciate it.

The mailform model returns valid, even if the nickname is given. But you can check if it is spam, which prohibits the mail from being sent.
I use this to check if the spam detection works(with rspec):
it 'should be marked spam if it contains :nickname' do
expect(FactoryGirl.build(:contact_with_nickname)).to be_spam
end

Related

#<ActionController::ParameterMissing: param is missing or the value is empty: user>

Gone through a lot of answers but still couldn't find the solution.
I have been trying to get a successful response for a POST request to the following controller,
def create
#user = User.new(user_params)
if #user.save
render json: #user, status: :created, location: #user
else
render json: #user.errors, status: :unprocessable_entity
end
private
def user_params
params.require(:user).permit(:name, :email, :phone, :password)
end
end
Although I send all the parameters mentioned,in the request,I am still facing the error.
"status": 400,
"error": "Bad Request",
"exception": "#<ActionController::ParameterMissing: param is missing or the value is empty: user>"
I am using rails version 5.2.1
If you look at the logs, what does the data transferred in your post request look like?
When you get that type of error, often it's because you send the data like this:
{ first_name: 'John', last_name: 'Doe', ...}
When the server expects you to nest this into a user object (hence the require(:user) in your strong_params:
{ user: { first_name: 'John', ... } }
This is Worked for me.
I made just only one hash in params method instead of nested hash.
my user_params method was:-
def user_params
params.permit(:name, :email, :phone, :password)
end
OR You can you your method but your paramter passed in user hash like below.
{user: {name: "bittu", email: "abc#yopmail.com", phome: 123456, password: "123456" } }

Ruby Motion, Rails 3.x, Devise login through custom api/v1/sessions_controller.rb

I'm using this lucatironi tutorial to do my RM/rails/devise native authentication. I got everything working except one piece where I authenticate in the sessions_controller.rb
I'm sending in
{ session : { email: "test#five.com", password: "password" } } (bubblewrap is forcing a 'sessions' node onto my JSON!)
resource_name is :api_v1_user
controller_path is "api/v1/sessions"
class Api::V1::SessionsController < Devise::SessionsController
def create
warden.authenticate!(:scope => resource_name, :store => false, :recall => "#{controller_path}#failure")
render :status => 200,
:json => { :success => true,
:info => "Logged in",
:data => { :auth_token => current_user.authentication_token } }
end
end
All I get is an alert in the app "Login Failed"
Thanks for any help
Did you remember to call skip_before_filter :verify_authenticity_token? Given that the request is not coming from a rails-generated form, the token wouldn't be there.
So I figured this out.
authenticate! doesn't return annything
has to be "authenticate" with no "!"
that was it!

RSpec uniqueness email test fails with FactoryGirl

Edit
Using the answers to the question I changed the test to the following which tests correctly and passes..
describe "when email is already taken" do
let(:user_with_same_email) { #user.dup }
before do
user_with_same_email.email.upcase!
user_with_same_email.save
end
it { user_with_same_email.should_not be_valid }
end
Note: Not using let(:user_with_same_email) { #user.dup } makes the test fail as it cannot find the variable user_with_same_email if it's simply duplicated in the before block as in the chosen answer to this question.
I have a User model and a user_spec.rb test file which has various validations against the User models attributes.
Previously I was writing the following at the top of my user_spec.rb file to test the User model:
describe User do
before do
#user = User.new(name: "Example User", email: "user#example.com",
password: "foobar88", password_confirmation: "foobar88")
end
...
I wanted to move this model creation to FactoryGirl so I created a factories.rb file:
FactoryGirl.define do
factory :user do
name "foo"
email { "#{name}#example.com" }
password "foobar99"
password_confirmation "foobar99"
end
end
I then changed my user_spec.rb:
describe User do
before do
#user = FactoryGirl.create(:user)
end
...
Now every test passes as before except one:
describe "when email is already taken" do
before do
user_with_same_email = #user.dup
user_with_same_email.email = #user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
Now unless `FactoryGirl is skipping my email uniqueness validation I can't figure out what is going wrong here.
My User model validation code:
class User < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i unless const_defined?(:VALID_EMAIL_REGEX)
has_secure_password
attr_accessible :name, :email, :password, :password_confirmation
has_many :programs
before_save { self.email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
The problem is that when you say it { should_not be_valid }, RSpec checks the subject. in this case the subject is User.new (you have "describe User" at the top so unless you specified something else this is the default).
You want to check the user_with_same_email for validity instead.
edit:
Try this, I think it might work:
describe "when email is already taken" do
before do
#user_with_same_email = #user.dup
#user_with_same_email.email = #user.email.upcase
#user_with_same_email.save
end
it { #user_with_same_email.should_not be_valid }
end
Looks like perhaps you're doing (or referencing) Michael Hartl's Rails Tutorial. Here's what my code looks like for what you're doing, so I hope it can be of use:
spec/models/user_spec.rb
describe User do
let(:user) { valid_user }
subject { user }
# ...
context "when email address is already taken" do
before { save_user(user) }
it { should_not be_valid }
end
# ...
end
spec/support/utilities.rb (to create a specific user)
def valid_user
User.new(name: "Example User",
email: "user#example.com",
password: "foobar",
password_confirmation: "foobar")
end
# ...
def save_user(user)
user_with_same_email = user.dup
user_with_same_email.email.upcase!
user_with_same_email.save
end
For reference: spec/factories.rb (to just create any old random user)
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}#example.com" }
password "foobar"
password_confirmation "foobar"
# ...
end
# ...
end
Update: Found the answer you were looking for at this StackOverflow answer outlining the same problem. I tested it with my code as well and it worked for me.
Update 2: Changed my code around as well, using FactoryGirl.build for times when I want a user but don't want it saved to the database. This StackOverflow answer helped me understand.
spec/models/user_spec.rb
describe User do
let(:user) { FactoryGirl.create(:user) }
subject { user }
# ...
context "when email address is already taken" do
let(:user_with_same_email) do
FactoryGirl.build(:user, email: user.email)
end
subject { user_with_same_email }
before do
user_with_same_email.email.upcase!
user_with_same_email.save
end
it { should_not be_valid }
end
# ...
end
Thanks for asking this question. Gave me some food for thought and some refactoring to do in my own code.

Failing test in ruby tutorial (Michael Hartl)

I'm studying Michael Hartl's tutorial. I'm using RSPEC to run the test.
So far so good but it seems that I've hit the wall with the following example.
Here is the test that fails (it should pass):
describe "authenticate method" do
it "should return the user on email/password match" do
matching_user = User.authenticate(#attr[:email], #attr[:password])
matching_user.should == #user
end
end
Just in case.
#user defined as:
before(:each) do
#user = User.create!(#attr)
end
#attr defined as:
before(:each) do
#attr = {
:name => "Example user",
:email => "user#example.com",
:password => "foobar",
:password_confirmation => "foobar"
}
end
Entries in user.rb
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
Error message displayed when the test is failing
c:\RailsInstaller\work\apptwit>rspec spec/models/user_spec.rb
.................F
Failures:
1) User password validations password encryption authenticate method should return the user on email/password
Failure/Error: matching_user.should == #user
expected: #<User id: 1, name: "Example user", email: "user#example.com", created_at: "2011-12-07 19:08:23
ed_at: "2011-12-07 19:08:23", encrypted_password: "fbdbaf712fa1b6c925c4ab2192e73ac9f9d1bedf67630610d68...">
got: nil (using ==)
# ./spec/models/user_spec.rb:204:in `block (5 levels) in <top (required)>'
Finished in 221.37 seconds
18 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:202 # User password validations password encryption authenticate method should
he user on email/password match
I would appreciate any pointers,
Thanks a lot.
If matching_user is nil, then you might want to put some puts email and puts user.inspect statements in self.authenticate to debug it.
It seems as though it's either not able to find the user by email or your password is incorrect for some reason in the authenticate method.

Rails 3 + Rspec 2: Validation failed: Email has already been taken

I have 2 models, User and Bucket. User has_many Buckets and a Bucket belongs_to a User.
In factories.rb, I have:
Factory.define :user do |user|
user.email "teste#test.com"
user.password "foobar"
user.password_confirmation "foobar"
end
Factory.sequence :email do |n|
"person-#{n}#example.com"
end
Factory.define :bucket do |bucket|
bucket.email "user#example.com"
bucket.confirmation false
bucket.association :user
end
and I have a login_user module as follows:
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
#user = Factory.create(:user)
##user.confirm!
sign_in #user
end
end
I am using Spork and Watch and my Buckets_controller_spec.rb is as simple as:
describe "User authenticated: " do
login_user
#bucket = Factory(:bucket)
it "should get index" do
get 'index'
response.should be_success
end
...
end
The error is always the same:
Failures:
1) BucketsController User authenticated: should get index
Failure/Error: Unable to find matching line from backtrace
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
# ./lib/controller_macros.rb:12:in `block in login_user'
And it only happens when I have the Factory(:bucket). The login works fine when I don't add the Factory(:bucket).
It's always the same error. I have tried adding :email => Factory.next(:email) to the user, but no success.
Edit:
In rails c test:
ruby-1.9.2-p180 :019 > bucket = Factory(:bucket, :email => "hello#hello.com")
ActiveRecord::RecordInvalid: Validation failed: Email has already been taken
ruby-1.9.2-p180 :018 > Bucket.create(:email => "hello#hello.com")
=> #<Bucket id: 2, email: "hello#hello.com", confirmation: nil, created_at: "2011-04-08 21:59:12", updated_at: "2011-04-08 21:59:12", user_id: nil>
Edit 2:
I found out that the error is in the association, however, I don't know how to fix it.
bucket.association :user
When you define a factory with an association you need to give the factory an object to associate with whenever you use the factory.
This should work:
describe "User authenticated: " do
login_user
#bucket = Factory(:bucket, :user => #user)
it "should get index" do
get 'index'
response.should be_success
end
end
That way factorygirl knows to make a bucket which is associated with #user.
Try this in your user factory:
Factory.define :user do |f|
f.sequence(:email) { |n| "test#{n}#example.com" }
...
end
I think that's probably your problem. When you use f.email = "anyvalue" it's going to use that value every time. I see you were trying to create a sequence in the next block, but I'm not sure that sequence is getting used.
ALSO - be aware that if you get tests interrupted by a crash or something, sometimes bogus test data can get left in your test DB instead of being rolled back.
Very first thing I try if something worked once and then quit working is to reset the test db.
rake db:test:prepare
That will clean everything out.
If this doesn't work let me know and I'll take a second look!
If someone is getting this recently with your views. Try using Database Cleaner.
For more info: RailsTutorial - chapter 8.4.3 - Test database not clearing after adding user in integration test