require File.expand_path(File.dirname(__FILE__)+'/test_helper')
describe 'Textcaptcha' do
describe 'validations' do
before(:each) do
@note = Note.new
@note.textcaptcha
end
it 'should validate an ActiveRecord object (with multiple correct answers)' do
@note.spam_question.must_equal('1+1')
@note.valid?.must_equal false
@note.errors[:spam_answer].first.must_equal('is incorrect, try another question instead')
@note.spam_answer = 'two'
@note.valid?.must_equal true
@note.errors[:spam_answer].must_be_empty
@note.spam_answer = '2'
@note.valid?.must_equal true
@note.errors[:spam_answer].must_be_empty
end
it 'should strip whitespace and downcase spam answer' do
@note.spam_answer = ' tWo '
@note.valid?.must_equal true
@note.errors[:spam_answer].must_be_empty
end
it 'should always be valid when record has been saved' do
@note.spam_answer = '2'
@note.save!
@note.textcaptcha
@note.spam_answer = 'wrong answer'
@note.new_record?.must_equal false
@note.valid?.must_equal true
@note.errors[:spam_answer].must_be_empty
end
it 'should always be valid when perform_textcaptcha? is false' do
@note.turn_off_captcha = true
@note.valid?.must_equal true
@note.errors[:spam_answer].must_be_empty
@note.save.must_equal true
end
it 'should validate a non ActiveRecord object' do
@contact = Contact.new
@contact.textcaptcha
@contact.spam_question.must_equal('one+1')
@contact.spam_answer = 'wrong'
@contact.valid?.must_equal false
@contact.spam_answer = 'two'
@contact.valid?.must_equal true
@contact.errors[:spam_answer].must_be_empty
end
it 'should allow validation to be skipped' do
@note.valid?.must_equal false
@note.skip_textcaptcha = true
@note.valid?.must_equal true
end
it 'should protect skip_textcaptcha attribute from mass assignment' do
@note = Note.new(:skip_textcaptcha => true)
@note.skip_textcaptcha.must_equal nil
end
end
describe 'encryption' do
before(:each) do
@note = Note.new
end
it 'should encrypt spam_answers (joined by - seperator) MD5 digested and using BCrypt engine with salt' do
@note.spam_answers.must_be_nil
@note.textcaptcha
encrypted_answers = [2,' TwO '].collect { |answer| BCrypt::Engine.hash_secret(Digest::MD5.hexdigest(answer.to_s.strip.downcase), '$2a$10$j0bmycH.SVfD1b5mpEGPpe', 1) }.join('-')
@note.spam_answers.must_equal('$2a$10$j0bmycH.SVfD1b5mpEGPpePFe1wBxOn7Brr9lMuLRxv6lg4ZYjJ22-$2a$10$j0bmycH.SVfD1b5mpEGPpe8v5mqqpDaExuS/hZu8Xkq8krYL/T8P.')
@note.spam_answers.must_equal(encrypted_answers)
end
it 'should raise error if bcyrpt salt is invalid' do
@note.textcaptcha_config[:bcrypt_salt] = 'bad salt'
proc { @note.textcaptcha }.must_raise BCrypt::Errors::InvalidSalt
@note.textcaptcha_config[:bcrypt_salt] ='$2a$10$j0bmycH.SVfD1b5mpEGPpe'
end
end
describe 'textcaptcha API' do
after(:each) do
FakeWeb.clean_registry
end
it 'should generate spam question from the service' do
@review = Review.new
@review.textcaptcha
@review.spam_question.wont_be_nil
@review.spam_question.wont_equal('The green hat is what color?')
@review.spam_answers.wont_be_nil
@review.valid?.must_equal false
@review.errors[:spam_answer].first.must_equal('is incorrect, try another question instead')
end
it 'should parse a single answer from XML response' do
@review = Review.new
question = 'If tomorrow is Saturday, what day is today?'
body = "#{question}f6f7fec07f372b7bd5eb196bbca0f3f4"
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :body => body)
@review.textcaptcha
@review.spam_question.must_equal(question)
@review.spam_answers.must_equal('$2a$10$j0bmycH.SVfD1b5mpEGPpecvhlumIBvWXI4HQWk0xa74DebZDx772')
@review.spam_answers.split('-').length.must_equal(1)
end
it 'should parse multiple answers from XML response' do
@review = Review.new
question = 'If tomorrow is Saturday, what day is today?'
body = "#{question}123"
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :body => body)
@review.textcaptcha
@review.spam_question.must_equal(question)
@review.spam_answers.split('-').length.must_equal(3)
end
describe 'service is unavailable' do
describe 'should fallback to a user defined question' do
before(:each) do
@review = Review.new
end
it 'when errors occur' do
[SocketError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, URI::InvalidURIError].each do |error|
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :exception => error)
@review.textcaptcha
@review.spam_question.must_equal('The green hat is what color?')
@review.spam_answers.wont_be_nil
end
end
it 'when response is OK but body cannot be parsed as XML' do
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :body => 'here be gibberish')
@review.textcaptcha
@review.spam_question.must_equal('The green hat is what color?')
@review.spam_answers.wont_be_nil
end
it 'when response is OK but empty' do
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :body => '')
@review.textcaptcha
@review.spam_question.must_equal('The green hat is what color?')
@review.spam_answers.wont_be_nil
end
end
end
it 'should not generate any spam question or answer when no user defined questions set' do
@comment = Comment.new
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :exception => SocketError)
@comment.textcaptcha
@comment.spam_question.must_equal 'ActsAsTextcaptcha >> no API key (or questions) set and/or the textcaptcha service is currently unavailable (answer ok to bypass)'
@comment.spam_answers.must_equal 'ok'
end
it 'should not generate any spam question or answer when user defined questions set incorrectly' do
@comment = MovieReview.new
FakeWeb.register_uri(:get, %r|http://textcaptcha\.com/api/|, :exception => SocketError)
@comment.textcaptcha
@comment.spam_question.must_equal 'ActsAsTextcaptcha >> no API key (or questions) set and/or the textcaptcha service is currently unavailable (answer ok to bypass)'
@comment.spam_answers.must_equal 'ok'
end
end
describe 'configuration' do
it 'should be configured with inline hash' do
Review.textcaptcha_config.must_equal({ :api_key => '8u5ixtdnq9csc84cok0owswgo',
:bcrypt_salt => '$2a$10$j0bmycH.SVfD1b5mpEGPpe',
:bcrypt_cost => '3',
:questions => [{ 'question' => 'The green hat is what color?', 'answers' => 'green' }]})
end
it 'should be configured with textcaptcha.yml' do
Widget.textcaptcha_config[:api_key].must_equal '6eh1co0j12mi2ogcoggkkok4o'
Widget.textcaptcha_config[:bcrypt_salt].must_equal '$2a$10$qhSefD6gKtmq6M0AzXk4CO'
Widget.textcaptcha_config[:bcrypt_cost].must_equal 1
Widget.textcaptcha_config[:questions].length.must_equal 10
end
end
end