acts_as_textcaptcha 4.2.0 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.rubocop.yml +1165 -0
- data/.simplecov +11 -0
- data/.travis.yml +30 -8
- data/Appraisals +9 -6
- data/CHANGELOG.md +94 -34
- data/CODE_OF_CONDUCT.md +54 -31
- data/CONTRIBUTING.md +14 -9
- data/Gemfile +2 -2
- data/LICENSE +165 -0
- data/PULL_REQUEST_TEMPLATE.md +16 -0
- data/README.md +206 -228
- data/Rakefile +26 -19
- data/acts_as_textcaptcha.gemspec +57 -41
- data/bin/console +2 -5
- data/bin/setup +7 -0
- data/gemfiles/rails_3.gemfile +1 -0
- data/gemfiles/rails_4.gemfile +2 -1
- data/gemfiles/rails_5.gemfile +2 -1
- data/gemfiles/rails_6.gemfile +8 -0
- data/lib/acts_as_textcaptcha.rb +9 -4
- data/lib/acts_as_textcaptcha/errors.rb +21 -0
- data/lib/acts_as_textcaptcha/framework/rails.rb +3 -1
- data/lib/acts_as_textcaptcha/railtie.rb +9 -0
- data/lib/acts_as_textcaptcha/tasks/textcaptcha.rake +17 -0
- data/lib/acts_as_textcaptcha/textcaptcha.rb +75 -72
- data/lib/acts_as_textcaptcha/textcaptcha_api.rb +39 -45
- data/lib/acts_as_textcaptcha/textcaptcha_cache.rb +12 -16
- data/lib/acts_as_textcaptcha/textcaptcha_config.rb +47 -0
- data/lib/acts_as_textcaptcha/textcaptcha_helper.rb +13 -14
- data/lib/acts_as_textcaptcha/version.rb +3 -1
- metadata +68 -46
- data/.coveralls.yml +0 -1
- data/LICENSE.txt +0 -21
- data/config/textcaptcha.yml +0 -34
- data/lib/tasks/textcaptcha.rake +0 -21
- data/test/schema.rb +0 -34
- data/test/test_helper.rb +0 -44
- data/test/test_models.rb +0 -69
- data/test/textcaptcha_api_test.rb +0 -46
- data/test/textcaptcha_cache_test.rb +0 -25
- data/test/textcaptcha_helper_test.rb +0 -68
- data/test/textcaptcha_test.rb +0 -198
data/.coveralls.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
service_name: travis-ci
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2016 Matthew Hutchinson
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
data/config/textcaptcha.yml
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
development: &common_settings
|
2
|
-
api_key: PASTE_YOUR_TEXTCAPCHA_API_KEY_HERE # grab one from http://textcaptcha.com/api
|
3
|
-
http_read_timeout: 60 # Optional seconds to wait for one block to be read from http://textcaptcha.com/api
|
4
|
-
# http_open_timeout: 10 # Optional seconds to wait for the connection to open
|
5
|
-
# cache_expiry_minutes: 10 # Optional minutes for captcha answers to persist in the cache (default 10 minutes)
|
6
|
-
|
7
|
-
questions:
|
8
|
-
- question: 'Is ice hot or cold?'
|
9
|
-
answers: 'cold'
|
10
|
-
- question: 'what color is an orange?'
|
11
|
-
answers: 'orange'
|
12
|
-
- question: 'what is two plus 3?'
|
13
|
-
answers: '5,five'
|
14
|
-
- question: 'what is 5 times two?'
|
15
|
-
answers: '10,ten'
|
16
|
-
- question: 'How many colors in the list, green, brown, foot and blue?'
|
17
|
-
answers: '3,three'
|
18
|
-
- question: 'what is Georges name?'
|
19
|
-
answers: 'george'
|
20
|
-
- question: '11 minus 1?'
|
21
|
-
answers: '10,ten'
|
22
|
-
- question: 'is boiling water hot or cold?'
|
23
|
-
answers: 'hot'
|
24
|
-
- question: 'what color is my blue shirt today?'
|
25
|
-
answers: 'blue'
|
26
|
-
- question: 'what is 16 plus 4?'
|
27
|
-
answers: '20,twenty'
|
28
|
-
|
29
|
-
test:
|
30
|
-
<<: *common_settings
|
31
|
-
api_key: 6eh1co0j12mi2ogcoggkkok4o
|
32
|
-
|
33
|
-
production:
|
34
|
-
<<: *common_settings
|
data/lib/tasks/textcaptcha.rake
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
namespace :textcaptcha do
|
2
|
-
|
3
|
-
desc "Creates a template config file in config/textcaptcha.yml"
|
4
|
-
task :config do
|
5
|
-
src = File.join(File.dirname(__FILE__), '../..', 'config', 'textcaptcha.yml')
|
6
|
-
dest = File.join(Rails.root, 'config', 'textcaptcha.yml')
|
7
|
-
if File.exist?(dest)
|
8
|
-
puts "\nOoops, a textcaptcha config file at #{dest} already exists ... aborting.\n\n"
|
9
|
-
else
|
10
|
-
config = ''
|
11
|
-
f = File.open(src, 'r')
|
12
|
-
f.each_line { |line| config += line }
|
13
|
-
config.gsub!(/ api_key:(.*)# for gem test purposes only$/, " api_key: PASTE_YOUR_TEXTCAPCHA_API_KEY_HERE")
|
14
|
-
|
15
|
-
f = File.new(dest, 'w')
|
16
|
-
f.write(config)
|
17
|
-
f.close
|
18
|
-
puts "\ntextcaptcha.yml generated at #{dest}\nNOTE: edit this file and add your textcaptcha api key, grab one from http://textcaptcha.com/api\n\n"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/test/schema.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
ActiveRecord::Schema.define(:version => 0) do
|
2
|
-
|
3
|
-
create_table :widgets, :force => true do |t|
|
4
|
-
t.string :name
|
5
|
-
end
|
6
|
-
|
7
|
-
create_table :comments, :force => true do |t|
|
8
|
-
t.string :name
|
9
|
-
end
|
10
|
-
|
11
|
-
create_table :fast_comments, :force => true do |t|
|
12
|
-
t.string :name
|
13
|
-
end
|
14
|
-
|
15
|
-
create_table :reviews, :force => true do |t|
|
16
|
-
t.string :name
|
17
|
-
end
|
18
|
-
|
19
|
-
create_table :movie_reviews, :force => true do |t|
|
20
|
-
t.string :name
|
21
|
-
end
|
22
|
-
|
23
|
-
create_table :notes, :force => true do |t|
|
24
|
-
t.string :name
|
25
|
-
end
|
26
|
-
|
27
|
-
create_table :strong_protected_widgets, :force => true do |t|
|
28
|
-
t.string :name
|
29
|
-
end
|
30
|
-
|
31
|
-
create_table :strong_accessible_widgets, :force => true do |t|
|
32
|
-
t.string :name
|
33
|
-
end
|
34
|
-
end
|
data/test/test_helper.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)+'./../lib/acts_as_textcaptcha'))
|
2
|
-
|
3
|
-
ENV['RAILS_ENV'] = 'test'
|
4
|
-
|
5
|
-
# ensure tmp dir exists
|
6
|
-
FileUtils.mkdir_p './tmp'
|
7
|
-
|
8
|
-
# confgure test coverage reporting
|
9
|
-
if ENV['COVERAGE']
|
10
|
-
require 'simplecov'
|
11
|
-
SimpleCov.start do
|
12
|
-
add_filter '/test/'
|
13
|
-
add_filter '/vendor/'
|
14
|
-
end
|
15
|
-
SimpleCov.at_exit do
|
16
|
-
SimpleCov.result.format!
|
17
|
-
`open ./coverage/index.html` if RUBY_PLATFORM =~ /darwin/
|
18
|
-
end
|
19
|
-
elsif ENV['TRAVIS']
|
20
|
-
require 'coveralls'
|
21
|
-
Coveralls.wear!
|
22
|
-
end
|
23
|
-
|
24
|
-
require 'minitest/autorun'
|
25
|
-
require 'webmock/minitest'
|
26
|
-
require 'rails/all'
|
27
|
-
require 'acts_as_textcaptcha'
|
28
|
-
require './test/test_models'
|
29
|
-
|
30
|
-
# load and initialize test db schema
|
31
|
-
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => 'tmp/acts_as_textcaptcha_test.sqlite3.db')
|
32
|
-
load(File.dirname(__FILE__) + "/schema.rb")
|
33
|
-
|
34
|
-
# initialize the Rails cache (use a basic memory store in tests)
|
35
|
-
if Rails.version >= '4'
|
36
|
-
Rails.cache = ActiveSupport::Cache::MemoryStore.new
|
37
|
-
else
|
38
|
-
RAILS_CACHE = ActiveSupport::Cache::MemoryStore.new
|
39
|
-
end
|
40
|
-
|
41
|
-
# additional helper methods for use in tests
|
42
|
-
def find_in_cache(key)
|
43
|
-
Rails.cache.read("#{ActsAsTextcaptcha::TextcaptchaCache::CACHE_KEY_PREFIX}#{key}")
|
44
|
-
end
|
data/test/test_models.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# models for use in tests
|
2
|
-
class ApplicationRecord < ActiveRecord::Base
|
3
|
-
self.abstract_class = true
|
4
|
-
end
|
5
|
-
|
6
|
-
class Widget < ApplicationRecord
|
7
|
-
# uses textcaptcha.yml file for configuration
|
8
|
-
acts_as_textcaptcha
|
9
|
-
end
|
10
|
-
|
11
|
-
class Comment < ApplicationRecord
|
12
|
-
# inline options (symbol keys) with api_key only
|
13
|
-
acts_as_textcaptcha :api_key => '8u5ixtdnq9csc84cok0owswgo'
|
14
|
-
end
|
15
|
-
|
16
|
-
class FastComment < ApplicationRecord
|
17
|
-
# inline options with super fast (0.006 seconds) cache expiry time
|
18
|
-
acts_as_textcaptcha :cache_expiry_minutes => '0.0001',
|
19
|
-
:questions => [{ :question => '1+1', :answers => '2,two' }]
|
20
|
-
end
|
21
|
-
|
22
|
-
class Review < ApplicationRecord
|
23
|
-
# inline options with all possible options
|
24
|
-
acts_as_textcaptcha :api_key => '8u5ixtdnq9csc84cok0owswgo',
|
25
|
-
:questions => [{ :question => 'The green hat is what color?', :answers => 'green' }]
|
26
|
-
end
|
27
|
-
|
28
|
-
class MovieReview < ApplicationRecord
|
29
|
-
# inline options with all possible options
|
30
|
-
acts_as_textcaptcha 'api_key' => '8u5ixtdnq9csc84cok0owswgo',
|
31
|
-
'questions' => [{ 'Question' => 'The green hat is what color?', 'answers' => nil }]
|
32
|
-
end
|
33
|
-
|
34
|
-
class Note < ApplicationRecord
|
35
|
-
# inline options (string keys) with user defined questions only (no textcaptcha service)
|
36
|
-
acts_as_textcaptcha 'questions' => [{ 'question' => '1+1', 'answers' => '2,two' }]
|
37
|
-
|
38
|
-
# allows toggling perform_textcaptcha on/off (default on)
|
39
|
-
attr_accessor :turn_off_captcha
|
40
|
-
|
41
|
-
def perform_textcaptcha?
|
42
|
-
super && !turn_off_captcha
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class Contact
|
47
|
-
# non active record object (symbol keys), no API used
|
48
|
-
include ActiveModel::Validations
|
49
|
-
include ActiveModel::Conversion
|
50
|
-
extend ActsAsTextcaptcha::Textcaptcha
|
51
|
-
acts_as_textcaptcha :questions => [{ :question => 'one+1', :answers => "2,two,апельсин" }]
|
52
|
-
end
|
53
|
-
|
54
|
-
class StrongAccessibleWidget < ApplicationRecord
|
55
|
-
|
56
|
-
# stub out attr_accessbile interface for testing
|
57
|
-
def self.accessible_attributes(role = :default); end
|
58
|
-
def self.attr_accessible(*args); end
|
59
|
-
|
60
|
-
acts_as_textcaptcha 'questions' => [{ 'question' => '1+1', 'answers' => '2,two' }]
|
61
|
-
end
|
62
|
-
|
63
|
-
class StrongProtectedWidget < StrongAccessibleWidget
|
64
|
-
|
65
|
-
# stub out attr_protected interface for testing
|
66
|
-
def self.attr_protected(*args); end
|
67
|
-
|
68
|
-
acts_as_textcaptcha 'questions' => [{ 'question' => '1+1', 'answers' => '2,two' }]
|
69
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
|
-
|
3
|
-
describe 'TextcaptchaApi' do
|
4
|
-
|
5
|
-
describe 'with a valid xml response' do
|
6
|
-
|
7
|
-
before(:each) do
|
8
|
-
body = "<captcha><question>1+1?</question><answer>1</answer><answer>2</answer><answer>3</answer></captcha>"
|
9
|
-
stub_request(:get, "http://textcaptcha.com/api/abc").to_return(:body => body)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should fetch and parse an answer from the service' do
|
13
|
-
result = ActsAsTextcaptcha::TextcaptchaApi.fetch('abc')
|
14
|
-
result[0].must_equal '1+1?'
|
15
|
-
result[1].must_equal ['1', '2', '3']
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'should allow http options to be set' do
|
19
|
-
result = ActsAsTextcaptcha::TextcaptchaApi.fetch('abc', { :http_read_timeout => 30,
|
20
|
-
:http_open_timeout => 5 })
|
21
|
-
result.length.must_equal 2
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should return nil when Net::HTTP errors occur' do
|
26
|
-
[
|
27
|
-
SocketError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
28
|
-
Errno::EHOSTUNREACH, EOFError, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
29
|
-
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
|
30
|
-
URI::InvalidURIError
|
31
|
-
].each do |error|
|
32
|
-
stub_request(:get, "http://textcaptcha.com/api/xyz").to_raise(error)
|
33
|
-
assert_nil ActsAsTextcaptcha::TextcaptchaApi.fetch('xyz')
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'should return nil when body cannot be parsed as XML' do
|
38
|
-
stub_request(:get, "http://textcaptcha.com/api/jibber").to_return(:body => 'here be gibberish')
|
39
|
-
assert_nil ActsAsTextcaptcha::TextcaptchaApi.fetch('jibber')
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should return nil when body is empty' do
|
43
|
-
stub_request(:get, "http://textcaptcha.com/api/empty").to_return(:body => '')
|
44
|
-
assert_nil ActsAsTextcaptcha::TextcaptchaApi.fetch('empty')
|
45
|
-
end
|
46
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
|
-
|
3
|
-
describe 'TextcaptchaCache' do
|
4
|
-
|
5
|
-
before(:each) do
|
6
|
-
@cache = ActsAsTextcaptcha::TextcaptchaCache.new
|
7
|
-
@cache.write('mykey', [1,2,3])
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'should write to the cache' do
|
11
|
-
@cache.write('my-new-key', 'abc')
|
12
|
-
@cache.read('my-new-key').must_equal 'abc'
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should read from the cache' do
|
16
|
-
@cache.read('mykey').must_equal [1,2,3]
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should delete from the cache' do
|
20
|
-
@cache.read('mykey').must_equal [1,2,3]
|
21
|
-
@cache.delete('mykey')
|
22
|
-
|
23
|
-
assert_nil @cache.read('mykey')
|
24
|
-
end
|
25
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
|
-
require 'action_controller'
|
3
|
-
require 'action_view'
|
4
|
-
|
5
|
-
class NotesController < ActionController::Base; end
|
6
|
-
|
7
|
-
class Template < ActionView::Base
|
8
|
-
def protect_against_forgery?; false; end
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
describe 'TextcaptchaHelper' do
|
13
|
-
|
14
|
-
before(:each) do
|
15
|
-
@controller = NotesController.new
|
16
|
-
@note = Note.new
|
17
|
-
@note.textcaptcha
|
18
|
-
end
|
19
|
-
|
20
|
-
def render_template(assigns = { :note => @note })
|
21
|
-
template = <<-ERB
|
22
|
-
<%= form_for(@note, :url => '/') do |f| %>
|
23
|
-
<%= textcaptcha_fields(f) do %>
|
24
|
-
<div class="field textcaptcha">
|
25
|
-
<%= f.label :textcaptcha_answer, @note.textcaptcha_question %><br/>
|
26
|
-
<%= f.text_field :textcaptcha_answer, :value => '' %>
|
27
|
-
</div>
|
28
|
-
<% end %>
|
29
|
-
<% end %>
|
30
|
-
ERB
|
31
|
-
|
32
|
-
Template.new([], assigns, @controller).render(:inline => template)
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should render question and answer fields, with hidden textcaptcha_key field' do
|
36
|
-
html = render_template
|
37
|
-
|
38
|
-
assert_match(/\<label for\=\"note_textcaptcha_answer\"\>1\+1\<\/label\>/, html)
|
39
|
-
assert_match(/\<input(.*)name\=\"note\[textcaptcha_answer\]\"(.*)\/\>/, html)
|
40
|
-
assert_match(/\<input(.*)name\=\"note\[textcaptcha_key\]\"(.*)\/\>/, html)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should render hidden answer and textcaptcha_key when only answer is present' do
|
44
|
-
@note.textcaptcha_question = nil
|
45
|
-
@note.textcaptcha_answer = 2
|
46
|
-
html = render_template
|
47
|
-
|
48
|
-
refute_match(/\<label for\=\"note_textcaptcha_answer\"\>1\+1\<\/label\>/, html)
|
49
|
-
assert_match(/\<input(.*)name\=\"note\[textcaptcha_answer\]\"(.*)\/\>/, html)
|
50
|
-
assert_match(/\<input(.*)name\=\"note\[textcaptcha_key\]\"(.*)\/\>/, html)
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should not render any question or answer when perform_textcaptcha? is false' do
|
54
|
-
@note.turn_off_captcha = true
|
55
|
-
html = render_template
|
56
|
-
|
57
|
-
refute_match(/note_textcaptcha_answer/, html)
|
58
|
-
refute_match(/note_textcaptcha_key/, html)
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'should not render any question or answer when textcaptcha_key is missing' do
|
62
|
-
@note.textcaptcha_key = nil
|
63
|
-
html = render_template
|
64
|
-
|
65
|
-
refute_match(/note_textcaptcha_answer/, html)
|
66
|
-
refute_match(/note_textcaptcha_key/, html)
|
67
|
-
end
|
68
|
-
end
|
data/test/textcaptcha_test.rb
DELETED
@@ -1,198 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)+'/test_helper')
|
2
|
-
|
3
|
-
describe 'Textcaptcha' do
|
4
|
-
|
5
|
-
describe 'validations' do
|
6
|
-
|
7
|
-
before(:each) do
|
8
|
-
@note = Note.new
|
9
|
-
@note.textcaptcha
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should validate an ActiveRecord object (with multiple correct answers)' do
|
13
|
-
@note.textcaptcha_question.must_equal('1+1')
|
14
|
-
@note.valid?.must_equal false
|
15
|
-
@note.errors[:textcaptcha_answer].first.must_equal('is incorrect, try another question instead')
|
16
|
-
|
17
|
-
@note.textcaptcha_answer = 'two'
|
18
|
-
@note.valid?.must_equal true
|
19
|
-
@note.errors[:textcaptcha_answer].must_be_empty
|
20
|
-
|
21
|
-
@note.textcaptcha_answer = '2'
|
22
|
-
@note.valid?.must_equal true
|
23
|
-
@note.errors[:textcaptcha_answer].must_be_empty
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should strip whitespace and downcase answer' do
|
27
|
-
@note.textcaptcha_answer = ' tWo '
|
28
|
-
@note.valid?.must_equal true
|
29
|
-
@note.errors[:textcaptcha_answer].must_be_empty
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'should always be valid when record has been saved' do
|
33
|
-
@note.textcaptcha_answer = '2'
|
34
|
-
@note.save!
|
35
|
-
@note.textcaptcha
|
36
|
-
|
37
|
-
@note.textcaptcha_answer = 'wrong answer'
|
38
|
-
@note.new_record?.must_equal false
|
39
|
-
@note.valid?.must_equal true
|
40
|
-
@note.errors[:textcaptcha_answer].must_be_empty
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should always be valid when perform_textcaptcha? is false' do
|
44
|
-
@note.turn_off_captcha = true
|
45
|
-
@note.valid?.must_equal true
|
46
|
-
@note.errors[:textcaptcha_answer].must_be_empty
|
47
|
-
|
48
|
-
@note.save.must_equal true
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'should validate a non ActiveRecord object' do
|
52
|
-
@contact = Contact.new
|
53
|
-
@contact.textcaptcha
|
54
|
-
|
55
|
-
@contact.textcaptcha_question.must_equal('one+1')
|
56
|
-
@contact.textcaptcha_answer = 'wrong'
|
57
|
-
@contact.valid?.must_equal false
|
58
|
-
|
59
|
-
@contact.textcaptcha_answer = 'two'
|
60
|
-
@contact.valid?.must_equal true
|
61
|
-
@contact.errors[:textcaptcha_answer].must_be_empty
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe 'with fast expiry time' do
|
66
|
-
|
67
|
-
before(:each) do
|
68
|
-
@comment = FastComment.new
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should work' do
|
72
|
-
@comment.textcaptcha
|
73
|
-
@comment.textcaptcha_question.must_equal('1+1')
|
74
|
-
@comment.textcaptcha_answer = 'two'
|
75
|
-
sleep(0.01)
|
76
|
-
|
77
|
-
@comment.valid?.must_equal false
|
78
|
-
@comment.errors[:textcaptcha_answer].first.must_equal('was not submitted quickly enough, try another question instead')
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe 'textcaptcha API' do
|
83
|
-
|
84
|
-
it 'should generate a question from the service' do
|
85
|
-
@review = Review.new
|
86
|
-
body = "<captcha><question>Something?</question><answer>f6f7fec07f372b7bd5eb196bbca0f3f4</answer></captcha>"
|
87
|
-
stub_request(:get, %r{http://textcaptcha.com/api/}).and_return(:body => body)
|
88
|
-
|
89
|
-
@review.textcaptcha
|
90
|
-
@review.textcaptcha_question.wont_be_nil
|
91
|
-
@review.textcaptcha_question.wont_equal('The green hat is what color?')
|
92
|
-
|
93
|
-
find_in_cache(@review.textcaptcha_key).wont_be_nil
|
94
|
-
|
95
|
-
@review.valid?.must_equal false
|
96
|
-
@review.errors[:textcaptcha_answer].first.must_equal('is incorrect, try another question instead')
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should parse a single answer from XML response' do
|
100
|
-
@review = Review.new
|
101
|
-
question = 'If tomorrow is Saturday, what day is today?'
|
102
|
-
body = "<captcha><question>#{question}</question><answer>f6f7fec07f372b7bd5eb196bbca0f3f4</answer></captcha>"
|
103
|
-
stub_request(:get, %r{http://textcaptcha.com/api/}).and_return(:body => body)
|
104
|
-
|
105
|
-
@review.textcaptcha
|
106
|
-
@review.textcaptcha_question.must_equal(question)
|
107
|
-
find_in_cache(@review.textcaptcha_key).must_equal(['f6f7fec07f372b7bd5eb196bbca0f3f4'])
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'should parse multiple answers from XML response' do
|
111
|
-
@review = Review.new
|
112
|
-
question = 'If tomorrow is Saturday, what day is today?'
|
113
|
-
body = "<captcha><question>#{question}</question><answer>1</answer><answer>2</answer><answer>3</answer></captcha>"
|
114
|
-
stub_request(:get, %r{http://textcaptcha.com/api}).and_return(:body => body)
|
115
|
-
|
116
|
-
@review.textcaptcha
|
117
|
-
@review.textcaptcha_question.must_equal(question)
|
118
|
-
find_in_cache(@review.textcaptcha_key).length.must_equal(3)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'should fallback to a user defined question when api returns nil' do
|
122
|
-
@review = Review.new
|
123
|
-
stub_request(:get, %r{http://textcaptcha.com/api}).and_return(:body => '')
|
124
|
-
@review.textcaptcha
|
125
|
-
@review.textcaptcha_question.must_equal('The green hat is what color?')
|
126
|
-
find_in_cache(@review.textcaptcha_key).wont_be_nil
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'should not generate any question or answer when no user defined questions set' do
|
130
|
-
@comment = Comment.new
|
131
|
-
|
132
|
-
stub_request(:get, %r{http://textcaptcha.com/api/}).to_raise(SocketError)
|
133
|
-
@comment.textcaptcha
|
134
|
-
assert_nil @comment.textcaptcha_question
|
135
|
-
assert_nil @comment.textcaptcha_key
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'should not generate any question or answer when user defined questions set incorrectly' do
|
139
|
-
@comment = MovieReview.new
|
140
|
-
|
141
|
-
stub_request(:get, %r{http://textcaptcha.com/api/}).to_raise(SocketError)
|
142
|
-
@comment.textcaptcha
|
143
|
-
assert_nil @comment.textcaptcha_question
|
144
|
-
assert_nil @comment.textcaptcha_key
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
describe 'configuration' do
|
149
|
-
|
150
|
-
it 'should be configured with inline hash' do
|
151
|
-
Review.textcaptcha_config.must_equal({ :api_key => '8u5ixtdnq9csc84cok0owswgo',
|
152
|
-
:questions => [{ :question => 'The green hat is what color?', :answers => 'green' }]})
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'should be configured with textcaptcha.yml' do
|
156
|
-
Widget.textcaptcha_config[:api_key].must_equal('6eh1co0j12mi2ogcoggkkok4o')
|
157
|
-
Widget.textcaptcha_config[:questions].length.must_equal(10)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
describe 'with strong parameters' do
|
162
|
-
|
163
|
-
it 'should work with accessible_attr widget ' do
|
164
|
-
@widget = StrongAccessibleWidget.new
|
165
|
-
|
166
|
-
@widget.textcaptcha
|
167
|
-
@widget.textcaptcha_question.must_equal('1+1')
|
168
|
-
@widget.valid?.must_equal false
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'should work with protected_attr widget ' do
|
172
|
-
@widget = StrongProtectedWidget.new
|
173
|
-
|
174
|
-
@widget.textcaptcha
|
175
|
-
@widget.textcaptcha_question.must_equal('1+1')
|
176
|
-
@widget.valid?.must_equal false
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
describe 'when missing config' do
|
181
|
-
|
182
|
-
it 'should raise an error' do
|
183
|
-
YAML.stub :load, -> { raise 'some bad things happened' } do
|
184
|
-
|
185
|
-
error = assert_raises(ArgumentError) do
|
186
|
-
class NoConfig
|
187
|
-
include ActiveModel::Validations
|
188
|
-
include ActiveModel::Conversion
|
189
|
-
extend ActsAsTextcaptcha::Textcaptcha
|
190
|
-
acts_as_textcaptcha
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
error.message.must_match(/could not find any textcaptcha options/)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|