rjspotter-innate 2009.06.29

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 (128) hide show
  1. data/AUTHORS +10 -0
  2. data/CHANGELOG +3261 -0
  3. data/COPYING +18 -0
  4. data/MANIFEST +127 -0
  5. data/README.md +563 -0
  6. data/Rakefile +39 -0
  7. data/example/app/retro_games.rb +60 -0
  8. data/example/app/todo/layout/default.xhtml +11 -0
  9. data/example/app/todo/spec/todo.rb +63 -0
  10. data/example/app/todo/start.rb +51 -0
  11. data/example/app/todo/view/index.xhtml +39 -0
  12. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  13. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  14. data/example/app/whywiki_erb/start.rb +42 -0
  15. data/example/app/whywiki_erb/view/edit.erb +6 -0
  16. data/example/app/whywiki_erb/view/index.erb +12 -0
  17. data/example/custom_middleware.rb +35 -0
  18. data/example/hello.rb +11 -0
  19. data/example/howto_spec.rb +35 -0
  20. data/example/link.rb +27 -0
  21. data/example/provides.rb +31 -0
  22. data/example/session.rb +38 -0
  23. data/innate.gemspec +41 -0
  24. data/lib/innate.rb +269 -0
  25. data/lib/innate/action.rb +137 -0
  26. data/lib/innate/adapter.rb +76 -0
  27. data/lib/innate/cache.rb +134 -0
  28. data/lib/innate/cache/api.rb +128 -0
  29. data/lib/innate/cache/drb.rb +58 -0
  30. data/lib/innate/cache/file_based.rb +44 -0
  31. data/lib/innate/cache/marshal.rb +20 -0
  32. data/lib/innate/cache/memory.rb +21 -0
  33. data/lib/innate/cache/yaml.rb +20 -0
  34. data/lib/innate/current.rb +35 -0
  35. data/lib/innate/dynamap.rb +96 -0
  36. data/lib/innate/helper.rb +185 -0
  37. data/lib/innate/helper/aspect.rb +124 -0
  38. data/lib/innate/helper/cgi.rb +54 -0
  39. data/lib/innate/helper/flash.rb +36 -0
  40. data/lib/innate/helper/link.rb +94 -0
  41. data/lib/innate/helper/redirect.rb +85 -0
  42. data/lib/innate/helper/render.rb +152 -0
  43. data/lib/innate/helper/send_file.rb +26 -0
  44. data/lib/innate/log.rb +20 -0
  45. data/lib/innate/log/color_formatter.rb +49 -0
  46. data/lib/innate/log/hub.rb +77 -0
  47. data/lib/innate/middleware_compiler.rb +65 -0
  48. data/lib/innate/mock.rb +49 -0
  49. data/lib/innate/node.rb +1029 -0
  50. data/lib/innate/options.rb +37 -0
  51. data/lib/innate/options/dsl.rb +205 -0
  52. data/lib/innate/options/stub.rb +7 -0
  53. data/lib/innate/request.rb +141 -0
  54. data/lib/innate/response.rb +24 -0
  55. data/lib/innate/route.rb +114 -0
  56. data/lib/innate/session.rb +133 -0
  57. data/lib/innate/session/flash.rb +94 -0
  58. data/lib/innate/spec.rb +1 -0
  59. data/lib/innate/spec/bacon.rb +28 -0
  60. data/lib/innate/state.rb +26 -0
  61. data/lib/innate/state/accessor.rb +130 -0
  62. data/lib/innate/traited.rb +90 -0
  63. data/lib/innate/trinity.rb +18 -0
  64. data/lib/innate/version.rb +3 -0
  65. data/lib/innate/view.rb +97 -0
  66. data/lib/innate/view/erb.rb +14 -0
  67. data/lib/innate/view/etanni.rb +33 -0
  68. data/lib/innate/view/none.rb +9 -0
  69. data/spec/example/app/retro_games.rb +30 -0
  70. data/spec/example/hello.rb +13 -0
  71. data/spec/example/link.rb +25 -0
  72. data/spec/example/provides.rb +16 -0
  73. data/spec/example/session.rb +22 -0
  74. data/spec/helper.rb +10 -0
  75. data/spec/innate/action/layout.rb +121 -0
  76. data/spec/innate/action/layout/file_layout.xhtml +1 -0
  77. data/spec/innate/cache/common.rb +47 -0
  78. data/spec/innate/cache/marshal.rb +5 -0
  79. data/spec/innate/cache/memory.rb +5 -0
  80. data/spec/innate/cache/yaml.rb +5 -0
  81. data/spec/innate/dynamap.rb +22 -0
  82. data/spec/innate/helper.rb +86 -0
  83. data/spec/innate/helper/aspect.rb +75 -0
  84. data/spec/innate/helper/cgi.rb +37 -0
  85. data/spec/innate/helper/flash.rb +115 -0
  86. data/spec/innate/helper/link.rb +139 -0
  87. data/spec/innate/helper/redirect.rb +171 -0
  88. data/spec/innate/helper/render.rb +165 -0
  89. data/spec/innate/helper/send_file.rb +21 -0
  90. data/spec/innate/helper/view/aspect_hello.xhtml +1 -0
  91. data/spec/innate/helper/view/locals.xhtml +1 -0
  92. data/spec/innate/helper/view/loop.xhtml +4 -0
  93. data/spec/innate/helper/view/num.xhtml +1 -0
  94. data/spec/innate/helper/view/partial.xhtml +1 -0
  95. data/spec/innate/helper/view/recursive.xhtml +7 -0
  96. data/spec/innate/mock.rb +84 -0
  97. data/spec/innate/modes.rb +61 -0
  98. data/spec/innate/node/mapping.rb +37 -0
  99. data/spec/innate/node/node.rb +135 -0
  100. data/spec/innate/node/resolve.rb +82 -0
  101. data/spec/innate/node/view/another_layout/another_layout.xhtml +3 -0
  102. data/spec/innate/node/view/bar.xhtml +1 -0
  103. data/spec/innate/node/view/foo.html.xhtml +1 -0
  104. data/spec/innate/node/view/only_view.xhtml +1 -0
  105. data/spec/innate/node/view/with_layout.xhtml +1 -0
  106. data/spec/innate/node/wrap_action_call.rb +83 -0
  107. data/spec/innate/options.rb +123 -0
  108. data/spec/innate/parameter.rb +154 -0
  109. data/spec/innate/provides.rb +99 -0
  110. data/spec/innate/provides/list.html.xhtml +1 -0
  111. data/spec/innate/provides/list.txt.xhtml +1 -0
  112. data/spec/innate/request.rb +79 -0
  113. data/spec/innate/route.rb +135 -0
  114. data/spec/innate/session.rb +58 -0
  115. data/spec/innate/traited.rb +55 -0
  116. data/tasks/authors.rake +30 -0
  117. data/tasks/bacon.rake +66 -0
  118. data/tasks/changelog.rake +18 -0
  119. data/tasks/gem.rake +22 -0
  120. data/tasks/gem_setup.rake +99 -0
  121. data/tasks/grancher.rake +12 -0
  122. data/tasks/manifest.rake +4 -0
  123. data/tasks/rcov.rake +19 -0
  124. data/tasks/release.rake +53 -0
  125. data/tasks/reversion.rake +8 -0
  126. data/tasks/setup.rake +6 -0
  127. data/tasks/ycov.rake +84 -0
  128. metadata +218 -0
