manveru-innate 2009.02.25 → 2009.03.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/CHANGELOG +383 -0
  2. data/MANIFEST +17 -8
  3. data/README.md +222 -136
  4. data/Rakefile +7 -2
  5. data/example/provides.rb +28 -0
  6. data/innate.gemspec +19 -10
  7. data/lib/innate/action.rb +21 -47
  8. data/lib/innate/adapter.rb +65 -56
  9. data/lib/innate/cache.rb +16 -8
  10. data/lib/innate/dynamap.rb +39 -29
  11. data/lib/innate/helper/aspect.rb +60 -0
  12. data/lib/innate/helper/cgi.rb +2 -0
  13. data/lib/innate/helper/link.rb +43 -11
  14. data/lib/innate/helper/partial.rb +6 -5
  15. data/lib/innate/helper.rb +10 -13
  16. data/lib/innate/log/hub.rb +1 -0
  17. data/lib/innate/log.rb +3 -6
  18. data/lib/{rack → innate}/middleware_compiler.rb +19 -12
  19. data/lib/innate/mock.rb +3 -2
  20. data/lib/innate/node.rb +573 -179
  21. data/lib/innate/options/dsl.rb +46 -6
  22. data/lib/innate/options/stub.rb +7 -0
  23. data/lib/innate/options.rb +14 -93
  24. data/lib/innate/request.rb +21 -7
  25. data/lib/innate/response.rb +12 -0
  26. data/lib/innate/route.rb +2 -3
  27. data/lib/innate/session.rb +37 -20
  28. data/lib/innate/spec.rb +4 -0
  29. data/lib/innate/state/fiber.rb +14 -7
  30. data/lib/innate/state/thread.rb +10 -2
  31. data/lib/innate/state.rb +8 -11
  32. data/lib/innate/traited.rb +14 -6
  33. data/lib/innate/trinity.rb +0 -4
  34. data/lib/innate/version.rb +1 -1
  35. data/lib/innate/view/erb.rb +4 -2
  36. data/lib/innate/view/none.rb +2 -2
  37. data/lib/innate/view.rb +14 -21
  38. data/lib/innate.rb +49 -30
  39. data/spec/helper.rb +8 -0
  40. data/spec/innate/action/layout.rb +9 -6
  41. data/spec/innate/cache/common.rb +3 -3
  42. data/spec/innate/helper/aspect.rb +3 -5
  43. data/spec/innate/helper/flash.rb +1 -1
  44. data/spec/innate/helper/link.rb +45 -2
  45. data/spec/innate/helper/partial.rb +34 -10
  46. data/spec/innate/helper/view/loop.erb +1 -1
  47. data/spec/innate/helper/view/recursive.erb +1 -1
  48. data/spec/innate/node/mapping.rb +37 -0
  49. data/spec/innate/node/node.rb +142 -0
  50. data/spec/innate/node/resolve.rb +82 -0
  51. data/spec/innate/node/{another_layout → view/another_layout}/another_layout.erb +0 -0
  52. data/spec/innate/node/{bar.html → view/bar.erb} +0 -0
  53. data/spec/innate/node/{foo.html.erb → view/foo.html.erb} +0 -0
  54. data/spec/innate/node/{only_view.html → view/only_view.erb} +0 -0
  55. data/spec/innate/node/view/with_layout.erb +1 -0
  56. data/spec/innate/node/wrap_action_call.rb +83 -0
  57. data/spec/innate/options.rb +28 -6
  58. data/spec/innate/provides/list.html.erb +1 -0
  59. data/spec/innate/provides/list.txt.erb +1 -0
  60. data/spec/innate/provides.rb +99 -0
  61. data/spec/innate/request.rb +23 -10
  62. data/spec/innate/route.rb +2 -4
  63. data/spec/innate/session.rb +1 -1
  64. data/spec/innate/state/fiber.rb +57 -0
  65. data/spec/innate/state/thread.rb +40 -0
  66. metadata +20 -11
  67. data/lib/rack/reloader.rb +0 -192
  68. data/spec/innate/node/with_layout.erb +0 -3
  69. data/spec/innate/node.rb +0 -224
