.gitignore 0100644 0000000 0000000 00000000026 12263007475 013313 0 ustar 00wheel wheel 0000000 0000000 rdoc
pkg
Gemfile.lock
CHANGELOG 0100644 0000000 0000000 00000001266 12263007475 012544 0 ustar 00wheel wheel 0000000 0000000 == 0.3.5 / 2012-05-02
* I18n for error messages
* Rails: delete flash keys if unused
== 0.3.4 / 2011-12-13
* Rails 3
* Remove jeweler
== 0.2.2 / 2009-09-14
* Add a timeout to the validator
* Give the documentation some love
== 0.2.1 / 2009-09-14
* Removed Ambethia namespace, and restructured classes a bit
* Added an example rails app in the example-rails branch
== 0.2.0 / 2009-09-12
* RecaptchaOptions AJAX API Fix
* Added 'cucumber' as a test environment to skip
* Ruby 1.9 compat fixes
* Added option :message => 'Custom error message' to verify_recaptcha
* Removed dependency on ActiveRecord constant
* Add I18n
== 0.1.0 / 2008-2-8
* 1 major enhancement
* Initial Gem Release
Gemfile 0100644 0000000 0000000 00000000047 12263007475 012621 0 ustar 00wheel wheel 0000000 0000000 source 'https://rubygems.org'
gemspec
LICENSE 0100644 0000000 0000000 00000002040 12263007475 012326 0 ustar 00wheel wheel 0000000 0000000 Copyright (c) 2007 Jason L Perry
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. README.rdoc 0100644 0000000 0000000 00000013230 12263007475 013132 0 ustar 00wheel wheel 0000000 0000000 = reCAPTCHA
Author:: Jason L Perry (http://ambethia.com)
Copyright:: Copyright (c) 2007-2013 Jason L Perry
License:: {MIT}[http://creativecommons.org/licenses/MIT/]
Info:: http://github.com/ambethia/recaptcha
Bugs:: http://github.com/ambethia/recaptcha/issues
This plugin adds helpers for the {reCAPTCHA API}[http://recaptcha.net]. In your
views you can use the +recaptcha_tags+ method to embed the needed javascript,
and you can validate in your controllers with +verify_recaptcha+.
Beforehand you need to configure Recaptcha with your custom private and public
key. You may find detailed examples below. Exceptions will be raised if you
call these methods and the keys can't be found.
== Rails Installation
reCAPTCHA for Rails > 3.0, add this to your Gemfile:
gem "recaptcha", :require => "recaptcha/rails"
Rails apps below 3.0 are no longer supported, but you can install an older
release and view it's README.
== Setting up your API Keys
There are multiple ways to setup your reCAPTCHA API key once you
{obtain}[http://recaptcha.net/whyrecaptcha.html] a pair.
=== Recaptcha.configure
You may use the block style configuration. The following code could be placed
into a +config/initializers/recaptcha.rb+ when used in a Rails project.
Recaptcha.configure do |config|
config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
config.proxy = 'http://myproxy.com.au:8080'
end
This way, you may also set additional options to fit recaptcha into your
deployment environment.
== Recaptcha#with_configuration
If you want to temporarily overwrite the configuration you set with `Recaptcha.configure` (when testing, for example), you can use a `Recaptcha#with_configuration` block:
Recaptcha.with_configuration(:public_key => '12345') do
# Do stuff with the overwritten public_key.
end
=== Heroku & Shell environment
Or, you can keep your keys out of your code base by exporting the following
environment variables. You might do this in the .profile/rc, or equivalent for
the user running your application. This would also be the preffered method
in an Heroku deployment.
export RECAPTCHA_PUBLIC_KEY = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
export RECAPTCHA_PRIVATE_KEY = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
=== Per call
You can also pass in your keys as options at runtime, for example:
recaptcha_tags :public_key => '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
and later,
verify_recaptcha :private_key => '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
This option might be useful, if the same code base is used for multiple
reCAPTCHA setups.
== To use 'recaptcha'
Add +recaptcha_tags+ to each form you want to protect. Place it where you want the recaptcha widget to appear.
Example:
<%= form_for @foo do |f| %>
# ... additional lines truncated for brevity ...
<%= recaptcha_tags %>
# ... additional lines truncated for brevity ...
<% end %>
And, add +verify_recaptcha+ logic to each form action that you've protected.
=== +recaptcha_tags+
Some of the options available:
:ssl :: Uses secure http for captcha widget (default +false+, but can be changed by setting +config.use_ssl_by_default+)
:noscript :: Include content (default +true+)
:display :: Takes a hash containing the +theme+ and +tabindex+ options per the API. (default +nil+), options: 'red', 'white', 'blackglass', 'clean', 'custom'
:ajax :: Render the dynamic AJAX captcha per the API. (default +false+)
:public_key :: Your public API key, takes precedence over the ENV variable (default +nil+)
:error :: Override the error code returned from the reCAPTCHA API (default +nil+)
You can also override the html attributes for the sizes of the generated +textarea+ and +iframe+
elements, if CSS isn't your thing. Inspect the source of +recaptcha_tags+ to see these options.
=== +verify_recaptcha+
This method returns +true+ or +false+ after processing the parameters from the reCAPTCHA widget. Why
isn't this a model validation? Because that violates MVC. You can use it like this, or how ever you
like. Passing in the ActiveRecord object is optional, if you do--and the captcha fails to verify--an
error will be added to the object for you to use.
Some of the options available:
:model :: Model to set errors
:attribute :: Model attribute to receive errors (default :base)
:message :: Custom error message
:private_key :: Your private API key, takes precedence over the ENV variable (default +nil+).
:timeout :: The number of seconds to wait for reCAPTCHA servers before give up. (default +3+)
respond_to do |format|
if verify_recaptcha(:model => @post, :message => "Oh! It's error with reCAPTCHA!") && @post.save
# ...
else
# ...
end
end
== I18n support
reCAPTCHA passes two types of error explanation to a linked model. It will use the I18n gem
to translate the default error message if I18n is available. To customize the messages to your locale,
add these keys to your I18n backend:
recaptcha.errors.verification_failed :: error message displayed if the captcha words didn't match
recaptcha.errors.recaptcha_unreachable :: displayed if a timeout error occured while attempting to verify the captcha
Also you can translate API response errors to human friendly by adding translations to the locale (+config/locales/en.yml+):
en:
recaptcha:
errors:
incorrect-captcha-sol: 'Fail'
== TODO
* Remove Rails/ActionController dependencies
* Framework agnostic
* Add some helpers to use in before_filter and what not
* Better documentation
Rakefile 0100644 0000000 0000000 00000000253 12263007475 012772 0 ustar 00wheel wheel 0000000 0000000 require "bundler/gem_tasks"
require "rake/testtask"
Rake::TestTask.new :test do |test|
test.libs << "lib"
test.pattern = "test/*_test.rb"
end
task :default => :test
init.rb 0100644 0000000 0000000 00000000301 12263007475 012607 0 ustar 00wheel wheel 0000000 0000000 # Rails plugin initialization.
# You can also install it as a gem:
# config.gem "ambethia-recaptcha", :lib => "recaptcha/rails", :source => "http://gems.github.com"
require 'recaptcha/rails' lib/recaptcha.rb 0100644 0000000 0000000 00000002431 12263007475 014352 0 ustar 00wheel wheel 0000000 0000000 require 'recaptcha/configuration'
require 'recaptcha/client_helper'
require 'recaptcha/verify'
module Recaptcha
RECAPTCHA_API_SERVER_URL = '//www.google.com/recaptcha/api'
RECAPTCHA_API_SECURE_SERVER_URL = 'https://www.google.com/recaptcha/api'
RECAPTCHA_VERIFY_URL = 'http://www.google.com/recaptcha/api/verify'
USE_SSL_BY_DEFAULT = false
HANDLE_TIMEOUTS_GRACEFULLY = true
SKIP_VERIFY_ENV = ['test', 'cucumber']
# Gives access to the current Configuration.
def self.configuration
@configuration ||= Configuration.new
end
# Allows easy setting of multiple configuration options. See Configuration
# for all available options.
#--
# The temp assignment is only used to get a nicer rdoc. Feel free to remove
# this hack.
#++
def self.configure
config = configuration
yield(config)
end
def self.with_configuration(config)
original_config = {}
config.each do |key, value|
original_config[key] = configuration.send(key)
configuration.send("#{key}=", value)
end
result = yield if block_given?
original_config.each { |key, value| configuration.send("#{key}=", value) }
result
end
class RecaptchaError < StandardError
end
end
if defined?(Rails)
require 'recaptcha/rails'
end
lib/recaptcha/client_helper.rb 0100644 0000000 0000000 00000006061 12263007475 017172 0 ustar 00wheel wheel 0000000 0000000 module Recaptcha
module ClientHelper
# Your public API can be specified in the +options+ hash or preferably
# using the Configuration.
def recaptcha_tags(options = {})
# Default options
key = options[:public_key] ||= Recaptcha.configuration.public_key
raise RecaptchaError, "No public key specified." unless key
error = options[:error] ||= ((defined? flash) ? flash[:recaptcha_error] : "")
uri = Recaptcha.configuration.api_server_url(options[:ssl])
lang = options[:display] && options[:display][:lang] ? options[:display][:lang].to_sym : ""
html = ""
if options[:display]
html << %{\n}
end
if options[:ajax]
html << <<-EOS
EOS
else
html << %{\n}
unless options[:noscript] == false
html << %{\n }
html << %{ \n }
html << %{\n }
html << %{ }
html << %{ \n}
end
end
return (html.respond_to?(:html_safe) && html.html_safe) || html
end # recaptcha_tags
private
def hash_to_json(hash)
result = "{"
result << hash.map do |k, v|
if v.is_a?(Hash)
"\"#{k}\": #{hash_to_json(v)}"
elsif ! v.is_a?(String) || k.to_s == "callback"
"\"#{k}\": #{v}"
else
"\"#{k}\": \"#{v}\""
end
end.join(", ")
result << "}"
end
end # ClientHelper
end # Recaptcha
lib/recaptcha/configuration.rb 0100644 0000000 0000000 00000003751 12263007475 017227 0 ustar 00wheel wheel 0000000 0000000 module Recaptcha
# This class enables detailed configuration of the recaptcha services.
#
# By calling
#
# Recaptcha.configuration # => instance of Recaptcha::Configuration
#
# or
# Recaptcha.configure do |config|
# config # => instance of Recaptcha::Configuration
# end
#
# you are able to perform configuration updates.
#
# Your are able to customize all attributes listed below. All values have
# sensitive default and will very likely not need to be changed.
#
# Please note that the public and private key for the reCAPTCHA API Access
# have no useful default value. The keys may be set via the Shell enviroment
# or using this configuration. Settings within this configuration always take
# precedence.
#
# Setting the keys with this Configuration
#
# Recaptcha.configure do |config|
# config.public_key = '6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy'
# config.private_key = '6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx'
# end
#
class Configuration
attr_accessor :nonssl_api_server_url,
:ssl_api_server_url,
:verify_url,
:skip_verify_env,
:private_key,
:public_key,
:proxy,
:handle_timeouts_gracefully,
:use_ssl_by_default
def initialize #:nodoc:
@nonssl_api_server_url = RECAPTCHA_API_SERVER_URL
@ssl_api_server_url = RECAPTCHA_API_SECURE_SERVER_URL
@verify_url = RECAPTCHA_VERIFY_URL
@skip_verify_env = SKIP_VERIFY_ENV
@handle_timeouts_gracefully = HANDLE_TIMEOUTS_GRACEFULLY
@use_ssl_by_default = USE_SSL_BY_DEFAULT
@private_key = ENV['RECAPTCHA_PRIVATE_KEY']
@public_key = ENV['RECAPTCHA_PUBLIC_KEY']
end
def api_server_url(ssl = nil) #:nodoc:
ssl = use_ssl_by_default if ssl.nil?
ssl ? ssl_api_server_url : nonssl_api_server_url
end
end
end
lib/recaptcha/merb.rb 0100644 0000000 0000000 00000000204 12263007475 015273 0 ustar 00wheel wheel 0000000 0000000 require 'recaptcha'
Merb::GlobalHelpers.send(:include, Recaptcha::ClientHelper)
Merb::Controller.send(:include, Recaptcha::Verify)
lib/recaptcha/rails.rb 0100644 0000000 0000000 00000000231 12263007475 015460 0 ustar 00wheel wheel 0000000 0000000 require 'net/http'
require 'recaptcha'
ActionView::Base.send(:include, Recaptcha::ClientHelper)
ActionController::Base.send(:include, Recaptcha::Verify) lib/recaptcha/railtie.rb 0100644 0000000 0000000 00000000517 12263007475 016006 0 ustar 00wheel wheel 0000000 0000000 require 'net/http'
require 'recaptcha'
module Rails
module Recaptcha
class Railtie < Rails::Railtie
initializer "setup config" do
begin
ActionView::Base.send(:include, ::Recaptcha::ClientHelper)
ActionController::Base.send(:include, ::Recaptcha::Verify)
end
end
end
end
end
lib/recaptcha/verify.rb 0100644 0000000 0000000 00000005524 12263007475 015664 0 ustar 00wheel wheel 0000000 0000000 require "uri"
module Recaptcha
module Verify
# Your private API can be specified in the +options+ hash or preferably
# using the Configuration.
def verify_recaptcha(options = {})
if !options.is_a? Hash
options = {:model => options}
end
env = options[:env] || ENV['RAILS_ENV']
return true if Recaptcha.configuration.skip_verify_env.include? env
model = options[:model]
attribute = options[:attribute] || :base
private_key = options[:private_key] || Recaptcha.configuration.private_key
raise RecaptchaError, "No private key specified." unless private_key
begin
recaptcha = nil
if(Recaptcha.configuration.proxy)
proxy_server = URI.parse(Recaptcha.configuration.proxy)
http = Net::HTTP::Proxy(proxy_server.host, proxy_server.port, proxy_server.user, proxy_server.password)
else
http = Net::HTTP
end
Timeout::timeout(options[:timeout] || 3) do
recaptcha = http.post_form(URI.parse(Recaptcha.configuration.verify_url), {
"privatekey" => private_key,
"remoteip" => request.remote_ip,
"challenge" => params[:recaptcha_challenge_field],
"response" => params[:recaptcha_response_field]
})
end
answer, error = recaptcha.body.split.map { |s| s.chomp }
unless answer == 'true'
flash[:recaptcha_error] = if defined?(I18n)
I18n.translate("recaptcha.errors.#{error}", {:default => error})
else
error
end
if model
message = "Word verification response is incorrect, please try again."
message = I18n.translate('recaptcha.errors.verification_failed', {:default => message}) if defined?(I18n)
model.errors.add attribute, options[:message] || message
end
return false
else
flash.delete(:recaptcha_error)
return true
end
rescue Timeout::Error
if Recaptcha.configuration.handle_timeouts_gracefully
flash[:recaptcha_error] = if defined?(I18n)
I18n.translate('recaptcha.errors.recaptcha_unreachable', {:default => 'Recaptcha unreachable.'})
else
'Recaptcha unreachable.'
end
if model
message = "Oops, we failed to validate your word verification response. Please try again."
message = I18n.translate('recaptcha.errors.recaptcha_unreachable', :default => message) if defined?(I18n)
model.errors.add attribute, options[:message] || message
end
return false
else
raise RecaptchaError, "Recaptcha unreachable."
end
rescue Exception => e
raise RecaptchaError, e.message, e.backtrace
end
end # verify_recaptcha
end # Verify
end # Recaptcha
lib/recaptcha/version.rb 0100644 0000000 0000000 00000000051 12263007475 016033 0 ustar 00wheel wheel 0000000 0000000 module Recaptcha
VERSION = "0.3.6"
end
recaptcha.gemspec 0100644 0000000 0000000 00000001446 12263007475 014631 0 ustar 00wheel wheel 0000000 0000000 # -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "recaptcha/version"
Gem::Specification.new do |s|
s.name = "recaptcha"
s.version = Recaptcha::VERSION
s.authors = ["Jason L Perry"]
s.email = ["jasper@ambethia.com"]
s.homepage = "http://github.com/ambethia/recaptcha"
s.summary = %q{Helpers for the reCAPTCHA API}
s.description = %q{This plugin adds helpers for the reCAPTCHA API}
s.rubyforge_project = "recaptcha"
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.require_paths = ["lib"]
s.add_development_dependency "mocha"
s.add_development_dependency "rake"
s.add_development_dependency "activesupport"
s.add_development_dependency "i18n"
end
test/recaptcha_test.rb 0100644 0000000 0000000 00000003562 12263007475 015630 0 ustar 00wheel wheel 0000000 0000000 require 'test/unit'
require 'cgi'
require File.dirname(File.expand_path(__FILE__)) + '/../lib/recaptcha'
class RecaptchaClientHelperTest < Test::Unit::TestCase
include Recaptcha
include Recaptcha::ClientHelper
include Recaptcha::Verify
attr_accessor :session
def setup
@session = {}
Recaptcha.configure do |config|
config.public_key = '0000000000000000000000000000000000000000'
config.private_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
end
end
def test_recaptcha_tags
# Might as well match something...
assert_match /"\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
end
def test_ssl_by_default
Recaptcha.configuration.use_ssl_by_default = true
assert_match /https:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags
end
def test_relative_protocol_by_default_without_ssl
Recaptcha.configuration.use_ssl_by_default = false
assert_match /\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags(:ssl => false)
end
def test_recaptcha_tags_with_ssl
assert_match /https:\/\/www.google.com\/recaptcha\/api\/challenge/, recaptcha_tags(:ssl => true)
end
def test_recaptcha_tags_without_noscript
assert_no_match /noscript/, recaptcha_tags(:noscript => false)
end
def test_should_raise_exception_without_public_key
assert_raise RecaptchaError do
Recaptcha.configuration.public_key = nil
recaptcha_tags
end
end
def test_different_configuration_within_with_configuration_block
key = Recaptcha.with_configuration(:public_key => '12345') do
Recaptcha.configuration.public_key
end
assert_equal('12345', key)
end
def test_reset_configuration_after_with_configuration_block
Recaptcha.with_configuration(:public_key => '12345')
assert_equal('0000000000000000000000000000000000000000', Recaptcha.configuration.public_key)
end
end
test/verify_recaptcha_test.rb 0100644 0000000 0000000 00000013004 12263007475 017204 0 ustar 00wheel wheel 0000000 0000000 # coding: utf-8
require 'test/unit'
require 'rubygems'
require 'active_support'
require 'active_support/core_ext/string'
require 'mocha/setup'
require 'i18n'
require 'net/http'
require File.dirname(File.expand_path(__FILE__)) + '/../lib/recaptcha'
class RecaptchaVerifyTest < Test::Unit::TestCase
def setup
Recaptcha.configuration.private_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
@controller = TestController.new
@controller.request = stub(:remote_ip => "1.1.1.1")
@controller.params = {:recaptcha_challenge_field => "challenge", :recaptcha_response_field => "response"}
@expected_post_data = {}
@expected_post_data["privatekey"] = Recaptcha.configuration.private_key
@expected_post_data["remoteip"] = @controller.request.remote_ip
@expected_post_data["challenge"] = "challenge"
@expected_post_data["response"] = "response"
@expected_uri = URI.parse(Recaptcha.configuration.verify_url)
end
def test_should_raise_exception_without_private_key
assert_raise Recaptcha::RecaptchaError do
Recaptcha.configuration.private_key = nil
@controller.verify_recaptcha
end
end
def test_should_return_false_when_key_is_invalid
expect_http_post(response_with_body("false\ninvalid-site-private-key"))
assert !@controller.verify_recaptcha
assert_equal "invalid-site-private-key", @controller.flash[:recaptcha_error]
end
def test_returns_true_on_success
@controller.flash[:recaptcha_error] = "previous error that should be cleared"
expect_http_post(response_with_body("true\n"))
assert @controller.verify_recaptcha
assert_nil @controller.flash[:recaptcha_error]
end
def test_errors_should_be_added_to_model
expect_http_post(response_with_body("false\nbad-news"))
errors = mock
errors.expects(:add).with(:base, "Word verification response is incorrect, please try again.")
model = mock(:errors => errors)
assert !@controller.verify_recaptcha(:model => model)
assert_equal "bad-news", @controller.flash[:recaptcha_error]
end
def test_returns_true_on_success_with_optional_key
@controller.flash[:recaptcha_error] = "previous error that should be cleared"
# reset private key
@expected_post_data["privatekey"] = 'ADIFFERENTPRIVATEKEYXXXXXXXXXXXXXX'
expect_http_post(response_with_body("true\n"))
assert @controller.verify_recaptcha(:private_key => 'ADIFFERENTPRIVATEKEYXXXXXXXXXXXXXX')
assert_nil @controller.flash[:recaptcha_error]
end
def test_timeout
expect_http_post(Timeout::Error, :exception => true)
assert !@controller.verify_recaptcha()
assert_equal "Recaptcha unreachable.", @controller.flash[:recaptcha_error]
end
def test_timeout_when_handle_timeouts_gracefully_disabled
Recaptcha.with_configuration(:handle_timeouts_gracefully => false) do
expect_http_post(Timeout::Error, :exception => true)
assert_raise Recaptcha::RecaptchaError, "Recaptcha unreachable." do
assert @controller.verify_recaptcha()
end
assert_nil @controller.flash[:recaptcha_error]
end
end
def test_message_should_use_i18n
I18n.locale = :de
verification_failed_translated = "Sicherheitscode konnte nicht verifiziert werden."
verification_failed_default = "Word verification response is incorrect, please try again."
recaptcha_unreachable_translated = "Netzwerkfehler, bitte versuchen Sie es später erneut."
recaptcha_unreachable_default = "Oops, we failed to validate your word verification response. Please try again."
I18n.expects(:translate).with('recaptcha.errors.bad-news', {:default => 'bad-news'})
I18n.expects(:translate).with('recaptcha.errors.recaptcha_unreachable', {:default => 'Recaptcha unreachable.'})
I18n.expects(:translate).with('recaptcha.errors.verification_failed', :default => verification_failed_default).returns(verification_failed_translated)
I18n.expects(:translate).with('recaptcha.errors.recaptcha_unreachable', :default => recaptcha_unreachable_default).returns(recaptcha_unreachable_translated)
errors = mock
errors.expects(:add).with(:base, verification_failed_translated)
errors.expects(:add).with(:base, recaptcha_unreachable_translated)
model = mock; model.stubs(:errors => errors)
expect_http_post(response_with_body("false\nbad-news"))
@controller.verify_recaptcha(:model => model)
expect_http_post(Timeout::Error, :exception => true)
@controller.verify_recaptcha(:model => model)
end
def test_it_translates_api_response_with_i18n
api_error_translated = "Bad news, body :("
expect_http_post(response_with_body("false\nbad-news"))
I18n.expects(:translate).with('recaptcha.errors.bad-news', :default => 'bad-news').returns(api_error_translated)
assert !@controller.verify_recaptcha
assert_equal api_error_translated, @controller.flash[:recaptcha_error]
end
def test_it_fallback_to_api_response_if_i18n_translation_is_missing
expect_http_post(response_with_body("false\nbad-news"))
assert !@controller.verify_recaptcha
assert_equal 'bad-news', @controller.flash[:recaptcha_error]
end
private
class TestController
include Recaptcha::Verify
attr_accessor :request, :params, :flash
def initialize
@flash = {}
end
end
def expect_http_post(response, options = {})
unless options[:exception]
Net::HTTP.expects(:post_form).with(@expected_uri, @expected_post_data).returns(response)
else
Net::HTTP.expects(:post_form).raises response
end
end
def response_with_body(body)
stub(:body => body)
end
end