controll 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +19 -0
  4. data/Gemfile.lock +134 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +320 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/controll.gemspec +184 -0
  10. data/lib/controll.rb +14 -0
  11. data/lib/controll/assistant.rb +19 -0
  12. data/lib/controll/command.rb +24 -0
  13. data/lib/controll/commander.rb +24 -0
  14. data/lib/controll/errors.rb +1 -0
  15. data/lib/controll/executor.rb +6 -0
  16. data/lib/controll/executor/base.rb +16 -0
  17. data/lib/controll/executor/notificator.rb +12 -0
  18. data/lib/controll/flow_handler.rb +11 -0
  19. data/lib/controll/flow_handler/base.rb +19 -0
  20. data/lib/controll/flow_handler/control.rb +85 -0
  21. data/lib/controll/flow_handler/errors.rb +5 -0
  22. data/lib/controll/flow_handler/event_helper.rb +18 -0
  23. data/lib/controll/flow_handler/redirect.rb +51 -0
  24. data/lib/controll/flow_handler/redirect/action.rb +45 -0
  25. data/lib/controll/flow_handler/redirect/mapper.rb +41 -0
  26. data/lib/controll/flow_handler/render.rb +51 -0
  27. data/lib/controll/helper.rb +101 -0
  28. data/lib/controll/helper/event_matcher.rb +21 -0
  29. data/lib/controll/helper/hash_access.rb +26 -0
  30. data/lib/controll/helper/notify.rb +74 -0
  31. data/lib/controll/helper/params.rb +20 -0
  32. data/lib/controll/helper/path_resolver.rb +45 -0
  33. data/lib/controll/helper/session.rb +20 -0
  34. data/lib/controll/notify.rb +7 -0
  35. data/lib/controll/notify/base.rb +75 -0
  36. data/lib/controll/notify/flash.rb +52 -0
  37. data/lib/controll/notify/typed.rb +39 -0
  38. data/spec/acceptance/app_test.rb +156 -0
  39. data/spec/app/.gitignore +15 -0
  40. data/spec/app/Gemfile +6 -0
  41. data/spec/app/Gemfile.lock +108 -0
  42. data/spec/app/README.rdoc +261 -0
  43. data/spec/app/Rakefile +7 -0
  44. data/spec/app/app/controllers/application_controller.rb +6 -0
  45. data/spec/app/app/controllers/posts_controller.rb +52 -0
  46. data/spec/app/app/models/.gitkeep +0 -0
  47. data/spec/app/app/models/post.rb +88 -0
  48. data/spec/app/app/views/layouts/application.html.erb +13 -0
  49. data/spec/app/app/views/posts/_form.html.erb +31 -0
  50. data/spec/app/app/views/posts/edit.html.erb +6 -0
  51. data/spec/app/app/views/posts/index.html.erb +23 -0
  52. data/spec/app/app/views/posts/new.html.erb +5 -0
  53. data/spec/app/app/views/posts/show.html.erb +8 -0
  54. data/spec/app/config.ru +4 -0
  55. data/spec/app/config/application.rb +16 -0
  56. data/spec/app/config/boot.rb +6 -0
  57. data/spec/app/config/environment.rb +5 -0
  58. data/spec/app/config/environments/development.rb +21 -0
  59. data/spec/app/config/environments/test.rb +29 -0
  60. data/spec/app/config/initializers/backtrace_silencers.rb +7 -0
  61. data/spec/app/config/initializers/inflections.rb +15 -0
  62. data/spec/app/config/initializers/mime_types.rb +5 -0
  63. data/spec/app/config/initializers/secret_token.rb +7 -0
  64. data/spec/app/config/initializers/session_store.rb +8 -0
  65. data/spec/app/config/locales/en.yml +5 -0
  66. data/spec/app/config/routes.rb +62 -0
  67. data/spec/app/db/seeds.rb +7 -0
  68. data/spec/app/lib/assets/.gitkeep +0 -0
  69. data/spec/app/lib/tasks/.gitkeep +0 -0
  70. data/spec/app/log/.gitkeep +0 -0
  71. data/spec/app/public/404.html +26 -0
  72. data/spec/app/public/422.html +26 -0
  73. data/spec/app/public/500.html +25 -0
  74. data/spec/app/public/favicon.ico +0 -0
  75. data/spec/app/public/index.html +241 -0
  76. data/spec/app/public/javascripts/application.js +9663 -0
  77. data/spec/app/public/robots.txt +5 -0
  78. data/spec/app/public/stylesheets/application.css +83 -0
  79. data/spec/app/script/rails +6 -0
  80. data/spec/app/spec/controllers/posts_controller_spec.rb +59 -0
  81. data/spec/app/spec/isolated_spec_helper.rb +6 -0
  82. data/spec/app/spec/spec_helper.rb +5 -0
  83. data/spec/app/spec/unit/controllers/posts_controller_isolated_spec.rb +63 -0
  84. data/spec/app/spec/unit/controllers/posts_controller_spec.rb +59 -0
  85. data/spec/app/test/functional/.gitkeep +0 -0
  86. data/spec/app/test/functional/posts_controller_test.rb +67 -0
  87. data/spec/app/test/isolated_test_helper.rb +7 -0
  88. data/spec/app/test/test_helper.rb +6 -0
  89. data/spec/app/test/unit/.gitkeep +0 -0
  90. data/spec/app/test/unit/controllers/posts_controller_isolated_test.rb +71 -0
  91. data/spec/app/test/unit/controllers/posts_controller_test.rb +67 -0
  92. data/spec/app/vendor/assets/javascripts/.gitkeep +0 -0
  93. data/spec/app/vendor/assets/stylesheets/.gitkeep +0 -0
  94. data/spec/app/vendor/plugins/.gitkeep +0 -0
  95. data/spec/controll/asssistant_spec.rb +5 -0
  96. data/spec/controll/command_spec.rb +56 -0
  97. data/spec/controll/commander_spec.rb +68 -0
  98. data/spec/controll/executor/notificator_spec.rb +27 -0
  99. data/spec/controll/flow_handler/control_spec.rb +159 -0
  100. data/spec/controll/flow_handler/redirect/action_spec.rb +48 -0
  101. data/spec/controll/flow_handler/redirect/mapper_spec.rb +69 -0
  102. data/spec/controll/flow_handler/redirect_spec.rb +93 -0
  103. data/spec/controll/flow_handler/render_spec.rb +110 -0
  104. data/spec/controll/helper/event_matcher_spec.rb +21 -0
  105. data/spec/controll/helper/hash_access_spec.rb +25 -0
  106. data/spec/controll/helper/notify_spec.rb +48 -0
  107. data/spec/controll/helper/params_spec.rb +28 -0
  108. data/spec/controll/helper/path_resolver_spec.rb +49 -0
  109. data/spec/controll/helper/session_spec.rb +28 -0
  110. data/spec/controll/helper_spec.rb +108 -0
  111. data/spec/controll/notify/base_spec.rb +123 -0
  112. data/spec/controll/notify/flash_spec.rb +27 -0
  113. data/spec/controll/notify/message_handler.rb +72 -0
  114. data/spec/controll/notify/typed_spec.rb +28 -0
  115. data/spec/functional_test_helper.rb +25 -0
  116. data/spec/helper.rb +33 -0
  117. data/spec/rspec_controller_class.rb +15 -0
  118. data/spec/rspec_functional_helper.rb +25 -0
  119. data/spec/rspec_helper.rb +42 -0
  120. data/spec/spec_helper.rb +11 -0
  121. data/spec/test_helper.rb +183 -0
  122. data/spec/unit/functional_test_helper_test.rb +65 -0
  123. data/spec/unit/macros_test.rb +43 -0
  124. data/spec/unit/mixin_test.rb +147 -0
  125. data/spec/unit/rspec_functional_helper.rb +42 -0
  126. data/spec/unit/rspec_helper_test.rb +91 -0
  127. data/spec/unit/test_helper_test.rb +235 -0
  128. metadata +289 -0