data/lib/innate/view.rb CHANGED
@@ -8,8 +8,9 @@ module Innate
8
8
 
9
9
  module_function
10
10
 
11
- def render(ext, action, string)
12
- get(ext).render(action, string)
11
+ def exts_of(engine)
12
+ name = engine.to_s
13
+ ENGINE.reject{|k,v| v != name }.keys
13
14
  end
14
15
 
15
16
  # Try to obtain given engine by its registered name.
@@ -22,7 +23,7 @@ module Innate
22
23
  elsif klass = ENGINE[eoe]
23
24
  TEMP[eoe] = obtain(klass)
24
25
  else
25
- TEMP[eoe] = const_get(eoe.capitalize)
26
+ TEMP[eoe] = obtain(eoe, View)
26
27
  end
27
28
  end
28
29
 
@@ -30,11 +31,10 @@ module Innate
30
31
  # class will cause race conditions and one call may return the wrong class
31
32
  # on the first request (before TEMP is set).
32
33
  # No mutex is used in Fiber environment, see Innate::State and subclasses.
33
- def obtain(klass)
34
+ def obtain(klass, root = Object)
34
35
  STATE.sync do
35
- obj = Object
36
- klass.split('::').each{|e| obj = obj.const_get(e) }
37
- obj
36
+ klass.scan(/\w+/){|part| root = root.const_get(part) }
37
+ root
38
38
  end
39
39
  end
40
40
 
@@ -47,23 +47,16 @@ module Innate
47
47
  def register(klass, *exts)
48
48
  exts.each do |ext|
49
49
  ext = ext.to_s
50
- if k = ENGINE[ext]
51
- Log.warn "#{ext} is assigned to #{k} already"
52
- else
53
- ENGINE[ext] = klass
54
- end
50
+ k = ENGINE[ext]
51
+ Log.warn("overwriting %p which is set to %p already" % [ext, k]) if k
52
+ ENGINE[ext] = klass
55
53
  end
56
54
  end
57
55
 
58
- # Combine Kernel#autoload and Innate::View::register
56
+ autoload :None, 'innate/view/none'
57
+ autoload :ERB, 'innate/view/erb'
59
58
 
60
- def auto_register(name, *exts)
61
- autoload(name, "innate/view/#{name}".downcase)
62
- register("#{self}::#{name}", *exts)
63
- end
64
-
65
- auto_register :None, :css
66
- auto_register :None, :html, :htm
67
- auto_register :ERB, :erb
59
+ register 'Innate::View::None', :css, :html, :htm
60
+ register 'Innate::View::ERB', :erb
68
61
  end
69
62
  end
data/lib/innate.rb CHANGED
@@ -21,6 +21,7 @@ module Innate
21
21
  require 'set'
22
22
  require 'pathname'
23
23
  require 'digest/sha1'
24
+ require 'digest/sha2'
24
25
  require 'ipaddr'
25
26
  require 'socket'
26
27
  require 'logger'
@@ -29,19 +30,25 @@ module Innate
29
30
  # 3rd party
30
31
  require 'rack'
31
32
 
32
- # innate core patches
33
+ # innates ruby core patches
33
34
  require 'innate/core_compatibility/string'
34
35
  require 'innate/core_compatibility/basic_object'
35
36
 
36
37
  # innate core
37
38
  require 'innate/version'
38
39
  require 'innate/traited'
40
+ require 'innate/trinity'
41
+ require 'innate/middleware_compiler'
42
+ require 'innate/options/dsl'
43
+ require 'innate/options/stub'
44
+ require 'innate/dynamap'
45
+
46
+ # innate full
39
47
  require 'innate/cache'
40
48
  require 'innate/node'
41
49
  require 'innate/options'
