raw 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/doc/CONTRIBUTORS +106 -0
  2. data/doc/LICENSE +32 -0
  3. data/doc/coding_conventions.txt +11 -0
  4. data/lib/raw.rb +42 -0
  5. data/lib/raw/adapter.rb +113 -0
  6. data/lib/raw/adapter/cgi.rb +41 -0
  7. data/lib/raw/adapter/fastcgi.rb +48 -0
  8. data/lib/raw/adapter/mongrel.rb +146 -0
  9. data/lib/raw/adapter/script.rb +94 -0
  10. data/lib/raw/adapter/webrick.rb +144 -0
  11. data/lib/raw/adapter/webrick/vcr.rb +91 -0
  12. data/lib/raw/cgi.rb +323 -0
  13. data/lib/raw/cgi/cookie.rb +47 -0
  14. data/lib/raw/cgi/http.rb +62 -0
  15. data/lib/raw/compiler.rb +138 -0
  16. data/lib/raw/compiler/filter/cleanup.rb +21 -0
  17. data/lib/raw/compiler/filter/elements.rb +166 -0
  18. data/lib/raw/compiler/filter/elements/element.rb +210 -0
  19. data/lib/raw/compiler/filter/localization.rb +23 -0
  20. data/lib/raw/compiler/filter/markup.rb +32 -0
  21. data/lib/raw/compiler/filter/morph.rb +123 -0
  22. data/lib/raw/compiler/filter/morph/each.rb +34 -0
  23. data/lib/raw/compiler/filter/morph/for.rb +11 -0
  24. data/lib/raw/compiler/filter/morph/if.rb +26 -0
  25. data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
  26. data/lib/raw/compiler/filter/morph/standard.rb +55 -0
  27. data/lib/raw/compiler/filter/morph/times.rb +27 -0
  28. data/lib/raw/compiler/filter/script.rb +116 -0
  29. data/lib/raw/compiler/filter/squeeze.rb +16 -0
  30. data/lib/raw/compiler/filter/static_include.rb +74 -0
  31. data/lib/raw/compiler/filter/template.rb +121 -0
  32. data/lib/raw/compiler/reloader.rb +96 -0
  33. data/lib/raw/context.rb +154 -0
  34. data/lib/raw/context/flash.rb +157 -0
  35. data/lib/raw/context/global.rb +88 -0
  36. data/lib/raw/context/request.rb +338 -0
  37. data/lib/raw/context/response.rb +57 -0
  38. data/lib/raw/context/session.rb +198 -0
  39. data/lib/raw/context/session/drb.rb +11 -0
  40. data/lib/raw/context/session/file.rb +15 -0
  41. data/lib/raw/context/session/memcached.rb +13 -0
  42. data/lib/raw/context/session/memory.rb +12 -0
  43. data/lib/raw/context/session/og.rb +15 -0
  44. data/lib/raw/context/session/pstore.rb +13 -0
  45. data/lib/raw/control.rb +18 -0
  46. data/lib/raw/control/attribute.rb +91 -0
  47. data/lib/raw/control/attribute/checkbox.rb +25 -0
  48. data/lib/raw/control/attribute/datetime.rb +21 -0
  49. data/lib/raw/control/attribute/file.rb +20 -0
  50. data/lib/raw/control/attribute/fixnum.rb +26 -0
  51. data/lib/raw/control/attribute/float.rb +26 -0
  52. data/lib/raw/control/attribute/options.rb +38 -0
  53. data/lib/raw/control/attribute/password.rb +16 -0
  54. data/lib/raw/control/attribute/text.rb +16 -0
  55. data/lib/raw/control/attribute/textarea.rb +16 -0
  56. data/lib/raw/control/none.rb +16 -0
  57. data/lib/raw/control/relation.rb +59 -0
  58. data/lib/raw/control/relation/belongs_to.rb +0 -0
  59. data/lib/raw/control/relation/has_many.rb +97 -0
  60. data/lib/raw/control/relation/joins_many.rb +0 -0
  61. data/lib/raw/control/relation/many_to_many.rb +0 -0
  62. data/lib/raw/control/relation/refers_to.rb +29 -0
  63. data/lib/raw/controller.rb +37 -0
  64. data/lib/raw/controller/publishable.rb +160 -0
  65. data/lib/raw/dispatcher.rb +209 -0
  66. data/lib/raw/dispatcher/format.rb +108 -0
  67. data/lib/raw/dispatcher/format/atom.rb +31 -0
  68. data/lib/raw/dispatcher/format/css.rb +0 -0
  69. data/lib/raw/dispatcher/format/html.rb +42 -0
  70. data/lib/raw/dispatcher/format/json.rb +31 -0
  71. data/lib/raw/dispatcher/format/rss.rb +33 -0
  72. data/lib/raw/dispatcher/format/xoxo.rb +31 -0
  73. data/lib/raw/dispatcher/mounter.rb +60 -0
  74. data/lib/raw/dispatcher/router.rb +111 -0
  75. data/lib/raw/errors.rb +19 -0
  76. data/lib/raw/helper.rb +86 -0
  77. data/lib/raw/helper/benchmark.rb +23 -0
  78. data/lib/raw/helper/buffer.rb +60 -0
  79. data/lib/raw/helper/cookie.rb +32 -0
  80. data/lib/raw/helper/debug.rb +28 -0
  81. data/lib/raw/helper/default.rb +16 -0
  82. data/lib/raw/helper/feed.rb +451 -0
  83. data/lib/raw/helper/form.rb +284 -0
  84. data/lib/raw/helper/javascript.rb +59 -0
  85. data/lib/raw/helper/layout.rb +40 -0
  86. data/lib/raw/helper/navigation.rb +87 -0
  87. data/lib/raw/helper/pager.rb +305 -0
  88. data/lib/raw/helper/table.rb +247 -0
  89. data/lib/raw/helper/xhtml.rb +218 -0
  90. data/lib/raw/helper/xml.rb +125 -0
  91. data/lib/raw/mixin/magick.rb +35 -0
  92. data/lib/raw/mixin/sweeper.rb +71 -0
  93. data/lib/raw/mixin/thumbnails.rb +1 -0
  94. data/lib/raw/mixin/webfile.rb +165 -0
  95. data/lib/raw/render.rb +271 -0
  96. data/lib/raw/render/builder.rb +26 -0
  97. data/lib/raw/render/caching.rb +81 -0
  98. data/lib/raw/render/call.rb +43 -0
  99. data/lib/raw/render/send_file.rb +46 -0
  100. data/lib/raw/render/stream.rb +39 -0
  101. data/lib/raw/scaffold.rb +13 -0
  102. data/lib/raw/scaffold/controller.rb +25 -0
  103. data/lib/raw/scaffold/model.rb +157 -0
  104. data/lib/raw/test.rb +5 -0
  105. data/lib/raw/test/assertions.rb +169 -0
  106. data/lib/raw/test/context.rb +55 -0
  107. data/lib/raw/test/testcase.rb +79 -0
  108. data/lib/raw/util/attr.rb +128 -0
  109. data/lib/raw/util/encode_uri.rb +149 -0
  110. data/lib/raw/util/html_filter.rb +538 -0
  111. data/lib/raw/util/markup.rb +130 -0
  112. data/test/glue/tc_webfile.rb +1 -0
  113. data/test/nitro/CONFIG.rb +3 -0
  114. data/test/nitro/adapter/raw_post1.bin +9 -0
  115. data/test/nitro/adapter/tc_webrick.rb +16 -0
  116. data/test/nitro/cgi/tc_cookie.rb +14 -0
  117. data/test/nitro/cgi/tc_request.rb +61 -0
  118. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  119. data/test/nitro/compiler/tc_compiler.rb +25 -0
  120. data/test/nitro/dispatcher/tc_mounter.rb +47 -0
  121. data/test/nitro/helper/tc_feed.rb +135 -0
  122. data/test/nitro/helper/tc_navbar.rb +74 -0
  123. data/test/nitro/helper/tc_pager.rb +35 -0
  124. data/test/nitro/helper/tc_table.rb +68 -0
  125. data/test/nitro/helper/tc_xhtml.rb +19 -0
  126. data/test/nitro/tc_caching.rb +19 -0
  127. data/test/nitro/tc_cgi.rb +222 -0
  128. data/test/nitro/tc_context.rb +17 -0
  129. data/test/nitro/tc_controller.rb +103 -0
  130. data/test/nitro/tc_controller_aspect.rb +32 -0
  131. data/test/nitro/tc_controller_params.rb +885 -0
  132. data/test/nitro/tc_dispatcher.rb +109 -0
  133. data/test/nitro/tc_element.rb +85 -0
  134. data/test/nitro/tc_flash.rb +59 -0
  135. data/test/nitro/tc_helper.rb +47 -0
  136. data/test/nitro/tc_render.rb +119 -0
  137. data/test/nitro/tc_router.rb +61 -0
  138. data/test/nitro/tc_server.rb +35 -0
  139. data/test/nitro/tc_session.rb +66 -0
  140. data/test/nitro/tc_template.rb +71 -0
  141. data/test/nitro/util/tc_encode_url.rb +87 -0
  142. data/test/nitro/util/tc_markup.rb +31 -0
  143. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  144. data/test/public/blog/inc1.xhtml +2 -0
  145. data/test/public/blog/inc2.xhtml +1 -0
  146. data/test/public/blog/list.xhtml +9 -0
  147. data/test/public/dummy_mailer/registration.xhtml +5 -0
  148. metadata +244 -0