@@ -0,0 +1,15 @@
1
+ module FocusedController
2
+ module RSpecControllerClass
3
+ def controller_class
4
+ metadata = self.metadata[:example_group]
5
+ klass = nil
6
+
7
+ until metadata.nil? || klass.respond_to?(:new)
8
+ klass = metadata[:description_args].first
9
+ metadata = metadata[:example_group]
10
+ end
11
+
12
+ klass.respond_to?(:new) ? klass : super
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ require 'action_controller'
2
+ require 'action_view'
3
+ require 'action_dispatch'
4
+ require 'rspec/rails'
5
+ require 'focused_controller/functional_test_helper'
6
+ require 'focused_controller/rspec_controller_class'
7
+
8
+ module FocusedController
9
+ module RSpecFunctionalHelper
10
+ def self.append_features(base)
11
+ base.class_eval do
12
+ # This must be included first
13
+ include RSpec::Rails::ControllerExampleGroup
14
+ extend ClassMethods
15
+ include FocusedController::FunctionalTestHelper
16
+ end
17
+
18
+ super
19
+ end
20
+
21
+ module ClassMethods
22
+ include FocusedController::RSpecControllerClass
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ require 'focused_controller/test_helper'
2
+ require 'focused_controller/rspec_controller_class'
3
+
4
+ begin
5
+ # Requiring specific files rather than just 'rspec/rails' because I don't
6
+ # want to force the configuration that 'rspec/rails' adds on people if they
7
+ # haven't specifically chosen to receive it.
8
+ require 'rspec/rails/matchers'
9
+ require 'rspec/rails/adapters'
10
+ require 'rspec/rails/example/rails_example_group'
11
+ rescue LoadError
12
+ end
13
+
14
+ module FocusedController
15
+ module RSpecHelper
16
+ def self.append_features(base)
17
+ base.class_eval do
18
+ # This must get included higher in the ancestor chain than
19
+ # this module so that inheritance works as desired
20
+ include FocusedController::TestHelper
21
+ extend ClassMethods
22
+ subject { controller }
23
+ end
24
+
25
+ super
26
+ end
27
+
28
+ if defined?(RSpec::Rails)
29
+ include RSpec::Rails::RailsExampleGroup
30
+ include RSpec::Rails::Matchers::RedirectTo
31
+ include RSpec::Rails::Matchers::RenderTemplate
32
+ end
33
+
34
+ module ClassMethods
35
+ include FocusedController::RSpecControllerClass
36
+
37
+ def stub_url(*helper_names)
38
+ before { stub_url(*helper_names) }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+ require 'rails'
3
+ require 'controll'
4
+
5
+ # Requires supporting files with custom matchers and macros, etc,
6
+ # in ./support/ and its subdirectories.
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
8
+
9
+ RSpec.configure do |config|
10
+
11
+ end
@@ -0,0 +1,183 @@
1
+ require 'action_dispatch'
2
+ require 'active_support/concern'
3
+ require 'active_support/core_ext/class/attribute'
4
+ require 'active_support/hash_with_indifferent_access'
5
+
6
+ module FocusedController
7
+ module TestHooks
8
+ attr_reader :_render_options
9
+
10
+ def render_to_body(options = {})
11
+ _process_options(options)
12
+ @_render_options = options
13
+ end
14
+
15
+ def url_for(options = nil)
16
+ if options.is_a?(StubbedURL)
17
+ options
18
+ else
19
+ super
20
+ end
21
+ end
22
+ end
23
+
24
+ class TestRequest < ActionDispatch::TestRequest
25
+ def initialize(env = {})
26
+ super
27
+ self.session = HashWithIndifferentAccess.new
28
+ end
29
+
30
+ def cookie_jar
31
+ @cookie_jar ||= ActionDispatch::Cookies::CookieJar.new
32
+ end
33
+
34
+ def flash
35
+ session['flash'] ||= ActionDispatch::Flash::FlashHash.new
36
+ end
37
+ end
38
+
39
+ class TestResponse < ActionDispatch::TestResponse
40
+ end
41
+
42
+ class StubbedURL
43
+ attr_reader :helper_name, :args
44
+
45
+ def initialize(helper_name, args)
46
+ @helper_name = helper_name.to_s
47
+ @args = args
48
+ end
49
+
50
+ def ==(other)
51
+ other.is_a?(self.class) &&
52
+ helper_name == other.helper_name &&
53
+ args == other.args
54
+ end
55
+
56
+ # Deals with _compute_redirect_to_location in action_controller/metal/redirecting
57
+ # (I don't feel proud about this...)
58
+ def gsub(*)
59
+ self
60
+ end
61
+
62
+ def to_s
63
+ "#{helper_name}(#{args.each(&:to_s).join(', ')})"
64
+ end
65
+ end
66
+
67
+ module TestHelper
68
+ extend ActiveSupport::Concern
69
+ include ActionDispatch::Assertions::ResponseAssertions
70
+
71
+ included do
72
+ class_attribute :_controller_class, :instance_reader => false, :instance_writer => false
73
+ end
74
+
75
+ module ClassMethods
76
+ def controller_class=(klass)
77
+ self._controller_class = klass
78
+ end
79
+
80
+ def controller_class
81
+ _controller_class || name.sub(/Test$/, '').constantize
82
+ end
83
+
84
+ def include_routes
85
+ if controller_class.respond_to?(:_routes) && controller_class._routes
86
+ include controller_class._routes.named_routes.module
87
+ end
88
+ end
89
+
90
+ def stub_url(*names)
91
+ setup { stub_url(*names) }
92
+ end
93
+ end
94
+
95
+ def controller
96
+ @controller ||= begin
97
+ controller = self.class.controller_class.new
98
+ controller.singleton_class.send :include, TestHooks
99
+ controller.request = request
100
+ controller.response = response
101
+ controller
102
+ end
103
+ end
104
+
105
+ def request
106
+ @request ||= TestRequest.new
107
+ end
108
+
109
+ def response
110
+ @response ||= TestResponse.new
111
+ end
112
+
113
+ def req(params = nil, session = nil, flash = nil)
114
+ controller.params = params if params
115
+ controller.session.update session if session
116
+ controller.flash.update flash if flash
117
+ controller.run
118
+ end
119
+
120
+ def session
121
+ controller.session
122
+ end
123
+
124
+ def flash
125
+ controller.flash
126
+ end
127
+
128
+ def cookies
129
+ request.cookie_jar
130
+ end
131
+
132
+ def assert_template(template, message = nil)
133
+ assert_equal template.to_s, controller._render_options[:template], message
134
+ end
135
+
136
+ def assert_response(type, message = nil)
137
+ controller # make sure controller is initialized
138
+ super
139
+ end
140
+
141
+ def assert_redirected_to(location, message = nil)
142
+ controller # make sure controller is initialized
143
+ super
144
+ end
145
+
146
+ def url_for(*args)
147
+ controller.url_for(*args)
148
+ end
149
+
150
+ def respond_to?(*args)
151
+ unless defined?(@_routes_included) && @_routes_included
152
+ self.class.include_routes
153
+ @_routes_included = true
154
+ end
155
+
156
+ super
157
+ end
158
+
159
+ def method_missing(method_name, *args, &block)
160
+ if respond_to?(method_name)
161
+ send(method_name, *args, &block)
162
+ else
163
+ super
164
+ end
165
+ end
166
+
167
+ def stub_url(*names)
168
+ [self, controller].each do |host|
169
+ host.singleton_class.class_eval do
170
+ names.each do |name|
171
+ define_method("#{name}_url") do |*args|
172
+ StubbedURL.new("#{name}_url", args)
173
+ end
174
+
175
+ define_method("#{name}_path") do |*args|
176
+ StubbedURL.new("#{name}_path", args)
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,65 @@
1
+ require 'helper'
2
+ require 'focused_controller/functional_test_helper'
3
+ require 'action_controller'
4
+
5
+ module FocusedController
6
+ module FunctionalTestHelper
7
+ class FakePostsController
8
+ class Action < ActionController::Base; end
9
+ class Index < Action; end
10
+ class Show < Action; end
11
+
12
+ class TestCase < ActionController::TestCase
13
+ include FocusedController::FunctionalTestHelper
14
+
15
+ def initialize(method_name = :foo)
16
+ super
17
+ end
18
+
19
+ def foo; end
20
+ end
21
+
22
+ class IndexTest < TestCase
23
+ end
24
+
25
+ class ShowTest < TestCase
26
+ end
27
+ end
28
+
29
+ describe FunctionalTestHelper do
30
+ subject { FakePostsController::IndexTest.new }
31
+
32
+ it 'automatically determines the controller class' do
33
+ FakePostsController::IndexTest.controller_class.
34
+ must_equal FakePostsController::Index
35
+ FakePostsController::ShowTest.controller_class.
36
+ must_equal FakePostsController::Show
37
+ end
38
+
39
+ it "doesn't require using the action name to dispatch the action" do
40
+ subject.singleton_class.class_eval do
41
+ attr_reader :last_process
42
+
43
+ def process(*args)
44
+ @last_process = args
45
+ end
46
+ end
47
+
48
+ subject.get :foo, :bar, :baz
49
+ subject.last_process.must_equal ['run', :foo, :bar, :baz, 'GET']
50
+
51
+ subject.post :foo, :bar, :baz
52
+ subject.last_process.must_equal ['run', :foo, :bar, :baz, 'POST']
53
+
54
+ subject.put :foo, :bar, :baz
55
+ subject.last_process.must_equal ['run', :foo, :bar, :baz, 'PUT']
56
+
57
+ subject.delete :foo, :bar, :baz
58
+ subject.last_process.must_equal ['run', :foo, :bar, :baz, 'DELETE']
59
+
60
+ subject.head :foo, :bar, :baz
61
+ subject.last_process.must_equal ['run', :foo, :bar, :baz, 'HEAD']
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,43 @@
1
+ require 'helper'
2
+
3
+ class ApplicationController
4
+ end
5
+
6
+ require 'focused_controller/macros'
7
+
8
+ class MyBaseAction < ::FocusedAction
9
+ end
10
+
11
+ module FocusedController
12
+ describe Macros do
13
+ describe ".focused_action" do
14
+ let(:klass) do
15
+ klass = Class.new(FocusedController::Test::MixinTestController)
16
+ klass.name = "PostsController"
17
+ klass.use_focused_macros
18
+ klass.action_parent MyBaseAction
19
+ klass
20
+ end
21
+
22
+ subject { klass }
23
+
24
+ describe 'create an Action class with a #run method' do
25
+ before do
26
+ subject.focused_action(:show) do
27
+ def run
28
+ "running"
29
+ end
30
+ end
31
+ end
32
+
33
+ it 'should have the superclass MyBaseAction' do
34
+ subject::Show.superclass.should == MyBaseAction
35
+ end
36
+
37
+ it 'should have a run method' do
38
+ subject::Show.new.run.should == "running"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,147 @@
1
+ require 'helper'
2
+ require 'action_controller'
3
+
4
+ module FocusedController
5
+ module Test
6
+ class MixinTestBaseController
7
+ def view_assigns
8
+ {'some' => 'var'}
9
+ end
10
+ end
11
+
12
+ class MixinTestController < ActionController::Base
13
+ include FocusedController::Mixin
14
+
15
+ class << self
16
+ attr_accessor :name
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module FocusedController
23
+ describe Mixin do
24
+ describe "with a PostsController::Show class" do
25
+ let(:klass) do
26
+ klass = Class.new(FocusedController::Test::MixinTestController)
27
+ klass.name = "PostsController::Show"
28
+ klass
29
+ end
30
+
31
+ subject { klass.new }
32
+
33
+ it "has a .controller_path of 'posts'" do
34
+ klass.controller_path.must_equal 'posts'
35
+ end
36
+
37
+ it "has a .call which dispatches the #run action" do
38
+ def klass.action(name)
39
+ if name.to_s == 'run'
40
+ proc { |env| "omg" }
41
+ end
42
+ end
43
+
44
+ klass.call(nil).must_equal "omg"
45
+ end
46
+
47
+ it "has an #action_name of 'show'" do
48
+ subject.action_name.must_equal 'show'
49
+ end
50
+
51
+ it "uses the run method for the action" do
52
+ subject.method_for_action('whatever').must_equal 'run'
53
+ end
54
+
55
+ it "removes all view assigns by default" do
56
+ subject.view_assigns.must_equal({})
57
+ end
58
+
59
+ it "can be configured to allow view assigns" do
60
+ subject.class.allow_view_assigns = true
61
+ subject.instance_variable_set('@foo', 'bar')
62
+ subject.view_assigns['foo'].must_equal('bar')
63
+ end
64
+
65
+ it "has a #run method by default" do
66
+ subject.run.must_equal nil
67
+ end
68
+ end
69
+
70
+ describe '.run' do
71
+ subject do
72
+ @klass = Class.new do
73
+ include FocusedController::Mixin
74
+ end
75
+ end
76
+
77
+ it 'defines a #run method' do
78
+ subject.run { 'running' }
79
+ subject.new.run.must_equal 'running'
80
+ end
81
+ end
82
+
83
+ describe '.expose' do
84
+ subject do
85
+ @klass = Class.new do
86
+ include FocusedController::Mixin
87
+
88
+ @helper_methods = []
89
+
90
+ class << self
91
+ attr_reader :helper_methods
92
+
93
+ def helper_method(name)
94
+ @helper_methods << name
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ it 'defines a #foo method' do
101
+ subject.expose(:foo) { 'bar' }
102
+ subject.new.foo.must_equal 'bar'
103
+ end
104
+
105
+ it 'declares the method a helper method' do
106
+ subject.expose(:foo) { 'bar' }
107
+ subject.helper_methods.must_equal [:foo]
108
+ end
109
+
110
+ it 'memoizes the result' do
111
+ count = 0
112
+ counter = proc { count += 1 }
113
+ subject.expose(:foo) { counter.call }
114
+
115
+ obj = subject.new
116
+ obj.foo.must_equal 1
117
+ obj.foo.must_equal 1
118
+ end
119
+
120
+ it 'it memoizes falsey values' do
121
+ val = true
122
+ meth = proc { val = !val }
123
+ subject.expose(:foo) { meth.call }
124
+
125
+ obj = subject.new
126
+ obj.foo.must_equal false
127
+ obj.foo.must_equal false
128
+ end
129
+
130
+ it 'instance evals the block' do
131
+ subject.expose(:foo) { @bar }
132
+ obj = subject.new
133
+ obj.instance_variable_set('@bar', 'bar')
134
+ obj.foo.must_equal 'bar'
135
+ end
136
+
137
+ it 'declares an attr_reader when called without a block' do
138
+ subject.expose :foo
139
+ subject.helper_methods.must_equal [:foo]
140
+
141
+ obj = subject.new
142
+ obj.instance_variable_set('@foo', 'bar')
143
+ obj.foo.must_equal 'bar'
144
+ end
145
+ end
146
+ end
147
+ end