42
50
  require 'innate/log'
43
51
  require 'innate/state'
44
- require 'innate/trinity'
45
52
  require 'innate/current'
46
53
  require 'innate/mock'
47
54
  require 'innate/adapter'
@@ -50,18 +57,15 @@ module Innate
50
57
  require 'innate/view'
51
58
  require 'innate/session'
52
59
  require 'innate/session/flash'
53
- require 'innate/dynamap'
54
60
  require 'innate/route'
55
61
 
56
- # innate lib/rack
57
- require 'rack/reloader'
58
- require 'rack/middleware_compiler'
59
-
60
62
  extend Trinity
61
63
 
62
64
  # Contains all the module functions for Innate, we keep them in a module so
63
65
  # Ramaze can simply use them as well.
64
66
  module SingletonMethods
67
+ PROXY_OPTIONS = { :port => 'adapter.port', :host => 'adapter.host',
68
+ :adapter => 'adapter.handler' }
65
69
  # The method that starts the whole business.
66
70
  #
67
71
  # Call Innate.start after you defined your application.
@@ -73,7 +77,7 @@ module Innate
73
77
  # We do return if options.started is true, which indicates that all you
74
78
  # wanted to do is setup the environment and update options.
75
79
  #
76
- # @usage
80
+ # @example usage
77
81
  #
78
82
  # # passing options
79
83
  # Innate.start :adapter => :mongrel, :mode => :live
@@ -93,7 +97,7 @@ module Innate
93
97
  # Port for the server
94
98
  # @option param :started [boolean] (false)
95
99
  # Indicate that calls Innate::start will be ignored
96
- # @option param :adapter [Symbol] (:webrick)
100
+ # @option param :handler [Symbol] (:webrick)
97
101
  # Web server to run on
98
102
  # @option param :setup [Array] ([Innate::Cache, Innate::Node])
99
103
  # Will send ::setup to each element during Innate::start
@@ -105,10 +109,19 @@ module Innate
105
109
  # Keep state in Thread or Fiber, fall back to Thread if Fiber not available
106
110
  # @option param :mode [Symbol] (:dev)
107
111
  # Indicates which default middleware to use, (:dev|:live)
108
- def start(param = {}, &block)
109
- options[:app][:root] = go_figure_root(param, caller)
110
- param.reject!{|k, v| [:root, :file].include?(k) }
111
- options.merge!(param)
112
+ def start(given_options = {}, &block)
113
+ root = given_options.delete(:root)
114
+ file = given_options.delete(:file)
115
+
116
+ if found_root = go_figure_root(:root => root, :file => file)
117
+ $0 = found_root
118
+ Innate.options.roots = [found_root]
119
+ end
120
+
121
+ PROXY_OPTIONS.each{|k,v| given_options[v] = given_options.delete(k) }
122
+ given_options.delete_if{|k,v| v.nil? }
123
+
124
+ options.merge!(given_options)
112
125
 
113
126
  setup_dependencies
114
127
  middleware!(options.mode, &block) if block_given?
@@ -116,24 +129,30 @@ module Innate
116
129
  return if options.started
117
130
  options.started = true
118
131
 
119
- trap(options[:trap]){ stop(10) } if options[:trap]
132
+ signal = options.trap
133
+ trap(signal){ stop(10) } if signal
120
134
 
121
- start!(options)
135
+ start!
122
136
  end
123
137
 
124
- def start!(options = Innate.options)
125
- Adapter.start(middleware(options.mode), options)
138
+ def start!(mode = options[:mode])
139
+ Adapter.start(middleware(mode))
126
140
  end
127
141
 
128
142
  def stop(wait = 3)
129
143
  Log.info("Shutdown within #{wait} seconds")
144
+ Timeout.timeout(wait){ teardown_dependencies }
130
145
  Timeout.timeout(wait){ exit }
131
146
  ensure
132
147
  exit!
133
148
  end
134
149
 
135
150
  def setup_dependencies
