Renamed helpers to correspond to renamed Controller classes.
[merb_radiant.git] / radiant_specs / spec / models / .svn / text-base / page_spec.rb.svn-base
blob806bfb90bec5b69480ca0e19f4fee43a2b945855
1 require File.dirname(__FILE__) + '/../spec_helper'
3 class PageSpecTestPage < Page
4   description 'this is just a test page'
5   
6   def headers
7     {
8       'cool' => 'beans',
9       'request' => @request.inspect[20..30],
10       'response' => @response.inspect[20..31]
11     }
12   end
13   
14   tag 'test1' do
15     'Hello world!'
16   end
17   
18   tag 'test2' do
19     'Another test.'
20   end
21 end
23 describe Page, 'validations' do
24   scenario :pages
25   test_helper :validations
26   
27   before :each do
28     @page = @model = Page.new(page_params)
29   end
30   
31   it 'should validate length of' do
32     {
33       :title => 255,
34       :slug => 100,
35       :breadcrumb => 160
36     }.each do |field, max|
37       assert_invalid field, ('%d-character limit' % max), 'x' * (max + 1)
38       assert_valid field, 'x' * max
39     end
40   end
41   
42   it 'should validate presence of' do
43     [:title, :slug, :breadcrumb].each do |field|
44       assert_invalid field, 'required', '', ' ', nil
45     end 
46   end
47   
48   it 'should validate format of' do
49     @page.parent = pages(:home)
50     assert_valid :slug, 'abc', 'abcd-efg', 'abcd_efg', 'abc.html', '/', '123'
51     assert_invalid :slug, 'invalid format', 'abcd efg', ' abcd', 'abcd/efg'
52   end
53   
54   it 'should validate numericality of' do
55     assert_invalid :status_id, 'required', '', nil
56     [:id, :status_id, :parent_id].each do |field|
57       assert_valid field, '1', '2'
58       assert_invalid field, 'must be a number', 'abcd', '1,2', '1.3'
59     end
60   end
61   
62   it 'should validate uniqueness of' do
63     @page.parent = pages(:parent)
64     assert_invalid :slug, 'slug already in use for child of parent', 'child', 'child-2', 'child-3'
65     assert_valid :slug, 'child-4'
66   end
67   
68   it 'should allow mass assignment for class name' do
69     @page.attributes = { :class_name => 'ArchivePage' }
70     assert_valid @page
71     @page.class_name.should == 'ArchivePage'
72   end
73   
74   it 'should not be valid when class name is not a descendant of page' do
75     @page.class_name = 'Object'
76     @page.valid?.should == false
77     assert_not_nil @page.errors.on(:class_name)
78     @page.errors.on(:class_name).should == 'must be set to a valid descendant of Page'
79   end
81   it 'should not be valid when class name is not a descendant of page and it is set through mass assignment' do
82     @page.attributes = {:class_name => 'Object' }
83     @page.valid?.should == false
84     assert_not_nil @page.errors.on(:class_name)
85     @page.errors.on(:class_name).should == 'must be set to a valid descendant of Page'
86   end
87     
88   it 'should be valid when class name is page or empty or nil' do
89     [nil, '', 'Page'].each do |value|
90       @page = ArchivePage.new(page_params)
91       @page.class_name = value
92       assert_valid @page
93       @page.class_name.should == value
94     end
95   end
96 end
98 describe Page, "behaviors" do
99   it 'should include' do
100     Page.included_modules.should include(StandardTags)
101     Page.included_modules.should include(Annotatable)
102   end
105 describe Page, "layout" do
106   scenario :pages_with_layouts
107   
108   it 'should be accessible' do
109     @page = pages(:first)
110     @page.layout_id.should == layout_id(:main)
111     @page.layout.name.should == "Main"
112   end
113   
114   it 'should be inherited' do
115     @page = pages(:inherited_layout)
116     @page.layout_id.should == nil
117     @page.layout.should == @page.parent.layout
118   end
121 describe Page do
122   scenario :pages
123   
124   before :each do
125     @page = pages(:first)
126   end
127   
128   it 'should have parts' do
129     @page.parts.count.should == 1
130     pages(:home).parts.count.should == 4
131   end
132   
133   it 'should destroy dependant parts' do
134     @page.parts.create(page_part_params(:name => 'test', :page_id => nil))
135     assert_kind_of PagePart, @page.parts.find_by_name('test')
136     
137     id = @page.id
138     @page.destroy
139     assert_nil PagePart.find_by_page_id_and_name(id, 'test')
140   end
141   
142   it 'should allow access to parts by name with a string' do
143     part = @page.part('body')
144     part.name.should == 'body'
145   end
146   
147   it 'should allow access to parts by name with a symbol' do
148     part = @page.part(:body)
149     part.name.should == 'body'
150   end
151   
152   it 'should allow access to parts by name when page is unsaved' do
153     part = PagePart.new(:content => "test", :name => "test")
154     @page.parts << part
155     @page.part('test').should == part
156     @page.part(:test).should == part
157   end
158   
159   it 'should allow access to parts by name created with the build method when page is unsaved' do
160     @page.parts.build(:content => "test", :name => "test")
161     @page.part('test').content.should == "test"
162     @page.part(:test).content.should == "test"
163   end
164   
165   it 'should set published_at when published' do
166     @page = Page.new(page_params(:status_id => '1', :published_at => nil))
167     assert_nil @page.published_at
168     
169     @page.status_id = Status[:published].id
170     @page.save
171     assert_not_nil @page.published_at
172     @page.published_at.day.should == Time.now.day
173   end 
174   
175   it 'should not update published_at when already published' do
176     @page = Page.new(page_params(:status_id => Status[:published].id))
177     @page.published_at.should be_kind_of(Time) 
178     
179     expected = @page.published_at
180     @page.save
181     @page.published_at.should == expected
182   end
183   
184   it 'should answer true when published' do
185     @page.status = Status[:published]
186     @page.published?.should == true
187   end
188   
189   it 'should answer false when not published' do
190     @page.status = Status[:draft]
191     @page.published?.should be_false
192   end
193   
194   it "should answer the page's url" do
195     @page = pages(:parent)
196     @page.url.should == '/parent/'
197     @page.children.first.url.should == '/parent/child/'
198     
199     grandchild = pages(:grandchild)
200     grandchild.url.should == '/parent/child/grandchild/'
201   end
202   
203   it 'should allow you to calculate a child url from the parent' do
204     @page = pages(:parent)
205     child = pages(:child)
206     @page.child_url(child).should == '/parent/child/'
207   end
208   
209   it 'should return the appropriate status code in headers' do
210     @page.headers.should == { 'Status' => ActionController::Base::DEFAULT_RENDER_STATUS_CODE }
211   end
212   
213   it 'should have status' do
214     @page = pages(:home)
215     @page.status.should == Status[:published]
216   end
217   
218   it 'should allow you to set the status' do
219     @page = pages(:home)
220     draft = Status[:draft]
221     @page.status = draft
222     @page.status.should == draft
223     @page.status_id.should == draft.id
224   end
225   
226   it 'should respond to cache? with true (by default)' do
227     @page.cache?.should == true
228   end
229   
230   it 'should respond to virtual? with false (by default)' do
231     @page.virtual?.should == false
232   end
233   
234   it 'should allow you to tell if a part exists based on a string or symbol' do
235     @page = pages(:home)
236     @page.has_part?(:body).should == true
237     @page.has_part?('sidebar').should == true
238     @page.has_part?(:obviously_false_part_name).should == false
239   end
240   
241   it 'should allow you to tell if a part is inherited' do
242     @page = pages(:child)
243     @page.has_part?(:sidebar).should == false
244     @page.inherits_part?(:sidebar).should == true
245     
246     @page = pages(:home)
247     @page.has_part?(:sidebar).should == true
248     @page.inherits_part?(:sidebar).should == false
249   end
250   
251   it 'should allow you to tell if a part exists or is inherited' do
252     @page = pages(:child)
253     @page.has_part?(:sidebar).should == false
254     @page.has_or_inherits_part?(:sidebar).should == true
255     @page.has_or_inherits_part?(:obviously_false_part_name).should == false
256     
257     @page = pages(:home)
258     @page.has_part?(:sidebar).should == true
259     @page.has_or_inherits_part?(:sidebar).should == true
260     @page.has_or_inherits_part?(:obviously_false_part_name).should == false
261   end
262   
263   it 'should support optimistic locking' do
264     p1, p2 = pages(:first), pages(:first)
265     p1.save!
266     lambda { p2.save! }.should raise_error(ActiveRecord::StaleObjectError) 
267   end
270 describe Page, "before save filter" do
271   scenario :home_page
272   
273   before :each do
274     Page.create(page_params(:title =>"Month Index", :class_name => "ArchiveMonthIndexPage"))
275     @page = Page.find_by_title("Month Index")
276   end
277   
278   it 'should set the class name correctly' do
279     @page.should be_kind_of(ArchiveMonthIndexPage)
280   end
281   
282   it 'should set the virtual bit correctly' do
283     @page.virtual?.should == true
284     @page.virtual.should == true
285   end
286   
287   it 'should update virtual based on new class name' do
288     # turn a regular page into a virtual page
289     @page.class_name = "ArchiveMonthIndexPage"
290     @page.save.should == true
291     @page.virtual?.should == true
292     @page.send(:read_attribute, :virtual).should == true
293     
294    # turn a virtual page into a non-virtual one
295    ["", nil, "Page", "EnvDumpPage"].each do |value|
296       @page = ArchiveYearIndexPage.create(page_params)
297       @page.class_name = value
298       @page.save.should == true
299       @page = Page.find @page.id
300       @page.should be_instance_of(Page.descendant_class(value))
301       @page.virtual?.should == false
302       @page.send(:read_attribute, :virtual).should == false
303     end
304   end
307 describe Page, "rendering" do
308   scenario :pages, :markup_pages, :snippets, :layouts
309   test_helper :render
310   
311   before :each do
312     @page = pages(:home)
313   end
314   
315   it 'should render' do
316     @page.render.should == 'Hello world!'
317   end
318   
319   it 'should render with a filter' do
320     pages(:textile).render.should == '<p>Some <strong>Textile</strong> content.</p>'
321   end
322   
323   it 'should render with tags' do
324     pages(:radius).render.should == "Radius body."
325   end
326   
327   it 'should render with a layout' do
328     @page.update_attribute(:layout_id, layout_id(:main))
329     @page.render.should == "<html>\n  <head>\n    <title>Home</title>\n  </head>\n  <body>\n    Hello world!\n  </body>\n</html>\n"
330   end
331   
332   it 'should render a part' do
333     @page.render_part(:body).should == "Hello world!"
334   end
335   
336   it 'should render a snippet' do
337     assert_snippet_renders :first, 'test'
338   end
339   
340   it 'should render a snippet with a filter' do
341     assert_snippet_renders :markdown, '<p><strong>markdown</strong></p>'
342   end
343   
344   it 'should render a snippet with a tag' do
345     assert_snippet_renders :radius, 'Home'
346   end
347   
348   it 'should render custom pages with tags' do
349     create_page "Test Page", :body => "<r:test1 /> <r:test2 />", :class_name => "PageSpecTestPage"
350     pages(:test_page).should render_as('Hello world! Another test. body.')
351   end
354 describe Page, "#find_by_url" do
355   scenario :pages, :file_not_found
356   
357   before :each do
358     @page = pages(:home)
359   end
360   
361   it 'should allow you to find the home page' do
362     @page.find_by_url('/') .should == @page
363   end
364   
365   it 'should allow you to find deeply nested pages' do
366     @page.find_by_url('/parent/child/grandchild/great-grandchild/').should == pages(:great_grandchild)
367   end
368   
369   it 'should not allow you to find virtual pages' do
370     @page.find_by_url('/virtual/').should == pages(:file_not_found)
371   end
372   
373   it 'should find the FileNotFoundPage when a page does not exist' do
374     @page.find_by_url('/nothing-doing/').should == pages(:file_not_found)
375   end
376   
377   it 'should find a custom file not found page' do
378     @page.find_by_url('/gallery/nothing-doing/').should == pages(:no_picture)
379   end
380   
381   it 'should not find draft pages in live mode' do
382     @page.find_by_url('/draft/').should == pages(:file_not_found)
383   end
384   
385   it 'should find draft pages in dev mode' do
386     @page.find_by_url('/draft/', false).should == pages(:draft)
387   end
390 describe Page, "class" do
391   it 'should have a description' do
392     PageSpecTestPage.description.should == 'this is just a test page'
393   end
394   
395   it 'should have a display name' do
396     Page.display_name.should == "Page"
397     
398     PageSpecTestPage.display_name.should == "Page Spec Test"
399     
400     PageSpecTestPage.display_name = "New Name"
401     PageSpecTestPage.display_name.should == "New Name"
402     
403     FileNotFoundPage.display_name.should == "File Not Found"
404   end
405   
406   it 'should list decendants' do
407     descendants = Page.descendants
408     assert_kind_of Array, descendants
409     assert_match /PageSpecTestPage/, descendants.inspect
410   end
411   
412   it 'should allow initialization with empty defaults' do
413     @page = Page.new_with_defaults({})
414     @page.parts.size.should == 0
415   end
416   
417   it 'should allow initialization with default page parts' do
418     @page = Page.new_with_defaults({ 'defaults.page.parts' => 'a, b, c'})
419     @page.parts.size.should == 3
420     @page.parts.first.name.should == 'a'
421     @page.parts.last.name.should == 'c'
422   end
423   
424   it 'should allow initialization with default page status' do
425     @page = Page.new_with_defaults({ 'defaults.page.status' => 'published' })
426     @page.status.should == Status[:published]
427   end  
428   
429   it 'should allow you to get the class name of a descendant class with a string' do
430     ["", nil, "Page"].each do |value|
431       Page.descendant_class(value).should == Page
432     end
433     Page.descendant_class("PageSpecTestPage").should == PageSpecTestPage
434   end
435   
436   it 'should allow you to determine if a string is a valid descendant class name' do
437     ["", nil, "Page", "PageSpecTestPage"].each do |value|
438       Page.is_descendant_class_name?(value).should == true
439     end
440     Page.is_descendant_class_name?("InvalidPage").should == false
441   end
444 describe Page, "class find_by_url" do
445   scenario :pages, :file_not_found
446   
447   it 'should find the home page' do
448     Page.find_by_url('/').should == pages(:home)
449   end
450   
451   it 'should find children' do
452     Page.find_by_url('/parent/child/').should == pages(:child)
453   end
454   
455   it 'should not find draft pages in live mode' do
456     Page.find_by_url('/draft/').should == pages(:file_not_found)
457     Page.find_by_url('/draft/', false).should == pages(:draft)
458   end
459   
460   it 'should raise an exception when root page is missing' do
461     pages(:home).destroy
462     Page.find_by_parent_id().should be_nil
463     lambda { Page.find_by_url "/" }.should raise_error(Page::MissingRootPageError, 'Database missing root page')
464   end
467 describe Page, "processing" do
468   scenario :pages_with_layouts
469   
470   before :all do
471     @request = ActionController::TestRequest.new :url => '/page/'
472     @response = ActionController::TestResponse.new
473   end
474   
475   it 'should set response body' do
476     @page = pages(:home)
477     @page.process(@request, @response)
478     @response.body.should match(/Hello world!/)
479   end
481   it 'should set headers and pass request and response' do
482     create_page "Test Page", :class_name => "PageSpecTestPage"
483     @page = pages(:test_page)
484     @page.process(@request, @response)
485     @response.headers['cool'].should == 'beans'
486     @response.headers['request'].should == 'TestRequest'
487     @response.headers['response'].should == 'TestResponse'
488   end
489   
490   it 'should set content type based on layout' do
491     @page = pages(:utf8)
492     @page.process(@request, @response)
493     assert_response :success
494     @response.headers['Content-Type'].should == 'text/html;charset=utf8'
495   end