@@ -0,0 +1,5 @@
1
+ require 'spec/helper'
2
+
3
+ $common_cache_class = Innate::Cache::Marshal
4
+
5
+ require 'spec/innate/cache/common'
@@ -0,0 +1,5 @@
1
+ require 'spec/helper'
2
+
3
+ $common_cache_class = Innate::Cache::Memory
4
+
5
+ require 'spec/innate/cache/common'
@@ -0,0 +1,5 @@
1
+ require 'spec/helper'
2
+
3
+ $common_cache_class = Innate::Cache::YAML
4
+
5
+ require 'spec/innate/cache/common'
@@ -0,0 +1,22 @@
1
+ require 'spec/helper'
2
+
3
+ describe Innate::DynaMap do
4
+ @app = lambda{|env| [200, {}, ['pass']] }
5
+
6
+ should 'raise if nothing is mapped' do
7
+ lambda{ Innate::DynaMap.call({}) }.should.raise(RuntimeError)
8
+ end
9
+
10
+ should 'not raise if nothing is mapped' do
11
+ Innate.map('/', &@app)
12
+ Innate::DynaMap.call('SCRIPT_NAME' => '/').should == [200, {}, ['pass']]
13
+ end
14
+
15
+ should 'return mapped object' do
16
+ Innate.at('/').should == @app
17
+ end
18
+
19
+ should 'return path to object' do
20
+ Innate.to(@app).should == '/'
21
+ end
22
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec/helper'
2
+ require 'innate/helper'
3
+
4
+ module Innate
5
+ module Helper
6
+ module SmileHelper
7
+ EXPOSE << self
8
+
9
+ def smile
10
+ ':)'
11
+ end
12
+ end
13
+
14
+ module FrownHelper
15
+ def frown
16
+ ':('
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ class HelperNodeExpose
23
+ include Innate::Node
24
+ map '/'
25
+
26
+ helper :smile_helper, :frown_helper
27
+
28
+ def frowny
29
+ "Oh, hi #{frown}"
30
+ end
31
+ end
32
+
33
+ describe HelperNodeExpose do
34
+ should 'expose an action' do
35
+ Innate::Mock.get('/smile').body.should == ':)'
36
+ Innate::Mock.get('/frown').status.should == 404
37
+ Innate::Mock.get('/frowny').body.should == "Oh, hi :("
38
+ end
39
+ end
40
+
41
+ class FooNodeLink
42
+ include Innate::Node
43
+ map '/foo'
44
+
45
+ helper :link, :cgi
46
+ end
47
+
48
+ describe Innate::Helper::Link do
49
+ FNL = FooNodeLink
50
+
51
+ should 'construct URI from ::r' do
52
+ FNL.r(:index).should == URI('/foo/index')
53
+ FNL.r(:/).should == URI('/foo/')
54
+ FNL.r(:index, :foo => :bar).should == URI('/foo/index?foo=bar')
55
+
56
+ uri = FNL.r(:index, :a => :b, :x => :y)
57
+ uri.query.split(';').sort.should == %w[a=b x=y]
58
+ end
59
+
60
+ should 'construct link from ::a' do
61
+ FNL.a(:index).should == '<a href="/foo/index">index</a>'
62
+ FNL.a('index', :index, :x => :y).should == '<a href="/foo/index?x=y">index</a>'
63
+ FNL.a('duh/bar', 'duh/bar', :x => :y).should == '<a href="/foo/duh/bar?x=y">duh/bar</a>'
64
+ FNL.a('foo', :/, :x => :y).should == '<a href="/foo/?x=y">foo</a>'
65
+ end
66
+
67
+ should 'return module when Module is given to #each' do
68
+ Innate::HelpersHelper.each_extend(self, Innate::Helper::Link) do |p|
69
+ p.should == Innate::Helper::Link
70
+ end
71
+ end
72
+
73
+ should 'raise if helpers are not found' do
74
+ lambda{
75
+ Innate::HelpersHelper.each(:foo, :bar)
76
+ }.should.raise(LoadError).
77
+ message.should == "Helper foo not found"
78
+ end
79
+
80
+ should 'raise if helper is not found' do
81
+ lambda{
82
+ Innate::HelpersHelper.try_require(:foo)
83
+ }.should.raise(LoadError).
84
+ message.should == "Helper foo not found"
85
+ end
86
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec/helper'
2
+
3
+ class AspectSpec
4
+ Innate.node('/', self).provide(:html, :None)
5
+
6
+ before(:with_before){ $aspect_spec_before += 40 }
7
+ def with_before; $aspect_spec_before += 2; end
8
+
9
+ after(:with_after){ $aspect_spec_after += 40 }
10
+ def with_after; $aspect_spec_after += 2; end
11
+
12
+ wrap(:with_wrap){ $aspect_spec_wrap += 20 }
13
+ def with_wrap; $aspect_spec_wrap += 2; end
14
+
15
+ before(:with_instance_var){ @foo = 'Hello'; @bar = 'World' }
16
+ def with_instance_var; "#{@foo} #{@bar}"; end
17
+ end
18
+
19
+ class AspectAllSpec
20
+ Innate.node('/all', self).provide(:html, :None)
21
+
22
+ before_all{ $aspect_spec_before_all += 40; @foo = 'Hello'; @bar = 'World' }
23
+ after_all{ $aspect_spec_after_all += 40 }
24
+ def before_first; $aspect_spec_before_all +=2 ; end
25
+ def before_second; $aspect_spec_before_all +=2; end
26
+ def with_instance_var_first; "#{@foo} #{@bar}"; end
27
+ def with_instance_var_second; "#{@foo} to the #{@bar}"; end
28
+ end
29
+
30
+ class AspecNoMethodSpec
31
+ Innate.node('/without_method', self)
32
+ include Innate::Node
33
+ map '/without_method'
34
+ map_views '/'
35
+ before_all{ @foo = 'Hello'; @bar = 'World'}
36
+ end
37
+
38
+ describe Innate::Helper::Aspect do
39
+ behaves_like :rack_test
40
+
41
+ it 'executes before aspect' do
42
+ $aspect_spec_before = 0
43
+ get('/with_before').body.should == '42'
44
+ $aspect_spec_before.should == 42
45
+ end
46
+
47
+ it 'executes after asepct' do
48
+ $aspect_spec_after = 0
49
+ get('/with_after').body.should == '2'
50
+ $aspect_spec_after.should == 42
51
+ end
52
+
53
+ it 'executes wrap aspects' do
54
+ $aspect_spec_wrap = 0
55
+ get('/with_wrap').body.should == '22'
56
+ $aspect_spec_wrap == 42
57
+ end
58
+
59
+ it 'calls before_all and after_all' do
60
+ $aspect_spec_before_all = $aspect_spec_after_all = 0
61
+ get('/all/before_first').body.should == '42'
62
+ $aspect_spec_before_all.should == 42
63
+ $aspect_spec_after_all.should == 40
64
+ get('/all/before_second').body.should == '84'
65
+ $aspect_spec_before_all.should == 84
66
+ $aspect_spec_after_all.should == 80
67
+ end
68
+
69
+ it 'makes instance variables in blocks available to view/method' do
70
+ get('/with_instance_var').body.should == 'Hello World'
71
+ get('/all/with_instance_var_first').body.should == 'Hello World'
72
+ get('/all/with_instance_var_second').body.should == 'Hello to the World'
73
+ get('/without_method/aspect_hello').body.should == "Hello World!"
74
+ end
75
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec/helper'
2
+ require 'innate/helper/cgi'
3
+
4
+ describe "url encode" do
5
+ extend Innate::Helper::CGI
6
+
7
+ it 'should url_encode strings' do
8
+ # ok, I believe that the web is dumb for this
9
+ # but this probably is a SHOULD thingy in the HTTP RFC
10
+ url_encode('title with spaces').should == 'title+with+spaces'
11
+ url_encode('[foo]').should == '%5Bfoo%5D'
12
+ u('//').should == '%2F%2F'
13
+ end
14
+ it 'should url_decode strings' do
15
+ url_decode('title%20with%20spaces').should == 'title with spaces'
16
+ url_decode('title+with+spaces').should == 'title with spaces'
17
+ end
18
+ it 'should be reversible' do
19
+ url_decode(u('../ etc/passwd')).should == '../ etc/passwd'
20
+ end
21
+ end
22
+
23
+ describe 'html escape' do
24
+ extend Innate::Helper::CGI
25
+
26
+ it 'should escape html' do
27
+ html_escape('& < >').should == '&amp; &lt; &gt;'
28
+ h('<&>').should == '&lt;&amp;&gt;'
29
+ end
30
+ it 'should unescape html' do
31
+ html_unescape('&lt; &amp; &gt;').should == '< & >'
32
+ end
33
+ it 'should be reversible' do
34
+ html_unescape(html_escape('2 > b && b <= 0')).should == '2 > b && b <= 0'
35
+ end
36
+ end
37
+
@@ -0,0 +1,115 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecFlash
4
+ include Innate::Node
5
+ map '/'
6
+
7
+ def welcome
8
+ flash[:name] = 'manveru'
9
+ "Welcome #{flash[:name]}"
10
+ end
11
+
12
+ def bye
13
+ "Bye #{flash[:name]}"
14
+ end
15
+
16
+ def check_empty
17
+ flash.empty?.to_s
18
+ end
19
+
20
+ def set_delete_key
21
+ flash[:name] = 'manveru'
22
+ flash.delete(:name)
23
+ flash[:name].to_s
24
+ end
25
+
26
+ def delete_key
27
+ flash.delete(:name)
28
+ "Bye #{flash[:name]}"
29
+ end
30
+
31
+ def merge!
32
+ flash.merge!(:name => 'feagliir').inspect
33
+ end
34
+
35
+ def merge
36
+ flash.merge(:name => 'feagliir').inspect
37
+ end
38
+
39
+ def inspect
40
+ flash[:yes] = :yeah
41
+ flash.inspect
42
+ end
43
+
44
+ def iterate
45
+ flash[:yes] = :yeah
46
+ elems = []
47
+ flash.each{|k,v| elems << [k,v] }
48
+ elems.inspect
49
+ end
50
+ end
51
+
52
+ class SpecFlashSub < SpecFlash
53
+ map '/sub'
54
+ end
55
+
56
+ describe Innate::Helper::Flash do
57
+ behaves_like :rack_test
58
+
59
+ should 'set and forget flash twice' do
60
+ get('/welcome').body.should == 'Welcome manveru'
61
+ get('/bye').body.should == 'Bye manveru'
62
+ get('/bye').body.should == 'Bye'
63
+
64
+ get('/welcome').body.should == 'Welcome manveru'
65
+ get('/bye').body.should == 'Bye manveru'
66
+ get('/bye').body.should == 'Bye'
67
+ end
68
+
69
+ should 'work over multiple nodes' do
70
+ get('/welcome').body.should == 'Welcome manveru'
71
+ get('/sub/bye').body.should == 'Bye manveru'
72
+ get('/sub/bye').body.should == 'Bye'
73
+
74
+ get('/sub/welcome').body.should == 'Welcome manveru'
75
+ get('/bye').body.should == 'Bye manveru'
76
+ get('/bye').body.should == 'Bye'
77
+ end
78
+
79
+ should 'check if flash is empty' do
80
+ get('/welcome').body.should == 'Welcome manveru'
81
+ get('/check_empty').body.should == 'false'
82
+ get('/check_empty').body.should == 'true'
83
+ end
84
+
85
+ should 'set and delete key within one request' do
86
+ get('/set_delete_key').body.should == ''
87
+ end
88
+
89
+ should 'set and delete key over two request' do
90
+ get('/welcome').body.should == 'Welcome manveru'
91
+ get('/delete_key').body.should == 'Bye'
92
+ end
93
+
94
+ should 'merge with hash' do
95
+ get('/merge').body.should == {:name => 'feagliir'}.inspect
96
+ get('/bye').body.should == 'Bye'
97
+ end
98
+
99
+ should 'merge! with hash' do
100
+ get('/merge!').body.should == {:name => 'feagliir'}.inspect
101
+ get('/bye').body.should == 'Bye feagliir'
102
+ end
103
+
104
+ should 'inspect combined' do
105
+ get('/welcome')
106
+ get('/inspect').body.should == {:name => 'manveru', :yes => :yeah}.inspect
107
+ end
108
+
109
+ should 'iterate over combined' do
110
+ get('/welcome')
111
+
112
+ hash = {:yes => :yeah, :name => 'manveru'}
113
+ Hash[*eval(get('/iterate').body).flatten].should == hash
114
+ end
115
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec/helper'
2
+
3
+ class One
4
+ include Innate::Node
5
+ map '/'
6
+
7
+ def auto_route
8
+ UsingRouteSelf.new.route.to_s
9
+ end
10
+ end
11
+
12
+ class Two
13
+ include Innate::Node
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
29
+ end
30
+
31
+ describe Innate::Helper::Link do
32
+ describe '#route' do
33
+ should 'respond with URI for node' do
34
+ One.route.should == URI('/')
35
+ Two.route.should == URI('/two/')
36
+ end
37
+
38
+ should 'respond with URI for node with path /' do
39
+ One.route('/').should == URI('/')
40
+ Two.route('/').should == URI('/two/')
41
+ end
42
+
43
+ should 'respond with URI for node with path /foo' do
44
+ One.route('/foo').should == URI('/foo')
45
+ One.route(:foo).should == URI('/foo')
46
+
47
+ Two.route('/foo').should == URI('/two/foo')
48
+ Two.route(:foo).should == URI('/two/foo')
49
+ end
50
+
51
+ should 'respond with URI for node with path /foo/bar' do
52
+ One.route('/foo/bar').should == URI('/foo/bar')
53
+ One.route(:foo, :bar).should == URI('/foo/bar')
54
+
55
+ Two.route('/foo/bar').should == URI('/two/foo/bar')
56
+ Two.route(:foo, :bar).should == URI('/two/foo/bar')
57
+ end
58
+
59
+ should 'respond with URI for node with path /foo/bar+baz' do
60
+ One.route('/foo/bar+baz').should == URI('/foo/bar+baz')
61
+ One.route(:foo, 'bar baz').should == URI('/foo/bar+baz')
62
+
63
+ Two.route('/foo/bar+baz').should == URI('/two/foo/bar+baz')
64
+ Two.route(:foo, 'bar baz').should == URI('/two/foo/bar+baz')
65
+ end
66
+
67
+ should 'respond with URI for node with GET params' do
68
+ One.route('/', :a => :b).should == URI('/?a=b')
69
+
70
+ One.route('/foo', :a => :b).should == URI('/foo?a=b')
71
+ One.route(:foo, :a => :b ).should == URI('/foo?a=b')
72
+
73
+ One.route('/foo/bar', :a => :b).should == URI('/foo/bar?a=b')
74
+ One.route(:foo, :bar, :a => :b).should == URI('/foo/bar?a=b')
75
+
76
+ Two.route('/', :a => :b).should == URI('/two/?a=b')
77
+
78
+ Two.route('foo', :a => :b).should == URI('/two/foo?a=b')
79
+ Two.route(:foo, :a => :b ).should == URI('/two/foo?a=b')
80
+ Two.route('/foo/bar', :a => :b).should == URI('/two/foo/bar?a=b')
81
+ Two.route(:foo, :bar, :a => :b).should == URI('/two/foo/bar?a=b')
82
+ end
83
+
84
+ should 'prefix the links as defined in the options' do
85
+ Innate.options.prefix = '/bar'
86
+ One.route('/foo').should == URI('/bar/foo')
87
+ Innate.options.prefix = '/'
88
+ end
89
+ end
90
+
91
+ describe '#anchor' do
92
+ should 'respond with a tag with default text' do
93
+ One.anchor('hello').should == '<a href="/hello">hello</a>'
94
+ Two.anchor('hello').should == '<a href="/two/hello">hello</a>'
95
+ end
96
+
97
+ should 'respond with a tag with explicit text' do
98
+ One.anchor('hello', :foo).should == '<a href="/foo">hello</a>'
99
+ Two.anchor('hello', :foo).should == '<a href="/two/foo">hello</a>'
100
+ end
101
+
102
+ should 'pass parameters to #route' do
103
+ One.anchor('hello', :foo, :a => :b).
104
+ should == '<a href="/foo?a=b">hello</a>'
105
+ Two.anchor('hello', :foo, :a => :b).
106
+ should == '<a href="/two/foo?a=b">hello</a>'
107
+ end
108
+
109
+ should 'escape text' do
110
+ One.anchor('<blink> & <a>', :foo).
111
+ should == '<a href="/foo">&lt;blink&gt; &amp; &lt;a&gt;</a>'
112
+ end
113
+ end
114
+
115
+ describe 'combining #anchor and #route' do
116
+ should 'not escape twice' do
117
+ One.anchor('foo', One.route(:index, :bar => 'a/b/c')).
118
+ should == '<a href="/index?bar=a%2Fb%2Fc">foo</a>'
119
+ end
120
+
121
+ should 'handle complete uris gracefully' do
122
+ One.anchor('foo', 'http://example.com/?foo=bar&baz=qux').
123
+ should == '<a href="http://example.com/?foo=bar&amp;baz=qux">foo</a>'
124
+ end
125
+
126
+ should 'be able to route from one node to another' do
127
+ Two.anchor('foo', One.route(:index)).should == '<a href="/index">foo</a>'
128
+ One.anchor('foo', Two.route(:index)).should == '<a href="/two/index">foo</a>'
129
+ end
130
+ end
131
+
132
+ describe '#route_self' do
133
+ behaves_like :rack_test
134
+ should 'provide a route to the node of the currently active action' do
135
+ get('/auto_route').body.should == '/elsewhere'
136
+ get('/two/auto_route').body.should == '/two/elsewhere'
137
+ end
138
+ end
139
+ end