136
- options[:setup].each{|obj| obj.setup }
151
+ options[:setup].each{|obj| obj.setup if obj.respond_to?(:setup) }
152
+ end
153
+
154
+ def teardown_dependencies
155
+ options[:setup].each{|obj| obj.teardown if obj.respond_to?(:teardown) }
137
156
  end
138
157
 
139
158
  # Treat Innate like a rack application, pass the rack +env+ and optionally
@@ -144,20 +163,20 @@ module Innate
144
163
  # @default mode options.mode
145
164
  # @return [Array] with [body, header, status]
146
165
  # @author manveru
147
- def call(env, mode = options.mode)
166
+ def call(env, mode = options[:mode])
148
167
  middleware(mode).call(env)
149
168
  end
150
169
 
151
- def middleware(mode, &block)
152
- Rack::MiddlewareCompiler.build(mode, &block)
170
+ def middleware(mode = options[:mode], &block)
171
+ options[:middleware_compiler].build(mode, &block)
153
172
  end
154
173
 
155
- def middleware!(mode, &block)
156
- Rack::MiddlewareCompiler.build!(mode, &block)
174
+ def middleware!(mode = options[:mode], &block)
175
+ options[:middleware_compiler].build!(mode, &block)
157
176
  end
158
177
 
159
- def middleware_recompile(mode = options.mode)
160
- Rack::MiddlewareCompiler::COMPILED[mode].compile!
178
+ def middleware_recompile(mode = options[:mode])
179
+ options[:middleware_compiler]::COMPILED[mode].compile!
161
180
  end
162
181
 
163
182
  # Innate can be started by:
@@ -170,7 +189,7 @@ module Innate
170
189
  #
171
190
  # TODO: better documentation and nice defaults, don't want to rely on a
172
191
  # filename, bad mojo.
173
- def go_figure_root(options, backtrace)
192
+ def go_figure_root(options, backtrace = caller)
174
193
  if o_file = options[:file]
175
194
  return File.dirname(o_file)
176
195
  elsif root = options[:root]
@@ -263,14 +282,14 @@ module Innate
263
282
  #
264
283
  # @see Rack::MiddlewareCompiler
265
284
  middleware :dev do |m|
266
- m.use(Rack::Lint, Rack::CommonLogger, Rack::ShowExceptions,
267
- Rack::ShowStatus, Rack::ConditionalGet, Rack::Head, Rack::Reloader)
285
+ m.apps(Rack::Lint, Rack::CommonLogger, Rack::ShowExceptions,
286
+ Rack::ShowStatus, Rack::ConditionalGet, Rack::Head, Rack::Reloader)
268
287
  m.innate
269
288
  end
270
289
 
271
290
  middleware :live do |m|
272
- m.use(Rack::CommonLogger, Rack::ShowStatus, Rack::ConditionalGet,
273
- Rack::Head)
291
+ m.apps(Rack::CommonLogger, Rack::ShowStatus, Rack::ConditionalGet,
292
+ Rack::Head)
274
293
  m.innate
275
294
  end
276
295
  end
data/spec/helper.rb CHANGED
@@ -1,2 +1,10 @@
1
+ if caller_line = caller.grep(%r!spec/innate/!).first
2
+ caller_file = caller_line.split(':', 2).first
3
+ caller_root = File.dirname(caller_file)
4
+ $0 = caller_file
5
+ end
6
+
1
7
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/innate'))
2
8
  require 'innate/spec'
9
+
10
+ Innate.options.roots = [caller_root] if caller_root
@@ -3,9 +3,12 @@
3
3
 
4
4
  require 'spec/helper'
5
5
 
6
- Innate.options.app.root = File.dirname(__FILE__)
6
+ class SpecActionLayout
7
+ include Innate::Node
8
+ map_layouts '/'
9
+ end
7
10
 
8
- class SpecActionLayoutMethod
11
+ class SpecActionLayoutMethod < SpecActionLayout
9
12
  Innate.node('/from_method', self)