@@ -0,0 +1,81 @@
1
+ require "fileutils"
2
+
3
+ require "facets/more/settings"
4
+ require "facets/core/file/self/write"
5
+ require "facets/core/kernel/eigenclass"
6
+
7
+ module Raw
8
+
9
+ # Add output caching to the Render.
10
+
11
+ module Caching
12
+
13
+ # Enable or disable view caching.
14
+
15
+ setting :enabled, :default => true, :doc => "Enable view caching"
16
+
17
+ private
18
+
19
+ # Cache the output (view) of the current action.
20
+
21
+ def cache_output
22
+ return unless (caching_enabled? and caching_allowed?)
23
+
24
+ if self.class.ann(@action, :cache) # or self.class.ann(:self, :cache)
25
+ path = File.join(@context.application.public_dir, @context.path)
26
+ FileUtils.makedirs(File.dirname(path))
27
+ Logger.debug "Caching '#{path}'" if $DBG
28
+ File.write(path, @out)
29
+ end
30
+ rescue => ex
31
+ Logger.error ex.to_s
32
+ end
33
+
34
+ # Explicitly expire the given cached file. If the filename has
35
+ # no extension attach .* to expire the cached files for
36
+ # all format representations.
37
+ #--
38
+ # TODO: use encode_uri
39
+ #++
40
+
41
+ def expire_output(*args)
42
+ path = encode_uri(*args)
43
+
44
+ if File.extname(path).blank?
45
+ # Clear all cached representations.
46
+ if path =~ %r{/$}
47
+ path << "index.*"
48
+ else
49
+ path << ".*"
50
+ end
51
+ end
52
+
53
+ path = File.join(Context.current.application.public_dir, path)
54
+
55
+ Logger.debug "Expiring cache files '#{path}'" if $DBG
56
+ FileUtils.rm_rf(path)
57
+ rescue => ex
58
+ # drink it!
59
+ end
60
+ alias_method :delete_output, :expire_output
61
+
62
+ # Enable or disable caching. Can be overriden per controller
63
+ # for extra fine grained caching control.
64
+
65
+ def caching_enabled?
66
+ Caching.enabled
67
+ end
68
+
69
+ # Is caching allowed for this action (page)? The default
70
+ # implementation does not cache post request or request
71
+ # with query parameters. You can work arround the second
72
+ # 'limitation' by cleverly using Nitro's implicit support
73
+ # for 'nice' URIs.
74
+
75
+ def caching_allowed?
76
+ not (@context.post? or @context.uri =~ /\?/)
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,43 @@
1
+ module Raw
2
+
3
+ #--
4
+ # Seaside style call/answer methods.
5
+ #++
6
+
7
+ module Render
8
+
9
+ # Call redirects to the given URI but push the original
10
+ # URI in a callstack, so that the target can return by
11
+ # executing answer.
12
+ #
13
+ #--
14
+ # FIXME: dont use yet, you have to encode the branch to
15
+ # make this safe for use.
16
+ #++
17
+
18
+ def call(*args)
19
+ (session[:CALL_STACK] ||= []).push(request.uri)
20
+ redirect(*args)
21
+ end
22
+
23
+ # Returns from a call by poping the callstack.
24
+ # Use force = false to make this mechanism more flexible.
25
+ #--
26
+ # FIXME: don't use yet.
27
+ #++
28
+
29
+ def answer(force = false, status = 303)
30
+ if stack = session[:CALL_STACK] and not stack.empty?
31
+ redirect(stack.pop, :status => status)
32
+ else
33
+ if force
34
+ raise 'Cannot answer, call stack is empty'
35
+ else
36
+ redirect_to_home
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,46 @@
1
+ require "raw/render"
2
+
3
+ module Raw
4
+
5
+ module Render
6
+
7
+ # Send a file download to the client.
8
+ #
9
+ # Like render and redirect, the action is exited upon calling
10
+ #
11
+ # [+fname+] That name of the file
12
+ # [+path+] Specifying true mean fname contains the full path.
13
+ # The default, false, uses Server.public_root as the path.
14
+ #
15
+ # [+return+] true on success, false on failure
16
+ #
17
+ # === Examples
18
+ #
19
+ # require "raw/render/send_file"
20
+ #
21
+ # class MyController < Nitro:Controller
22
+ # def download(fname)
23
+ # send_file(fname)
24
+ # end
25
+ # end
26
+ #
27
+ # class MyController < Nitro:Controller
28
+ # def download
29
+ # send_file("/etc/password", true)
30
+ # end
31
+ # end
32
+
33
+ def send_file(fname = nil, fullpath = false)
34
+ fname = fullpath ? fname : "#{@context.application.public_dir}/#{fname}"
35
+ f = File.open(fname, "rb")
36
+ @context.response_headers["Cache-control"] = "private"
37
+ @context.response_headers["Content-Length"] = "#{File.size?(f) || 0}"
38
+ @context.response_headers["Content-Type"] = "application/force-download"
39
+ @context.output_buffer = f
40
+ raise RenderExit
41
+ end
42
+ alias_method :sendfile, :send_file
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,39 @@
1
+ require "raw/render"
2
+
3
+ module Raw
4
+
5
+ module Render
6
+
7
+ # Enable streaming mode for the current HTTP Response.
8
+ # You can optionally provide an existing IO object for
9
+ # streaming.
10
+ #--
11
+ # This code is considered a hack fix. But it still is useful
12
+ # so for the moment it stays in the distribution.
13
+ #++
14
+
15
+ def stream(io = nil)
16
+ if io
17
+ # Reuse an existing IO if it exists.
18
+ @context.output_buffer = io
19
+ else
20
+ r, w = IO.pipe
21
+
22
+ @context.output_buffer = r
23
+ @out = w
24
+ r.sync = true
25
+ w.class.send(:define_method, :empty?) { false }
26
+
27
+ Thread.new do
28
+ begin
29
+ yield
30
+ ensure
31
+ w.close
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,13 @@
1
+ module Raw
2
+
3
+ # Scaffolding is one facet of Nitro's Rapid Application
4
+ # Develpoment (RAD) features. The scaffolder automatically
5
+ # generates common code for managed object and their
6
+ # controllers.
7
+
8
+ module Scaffold
9
+ end
10
+
11
+ require "raw/scaffold/model"
12
+
13
+ end
@@ -0,0 +1,25 @@
1
+ module Raw
2
+
3
+ module Scaffold
4
+
5
+ # Automatically creates a scaffold controller to handle the
6
+ # given models.
7
+
8
+ def self.controller(*models)
9
+ for m in models
10
+ scaffold_controller(m)
11
+ end
12
+ end
13
+
14
+ def self.enchant_controller(model)
15
+ eval %{
16
+
17
+ }
18
+ end
19
+
20
+ end
21
+
22
+ class Controller
23
+ end
24
+
25
+ end
@@ -0,0 +1,157 @@
1
+ module Raw
2
+
3
+ # Scaffolding is one facet of Nitro's Rapid Application
4
+ # Develpoment (RAD) features. The scaffolder automatically
5
+ # generates common code for managed object and their
6
+ # controllers.
7
+
8
+ module Scaffold
9
+
10
+ # Automatically enchant all models ?
11
+
12
+ setting :enchant_all_models, :default => false, :doc => 'Automatically enchant all models?'
13
+
14
+ # Enchant all models.
15
+
16
+ def self.all_models
17
+ if Scaffold.enchant_all_models
18
+ self.model(*Og.manager.managed_classes)
19
+ end
20
+ end
21
+
22
+ # 'Enchant' a model class (typically a managed class,
23
+ # entity). A collection of useful methods are magically
24
+ # added to the class and/or the class instances.
25
+ #
26
+ # * to_s
27
+ # * to_href
28
+ # * to_link
29
+ # * to_edit_href
30
+ # * to_admin_href
31
+ #--
32
+ # to_xxx is used instead of xxx in an attempt to avoid
33
+ # colisions with user defined methods.
34
+ #++
35
+
36
+ def self.model(*classes)
37
+ for c in classes
38
+ enchant_model c
39
+ end
40
+ end
41
+
42
+ #--
43
+ # Actually enchant the given class. Override this method
44
+ # to customize for your application. The string calculation
45
+ # code is deliberatly dynamic to work with Ruby's OO
46
+ # features.
47
+ #++
48
+
49
+ def self.enchant_model(klass)
50
+ # Find the controller that handles this model. Unless no
51
+ # controller annotation is defined, try to find a controller
52
+ # of the form: Model::Controller. Some examples:
53
+ #
54
+ # class Ticket
55
+ # ann :self, :controller => SpecialTicketController
56
+ # ..
57
+ # end
58
+ #
59
+ # or try to find a Ticket::Controller class.
60
+
61
+ controller = klass.ann(:self, :controller) || klass.constant('Controller')
62
+
63
+ # If the class defines a text_key use it to create more
64
+ # readable (and SEO friendly) URIs.
65
+
66
+ key = klass.ann(:self, :text_key) || 'oid'
67
+
68
+ # to_s
69
+
70
+ if klass.instance_methods.include? 'title'
71
+ define_instance_method klass, :to_s, %{ title }, force = true
72
+ elsif klass.instance_methods.include? 'name'
73
+ define_instance_method klass, :to_s, %{ name }, force = true
74
+ end
75
+
76
+ # to_href
77
+ # ex: /articles/23
78
+
79
+ define_instance_method klass, :to_href, %{
80
+ "\#{#{controller}.mount_path}/read/\#{#{key}}".squeeze('/')
81
+ }
82
+
83
+ # to_link
84
+ # ex: <a href="/articles/23">The article's title</a>
85
+
86
+ define_instance_method klass, :to_link, %{
87
+ %|<a href="\#{to_href}">\#{to_s}</a>|
88
+ }
89
+
90
+ # to_link
91
+ # ex: <a href="/articles/23">The article's title</a>
92
+
93
+ define_class_method klass, :controller, %{
94
+ #{controller}
95
+ }
96
+
97
+ if defined? OgAdminController
98
+ self.extend(OgAdminHelper)
99
+
100
+ # to_edit_href
101
+ # ex: admin/update/Article/23
102
+
103
+ define_instance_method klass, :to_edit_href, %{
104
+ "\#{OgAdminController.mount_path}/update/#{class_to_name(klass)}/\#{oid}"
105
+ }
106
+
107
+ # to_admin_href
108
+ # ex: admin/list/Article
109
+
110
+ define_instance_method klass, :to_admin_href, %{
111
+ "\#{AdminController.mount_path}/list/#{class_to_name(klass)}"
112
+ }
113
+
114
+ # to_admin_href
115
+ # ex: admin/list/Article
116
+
117
+ define_class_method klass, :to_admin_href, %{
118
+ "\#{AdminController.mount_path}/list/#{class_to_name(klass)}"
119
+ }
120
+ end
121
+ end
122
+
123
+ #--
124
+ # This helper defines an instance method for the
125
+ # scaffolded class. The method is only defined if the klass
126
+ # does not already respond to it.
127
+ #++
128
+
129
+ def self.define_instance_method(klass, meth, body, force = false)
130
+ if force or (!klass.instance_methods.include? meth.to_s)
131
+ klass.module_eval %{
132
+ def #{meth}
133
+ #{body}
134
+ end
135
+ }
136
+ end
137
+ end
138
+
139
+ #--
140
+ # This helper defines an class method for the
141
+ # scaffolded class. The method is only defined if the klass
142
+ # does not already respond to it.
143
+ #++
144
+
145
+ def self.define_class_method(klass, meth, body, force = false)
146
+ if force or (!klass.respond_to? meth.to_s)
147
+ klass.module_eval %{
148
+ def self.#{meth}
149
+ #{body}
150
+ end
151
+ }
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ end
@@ -0,0 +1,5 @@
1
+ $NITRO_NO_ENVIRONMENT = true
2
+ $NITRO_NO_INVOKE = true
3
+
4
+ require 'nitro/test/assertions'
5
+ require 'nitro/test/testcase'
@@ -0,0 +1,169 @@
1
+ require 'test/unit'
2
+ require 'test/unit/assertions'
3
+ require 'rexml/document'
4
+
5
+ module Test::Unit::Assertions
6
+
7
+ STATUS_MAP = {
8
+ :success => 200,
9
+ :ok => 200,
10
+ :redirect => 307
11
+ }
12
+
13
+ # :section: General assertions.
14
+
15
+ # Check the status of the response.
16
+
17
+ def assert_response(options = {})
18
+ unless options.is_a? Hash
19
+ options = { :status => options }
20
+ end
21
+ msg = options[:msg]
22
+ if status = options.fetch(:status, :success)
23
+ status = STATUS_MAP[status] if STATUS_MAP.has_key?(status)
24
+ assert_status(status, msg)
25
+ end
26
+ end
27
+
28
+ def assert_status(status, msg)
29
+ msg = format_msg("Status not '#{status}'", msg)
30
+ assert_block(msg) { @context.status == status }
31
+ end
32
+
33
+ #--
34
+ # Compile some helpers.
35
+ #++
36
+
37
+ for m in [:get, :post, :put, :delete, :head]
38
+ eval %{
39
+ def assert_#{m}(uri, headers = {}, params = {}, session = nil)
40
+ #{m}(uri, headers, params, session)
41
+ assert_response :success
42
+ end
43
+ }
44
+ end
45
+
46
+ def assert_output(options = {})
47
+ msg = options[:msg]
48
+ if re = options[:match] || options[:contains]
49
+ assert_output_match(re, msg)
50
+ end
51
+ if re = options[:no_match] || options[:contains_no]
52
+ assert_output_not_match(re, msg)
53
+ end
54
+ if content_type = options[:content_type]
55
+ assert_content_type(content_type, msg)
56
+ end
57
+ end
58
+
59
+ def assert_output_match(re, msg)
60
+ msg = format_msg("Rendered output does not match '#{re.source}'", msg)
61
+ assert_block(msg) { @context.body =~ Regexp.new(re) }
62
+ end
63
+ alias_method :assert_output_contains, :assert_output_match
64
+
65
+ def assert_output_not_match(re, msg)
66
+ msg = format_msg("Rendered output matches '#{re.source}'", msg)
67
+ assert_block(msg) { @context.out =~ Regexp.new(re) }
68
+ end
69
+ alias_method :assert_output_contains_not, :assert_output_match
70
+
71
+ def assert_content_type(ctype, msg)
72
+ msg = format_msg("Content type is not '#{ctype}' as expected", msg)
73
+ assert_block(msg) { @context.content_type == ctype }
74
+ end
75
+
76
+ # :section: Session related assertions.
77
+
78
+ def assert_session(options = {})
79
+ msg = options[:msg]
80
+ if key = options[:has]
81
+ assert_session_has(key, msg)
82
+ end
83
+ if key = options[:has_no] || options[:no]
84
+ assert_session_has_no(key, msg)
85
+ end
86
+ if key = options[:key] and value = options[:value]
87
+ assert_session_equal(key, value, msg)
88
+ end
89
+ end
90
+
91
+ def assert_session_has(key, msg = nil)
92
+ msg = format_msg("Object '#{key}' not found in session", msg)
93
+ assert_block(msg) { @context.session[key] }
94
+ end
95
+
96
+ def assert_session_has_no(key, msg = nil)
97
+ msg = format_msg("Unexpected object '#{key}' found in session", msg)
98
+ assert_block(msg) { !@context.session[key] }
99
+ end
100
+
101
+ def assert_session_equal(key, value, msg = nil)
102
+ msg = format_msg("The value of session object '#{key}' is '#{@context.session[key]}' but was expected '#{value}'", msg)
103
+ assert_block(msg) { @context.session[key] == value }
104
+ end
105
+
106
+ # :section: Cookies related assertions.
107
+
108
+ def assert_cookie(options = {})
109
+ msg = options[:msg]
110
+ if key = options[:has]
111
+ assert_cookie_has(key, msg)
112
+ end
113
+ if key = options[:has_no] || options[:no]
114
+ assert_cookie_has_no(key, msg)
115
+ end
116
+ if key = options[:key] and value = options[:value]
117
+ assert_cookie_equal(key, value, msg)
118
+ end
119
+ end
120
+
121
+ def assert_cookie_has(name, msg = nil)
122
+ msg = format_msg("Cookie '#{name}' not found", msg)
123
+ assert_block(msg) { @context.response_cookie(name) }
124
+ end
125
+
126
+ def assert_cookie_has_no(name, msg = nil)
127
+ msg = format_msg("Unexpected cookie '#{name}' found", msg)
128
+ assert_block(msg) { !@context.response_cookie(name) }
129
+ end
130
+
131
+ def assert_cookie_equal(name, value, msg = nil)
132
+ unless cookie = @context.response_cookie(name)
133
+ msg = format_msg("Cookie '#{name}' not found", msg)
134
+ assert_block(msg) { false }
135
+ end
136
+ msg = format_msg("The value of cookie '#{name}' is '#{cookie.value}' but was expected '#{value}'", msg)
137
+ assert_block(msg) { cookie.value == value }
138
+ end
139
+
140
+ # :section: Nitro::Template related assertions.
141
+
142
+ # :section: Redirection assertions.
143
+
144
+ def assert_redirected(options = {})
145
+ msg = options[:msg]
146
+
147
+ msg = format_msg("No redirection (status = #{@context.status})", msg)
148
+ assert_block(msg) { @context.redirect? }
149
+
150
+ if to = options[:to]
151
+ msg = format_msg("Not redirected to '#{to}'", msg)
152
+ assert_block(msg) { @context.response_headers['location'] == "http://#{to}" }
153
+ end
154
+ end
155
+
156
+ def assert_not_redirected(options = {})
157
+ msg = options[:msg]
158
+ msg = format_msg("Unexpected redirection (location = '#{@context.response_headers['location']}')", msg)
159
+ assert_block(msg) { !@context.redirect? }
160
+ end
161
+
162
+ # :section: Utility methods
163
+
164
+ def format_msg(message, extra) # :nodoc:
165
+ extra += ', ' if extra
166
+ return "#{extra}#{message}"
167
+ end
168
+
169
+ end