bot-away 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +14 -0
- data/History.txt +20 -0
- data/README.md +198 -0
- data/Rakefile +14 -94
- data/bot-away.gemspec +20 -87
- data/gemfiles/Gemfile.rails-3.0.x +8 -0
- data/gemfiles/Gemfile.rails-3.0.x.lock +121 -0
- data/gemfiles/Gemfile.rails-3.1.x +8 -0
- data/gemfiles/Gemfile.rails-3.1.x.lock +133 -0
- data/lib/bot-away.rb +15 -13
- data/lib/bot-away/action_dispatch/params_parser.rb +22 -0
- data/lib/bot-away/action_view/helpers/instance_tag.rb +36 -12
- data/lib/bot-away/param_parser.rb +2 -2
- data/lib/bot-away/railtie.rb +10 -0
- data/lib/bot-away/test_case.rb +58 -0
- data/lib/bot-away/test_case/controller_test_case.rb +11 -0
- data/lib/bot-away/test_case/instance_tag_test_case.rb +15 -0
- data/lib/bot-away/test_case/matchers.rb +20 -0
- data/lib/bot-away/test_case/matchers/honeypot_matcher.rb +30 -0
- data/lib/bot-away/test_case/matchers/obfuscation_matcher.rb +30 -0
- data/lib/bot-away/test_case/mock_object.rb +16 -0
- data/lib/bot-away/version.rb +12 -0
- data/lib/locale/honeypots.yml +6 -0
- data/spec/controllers/basic_form_view_spec.rb +112 -0
- data/spec/controllers/{test_controller_spec.rb → tests_controller_spec.rb} +29 -80
- data/spec/integration/params_post_spec.rb +42 -0
- data/spec/lib/action_view/helpers/instance_tag_spec.rb +94 -0
- data/spec/{views/lib → lib/action_view}/param_parser_spec.rb +10 -10
- data/spec/spec_helper.rb +37 -105
- data/spec/test_rails_app/app/controllers/tests_controller.rb +11 -0
- data/spec/test_rails_app/app/models/post.rb +13 -0
- data/spec/test_rails_app/app/views/tests/basic_form.html.erb +5 -0
- data/spec/test_rails_app/app/views/tests/model_form.html.erb +12 -0
- data/spec/test_rails_app/config/locales/bot-away-overrides.yml +6 -0
- data/spec/views/form_builder_spec.rb +118 -0
- metadata +94 -137
- data/Manifest.txt +0 -23
- data/README.rdoc +0 -179
- data/VERSION +0 -1
- data/lib/bot-away/action_dispatch/request.rb +0 -20
- data/spec/rspec_version.rb +0 -19
- data/spec/support/honeypot_matcher.rb +0 -30
- data/spec/support/obfuscation_helper.rb +0 -123
- data/spec/support/obfuscation_matcher.rb +0 -28
- data/spec/support/rails/mock_logger.rb +0 -21
- data/spec/support/test_controller.rb +0 -28
- data/spec/support/views/test/index.html.erb +0 -4
- data/spec/support/views/test/model_form.html.erb +0 -6
- data/spec/views/lib/action_view/helpers/instance_tag_spec.rb +0 -75
- data/spec/views/lib/disabled_for_spec.rb +0 -101
- data/spec/views/lib/form_builder_spec.rb +0 -56
@@ -15,7 +15,6 @@ module BotAway
|
|
15
15
|
|
16
16
|
if authenticity_token
|
17
17
|
if catch(:bastard) { deobfuscate! } == :took_the_bait
|
18
|
-
#params.clear
|
19
18
|
# don't clear the controller or action keys, as Rails 3 needs them
|
20
19
|
params.keys.each { |key| params.delete(key) unless %w(controller action).include?(key) }
|
21
20
|
params[:suspected_bot] = true
|
@@ -35,7 +34,8 @@ module BotAway
|
|
35
34
|
deobfuscate!(value, object_name ? "#{object_name}[#{key}]" : key)
|
36
35
|
else
|
37
36
|
if object_name && !BotAway.excluded?(:object_name => object_name, :method_name => key)
|
38
|
-
|
37
|
+
spun_key = spinner.encode("#{object_name}[#{key}]")
|
38
|
+
if value.blank? && params.keys.include?(spun_key)
|
39
39
|
current[key] = params.delete(spun_key)
|
40
40
|
else
|
41
41
|
#puts "throwing on #{object_name}[#{key}] because its not blank" if !value.blank?
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rails/engine'
|
2
|
+
require 'rails/version'
|
3
|
+
|
4
|
+
class BotAway::Railtie < Rails::Engine
|
5
|
+
if Rails::VERSION::MINOR == 0 # Rails 3.0.x
|
6
|
+
paths.config.locales = File.expand_path("../locale/honeypots.yml", File.dirname(__FILE__))
|
7
|
+
else
|
8
|
+
paths["config/locales"] = File.expand_path("../locale/honeypots.yml", File.dirname(__FILE__))
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module BotAway::TestCase
|
2
|
+
autoload :ControllerTestCase, 'bot-away/test_case/controller_test_case'
|
3
|
+
autoload :InstanceTagTestCase, 'bot-away/test_case/instance_tag_test_case'
|
4
|
+
autoload :MockObject, 'bot-away/test_case/mock_object'
|
5
|
+
autoload :Matchers, 'bot-away/test_case/matchers'
|
6
|
+
|
7
|
+
def builder
|
8
|
+
@builder ||= ActionView::Base.default_form_builder.new(object_name, mock_object, view, {}, proc {})
|
9
|
+
end
|
10
|
+
|
11
|
+
def enable_forgery_protection
|
12
|
+
# BotAway doesn't work without forgery protection, and RSpec-Rails 2 disables it.
|
13
|
+
# Lost way too many hours on this.
|
14
|
+
# Note: This has to happen in spec file because RSpec2 sets a before block, which runs
|
15
|
+
# after the ones set by config.
|
16
|
+
Rails.application.config.allow_forgery_protection = true
|
17
|
+
ActionController::Base.allow_forgery_protection = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def disable_forgery_protection
|
21
|
+
Rails.application.config.allow_forgery_protection = false
|
22
|
+
ActionController::Base.allow_forgery_protection = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def mock_object
|
26
|
+
@mock_object ||= MockObject.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def obfuscated_id
|
30
|
+
"f51a02a636f507f1bd64722451b71297"
|
31
|
+
end
|
32
|
+
|
33
|
+
def obfuscated_name
|
34
|
+
"cd538a9170613d6dedbcc54a0aa24881"
|
35
|
+
end
|
36
|
+
|
37
|
+
def object_name
|
38
|
+
"object_name"
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_name
|
42
|
+
"method_name"
|
43
|
+
end
|
44
|
+
|
45
|
+
def tag_id
|
46
|
+
"#{object_name}_#{method_name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def tag_name
|
50
|
+
"#{object_name}[#{method_name}]"
|
51
|
+
end
|
52
|
+
|
53
|
+
def dump
|
54
|
+
result = yield
|
55
|
+
puts result if ENV['DUMP']
|
56
|
+
result
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module BotAway::TestCase::ControllerTestCase
|
2
|
+
# note that this only matters for TEST requests; real ones use the params parser.
|
3
|
+
module ::ActionController::TestCase::Behavior
|
4
|
+
def process_with_deobfuscation(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
|
5
|
+
parameters = BotAway::ParamParser.new(request.ip, (parameters || {}).with_indifferent_access).params
|
6
|
+
process_without_deobfuscation(action, parameters, session, flash, http_method)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method_chain :process, :deobfuscation
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module BotAway::TestCase::InstanceTagTestCase
|
2
|
+
def self.included(base)
|
3
|
+
base.module_eval do
|
4
|
+
include RSpec::Rails::ViewExampleGroup
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def mock_object
|
9
|
+
@mock_object ||= BotAway::TestCase::MockObject.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_instance_tag
|
13
|
+
@default_instance_tag ||= ActionView::Helpers::InstanceTag.new("object_name", "method_name", view, mock_object)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BotAway::TestCase::Matchers
|
2
|
+
autoload :ObfuscationMatcher, 'bot-away/test_case/matchers/obfuscation_matcher'
|
3
|
+
autoload :HoneypotMatcher, 'bot-away/test_case/matchers/honeypot_matcher'
|
4
|
+
|
5
|
+
def be_obfuscated_as(obfuscated_name, obfuscated_id)
|
6
|
+
ObfuscationMatcher.new(obfuscated_name, obfuscated_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def include_honeypot_called(tag_name, tag_id)
|
10
|
+
HoneypotMatcher.new(tag_name, tag_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def be_obfuscated
|
14
|
+
be_obfuscated_as obfuscated_name, obfuscated_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def include_honeypot
|
18
|
+
include_honeypot_called tag_name, tag_id
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class BotAway::TestCase::Matchers::HoneypotMatcher
|
2
|
+
attr_reader :tag_name, :tag_id
|
3
|
+
|
4
|
+
def initialize(tag_name, tag_id)
|
5
|
+
@tag_name, @tag_id = tag_name, tag_id
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(target)
|
9
|
+
target = target.call if target.kind_of?(Proc)
|
10
|
+
@target = target
|
11
|
+
match(:id, tag_id) && match(:name, tag_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def match(key, value, suffix = nil)
|
15
|
+
@rx = /#{key}=['"]#{Regexp::escape value}["']/
|
16
|
+
@target[@rx]
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
"include a honeypot named '#{tag_name}' with id '#{tag_id}'"
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message
|
24
|
+
"expected #{@target.inspect}\n to match #{@rx.inspect}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def negative_failure_message
|
28
|
+
"expected #{@target.inspect}\n to not match #{@rx.inspect}"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class BotAway::TestCase::Matchers::ObfuscationMatcher
|
2
|
+
attr_reader :obfuscated_name, :obfuscated_id
|
3
|
+
|
4
|
+
def initialize(obfuscated_name, obfuscated_id)
|
5
|
+
@obfuscated_id, @obfuscated_name = obfuscated_id, obfuscated_name
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(target)
|
9
|
+
target = target.call if target.kind_of?(Proc)
|
10
|
+
@target = target
|
11
|
+
match(:id, obfuscated_id) && match(:name, obfuscated_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def match(key, value)
|
15
|
+
@rx = /#{key}=['"]#{Regexp::escape value}["']/
|
16
|
+
@target[@rx]
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
"be obfuscated as '#{obfuscated_name}' with id '#{obfuscated_id}'"
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message
|
24
|
+
"expected #{@target.inspect}\n to match #{@rx.inspect}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def negative_failure_message
|
28
|
+
"expected #{@target.inspect}\n to not match #{@rx.inspect}"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# For all intents and purposes this is a view spec, but because rspec mocks up the controller
|
4
|
+
# in view specs (and rightly so!), we need to technically run it as a controller spec in order
|
5
|
+
# to invoke a real controller first.
|
6
|
+
describe TestsController do
|
7
|
+
include BotAway::TestCase::ControllerTestCase
|
8
|
+
render_views
|
9
|
+
before { enable_forgery_protection }
|
10
|
+
|
11
|
+
let(:params) { { :controller => 'tests', :action => 'basic_form' } }
|
12
|
+
|
13
|
+
it "should use forgery protection" do # sanity check
|
14
|
+
subject.send(:protect_against_forgery?).should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
shared_examples_for "enabled" do
|
18
|
+
it "returns false when queried for disablement" do
|
19
|
+
BotAway.should_not be_disabled_for(params)
|
20
|
+
BotAway.should_not be_excluded(params)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "obfuscates the elements" do
|
24
|
+
get 'basic_form'
|
25
|
+
response.body.should =~ /id="c89ca970ba19a4174d332aa8cfbd0c42"/ # user_login
|
26
|
+
response.body.should =~ /id="f41749ab8ef9d2358cfd170fd9af2f5e"/ # user_password
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
shared_examples_for "disabled" do
|
31
|
+
it "returns true when queried for disablement" do
|
32
|
+
# ..."disablement"?
|
33
|
+
BotAway.should be_disabled_for(params)
|
34
|
+
BotAway.should be_excluded(params)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "does not obfuscate the elements" do
|
38
|
+
get 'basic_form'
|
39
|
+
response.body.should_not =~ /id="c89ca970ba19a4174d332aa8cfbd0c42"/ # user_login
|
40
|
+
response.body.should_not =~ /id="f41749ab8ef9d2358cfd170fd9af2f5e"/ # user_password
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with bot-away disabled for only this view" do
|
45
|
+
before { BotAway.disabled_for({:controller => 'tests', :action => 'basic_form'}) }
|
46
|
+
it_should_behave_like "disabled"
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with bot-away enabled for all views" do
|
50
|
+
it_should_behave_like "enabled"
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
context "with matching controller name" do
|
58
|
+
context "and no action" do
|
59
|
+
before { BotAway.disabled_for :controller => 'tests' }
|
60
|
+
it_should_behave_like "disabled"
|
61
|
+
end
|
62
|
+
|
63
|
+
context "and matching action" do
|
64
|
+
before { BotAway.disabled_for :controller => 'tests', :action => 'basic_form' }
|
65
|
+
it_should_behave_like "disabled"
|
66
|
+
end
|
67
|
+
|
68
|
+
context "and not matching action" do
|
69
|
+
before { BotAway.disabled_for :controller => 'tests', :action => 'create' }
|
70
|
+
it_should_behave_like "enabled"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with not matching controller name" do
|
75
|
+
context "and no action" do
|
76
|
+
before { BotAway.disabled_for :controller => 'users' }
|
77
|
+
it_should_behave_like "enabled"
|
78
|
+
end
|
79
|
+
|
80
|
+
context "and matching action" do
|
81
|
+
before { BotAway.disabled_for :controller => 'users', :action => 'basic_form' }
|
82
|
+
it_should_behave_like "enabled"
|
83
|
+
end
|
84
|
+
|
85
|
+
context "and not matching action" do
|
86
|
+
before { BotAway.disabled_for :controller => 'users', :action => 'create' }
|
87
|
+
it_should_behave_like "enabled"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "with no controller name" do
|
92
|
+
context "and matching action" do
|
93
|
+
before { BotAway.disabled_for :action => 'basic_form' }
|
94
|
+
it_should_behave_like "disabled"
|
95
|
+
end
|
96
|
+
|
97
|
+
context "and not matching action" do
|
98
|
+
before { BotAway.disabled_for :action => 'create' }
|
99
|
+
it_should_behave_like "enabled"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with matching mode" do
|
104
|
+
before { BotAway.disabled_for :mode => ENV['RAILS_ENV'] }
|
105
|
+
it_should_behave_like "disabled"
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with not matching mode" do
|
109
|
+
before { BotAway.disabled_for :mode => "this_is_not_#{ENV['RAILS_ENV']}" }
|
110
|
+
it_should_behave_like "enabled"
|
111
|
+
end
|
112
|
+
end
|
@@ -1,88 +1,42 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
# rails 2
|
6
|
-
|
7
|
-
def setup_default_controller
|
8
|
-
@request = ActionController::TestRequest.new
|
9
|
-
# can the authenticity token so that we can predict the generated element names
|
10
|
-
@request.session[:_csrf_token] = 'aVjGViz+pIphXt2pxrWfXgRXShOI0KXOILR23yw0WBo='
|
11
|
-
@request.remote_addr = '208.77.188.166' # example.com
|
12
|
-
@response = ActionController::TestResponse.new
|
13
|
-
@controller = TestController.new
|
14
|
-
|
15
|
-
@controller.request = @request
|
16
|
-
@controller.params = {}
|
17
|
-
@controller.send(:initialize_current_url)
|
18
|
-
@controller
|
19
|
-
end
|
20
|
-
|
21
|
-
include ActionController::TestProcess
|
22
|
-
|
23
|
-
def controller
|
24
|
-
@controller
|
25
|
-
end
|
26
|
-
else
|
27
|
-
# rails 3
|
28
|
-
def setup_default_controller
|
29
|
-
@controller.request.session[:_csrf_token] = 'aVjGViz+pIphXt2pxrWfXgRXShOI0KXOILR23yw0WBo='
|
30
|
-
@controller.request.remote_addr = '208.77.188.166'
|
31
|
-
|
32
|
-
@controller
|
33
|
-
end
|
34
|
-
|
35
|
-
#extend ActiveSupport::Concern
|
36
|
-
#include ActionController::TestCase::Behavior
|
37
|
-
delegate :session, :to => :controller
|
38
|
-
end
|
39
|
-
|
40
|
-
def prepare!(action = 'index', method = 'get')
|
41
|
-
controller
|
42
|
-
send(method, action)
|
43
|
-
if RAILS_VERSION < "3.0"
|
44
|
-
if @response.template.instance_variable_get("@exception")
|
45
|
-
raise @response.template.instance_variable_get("@exception")
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
before(:each) { setup_default_controller }
|
3
|
+
describe TestsController do
|
4
|
+
include BotAway::TestCase::ControllerTestCase
|
51
5
|
|
52
|
-
|
53
|
-
|
54
|
-
|
6
|
+
before do
|
7
|
+
disable_forgery_protection
|
8
|
+
request.session[:_csrf_token] = 'aVjGViz+pIphXt2pxrWfXgRXShOI0KXOILR23yw0WBo='
|
9
|
+
request.remote_addr = '208.77.188.166'
|
55
10
|
end
|
56
|
-
|
57
11
|
|
58
12
|
context "with a model" do
|
13
|
+
render_views
|
14
|
+
|
59
15
|
context "with forgery protection" do
|
60
|
-
before
|
61
|
-
|
62
|
-
|
16
|
+
before do
|
17
|
+
enable_forgery_protection
|
18
|
+
get 'model_form'
|
63
19
|
end
|
64
20
|
|
65
21
|
it "should work?" do
|
66
|
-
|
22
|
+
response.body.should =~ /<select/
|
67
23
|
end
|
68
24
|
end
|
69
25
|
|
70
26
|
context "without forgery protection" do
|
71
|
-
before
|
72
|
-
|
27
|
+
before do
|
28
|
+
get 'model_form'
|
73
29
|
end
|
74
30
|
|
75
31
|
it "should work?" do
|
76
|
-
|
32
|
+
response.body.should =~ /<select/
|
77
33
|
end
|
78
34
|
end
|
79
35
|
end
|
80
36
|
|
81
37
|
context "with forgery protection" do
|
82
|
-
before
|
83
|
-
|
84
|
-
prepare! if RAILS_VERSION < "3.0"
|
85
|
-
end
|
38
|
+
before { enable_forgery_protection }
|
39
|
+
|
86
40
|
#"object_name_method_name" name="object_name[method_name]" size="30" type="text" value="" /></div>
|
87
41
|
#<input id="e21372563297c728093bf74c3cb6b96c" name="a0844d45bf150668ff1d86a6eb491969" size="30" type="text" value="method_value" />
|
88
42
|
|
@@ -92,12 +46,12 @@ describe TestController do
|
|
92
46
|
'842d8d1c80014ce9f3d974614338605c' => 'some_value'
|
93
47
|
}
|
94
48
|
post 'proc_form', form
|
95
|
-
#puts
|
49
|
+
#puts response.body
|
96
50
|
controller.params[:object_name].should == { 'method_name' => 'some_value' }
|
97
51
|
end
|
98
52
|
|
99
53
|
context "after processing valid obfuscated post" do
|
100
|
-
before
|
54
|
+
before do
|
101
55
|
post 'proc_form', { 'authenticity_token' => '1234',
|
102
56
|
'object_name' => { 'method_name' => '' },
|
103
57
|
'842d8d1c80014ce9f3d974614338605c' => 'some_value'
|
@@ -152,36 +106,31 @@ describe TestController do
|
|
152
106
|
controller.request.remote_addr = '127.0.0.1'
|
153
107
|
post 'proc_form', form
|
154
108
|
# puts controller.params.inspect
|
155
|
-
controller.params.should == { 'action' => 'proc_form', 'controller' => '
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
109
|
+
controller.params.should == { 'action' => 'proc_form', 'controller' => 'tests',
|
110
|
+
'authenticity_token' => 'yPgTAsngzpBO8k1v83RGH26sTrQYD50Ou2oiMT4r/iw=',
|
111
|
+
'user_session' => {
|
112
|
+
'login' => 'admin',
|
113
|
+
'password' => 'pwpwpw',
|
114
|
+
'remember_me' => '1'
|
115
|
+
},
|
116
|
+
'commit' => 'Log In'
|
163
117
|
}
|
164
118
|
end
|
165
119
|
end
|
166
120
|
|
167
121
|
context "without forgery protection" do
|
168
|
-
before :each do
|
169
|
-
prepare! if RAILS_VERSION < "3.0"
|
170
|
-
end
|
171
|
-
|
172
122
|
it "processes non-obfuscated form post" do
|
173
123
|
form = { #'authenticity_token' => '1234',
|
174
124
|
'object_name' => { 'method_name' => 'test' }
|
175
125
|
}
|
176
126
|
post 'proc_form', form
|
177
|
-
# puts
|
127
|
+
# puts response.body
|
178
128
|
controller.params.should_not == { 'suspected_bot' => true }
|
179
129
|
controller.params[:object_name].should == { 'method_name' => 'test' }
|
180
130
|
end
|
181
131
|
|
182
132
|
it "produces non-obfuscated form elements" do
|
183
|
-
|
184
|
-
@response.body.should_not match(/<\/div><input/)
|
133
|
+
response.body.should_not match(/<\/div><input/)
|
185
134
|
end
|
186
135
|
end
|
187
136
|
end
|