10
13
  layout('method_layout')
11
14
 
@@ -22,7 +25,7 @@ class SpecActionLayoutMethod
22
25
  end
23
26
  end
24
27
 
25
- class SpecActionLayoutFile
28
+ class SpecActionLayoutFile < SpecActionLayout
26
29
  Innate.node('/from_file', self)
27
30
  layout('file_layout')
28
31
 
@@ -31,7 +34,7 @@ class SpecActionLayoutFile
31
34
  end
32
35
  end
33
36
 
34
- class SpecActionLayoutSpecific
37
+ class SpecActionLayoutSpecific < SpecActionLayout
35
38
  Innate.node('/specific', self)
36
39
  layout('file_layout'){|name, wish| name == 'index' }
37
40
 
@@ -44,7 +47,7 @@ class SpecActionLayoutSpecific
44
47
  end
45
48
  end
46
49
 
47
- class SpecActionLayoutDeny
50
+ class SpecActionLayoutDeny < SpecActionLayout
48
51
  Innate.node('/deny', self)
49
52
  layout('file_layout'){|name, wish| name != 'without' }
50
53
 
@@ -57,7 +60,7 @@ class SpecActionLayoutDeny
57
60
  end
58
61
  end
59
62
 
60
- class SpecActionLayoutMulti
63
+ class SpecActionLayoutMulti < SpecActionLayout
61
64
  Innate.node('/multi', self)
62
65
  layout('file_layout'){|name, wish| name =~ /index|second/ }
63
66
 
@@ -1,8 +1,8 @@
1
1
  require 'spec/helper'
2
2
 
3
- Innate.options.cache.names = [:one, :two]
4
- Innate.options.cache.one = $common_cache_class
5
- Innate.options.cache.two = $common_cache_class
3
+ Innate::Cache.options.names = [:one, :two]
4
+ Innate::Cache.options.one = $common_cache_class
5
+ Innate::Cache.options.two = $common_cache_class
6
6
  Innate.setup_dependencies
7
7
 
8
8
  describe $common_cache_class do
@@ -1,9 +1,7 @@
1
1
  require 'spec/helper'
2
- Innate.options.app.root = File.dirname(__FILE__)
3
- Innate.options.app.view = ''
4
2
 
5
3
  class AspectSpec
6
- Innate.node('/', self).provide(:html => :none)
4
+ Innate.node('/', self).provide(:html, :None)
7
5
 
8
6
  before(:with_before){ $aspect_spec_before += 40 }
9
7
  def with_before; $aspect_spec_before += 2; end
@@ -19,7 +17,7 @@ class AspectSpec
19
17
  end
20
18
 
21
19
  class AspectAllSpec
22
- Innate.node('/all', self).provide(:html => :none)
20
+ Innate.node('/all', self).provide(:html, :None)
23
21
 
24
22
  before_all{ $aspect_spec_before_all += 40; @foo = 'Hello'; @bar = 'World' }
25
23
  after_all{ $aspect_spec_after_all += 40 }
@@ -33,7 +31,7 @@ class AspecNoMethodSpec
33
31
  Innate.node('/without_method', self)
34
32
  include Innate::Node
35
33
  map '/without_method'
36
- view_root 'view'
34
+ map_views '/'
37
35
  before_all{ @foo = 'Hello'; @bar = 'World'}
38
36
  end
39
37
 
@@ -23,7 +23,7 @@ class SpecFlash
23
23
  def set_delete_key
24
24
  flash[:name] = 'manveru'
25
25
  flash.delete(:name)
26
- flash[:name]
26
+ flash[:name].to_s
27
27
  end
28
28
 
29
29
  def delete_key
@@ -3,11 +3,29 @@ require 'spec/helper'
3
3
  class One
4
4
  include Innate::Node
5
5
  map '/'
6
+
7
+ def auto_route
8
+ UsingRouteSelf.new.route.to_s
9
+ end
6
10
  end
