aslakjo-comatose 2.0.5.2

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 (93) hide show
  1. data/CHANGELOG +195 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +20 -0
  4. data/MANIFEST +91 -0
  5. data/README.markdown +159 -0
  6. data/Rakefile +176 -0
  7. data/SPECS +61 -0
  8. data/about.yml +7 -0
  9. data/bin/comatose +112 -0
  10. data/comatose.gemspec +113 -0
  11. data/generators/comatose_migration/USAGE +15 -0
  12. data/generators/comatose_migration/comatose_migration_generator.rb +74 -0
  13. data/generators/comatose_migration/templates/migration.rb +35 -0
  14. data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
  15. data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
  16. data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
  17. data/init.rb +2 -0
  18. data/install.rb +18 -0
  19. data/lib/acts_as_versioned.rb +543 -0
  20. data/lib/comatose/comatose_drop.rb +79 -0
  21. data/lib/comatose/configuration.rb +69 -0
  22. data/lib/comatose/page_wrapper.rb +119 -0
  23. data/lib/comatose/processing_context.rb +69 -0
  24. data/lib/comatose/tasks/admin.rb +60 -0
  25. data/lib/comatose/tasks/data.rb +82 -0
  26. data/lib/comatose/tasks/setup.rb +52 -0
  27. data/lib/comatose/version.rb +4 -0
  28. data/lib/comatose.rb +33 -0
  29. data/lib/comatose_admin_controller.rb +395 -0
  30. data/lib/comatose_admin_helper.rb +37 -0
  31. data/lib/comatose_controller.rb +138 -0
  32. data/lib/comatose_helper.rb +3 -0
  33. data/lib/comatose_page.rb +141 -0
  34. data/lib/liquid/block.rb +96 -0
  35. data/lib/liquid/context.rb +190 -0
  36. data/lib/liquid/document.rb +17 -0
  37. data/lib/liquid/drop.rb +48 -0
  38. data/lib/liquid/errors.rb +7 -0
  39. data/lib/liquid/extensions.rb +53 -0
  40. data/lib/liquid/file_system.rb +62 -0
  41. data/lib/liquid/htmltags.rb +64 -0
  42. data/lib/liquid/standardfilters.rb +111 -0
  43. data/lib/liquid/standardtags.rb +399 -0
  44. data/lib/liquid/strainer.rb +42 -0
  45. data/lib/liquid/tag.rb +25 -0
  46. data/lib/liquid/template.rb +88 -0
  47. data/lib/liquid/variable.rb +39 -0
  48. data/lib/liquid.rb +52 -0
  49. data/lib/redcloth.rb +1129 -0
  50. data/lib/support/class_options.rb +36 -0
  51. data/lib/support/inline_rendering.rb +48 -0
  52. data/lib/support/route_mapper.rb +50 -0
  53. data/lib/text_filters/markdown.rb +14 -0
  54. data/lib/text_filters/markdown_smartypants.rb +15 -0
  55. data/lib/text_filters/none.rb +8 -0
  56. data/lib/text_filters/rdoc.rb +13 -0
  57. data/lib/text_filters/simple.rb +8 -0
  58. data/lib/text_filters/textile.rb +15 -0
  59. data/lib/text_filters.rb +140 -0
  60. data/rails/init.rb +3 -0
  61. data/resources/layouts/comatose_admin_template.html.erb +28 -0
  62. data/resources/public/images/collapsed.gif +0 -0
  63. data/resources/public/images/expanded.gif +0 -0
  64. data/resources/public/images/no-children.gif +0 -0
  65. data/resources/public/images/page.gif +0 -0
  66. data/resources/public/images/spinner.gif +0 -0
  67. data/resources/public/images/title-hover-bg.gif +0 -0
  68. data/resources/public/javascripts/comatose_admin.js +401 -0
  69. data/resources/public/stylesheets/comatose_admin.css +404 -0
  70. data/tasks/comatose.rake +9 -0
  71. data/test/behaviors.rb +106 -0
  72. data/test/fixtures/comatose_pages.yml +96 -0
  73. data/test/functional/comatose_admin_controller_test.rb +114 -0
  74. data/test/functional/comatose_controller_test.rb +44 -0
  75. data/test/javascripts/test.html +26 -0
  76. data/test/javascripts/test_runner.js +307 -0
  77. data/test/test_helper.rb +55 -0
  78. data/test/unit/class_options_test.rb +52 -0
  79. data/test/unit/comatose_page_test.rb +136 -0
  80. data/test/unit/processing_context_test.rb +108 -0
  81. data/test/unit/text_filters_test.rb +52 -0
  82. data/views/comatose_admin/_form.html.erb +96 -0
  83. data/views/comatose_admin/_page_list_item.html.erb +60 -0
  84. data/views/comatose_admin/delete.html.erb +18 -0
  85. data/views/comatose_admin/edit.html.erb +5 -0
  86. data/views/comatose_admin/index.html.erb +29 -0
  87. data/views/comatose_admin/new.html.erb +5 -0
  88. data/views/comatose_admin/reorder.html.erb +30 -0
  89. data/views/comatose_admin/versions.html.erb +40 -0
  90. data/views/layouts/comatose_admin.html.erb +837 -0
  91. data/views/layouts/comatose_admin_customize.html.erb +28 -0
  92. data/views/layouts/comatose_content.html.erb +17 -0
  93. metadata +148 -0
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'comatose_controller'
3
+ require 'comatose_helper'
4
+
5
+ # Re-raise errors caught by the controller.
6
+ class ComatoseController
7
+ def rescue_action(e) raise e end
8
+ end
9
+
10
+
11
+ class ComatoseControllerTest < Test::Unit::TestCase
12
+
13
+ fixtures :comatose_pages
14
+
15
+ def setup
16
+ @controller = ComatoseController.new
17
+ @request = ActionController::TestRequest.new
18
+ @response = ActionController::TestResponse.new
19
+ end
20
+
21
+ def test_truth
22
+ assert true
23
+ end
24
+
25
+ should "show pages based on path_info" do
26
+
27
+ # Get the faq page...
28
+ get :show, :page=>'faq', :index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
29
+ assert_response :success
30
+ assert_tag :tag=>'h1', :child=>/Frequently Asked Questions/
31
+
32
+ # Get a question page using rails 2.0 array style...
33
+ get :show, :page=>['faq','question-one'], :index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
34
+ assert_response :success
35
+ assert_tag :tag=>'title', :child=>/Question/
36
+
37
+ # Get a question page using rails 1.x path style...
38
+ get :show, :page=>ActionController::Routing::PathSegment::Result.new_escaped(['faq','question-one']),
39
+ :index=>'', :layout=>'comatose_content.html.erb', :use_cache=>'false'
40
+ assert_response :success
41
+ assert_tag :tag=>'title', :child=>/Question/
42
+ end
43
+
44
+ end
@@ -0,0 +1,26 @@
1
+ <html>
2
+ <!-- Required Scripts -->
3
+ <script src="../../../../../public/javascripts/prototype.js" type="text/javascript"></script>
4
+ <script src="../../../../../public/javascripts/effects.js" type="text/javascript"></script>
5
+ <script src="../../../../../public/javascripts/dragdrop.js" type="text/javascript"></script>
6
+ <script src="../../../../../public/javascripts/controls.js" type="text/javascript"></script>
7
+ <script src="../../resources/public/javascripts/comatose_admin.js"></script>
8
+ <!-- Unit Tests -->
9
+
10
+ <script>
11
+ var Tests = {
12
+ title: "Comatose JS Tests",
13
+ // description: "Methods that start with testFail test that assertions fail property.",
14
+
15
+ test_String_toSlug: function() {
16
+ assertEqual( 'hello-how-are-you', 'Hello, How Are You?'.toSlug() );
17
+ assertEqual( 'i-have-too-much-space', 'I have too much space'.toSlug() );
18
+ assertEqual( 'what-about-dashes', 'What about - dashes?'.toSlug() );
19
+ assertEqual( 'a-bizarre-title', 'A !@!@#$%^&*()_+{} Bizarre TiTle!'.toSlug() );
20
+ assertEqual( '001-numbers-too', '001 Numbers too'.toSlug() );
21
+ }
22
+ }
23
+ </script>
24
+ <!-- UnitTestRunner -->
25
+ <script src="test_runner.js"></script>
26
+ </html>
@@ -0,0 +1,307 @@
1
+ /*
2
+ = Test Framework
3
+ version 1.0
4
+ created by M@ McCray (http://www.mattmccray.com)
5
+
6
+ This is a simple JavaScript test framework.
7
+
8
+ = TODO:
9
+
10
+ * Add support for calling Tests.setup() and Tests.teardown()
11
+ * Documentation!
12
+ * Add support for methods that don't start with 'test'?
13
+ * Make test method names more English?
14
+ */
15
+
16
+ // We're gonna run all this in it's own scope so it doesn't pollute the test namespace
17
+ (function(){
18
+ var HTML = {
19
+ _all_tags: ['a','abbr','acronym','address','area','b','base','bdo','big','blockquote','body','br','button','caption','cite','code','col','colgroup','dd','del','dfn','div','dl','DOCTYPE','dt','em','fieldset','form','h1','h2','h3','h4','h5','h6','head','html','hr','i','img','input','ins','kbd','label','legend','li','link','map','meta','noscript','object','ol','optgroup','option','p','param','pre','q','samp','script','select','small','span','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul'],
20
+ _init: function() {
21
+ for(var $i=0; $i<this._all_tags.length; $i++) {
22
+ var $tag = this._all_tags[$i]
23
+ eval( 'HTML.'+ $tag +' = function (){ return HTML._write_tag("'+ $tag +'", arguments); }' );
24
+ //this[$tag] = new Function("return HTML._write_tag('"+ $tag +"', arguments);")
25
+ this.namespace += ';var '+ $tag +' = HTML.'+ $tag;
26
+ }
27
+ },
28
+ _write_tag: function(tag, options) {
29
+ var $content = ''; var $atts = "";
30
+ for(var $i=0; $i<options.length; $i++) {
31
+ var $arg = options[$i];
32
+ if (typeof($arg) == 'string' || typeof($arg) == 'number')
33
+ $content += $arg.toString();
34
+ else if (typeof($arg) == 'function')
35
+ $content += $arg();
36
+ else if ( $arg instanceof Object)
37
+ for($prop in $arg) $atts += ' '+ $prop +'="'+ $arg[$prop] +'"';
38
+ }
39
+ if($content == '')
40
+ return '<'+ tag + $atts +'/>';
41
+ else
42
+ return '<'+ tag + $atts +'>'+ $content +'</'+ tag +'>';
43
+ },
44
+ namespace: 'var text = HTML.text',
45
+ toString: function() { return this.namespace; },
46
+ text: function() {
47
+ var $content='';
48
+ for(var $i=0; $i<arguments.length; $i++) $content += arguments[$i].toString();
49
+ return $content;
50
+ }
51
+ };
52
+ HTML._init();
53
+ eval(HTML.namespace);
54
+
55
+ var list_html = "";
56
+ var page_title = "Test Cases";
57
+ var page_desc = "";
58
+
59
+ window.methodList = [];
60
+ if( typeof(Tests) != 'undefined' ) {
61
+ if(Tests.title) page_title = Tests.title;
62
+ if(Tests.description) page_desc = Tests.description;
63
+
64
+ for(func in Tests) {
65
+ if(/test/.test(func)) {
66
+ methodList.push(func);
67
+ list_html += li ({id:func, 'class':'untested'},
68
+ span (func.toString()),
69
+ div (' ', {id: (func +'-error')})
70
+ )
71
+ }
72
+ }
73
+ } else {
74
+ list_html = li('No tests defined!', {'class':'fail'})
75
+ }
76
+
77
+ // Generate HTML
78
+
79
+ if( page_desc != '' ) page_desc = p( page_desc,{'class':'description'});
80
+
81
+ document.write(
82
+ head (
83
+ title ( "(", page_title, ")", " :: JavaScript Test Framework" ),
84
+ style (
85
+ "BODY { font-family:Helvetica,Verdana,Sans-Serif; background:#E0E0E0; }",
86
+ "LI { padding:3px; }",
87
+ "H1 { margin-top:0; color:navy; }",
88
+ "INPUT { font-size:105%; font-weight:bold; }",
89
+ "#main { width:650px; margin:0 auto; background:#FFF; padding:20px; border:1px solid #BBB; }",
90
+ "#status { padding:10px; }",
91
+ "#sidebar { background:#F0F0F0; float:right; width:200px; padding:5px 15px; font-size:85%; border:10px solid white; border-top:0px; }",
92
+ ".description { background:#FFC; padding:10px; font-size:85%; }",
93
+ ".credit { padding:0px 2px; font-size:90%; color:gray; }",
94
+ ".untested { color:#C5C5C5; }",
95
+ ".untested SPAN { color:black; }",
96
+ ".pass { color:#0F0; }",
97
+ ".pass SPAN { color:#363; }",
98
+ ".fail { color:red; }",
99
+ ".fail DIV { font-size:85%; color:#666; }",
100
+ ".fail SPAN { color:maroon; }",
101
+ ".fail UL { margin:0px; padding:0px; padding-left:10px; list-style:none; }",
102
+ ".fail LI { padding:2px; }",
103
+ ".assertion-type { color:black !important; font-weight:bold; }",
104
+ ".exception-type { color:red !important; font-weight:bold; }"
105
+ )
106
+ ),
107
+ body (
108
+ div ({id:'main'},
109
+ div ({id:'sidebar'},
110
+ p ("This is a simple JavaScript test framework."),
111
+ p ("To read the tests, just view-source."),
112
+ p ("Created by M@ McCray. Released under the MIT license.", {'class':'credit'})
113
+ ),
114
+ h1 (page_title),
115
+ page_desc,
116
+ ul ({id:'test-list'},
117
+ list_html
118
+ ),
119
+ table( tr(
120
+ td(
121
+ input ({ type:'button', onclick:'runAllTests()', value:'Run All Tests'})
122
+ ),
123
+ td(
124
+ div ('&nbsp;',{id:'status'})
125
+ )
126
+ ))
127
+ ),
128
+ div ('&nbsp;', {id:'work-area'})
129
+ )
130
+ );
131
+
132
+ window.assertionCount = 0;
133
+ window.assertionFailCount = 0;
134
+ window.assertionErrorCount = 0;
135
+
136
+ var assertionFailures = [];
137
+
138
+ // Exported functions
139
+ window.runAllTests = function() {
140
+ var errors = [];
141
+ assertionCount = 0;
142
+ assertionFailCount = 0;
143
+
144
+ forEach(methodList, function(func){
145
+ setStatus('Evaluating '+ func +'...');
146
+
147
+ assertionFailures = [];
148
+ assertionExceptions = [];
149
+ try {
150
+ Tests[func]()
151
+ } catch (ex) {
152
+ assertionErrorCount++;
153
+ assertionExceptions.push(ex)
154
+ }
155
+ if( assertionFailures.length == 0 && assertionExceptions.length == 0) {
156
+ $(func).className = 'pass';
157
+ } else {
158
+ $(func).className = 'fail';
159
+ var results = ""
160
+
161
+ forEach(assertionFailures, function(err){
162
+ results += li (
163
+ span (err.assertionType, {'class':'assertion-type'}), ': ',
164
+ (err.message || err.extraInformation)
165
+ );
166
+ });
167
+
168
+ forEach(assertionExceptions, function(err){
169
+ results += li (
170
+ span ('Error', {'class':'exception-type'}), ': ',
171
+ (err.description || err.message || err)
172
+ );
173
+ });
174
+
175
+ setResults( func, ul (results) )
176
+ }
177
+ });
178
+
179
+ setStatus( div (
180
+ assertionCount,
181
+ " assertions, ",
182
+ span ((assertionCount - assertionFailCount), {'class':'pass'}),
183
+ " passed",
184
+ show_if (assertionFailCount, text( ", ",
185
+ span (assertionFailCount, {'class':'fail'}),
186
+ " failed" )
187
+ ),
188
+ show_if (assertionErrorCount, text( ", ",
189
+ span (assertionErrorCount, {'class':'fail'}),
190
+ " error(s)")
191
+ ),
192
+ "."
193
+ ));
194
+ }
195
+
196
+ // Assertions
197
+ window.assert = function(condition, msg) {
198
+ window.assertionCount++;
199
+ if(!condition) {
200
+ ex = 'true was expected, but value was '+ condition;
201
+ assertError(msg, 'assert', ex);
202
+ }
203
+ }
204
+
205
+ window.assertFalse = function(condition, msg) {
206
+ window.assertionCount++;
207
+ if(condition) {
208
+ ex = 'false was expected, but value was '+ condition;
209
+ assertError(msg, 'assertFalse', ex);
210
+ }
211
+ }
212
+
213
+ window.assertNull = function(condition, msg) {
214
+ window.assertionCount++;
215
+ if(null != condition) {
216
+ ex = 'null was expected, but value was '+ condition;
217
+ assertError(msg, 'assertNull', ex);
218
+ }
219
+ }
220
+
221
+ window.assertNotNull = function(condition, msg) {
222
+ window.assertionCount++;
223
+ if(null == condition) {
224
+ ex = 'null was not expected, but value was '+ condition;
225
+ assertError(msg, 'assertNotNull', ex);
226
+ }
227
+ }
228
+
229
+ window.assertEqual = function(condition1, condition2, msg) {
230
+ window.assertionCount++;
231
+ ex = condition1 +' was expected, but value was '+ condition2;
232
+ if(condition1 != condition2) {
233
+ assertError(msg, 'assertEqual', ex);
234
+ }
235
+ }
236
+
237
+ window.assertNotEqual = function(condition1, condition2, msg) {
238
+ window.assertionCount++;
239
+ if(condition1 == condition2) {
240
+ ex = condition1 +' was not expected, but value was '+ condition2;
241
+ assertError(msg, 'assertNotEqual', ex);
242
+ }
243
+ }
244
+
245
+ window.assertUndefined = function(object, msg) {
246
+ window.assertionCount++;
247
+ if(object != 'undefined' ) {
248
+ ex = object +' was defined';
249
+ assertError(msg, 'assertUndefined', ex);
250
+ }
251
+ }
252
+
253
+ window.assertDefined = function(object, msg) {
254
+ window.assertionCount++;
255
+ if(object == 'undefined' ) {
256
+ ex = object +' was undefined';
257
+ assertError(msg, 'assertDefined', ex);
258
+ }
259
+ }
260
+
261
+ // Private functions
262
+ function $(elem) {
263
+ return document.getElementById(elem);
264
+ }
265
+
266
+ function log() {
267
+ var msg = [];
268
+ forEach(arguments, function(arg){ msg.push( arg || '' ); });
269
+ if(window.console && window.console.log) {
270
+ window.console.log(msg.join(' '))
271
+ } else if(window.console && window.console.info) {
272
+ window.console.info(msg.join(' '))
273
+ }
274
+ }
275
+
276
+ function forEach(array, block, context) {
277
+ for (var i = 0; i < array.length; i++) {
278
+ block.call(context, array[i], i, array);
279
+ }
280
+ }
281
+
282
+ function show_if(list, html) {
283
+ if(list > 0)
284
+ return html;
285
+ else
286
+ return '';
287
+ }
288
+
289
+ function setStatus(msg) {
290
+ $('status').innerHTML = msg;
291
+ }
292
+
293
+ function setResults(func, msg) {
294
+ $(func+'-error').innerHTML = msg;
295
+ }
296
+
297
+ function assertError(errorMessage, assertionType, extraInfo) {
298
+ window.assertionFailCount++;
299
+ assertionFailures.push({
300
+ assertionType: assertionType,
301
+ message: errorMessage,
302
+ extraInformation: extraInfo.toString().replace(/</g, '&lt;'),
303
+ description: errorMessage +"\n"+ extraInfo.toString().replace(/</g, '&lt;')
304
+ });
305
+ }
306
+
307
+ })();
@@ -0,0 +1,55 @@
1
+ ENV["RAILS_ENV"] = 'test'
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
4
+
5
+ require 'test/unit'
6
+ require 'test_help'
7
+
8
+ class Test::Unit::TestCase
9
+
10
+ self.fixture_path = File.expand_path( File.join(File.dirname(__FILE__), 'fixtures') )
11
+
12
+ self.use_transactional_fixtures = true
13
+ self.use_instantiated_fixtures = false
14
+
15
+ def setup
16
+ Comatose.configure do |config|
17
+ config.default_filter = :textile
18
+ config.default_processor = :liquid
19
+ config.authorization = Proc.new { true }
20
+ config.admin_authorization = Proc.new { true }
21
+ config.admin_get_author = Proc.new { request.env['REMOTE_ADDR'] }
22
+ config.admin_get_root_page = Proc.new { ComatosePage.root }
23
+ end
24
+ TextFilters.default_filter = "Textile"
25
+ end
26
+
27
+ def create_page(options={})
28
+ ComatosePage.create({ :title => 'Comatose Page', :author=>'test', :parent_id=>1 }.merge(options))
29
+ end
30
+
31
+ def comatose_page(sym)
32
+ ComatosePage.find_by_slug(sym.to_s.dasherize)
33
+ end
34
+
35
+ def assert_difference(object, method = nil, difference = 1)
36
+ initial_value = object.send(method)
37
+ yield
38
+ assert_equal initial_value + difference, object.send(method), "#{object}##{method}"
39
+ end
40
+
41
+ def assert_no_difference(object, method, &block)
42
+ assert_difference object, method, 0, &block
43
+ end
44
+
45
+ class << self
46
+ def should(behave,&block)
47
+ method_name = "test_should_#{behave.gsub(' ', '_')}"
48
+ if block
49
+ define_method method_name, &block
50
+ else
51
+ puts ">>> Untested: #{name.sub(/Test$/,'')} should #{behave}"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'support/class_options'
3
+
4
+ class ClassOptionsTest < Test::Unit::TestCase
5
+
6
+ class Opts
7
+ define_option :nothing, nil
8
+ define_option :nada
9
+ define_option :name, "Matt"
10
+ define_option :age, 30
11
+ define_option :mode, :test
12
+ define_option :listing, ['one', 'two', 'three']
13
+ define_option :opts_1, {'one'=>'ONE', 'two'=>'TWO'}
14
+ define_option :opts_2, {:one=>'ONE', :two=>'TWO'}
15
+ define_option :should_work, true
16
+ define_option :would_surprise, false
17
+ end
18
+
19
+ should "allow nil as a default" do
20
+ assert_equal nil, Opts.nothing
21
+ assert_equal nil, Opts.nada
22
+ end
23
+
24
+ should "allow boolean defaults" do
25
+ assert_equal true, Opts.should_work
26
+ assert_equal false, Opts.would_surprise
27
+ end
28
+
29
+ should "allow string defaults" do
30
+ assert_equal 'Matt', Opts.name
31
+ end
32
+
33
+ should "allow numeric defaults" do
34
+ assert_equal 30, Opts.age
35
+ end
36
+
37
+ should "allow symbolic defaults" do
38
+ assert_equal :test, Opts.mode
39
+ end
40
+
41
+ should "allow array literals as defaults" do
42
+ assert_equal ['one', 'two', 'three'], Opts.listing
43
+ end
44
+
45
+ should "allow hash literals as defaults" do
46
+ h1 = {'one'=>'ONE', 'two'=>'TWO'}
47
+ h2 = {:one=>'ONE', :two=>'TWO'}
48
+ assert_equal h1, Opts.opts_1
49
+ assert_equal h2, Opts.opts_2
50
+ end
51
+
52
+ end
@@ -0,0 +1,136 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ComatosePageTest < Test::Unit::TestCase
4
+
5
+ fixtures :comatose_pages
6
+
7
+ should "create page" do
8
+ assert_difference ComatosePage, :count do
9
+ page = create_page :title=>'New Page Name'
10
+ assert !page.new_record?, "#{page.errors.full_messages.to_sentence}"
11
+ end
12
+ end
13
+
14
+ should "create a new version of an updated page" do
15
+ page = create_page
16
+ assert_difference page, :version do
17
+ page.update_attribute :body, "I'm the new content!"
18
+ assert_equal "<p>I&#8217;m the new content!</p>", page.to_html
19
+ end
20
+ end
21
+
22
+ should "render content through textile and liquid processors" do
23
+ page = create_page :title=>'Title Here', :body=>'h1. {{page.title}}'
24
+ assert_equal "<h1>Title Here</h1>", page.to_html
25
+ end
26
+
27
+ should "not allow creation of page when missing a title" do
28
+ assert_no_difference ComatosePage, :count do
29
+ p = create_page(:title => nil)
30
+ assert p.errors.on(:title)
31
+ end
32
+ end
33
+
34
+ should "have good fixtures for this to work out" do
35
+ assert_equal 'Home Page', root_page.title
36
+ assert_equal 'home-page', root_page.slug
37
+ assert_equal 'Comatose', root_page.author
38
+ assert_equal "", root_page.full_path
39
+ assert_equal 'faq', faq_page.full_path
40
+ end
41
+
42
+ should "generate slugs correctly" do
43
+ assert_equal 'hello-how-are-you', new_page_slug( "Hello, How Are You?" )
44
+ assert_equal 'i-have-too-much-space', new_page_slug( "I have too much space" )
45
+ assert_equal 'i-have-leading-and-trailing-space', new_page_slug( " I have leading and trailing space " )
46
+ assert_equal 'what-about-dashes', new_page_slug( "What about - dashes?" )
47
+ assert_equal 'a-bizarre-title', new_page_slug( 'A !@!@#$%^<>&*()_+{} Bizarre TiTle!' )
48
+ assert_equal '001-numbers-too', new_page_slug( "001 Numbers too" )
49
+ end
50
+
51
+ should "generate page paths correctly" do
52
+ products = root_page.children.create( :title=>'Products' )
53
+ assert_equal 'products', products.full_path
54
+
55
+ books = products.children.create( :title=>'Books' )
56
+ assert_equal 'products/books', books.full_path
57
+
58
+ novels = books.children.create( :title=>'Novels' )
59
+ assert_equal 'products/books/novels', novels.full_path
60
+
61
+ comics = books.children.create( :title=>'Comics' )
62
+ assert_equal 'products/books/comics', comics.full_path
63
+ end
64
+
65
+ should "update page paths when pages are moved" do
66
+ page = comatose_page :params
67
+ assert_equal 'params', page.full_path
68
+
69
+ q1pg = comatose_page :question_one
70
+ page.parent_id = q1pg.id
71
+ assert page.save, "Page.save"
72
+
73
+ page.reload
74
+ assert_equal 'faq/question-one/params', page.full_path
75
+
76
+ q1pg.reload
77
+ q1pg.slug = "q-1"
78
+ assert q1pg.save, "Page.save"
79
+ assert_equal "faq/q-1", q1pg.full_path
80
+
81
+ page.reload
82
+ assert_equal 'faq/q-1/params', page.full_path
83
+ end
84
+
85
+ should "set an AR error with processor syntax error info" do
86
+ page = create_page :title=>'Title Here', :body=>'h1. {% crap %}'
87
+ assert !page.save, page.errors.full_messages.to_sentence
88
+ end
89
+
90
+ should "render body text accurately" do
91
+ assert_equal "<h1>Home Page</h1>\n<p>This is your <strong>home page</strong>.</p>", root_page.to_html
92
+ assert_equal "<h1>Frequently Asked Questions</h1>\n<h2><a href=\"/faq/question-one\">Question One?</a></h2>\n<p>Content for <strong>question one</strong>.</p>\n<h2><a href=\"/faq/question-two\">Question Two?</a></h2>\n<p>Content for <strong>question two</strong>.</p>", faq_page.to_html
93
+ end
94
+
95
+ should "render data from parameterized calls too" do
96
+ assert_equal "<p>I&#8217;m</p>", param_driven_page.to_html
97
+ assert_equal "<p>I&#8217;m From the Params Hash</p>", param_driven_page.to_html(:extra=>'From the Params Hash')
98
+ end
99
+
100
+ should "render data from a Drop" do
101
+ Comatose.define_drop "app" do
102
+ def test
103
+ "From Drop"
104
+ end
105
+ end
106
+ p = create_page(:title=>'Test Drop', :body=>'{{ app.test }}')
107
+ assert_equal "<p>From Drop</p>", p.to_html
108
+ end
109
+
110
+ # Test illustrates broken partial, sort of
111
+ # <%= render :comatose => 'faq/question-one' %> should work, but does not
112
+ should "render inline partial" do
113
+ Comatose.config.default_processor = :erb
114
+ page = create_page :body => "Included: <%= ComatosePage.find_by_path('faq/question-one').to_html %>", :filter_type => :none
115
+ assert_equal "Included: <p>Content for <strong>question one</strong>.</p>", page.to_html
116
+ end
117
+
118
+ protected
119
+
120
+ def new_page_slug(title)
121
+ create_page( :title=>title ).slug
122
+ end
123
+
124
+ def root_page
125
+ ComatosePage.root
126
+ end
127
+
128
+ def faq_page
129
+ comatose_page :faq
130
+ end
131
+
132
+ def param_driven_page
133
+ comatose_page :params
134
+ end
135
+
136
+ end