filter_assertions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +52 -0
  5. data/Rakefile +31 -0
  6. data/filter_assertions.gemspec +25 -0
  7. data/install.rb +1 -0
  8. data/lib/filter_assertions.rb +7 -0
  9. data/lib/filter_assertions/assertions.rb +130 -0
  10. data/lib/filter_assertions/version.rb +3 -0
  11. data/test/dummy/Rakefile +7 -0
  12. data/test/dummy/app/controllers/application_controller.rb +21 -0
  13. data/test/dummy/app/controllers/posts_controller.rb +37 -0
  14. data/test/dummy/app/helpers/application_helper.rb +2 -0
  15. data/test/dummy/app/helpers/posts_helper.rb +2 -0
  16. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  17. data/test/dummy/config.ru +4 -0
  18. data/test/dummy/config/application.rb +45 -0
  19. data/test/dummy/config/boot.rb +10 -0
  20. data/test/dummy/config/database.yml +22 -0
  21. data/test/dummy/config/environment.rb +5 -0
  22. data/test/dummy/config/environments/development.rb +26 -0
  23. data/test/dummy/config/environments/production.rb +49 -0
  24. data/test/dummy/config/environments/test.rb +35 -0
  25. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  26. data/test/dummy/config/initializers/inflections.rb +10 -0
  27. data/test/dummy/config/initializers/mime_types.rb +5 -0
  28. data/test/dummy/config/initializers/secret_token.rb +7 -0
  29. data/test/dummy/config/initializers/session_store.rb +8 -0
  30. data/test/dummy/config/locales/en.yml +5 -0
  31. data/test/dummy/config/routes.rb +58 -0
  32. data/test/dummy/public/404.html +26 -0
  33. data/test/dummy/public/422.html +26 -0
  34. data/test/dummy/public/500.html +26 -0
  35. data/test/dummy/public/favicon.ico +0 -0
  36. data/test/dummy/public/javascripts/application.js +2 -0
  37. data/test/dummy/public/javascripts/controls.js +965 -0
  38. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  39. data/test/dummy/public/javascripts/effects.js +1123 -0
  40. data/test/dummy/public/javascripts/prototype.js +6001 -0
  41. data/test/dummy/public/javascripts/rails.js +191 -0
  42. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  43. data/test/dummy/script/rails +6 -0
  44. data/test/filter_assertions_test.rb +65 -0
  45. data/test/test_helper.rb +17 -0
  46. data/uninstall.rb +1 -0
  47. metadata +186 -0
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in filter_assertions.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Daniel Pietzsch, Vít Krchov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # filter_assertions gem for Rails 3
2
+
3
+ This gem extends the class `ActiveSupport::TestCase` by adding assertions to test if before filters have been applied (via `before_filter` or `append_before_filter`) or skipped (via `skip_before_filter`).
4
+
5
+ These assertions are added for use in your functional tests:
6
+
7
+ * `assert_before_filter`: use this to test your `before_filter` or `append_before_filter` statements.
8
+ * `assert_no_before_filter`: use this to test your `skip_before_filter` statements.
9
+ * `assert_forgery_protection`: use this to test your `protect_from_forgery` statements.
10
+
11
+ ## Installation
12
+
13
+ Include the gem in your Gemfile:
14
+
15
+ gem "filter_assertions"
16
+
17
+ ## Examples
18
+
19
+ # Test if the before_filter :authenticate applies to all actions in the controller
20
+ assert_before_filter :authenticate
21
+
22
+ # Test if the filter only applies to actions 'index' and 'new'
23
+ assert_before_filter :authenticate, :only => [:index, :new]
24
+
25
+ # Test if the filter applies to all actions axcept 'index'
26
+ assert_before_filter :authenticate, :except => :index
27
+
28
+ The `assert_no_before_filter` assertion takes the same options and the `assert_forgery_protection` *only takes the `:except` or `:only` options*.
29
+
30
+ There are different ways to test for the same functionality:
31
+
32
+ # These two assertion are equivalent
33
+ assert_before_filter :authenticate, :except => :index
34
+ assert_no_before_filter :authenticate, :only => :index
35
+
36
+ ## How it works
37
+
38
+ The assertions of this plugin do not test for functionality of your before\_filters. It looks for the specified filters in the controller's filter\_chain and checks if the filters are applied or skipped for the specified actions.
39
+ That means you can even check for before\_filters when you usually skip them in your functional tests.
40
+
41
+ ## Why would I want to test for before_filters like that?
42
+
43
+ It's usually a good idea to test your controllers *including* its before\_filters and create different tests for when a before_filter applies and for when it doesn't.
44
+ But there might be cases when you can't do this easily. Maybe there's an external dependency a filter relies on - such as an external service or app for authentication for example. With this plugin, you could skip all before\_filters for your tests and still be able to test if they would normally apply (deployed on a server for example).
45
+
46
+ However - as said before - this plugin does not test any functionality of the filters themselves. The assertions only check if the filters apply to all actions or a subset of actions of the controller you are testing.
47
+
48
+ ## Credits
49
+
50
+ This gem is based on the plugin [filter_assertions](https://github.com/pie4dan/filter_assertions) created by Daniel Pietzsch.
51
+
52
+ Copyright (c) 2011 Daniel Pietzsch and Vít Krchov, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rake/rdoctask'
11
+
12
+ require 'rake/testtask'
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << 'lib'
16
+ t.libs << 'test'
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = false
19
+ end
20
+
21
+ task :default => :test
22
+
23
+ Rake::RDocTask.new(:rdoc) do |rdoc|
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = 'FilterAssertions'
26
+ rdoc.options << '--line-numbers' << '--inline-source'
27
+ rdoc.rdoc_files.include('README.rdoc')
28
+ rdoc.rdoc_files.include('lib/**/*.rb')
29
+ end
30
+
31
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../lib/filter_assertions/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'filter_assertions'
5
+ s.version = FilterAssertions::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = 'Gem adding assertions to test if before filters have been applied.'
8
+ s.description = <<-DESC
9
+ Gem extends the class ActiveSupport::TestCase by adding assertions to test if before filters have been applied (via before_filter or append_before_filter) or skipped (via skip_before_filter).
10
+ DESC
11
+ s.authors = ['Daniel Pietzsch', 'Vít Krchov']
12
+ s.email = 'vit.krchov@gmail.com'
13
+ s.homepage = 'https://github.com/vita/filter_assertions'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
17
+ s.require_path = 'lib'
18
+
19
+ s.add_dependency 'bundler', '~> 1.0.0'
20
+ s.add_dependency 'rails', '>= 3.0.0'
21
+
22
+ s.add_development_dependency 'turn'
23
+ s.add_development_dependency 'shoulda'
24
+ s.add_development_dependency 'sqlite3-ruby'
25
+ end
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,7 @@
1
+ require 'filter_assertions/assertions'
2
+
3
+ # Extends the ActiveSupport::TestCase class.
4
+ # Adds assertions to test if a before_filter is applied or skipped
5
+ class ActiveSupport::TestCase
6
+ include FilterAssertions::Assertions
7
+ end
@@ -0,0 +1,130 @@
1
+ # Assertions to test if a before_filter is applied or skipped
2
+ module FilterAssertions
3
+ module Assertions
4
+ # This method is the matching assertion to the before_filter or append_before_filter methods
5
+ #
6
+ # Examples:
7
+ # - assert_before_filter :authenticate
8
+ # - assert_before_filter :authenticate, :only => [:index, :new]
9
+ # - assert_before_filter :authenticate, :except => :index
10
+ def assert_before_filter(before_filter_name, options = {})
11
+ filter = find_matching_before_filter(before_filter_name)
12
+
13
+ raise NameError, "Couldn't find filter '#{before_filter_name}'" if filter.nil?
14
+
15
+ if options.blank?
16
+ # When the filter's options are empty, it means the filter applies to all controller methods.
17
+ assert (filter.options[:only].blank? and filter.options[:except].blank?), "The filter #{before_filter_name} has only/except options and does not apply to all actions."
18
+ else
19
+ # The Array() cast makes sure that if you only enter one action without brackets
20
+ # (instead of listing multiple actions), that it's converted to an Array
21
+ # and can be processed with the code below
22
+ actions_only = Array(options[:only])
23
+ actions_except = Array(options[:except])
24
+
25
+ raise ArgumentError, "Unrecognised options. Valid options: :only and :except" if actions_only.blank? && actions_except.blank?
26
+
27
+ assert_block "The filter '#{before_filter_name}' does NOT apply to all the actions specified." do
28
+ filter_only_applies_to_actions?(filter, actions_only)
29
+ end if actions_only.present?
30
+
31
+ assert_block "The filter '#{before_filter_name}' applies to more actions than specified." do
32
+ filter_is_excepted_from_actions?(filter, actions_except)
33
+ end if actions_except.present?
34
+ end
35
+ end
36
+
37
+ # This method is the matching assertion to the skip_before_filter method
38
+ #
39
+ # Examples:
40
+ # - assert_no_before_filter :authenticate
41
+ # - assert_no_before_filter :authenticate, :only => [:index, :new]
42
+ # - assert_no_before_filter :authenticate, :except => :index
43
+ def assert_no_before_filter(before_filter_name, options = {})
44
+ filter = find_matching_before_filter(before_filter_name)
45
+
46
+ if options.blank?
47
+ # if the options are blank no filter should have been found, because it is then skipped for all actions
48
+ assert filter.nil?, "The filter #{before_filter_name} has only/except options and is not skipped for all actions."
49
+ else
50
+ # The Array() cast makes sure that if you only enter one action without brackets
51
+ # (instead of listing multiple actions), that it's converted to an Array
52
+ # and can be processed with the code below
53
+ actions_only = Array(options[:only])
54
+ actions_except = Array(options[:except])
55
+
56
+ raise ArgumentError, "Unrecognised options. Valid options are :only and :except" if actions_only.blank? && actions_except.blank?
57
+
58
+ assert_block "The filter '#{before_filter_name}' is NOT skipped for all the actions specified." do
59
+ filter_is_excepted_from_actions?(filter, actions_only)
60
+ end if actions_only.present?
61
+
62
+ assert_block "The filter '#{before_filter_name}' is skipped for more actions than specified." do
63
+ filter_only_applies_to_actions?(filter, actions_except)
64
+ end if actions_except.present?
65
+ end
66
+ end
67
+
68
+ # The protect_from_forgery method is just a wrapper for
69
+ # another before_filter. And so is this assertion method
70
+ # just a wrapper for the assert_before_filter method.
71
+ def assert_forgery_protection(options = {})
72
+ assert_before_filter(:verify_authenticity_token, options)
73
+ end
74
+
75
+ #########################
76
+ private
77
+ #########################
78
+
79
+ # Returns the ActiveSupport::Callbacks::Callback object matching before_filter_name or nil
80
+ def find_matching_before_filter(before_filter_name)
81
+ @controller._process_action_callbacks.each do |c|
82
+ return c if c.kind == :before and c.filter == before_filter_name
83
+ end
84
+
85
+ nil
86
+ end
87
+
88
+ def filter_only_applies_to_actions?(filter, actions)
89
+ all_actions_without_supplied_ones = get_all_controller_actions.reject { |action| actions.include?(action) }
90
+
91
+ filter_applies_to_all_actions?(filter, actions) && filter_is_skipped_for_all_actions?(filter, all_actions_without_supplied_ones)
92
+ end
93
+
94
+ def filter_is_excepted_from_actions?(filter, actions)
95
+ all_actions_without_supplied_ones = get_all_controller_actions.reject { |action| actions.include?(action) }
96
+
97
+ filter_is_skipped_for_all_actions?(filter, actions) && filter_applies_to_all_actions?(filter, all_actions_without_supplied_ones)
98
+ end
99
+
100
+ def filter_applies_to_all_actions?(filter, actions)
101
+ actions.all? { |action| before_filter_applied?(filter, action) }
102
+ end
103
+
104
+ def filter_is_skipped_for_all_actions?(filter, actions)
105
+ actions.all? { |action| !before_filter_applied?(filter, action) }
106
+ end
107
+
108
+ # Checks if the given filter is applied to the given action
109
+ def before_filter_applied?(filter, action)
110
+ return false if filter.nil? || action.nil?
111
+
112
+ # if it is a skip_before_filter
113
+ if filter.per_key and (filter.per_key[:if].present? or filter.per_key[:unless].present?)
114
+ action_name = action.to_s
115
+ return eval(filter.per_key[:if].to_s) if filter.per_key[:if].present?
116
+ return !eval(filter.per_key[:unless].to_s) if filter.per_key[:unless].present?
117
+ else
118
+ return true if filter.options.empty? # because then a normal filter would be applied to all actions
119
+ return !filter.options[:except].include?(action) if filter.options[:except].present?
120
+ return filter.options[:only].include?(action) if filter.options[:only].present?
121
+ end
122
+ end
123
+
124
+ # Gets all the actions of the tested controller
125
+ # Returns an Array of Symbols (the names of the actions)
126
+ def get_all_controller_actions
127
+ @controller.action_methods.map(&:to_sym)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,3 @@
1
+ module FilterAssertions
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,21 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+
4
+ before_filter :authenticate
5
+ before_filter :find_news
6
+ before_filter :find_posts
7
+
8
+ private
9
+
10
+ def authenticate
11
+ # code ...
12
+ end
13
+
14
+ def find_news
15
+ # code ...
16
+ end
17
+
18
+ def find_posts
19
+ # code
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ class PostsController < ApplicationController
2
+
3
+ skip_before_filter :authenticate, :only => [:index, :show]
4
+ before_filter :increment_counter, :only => [:show]
5
+ before_filter :find_top_posts
6
+ skip_before_filter :find_news
7
+ before_filter :find_post, :except => [:index]
8
+ skip_before_filter :find_posts, :except => [:index]
9
+
10
+ def index; end
11
+
12
+ def show; end
13
+
14
+ def new; end
15
+
16
+ def create; end
17
+
18
+ def edit; end
19
+
20
+ def update; end
21
+
22
+ def destroy; end
23
+
24
+ private
25
+
26
+ def increment_counter
27
+ # code ...
28
+ end
29
+
30
+ def find_top_posts
31
+ # code ...
32
+ end
33
+
34
+ def find_post
35
+ # code ...
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module PostsHelper
2
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "active_model/railtie"
4
+ require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_view/railtie"
7
+ require "action_mailer/railtie"
8
+
9
+ Bundler.require
10
+ require "filter_assertions"
11
+
12
+ module Dummy
13
+ class Application < Rails::Application
14
+ # Settings in config/environments/* take precedence over those specified here.
15
+ # Application configuration should go into files in config/initializers
16
+ # -- all .rb files in that directory are automatically loaded.
17
+
18
+ # Custom directories with classes and modules you want to be autoloadable.
19
+ # config.autoload_paths += %W(#{config.root}/extras)
20
+
21
+ # Only load the plugins named here, in the order given (default is alphabetical).
22
+ # :all can be used as a placeholder for all plugins not explicitly named.
23
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
+
25
+ # Activate observers that should always be running.
26
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
+
28
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30
+ # config.time_zone = 'Central Time (US & Canada)'
31
+
32
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34
+ # config.i18n.default_locale = :de
35
+
36
+ # JavaScript files you want as :defaults (application.js is always included).
37
+ # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
38
+
39
+ # Configure the default encoding used in templates for Ruby 1.9.
40
+ config.encoding = "utf-8"
41
+
42
+ # Configure sensitive parameters which will be filtered from the log file.
43
+ config.filter_parameters += [:password]
44
+ end
45
+ end