7
11
 
8
12
  class Two
9
13
  include Innate::Node
10
14
  map '/two'
15
+
16
+ def auto_route
17
+ UsingRouteSelf.new.route.to_s
18
+ end
19
+ end
20
+
21
+ class UsingRouteSelf
22
+ include Innate::Helper::Link
23
+
24
+ attr_reader :route
25
+
26
+ def initialize
27
+ @route = route_self(:elsewhere)
28
+ end
11
29
  end
12
30
 
13
31
  describe Innate::Helper::Link do
@@ -56,9 +74,9 @@ describe Innate::Helper::Link do
56
74
  end
57
75
 
58
76
  should 'prefix the links as defined in the options' do
59
- Innate.options.app.prefix = '/bar'
77
+ Innate.options.prefix = '/bar'
60
78
  One.route('/foo').should == URI('/bar/foo')
61
- Innate.options.app.prefix = '/'
79
+ Innate.options.prefix = '/'
62
80
  end
63
81
  end
64
82
 
@@ -85,4 +103,29 @@ describe Innate::Helper::Link do
85
103
  should == '<a href="/foo">&lt;blink&gt; &amp; &lt;a&gt;</a>'
86
104
  end
87
105
  end
106
+
107
+ describe 'combining #anchor and #route' do
108
+ should 'not escape twice' do
109
+ One.anchor('foo', One.route(:index, :bar => 'a/b/c')).
110
+ should == '<a href="/index?bar=a%2Fb%2Fc">foo</a>'
111
+ end
112
+
113
+ should 'handle complete uris gracefully' do
114
+ One.anchor('foo', 'http://example.com/?foo=bar&baz=qux').
115
+ should == '<a href="http://example.com/?foo=bar&amp;baz=qux">foo</a>'
116
+ end
117
+
118
+ should 'be able to route from one node to another' do
119
+ Two.anchor('foo', One.route(:index)).should == '<a href="/index">foo</a>'
120
+ One.anchor('foo', Two.route(:index)).should == '<a href="/two/index">foo</a>'
121
+ end
122
+ end
123
+
124
+ describe '#route_self' do
125
+ behaves_like :mock
126
+ should 'provide a route to the node of the currently active action' do
127
+ get('/auto_route').body.should == '/elsewhere'
128
+ get('/two/auto_route').body.should == '/two/elsewhere'
129
+ end
130
+ end
88
131
  end
@@ -1,8 +1,8 @@
1
1
  require 'spec/helper'
2
2
 
3
- Innate.options.app.root = File.dirname(__FILE__)
4
3
  class SpecHelperPartial
5
4
  Innate.node '/'
5
+ map_views '/'
6
6
 
7
7
  def index
8
8
  '<html><head><title><%= render_partial("/title") %></title></head></html>'
@@ -20,26 +20,38 @@ class SpecHelperPartial
20
20
  "Message: #{request[:msg]}"
21
21
  end
22
22
 
23
+ def without_ext
24
+ render_template('partial')
25
+ end
26
+
27
+ def with_real_ext
28
+ render_template('partial.erb')
29
+ end
30
+
31
+ def with_needed_ext
32
+ render_template('partial.html')
33
+ end
34
+
23
35
  def composed
24
36
  @here = 'there'
25
- 'From Action | ' << render_template("partial.erb")
37
+ 'From Action | ' << render_template("partial")
26
38
  end
27
39
 
28
40
  def recursive
29
41
  @n = 1
30
42
  end
31
43
 
32
- def without_ext
33
- render_template('partial')
44
+ def with_variable
45
+ here = 'there'
46
+ render_template("partial", :here => here)
34
47
  end
35
48
  end
36
49
 
37
50
  class SpecHelperPartialWithLayout < SpecHelperPartial
38
51
  Innate.node '/with_layout'
39
52
  layout('layout')
40
- view_root '/'
41
53
 
