strelka 0.0.1pre4

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.
Files changed (40) hide show
  1. data/.gemtest +0 -0
  2. data/History.rdoc +4 -0
  3. data/IDEAS.textile +174 -0
  4. data/Manifest.txt +38 -0
  5. data/README.rdoc +66 -0
  6. data/Rakefile +64 -0
  7. data/bin/leash +403 -0
  8. data/data/strelka/apps/strelka-admin +65 -0
  9. data/data/strelka/apps/strelka-setup +26 -0
  10. data/data/strelka/bootstrap-config.rb +34 -0
  11. data/data/strelka/templates/admin/console.tmpl +21 -0
  12. data/data/strelka/templates/layout.tmpl +30 -0
  13. data/lib/strelka/app/defaultrouter.rb +85 -0
  14. data/lib/strelka/app/filters.rb +70 -0
  15. data/lib/strelka/app/parameters.rb +64 -0
  16. data/lib/strelka/app/plugins.rb +205 -0
  17. data/lib/strelka/app/routing.rb +140 -0
  18. data/lib/strelka/app/templating.rb +157 -0
  19. data/lib/strelka/app.rb +175 -0
  20. data/lib/strelka/behavior/plugin.rb +36 -0
  21. data/lib/strelka/constants.rb +53 -0
  22. data/lib/strelka/httprequest.rb +52 -0
  23. data/lib/strelka/logging.rb +241 -0
  24. data/lib/strelka/mixins.rb +143 -0
  25. data/lib/strelka/process.rb +19 -0
  26. data/lib/strelka.rb +40 -0
  27. data/spec/data/layout.tmpl +3 -0
  28. data/spec/data/main.tmpl +1 -0
  29. data/spec/lib/constants.rb +32 -0
  30. data/spec/lib/helpers.rb +134 -0
  31. data/spec/strelka/app/defaultrouter_spec.rb +215 -0
  32. data/spec/strelka/app/parameters_spec.rb +74 -0
  33. data/spec/strelka/app/plugins_spec.rb +167 -0
  34. data/spec/strelka/app/routing_spec.rb +139 -0
  35. data/spec/strelka/app/templating_spec.rb +169 -0
  36. data/spec/strelka/app_spec.rb +160 -0
  37. data/spec/strelka/httprequest_spec.rb +54 -0
  38. data/spec/strelka/logging_spec.rb +72 -0
  39. data/spec/strelka_spec.rb +27 -0
  40. metadata +226 -0
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mongrel2/handler'
4
+ require 'strelka' unless defined?( Strelka )
5
+
6
+
7
+ # The process-style handler base class.
8
+ class Strelka::Process < Mongrel2::Handler
9
+ include Strelka::Loggable,
10
+ Strelka::Constants
11
+
12
+ ### Create a new Process.
13
+ def initialize( * )
14
+ @
15
+ end
16
+
17
+
18
+ end # class Strelka::Process
19
+
data/lib/strelka.rb ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mongrel2'
4
+ require 'configurability'
5
+
6
+ # An application framework for Ruby-mongrel2
7
+ #
8
+ # == Author/s
9
+ #
10
+ # * Michael Granger <ged@FaerieMUD.org>
11
+ #
12
+ module Strelka
13
+
14
+ # Library version constant
15
+ VERSION = '0.0.1'
16
+
17
+ # Version-control revision constant
18
+ REVISION = %q$Revision: 1e34f33f76af $
19
+
20
+
21
+ require 'strelka/logging'
22
+ extend Strelka::Logging
23
+
24
+ require 'strelka/constants'
25
+ include Strelka::Constants
26
+
27
+
28
+ ### Get the library version. If +include_buildnum+ is true, the version string will
29
+ ### include the VCS rev ID.
30
+ def self::version_string( include_buildnum=false )
31
+ vstring = "%s %s" % [ self.name, VERSION ]
32
+ vstring << " (build %s)" % [ REVISION[/: ([[:xdigit:]]+)/, 1] || '0' ] if include_buildnum
33
+ return vstring
34
+ end
35
+
36
+ require 'strelka/app'
37
+ require 'strelka/httprequest'
38
+
39
+ end # module Strelka
40
+
@@ -0,0 +1,3 @@
1
+ A minimal layout template.
2
+ <?attr body ?>
3
+
@@ -0,0 +1 @@
1
+ A template for testing the Templating plugin.
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'strelka' unless defined?( Strelka )
4
+
5
+
6
+ ### A collection of constants used in testing
7
+ module Strelka::TestConstants # :nodoc:all
8
+
9
+ include Strelka::Constants
10
+
11
+ unless defined?( TEST_HOST )
12
+
13
+ TEST_HOST = 'localhost'
14
+
15
+ # App id for testing
16
+ TEST_APPID = 'BD17D85C-4730-4BF2-999D-9D2B2E0FCCF9'
17
+
18
+ # 0mq socket specifications for Handlers
19
+ TEST_SEND_SPEC = 'tcp://127.0.0.1:9998'
20
+ TEST_RECV_SPEC = 'tcp://127.0.0.1:9997'
21
+
22
+
23
+
24
+ # Freeze all testing constants
25
+ constants.each do |cname|
26
+ const_get(cname).freeze
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent
7
+
8
+ srcdir = basedir.parent
9
+ mongrel2dir = srcdir + 'Mongrel2/lib'
10
+
11
+ libdir = basedir + "lib"
12
+
13
+ $LOAD_PATH.unshift( mongrel2dir.to_s ) unless $LOAD_PATH.include?( mongrel2dir.to_s )
14
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
15
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
16
+ }
17
+
18
+ # SimpleCov test coverage reporting; enable this using the :coverage rake task
19
+ if ENV['COVERAGE']
20
+ $stderr.puts "\n\n>>> Enabling coverage report.\n\n"
21
+ require 'simplecov'
22
+ SimpleCov.start do
23
+ add_filter 'spec'
24
+ add_group "Needing tests" do |file|
25
+ file.covered_percent < 90
26
+ end
27
+ end
28
+ end
29
+
30
+ require 'configurability'
31
+ require 'pathname'
32
+ require 'tmpdir'
33
+
34
+ require 'rspec'
35
+ require 'mongrel2'
36
+ require 'mongrel2/testing'
37
+
38
+ require 'strelka'
39
+
40
+ require 'spec/lib/constants'
41
+ # require 'spec/lib/matchers'
42
+
43
+ ### RSpec helper functions.
44
+ module Strelka::SpecHelpers
45
+ include Strelka::TestConstants
46
+
47
+ class ArrayLogger
48
+ ### Create a new ArrayLogger that will append content to +array+.
49
+ def initialize( array )
50
+ @array = array
51
+ end
52
+
53
+ ### Write the specified +message+ to the array.
54
+ def write( message )
55
+ @array << message
56
+ end
57
+
58
+ ### No-op -- this is here just so Logger doesn't complain
59
+ def close; end
60
+
61
+ end # class ArrayLogger
62
+
63
+
64
+ unless defined?( LEVEL )
65
+ LEVEL = {
66
+ :debug => Logger::DEBUG,
67
+ :info => Logger::INFO,
68
+ :warn => Logger::WARN,
69
+ :error => Logger::ERROR,
70
+ :fatal => Logger::FATAL,
71
+ }
72
+ end
73
+
74
+ ###############
75
+ module_function
76
+ ###############
77
+
78
+ ### Make an easily-comparable version vector out of +ver+ and return it.
79
+ def vvec( ver )
80
+ return ver.split('.').collect {|char| char.to_i }.pack('N*')
81
+ end
82
+
83
+
84
+ ### Reset the logging subsystem to its default state.
85
+ def reset_logging
86
+ Strelka.reset_logger
87
+ Mongrel2.reset_logger
88
+ end
89
+
90
+
91
+ ### Alter the output of the default log formatter to be pretty in SpecMate output
92
+ def setup_logging( level=Logger::FATAL )
93
+
94
+ # Turn symbol-style level config into Logger's expected Fixnum level
95
+ if Strelka::Logging::LOG_LEVELS.key?( level.to_s )
96
+ level = Strelka::Logging::LOG_LEVELS[ level.to_s ]
97
+ end
98
+
99
+ logger = Logger.new( $stderr )
100
+ Strelka.logger = logger
101
+ Strelka.logger.level = level
102
+ Mongrel2.logger.level = level
103
+
104
+ # Only do this when executing from a spec in TextMate
105
+ if ENV['HTML_LOGGING'] || (ENV['TM_FILENAME'] && ENV['TM_FILENAME'] =~ /_spec\.rb/)
106
+ Thread.current['logger-output'] = []
107
+ logdevice = ArrayLogger.new( Thread.current['logger-output'] )
108
+ Strelka.logger = Logger.new( logdevice )
109
+ # Strelka.logger.level = level
110
+ Strelka.logger.formatter = Strelka::Logging::HtmlFormatter.new( logger )
111
+ Mongrel2.logger = Strelka.logger
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+
118
+ abort "You need a version of RSpec >= 2.6.0" unless defined?( RSpec )
119
+
120
+ ### Mock with RSpec
121
+ RSpec.configure do |c|
122
+ include Strelka::TestConstants
123
+
124
+ c.mock_with( :rspec )
125
+
126
+ c.extend( Strelka::TestConstants )
127
+ c.include( Strelka::TestConstants )
128
+ c.include( Mongrel2::SpecHelpers )
129
+ c.include( Strelka::SpecHelpers )
130
+ # c.include( Strelka::Matchers )
131
+ end
132
+
133
+ # vim: set nosta noet ts=4 sw=4:
134
+
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/defaultrouter'
15
+
16
+
17
+ #####################################################################
18
+ ### C O N T E X T S
19
+ #####################################################################
20
+
21
+ describe Strelka::App::DefaultRouter do
22
+
23
+ before( :all ) do
24
+ setup_logging( :fatal )
25
+ @request_factory = Mongrel2::RequestFactory.new( route: '/user' )
26
+ end
27
+
28
+ before( :each ) do
29
+ @router = Strelka::App::DefaultRouter.new
30
+ end
31
+
32
+ after( :all ) do
33
+ reset_logging()
34
+ end
35
+
36
+ context "a router with routes for 'foo', 'foo/bar'" do
37
+
38
+ before( :each ) do
39
+ @router.add_route( :GET, ['foo'], :the_foo_action )
40
+ @router.add_route( :GET, ['foo','bar'], :the_foo_bar_action )
41
+ end
42
+
43
+ it "routes /user/foo/bar/baz to the foo/bar action" do
44
+ req = @request_factory.get( '/user/foo/bar/baz' )
45
+ @router.route_request( req ).should == :the_foo_bar_action
46
+ end
47
+
48
+ it "routes /user/foo/bar to the foo/bar action" do
49
+ req = @request_factory.get( '/user/foo/bar' )
50
+ @router.route_request( req ).should == :the_foo_bar_action
51
+ end
52
+
53
+ it "routes /user/foo to the foo action" do
54
+ req = @request_factory.get( '/user/foo' )
55
+ @router.route_request( req ).should == :the_foo_action
56
+ end
57
+
58
+ it "doesn't route /user" do
59
+ req = @request_factory.get( '/user' )
60
+ @router.route_request( req ).should be_nil()
61
+ end
62
+
63
+ it "doesn't route /user/other" do
64
+ req = @request_factory.get( '/user/other' )
65
+ @router.route_request( req ).should be_nil()
66
+ end
67
+
68
+ end
69
+
70
+ context "a router with routes for 'foo', 'foo/bar', and a fallback action" do
71
+
72
+ before( :each ) do
73
+ @router.add_route( :GET, [], :the_fallback_action )
74
+ @router.add_route( :GET, ['foo'], :the_foo_action )
75
+ @router.add_route( :GET, ['foo','bar'], :the_foo_bar_action )
76
+ end
77
+
78
+ it "routes /user/foo/bar/baz to the foo/bar action" do
79
+ req = @request_factory.get( '/user/foo/bar/baz' )
80
+ @router.route_request( req ).should == :the_foo_bar_action
81
+ end
82
+
83
+ it "routes /user/foo/bar to the foo/bar action" do
84
+ req = @request_factory.get( '/user/foo/bar' )
85
+ @router.route_request( req ).should == :the_foo_bar_action
86
+ end
87
+
88
+ it "routes /user/foo to the foo action" do
89
+ req = @request_factory.get( '/user/foo' )
90
+ @router.route_request( req ).should == :the_foo_action
91
+ end
92
+
93
+ it "routes /user to the fallback action" do
94
+ req = @request_factory.get( '/user' )
95
+ @router.route_request( req ).should == :the_fallback_action
96
+ end
97
+
98
+ it "routes /user/other to the fallback action" do
99
+ req = @request_factory.get( '/user/other' )
100
+ @router.route_request( req ).should == :the_fallback_action
101
+ end
102
+
103
+ end
104
+
105
+ context "a router with routes for 'foo', 'foo/\w{3}', and 'foo/\w{6}'" do
106
+
107
+ before( :each ) do
108
+ @router.add_route( :GET, ['foo'], :the_foo_action )
109
+ @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
110
+ @router.add_route( :GET, ['foo',/\w{6}/], :the_foo_sixaction )
111
+ end
112
+
113
+ it "routes /user/foo/barbim/baz to the foo/\w{6} action" do
114
+ req = @request_factory.get( '/user/foo/barbim/baz' )
115
+ @router.route_request( req ).should == :the_foo_sixaction
116
+ end
117
+
118
+ it "routes /user/foo/barbat to the foo/\w{6} action" do
119
+ req = @request_factory.get( '/user/foo/barbat' )
120
+ @router.route_request( req ).should == :the_foo_sixaction
121
+ end
122
+
123
+ it "routes /user/foo/bar/baz to the foo/\w{3} action" do
124
+ req = @request_factory.get( '/user/foo/bar/baz' )
125
+ @router.route_request( req ).should == :the_foo_threeaction
126
+ end
127
+
128
+ it "routes /user/foo/bar to the foo/\w{3} action" do
129
+ req = @request_factory.get( '/user/foo/bar' )
130
+ @router.route_request( req ).should == :the_foo_threeaction
131
+ end
132
+
133
+ it "routes /user/foo to the foo action" do
134
+ req = @request_factory.get( '/user/foo' )
135
+ @router.route_request( req ).should == :the_foo_action
136
+ end
137
+
138
+ it "doesn't route /user" do
139
+ req = @request_factory.get( '/user' )
140
+ @router.route_request( req ).should be_nil()
141
+ end
142
+
143
+ it "doesn't route /user/other" do
144
+ req = @request_factory.get( '/user/other' )
145
+ @router.route_request( req ).should be_nil()
146
+ end
147
+
148
+ end
149
+
150
+ # get '/foo/\w{3}'
151
+ # get '/foo/\d+'
152
+
153
+ context "a router with routes for: 'foo/\w{3}', then 'foo/\d+'" do
154
+
155
+ before( :each ) do
156
+ @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
157
+ @router.add_route( :GET, ['foo',/\d+/], :the_foo_digitaction )
158
+ end
159
+
160
+ it "routes /user/foo/1 to the foo/\d+ action" do
161
+ req = @request_factory.get( '/user/foo/1' )
162
+ @router.route_request( req ).should == :the_foo_digitaction
163
+ end
164
+
165
+ it "routes /user/foo/12 to the foo/\d+ action" do
166
+ req = @request_factory.get( '/user/foo/12' )
167
+ @router.route_request( req ).should == :the_foo_digitaction
168
+ end
169
+
170
+ it "routes /user/foo/123 to the foo/\w{3} action" do
171
+ req = @request_factory.get( '/user/foo/123' )
172
+ @router.route_request( req ).should == :the_foo_threeaction
173
+ end
174
+
175
+ it "routes /user/foo/1234 to the foo/\d+ action" do
176
+ req = @request_factory.get( '/user/foo/1234' )
177
+ @router.route_request( req ).should == :the_foo_digitaction
178
+ end
179
+
180
+ end
181
+
182
+ # get '/foo/\d+'
183
+ # get '/foo/\w{3}'
184
+
185
+ context "a router with routes for: 'foo/\d+', then 'foo/\w{3}'" do
186
+
187
+ before( :each ) do
188
+ @router.add_route( :GET, ['foo',/\d+/], :the_foo_digitaction )
189
+ @router.add_route( :GET, ['foo',/\w{3}/], :the_foo_threeaction )
190
+ end
191
+
192
+ it "routes /user/foo/1 to the foo/\d+ action" do
193
+ req = @request_factory.get( '/user/foo/1' )
194
+ @router.route_request( req ).should == :the_foo_digitaction
195
+ end
196
+
197
+ it "routes /user/foo/12 to the foo/\d+ action" do
198
+ req = @request_factory.get( '/user/foo/12' )
199
+ @router.route_request( req ).should == :the_foo_digitaction
200
+ end
201
+
202
+ it "routes /user/foo/123 to the foo/\d+ action" do
203
+ req = @request_factory.get( '/user/foo/123' )
204
+ @router.route_request( req ).should == :the_foo_digitaction
205
+ end
206
+
207
+ it "routes /user/foo/1234 to the foo/\d+ action" do
208
+ req = @request_factory.get( '/user/foo/1234' )
209
+ @router.route_request( req ).should == :the_foo_digitaction
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/plugins'
15
+ require 'strelka/app/parameters'
16
+ require 'strelka/behavior/plugin'
17
+
18
+
19
+ #####################################################################
20
+ ### C O N T E X T S
21
+ #####################################################################
22
+
23
+ describe Strelka::App::Parameters do
24
+
25
+ before( :all ) do
26
+ setup_logging( :fatal )
27
+ end
28
+
29
+ after( :all ) do
30
+ reset_logging()
31
+ end
32
+
33
+
34
+ it_should_behave_like( "A Strelka::App Plugin" )
35
+
36
+
37
+ describe "an including App" do
38
+
39
+ before( :each ) do
40
+ @app = Class.new( Strelka::App ) do
41
+ plugin :parameters
42
+ end
43
+ end
44
+
45
+ it "has a parameters Hash" do
46
+ @app.parameters.should be_a( Hash )
47
+ end
48
+
49
+ it "can declare a parameter with a validation pattern" do
50
+ @app.class_eval do
51
+ param :username, /\w+/i
52
+ end
53
+
54
+ @app.parameters.should have( 1 ).member
55
+ @app.parameters[ :username ].
56
+ should include( :constraint => /(?<username>(?i-mx:\w+))/ )
57
+ end
58
+
59
+ it "inherits parameters from its superclass" do
60
+ @app.class_eval do
61
+ param :username, /\w+/i
62
+ end
63
+ subapp = Class.new( @app )
64
+
65
+ subapp.parameters.should have( 1 ).member
66
+ subapp.parameters[ :username ].
67
+ should include( :constraint => /(?<username>(?i-mx:\w+))/ )
68
+ end
69
+
70
+ end
71
+
72
+
73
+ end
74
+
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
6
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
7
+ }
8
+
9
+ require 'rspec'
10
+
11
+ require 'spec/lib/helpers'
12
+
13
+ require 'strelka'
14
+ require 'strelka/app/plugins'
15
+
16
+
17
+ #####################################################################
18
+ ### C O N T E X T S
19
+ #####################################################################
20
+
21
+ describe Strelka::App::Plugins do
22
+
23
+ before( :all ) do
24
+ setup_logging( :fatal )
25
+ @original_plugin_registry = Strelka::App.loaded_plugins.dup
26
+ end
27
+
28
+ after( :all ) do
29
+ Strelka::App.loaded_plugins.clear
30
+ Strelka::App.loaded_plugins.replace( @original_plugin_registry )
31
+ reset_logging()
32
+ end
33
+
34
+
35
+ describe "Plugin module" do
36
+
37
+ it "registers itself with a plugin registry" do
38
+ plugin = Module.new do
39
+ extend Strelka::App::Plugin
40
+ end
41
+
42
+ Strelka::App.loaded_plugins.should include( plugin.plugin_name => plugin )
43
+ end
44
+
45
+
46
+ it "extends the object even if included" do
47
+ plugin = Module.new do
48
+ include Strelka::App::Plugin
49
+ end
50
+
51
+ Strelka::App.loaded_plugins.should include( plugin.plugin_name => plugin )
52
+ end
53
+
54
+
55
+ context "that declares that it should run before another" do
56
+
57
+ before( :each ) do
58
+ @other_mod = Module.new { include Strelka::App::Plugin }
59
+ modname = @other_mod.plugin_name
60
+ @before_mod = Module.new do
61
+ include Strelka::App::Plugin
62
+ run_before( modname )
63
+ end
64
+ end
65
+
66
+ it "knows that it isn't after the other plugin" do
67
+ @before_mod.should_not be_after( @other_mod )
68
+ end
69
+
70
+ it "knows that it is before the other plugin" do
71
+ @before_mod.should be_before( @other_mod )
72
+ end
73
+
74
+ it "sorts before the other plugin" do
75
+ [ @other_mod, @before_mod].sort.should == [ @before_mod, @other_mod ]
76
+ end
77
+
78
+ end
79
+
80
+ context "that declares that it should run after another" do
81
+
82
+ before( :each ) do
83
+ @other_mod = Module.new { include Strelka::App::Plugin }
84
+ modname = @other_mod.plugin_name
85
+ @after_mod = Module.new do
86
+ include Strelka::App::Plugin
87
+ run_after( modname )
88
+ end
89
+ end
90
+
91
+ it "knows that it is after the other plugin" do
92
+ @after_mod.should be_after( @other_mod )
93
+ end
94
+
95
+ it "knows that is isn't before the other plugin" do
96
+ @after_mod.should_not be_before( @other_mod )
97
+ end
98
+
99
+ it "sorts after the other plugin" do
100
+ [ @after_mod, @other_mod ].sort.should == [ @other_mod, @after_mod ]
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+
108
+ context "loading" do
109
+ it "appends class methods if the plugin has them" do
110
+ plugin = Module.new do
111
+ include Strelka::App::Plugin
112
+ module ClassMethods
113
+ def a_class_method; return "yep."; end
114
+ end
115
+ end
116
+
117
+ app = Class.new( Strelka::App )
118
+ app.install_plugin( plugin )
119
+
120
+ app.a_class_method.should == "yep."
121
+ end
122
+
123
+ it "adds class-instance variables to the class if the plugin has them" do
124
+ plugin = Module.new do
125
+ include Strelka::App::Plugin
126
+ module ClassMethods
127
+ @testing_value = :default
128
+ attr_accessor :testing_value
129
+ end
130
+ end
131
+
132
+ app = Class.new( Strelka::App )
133
+ app.install_plugin( plugin )
134
+
135
+ app.testing_value.should == :default
136
+ app.testing_value = :not_the_default
137
+ app.testing_value.should == :not_the_default
138
+ end
139
+ end
140
+
141
+
142
+ context "plugin/plugins declarative" do
143
+
144
+ before( :each ) do
145
+ @including_class = Class.new { include Strelka::App::Plugins }
146
+ end
147
+
148
+ it "can declare a single plugin to load" do
149
+ klass = Class.new( @including_class ) do
150
+ plugin :routing
151
+ end
152
+
153
+ klass.ancestors.should include( Strelka::App::Routing )
154
+ end
155
+
156
+ it "can declare a list of plugins to load" do
157
+ klass = Class.new( @including_class ) do
158
+ plugins :templating, :routing
159
+ end
160
+
161
+ klass.ancestors.should include( Strelka::App::Routing, Strelka::App::Templating )
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+