42
- def layout
54
+ def layout
43
55
  '<h1>with layout</h1><%= @content %>'
44
56
  end
45
57
  end
@@ -59,6 +71,18 @@ describe Innate::Helper::Partial do
59
71
  get('/composed').body.strip.should == "From Action | From Partial there"
60
72
  end
61
73
 
74
+ should 'not require file extension' do
75
+ get('/without_ext').body.should == "From Partial \n"
76
+ end
77
+
78
+ it "the real extension will just be stripped" do
79
+ got = get('/with_real_ext').body.should == "From Partial \n"
80
+ end
81
+
82
+ it "works with the content representation instead" do
83
+ get('/with_needed_ext').body.should == "From Partial \n"
84
+ end
85
+
62
86
  should 'render_template in a loop' do
63
87
  get('/loop').body.gsub(/\s/,'').should == '12345'
64
88
  end
@@ -67,11 +91,11 @@ describe Innate::Helper::Partial do
67
91
  get('/recursive').body.gsub(/\s/,'').should == '{1{2{3{44}4}3}2}'
68
92
  end
69
93
 
70
- should 'not require file extension' do
71
- get('/without_ext').body.should == "From Partial \n"
72
- end
73
-
74
94
  should 'render template with layout' do
75
95
  get('/with_layout/without_ext').body.should == "<h1>with layout</h1>From Partial \n"
76
96
  end
97
+
98
+ it 'makes passed variables available in the template as instance variables' do
99
+ get('/with_variable').body.should == "From Partial there\n"
100
+ end
77
101
  end
@@ -1,4 +1,4 @@
1
1
  <% (1..5).each do |n| %>
2
2
  <% @n = n %>
3
- <%= render_template('num.erb') %>
3
+ <%= render_template('num') %>
4
4
  <% end %>
@@ -2,7 +2,7 @@
2
2
  <%= @n %>
3
3
  <% if @n < 4 %>
4
4
  <% @n += 1 %>
5
- <%= render_template('recursive.xhtml') %>
5
+ <%= render_template('recursive') %>
6
6
  <% end %>
7
7
  <%= @n %>
8
8
  }
@@ -0,0 +1,37 @@
1
+ require 'spec/helper'
2
+
3
+ describe 'Node::generate_mapping' do
4
+ def gen(const)
5
+ Innate::Node.generate_mapping(const)
6
+ end
7
+
8
+ should 'transform class names into snake_case locations' do
9
+ gen( 'O').should == '/o'
10
+ gen( 'Oo').should == '/oo'
11
+ gen( 'Ooo').should == '/ooo'
12
+ gen( 'OooO').should == '/oooo'
13
+ gen( 'OooOo').should == '/ooo_oo'
14
+ gen('OooOoo').should == '/ooo_ooo'
15
+ gen('OOOooo').should == '/oooooo'
16
+ gen('OooOOO').should == '/oooooo'
17
+ gen('OoOoOo').should == '/oo_oo_oo'
18
+ end
19
+
20
+ should 'transform namespaces into leading parts of the location' do
21
+ gen('O::O').should == '/o/o'
22
+ gen('O::O::O').should == '/o/o/o'
23
+ gen('O::O::O::O').should == '/o/o/o/o'
24
+ end
25
+
26
+ should 'transform leading parts just like standalone part' do
27
+ gen( 'O::O').should == '/o/o'
28
+ gen( 'Oo::O').should == '/oo/o'
29
+ gen( 'Ooo::O').should == '/ooo/o'
30
+ gen( 'OooO::O').should == '/oooo/o'
31
+ gen( 'OooOo::O').should == '/ooo_oo/o'
32
+ gen('OooOoo::O').should == '/ooo_ooo/o'
33
+ gen('OOOooo::O').should == '/oooooo/o'
34
+ gen('OooOOO::O').should == '/oooooo/o'
35
+ gen('OoOoOo::O').should == '/oo_oo_oo/o'
36
+ end
37
+ end