diff --git a/app/controllers/page_controller.rb b/app/controllers/page_controller.rb index 97b763f..4e3c5e8 100644 --- a/app/controllers/page_controller.rb +++ b/app/controllers/page_controller.rb @@ -3,15 +3,36 @@ class PageController < ApplicationController # http://domain.com/* -> maps to the tree structure stored in db # Currently in need of some serious refactoring def indexer + handle_xml + logger.info params['path'].inspect @page = Page.visible.find_page_by_path params['path'] @breadcrumb = @page.ancestors.reverse.collect { |x| [x.full_path, x.title] } if @page @top_page = params[:path][0] || 'root' render :template => "404", :status => 404, :layout => false and return unless @page - if @page.is_published? || (logged_in? && current_user.can_view_drafts?) - render :template => 'content/page' and return if @page.page_type == "page" - else - render :template => 'content/unpublished' and return if @page.page_type == "page" + respond_to do |format| + format.html do + if @page.is_published? || (logged_in? && current_user.can_view_drafts?) + render :template => 'content/page' and return if @page.page_type == "page" + else + render :template => 'content/unpublished' and return if @page.page_type == "page" + end + render :template => 'content/multipage' # FIXME: we seem to never, ever hit this anyway + end + format.xml do + @page.page_plugins + render :xml => @page.to_xml + end + end + end + + protected + # FIXME: This is awful, awful, but due to our route for pages, necessary at present + def handle_xml + if params['path'].is_a?(Array) + if params['path'].last =~ /\.xml/ + request.format = :xml + params['path'].last.gsub!(/\.xml/, '') + end end - render :template => 'content/multipage' end end diff --git a/app/models/page.rb b/app/models/page.rb index 84b367e..1de72fc 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -30,7 +30,7 @@ class Page < ActiveRecord::Base validates_presence_of :name, :title - named_scope :visible, lambda{ { :conditions => ["(expires_on > ? OR expires_on IS NULL) AND published = ? AND (publish_at <= ? OR publish_at IS NULL )", Time.now.getgm, true, Time.now.getgm] } } + named_scope :visible, lambda{ { :conditions => ["(expires_on > ? OR expires_on IS NULL) AND status = 'published' AND (publish_at <= ? OR publish_at IS NULL )", Time.now.getgm, Time.now.getgm] } } named_scope :self_and_siblings, lambda {|page| {:conditions => ["parent_id = ?", page.parent_id], :order => 'page_order'}} named_scope :expired, lambda {|p| { :conditions => ["expires_on < ?", Time.now.getgm] } } named_scope :expires_soon, lambda {|p| { :conditions => ["expires_on < ?", Time.now.getgm + 5.days ] } } @@ -187,8 +187,10 @@ def find_child(child_name) # Accepts params[:path] and returns the page object or nil def self.find_page_by_path(path) + logger.info path.inspect #logger.error("==> find_page_by_path: path = [ #{path.join("/")} ]") page = Page.root + return page if path == ['home'] # hack to make calling the home page path easier return nil if page.nil? # Not DRY. This piece of code handles multipage root @@ -251,6 +253,20 @@ def permalinkable_title title.downcase.gsub(/ /, '-') end + def to_xml(options = {}) + options[:indent] ||= 2 + xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) + xml.instruct! unless options[:skip_instruct] + xml.page do + attributes.to_xml(:builder => xml, :skip_instruct => true, :root => "attributes") + xml.tag!("page-plugins") do + self.page_plugins.each do |page_plugin| + page_plugin.module.attributes.to_xml(:builder => xml, :skip_instruct => true, :root => 'page-plugin') + end + end + end + end + protected def check_page_type self.page_type = "page" and return if self.body.blank? || (@split_pages = self.body.split(/\{pagebreak\}/i)).length == 1 diff --git a/app/models/page_plugin.rb b/app/models/page_plugin.rb index bb3390e..dd0b048 100644 --- a/app/models/page_plugin.rb +++ b/app/models/page_plugin.rb @@ -24,6 +24,10 @@ def module end end + def module_xml + self.module.to_xml(:skip_instruct => true) + end + def module_class Object.path2class(module_type) end diff --git a/config/environment.rb b/config/environment.rb index 3e82d2d..a64a434 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -58,6 +58,7 @@ config.gem 'thoughtbot-shoulda', :lib => 'shoulda', :source => 'http://gems.github.com' config.gem 'thoughtbot-factory_girl', :lib => 'factory_girl', :source => 'http://gems.github.com' config.gem 'flexmock' + config.gem 'hpricot', :source => 'http://code.whytheluckystiff.net' config.gem 'spicycode-rcov', :lib => 'rcov', :source => 'http://gems.github.com' config.gem 'jgre-monkeyspecdoc', :lib => 'monkeyspecdoc', :source => 'http://gems.github.com' diff --git a/lib/hpricot_test_helper.rb b/lib/hpricot_test_helper.rb new file mode 100644 index 0000000..9e2b8a3 --- /dev/null +++ b/lib/hpricot_test_helper.rb @@ -0,0 +1,60 @@ +require 'hpricot' + +module HpricotTestHelper + # returns the inner content of + # the first tag found by the css query + def tag(css_query) + process_output + @output.content_for(css_query) + end + + # returns an array of tag contents + # for all of the tags found by the + # css query + def tags(css_query) + process_output + @output.content_for_all(css_query) + end + + # returns a raw Hpricot::Elem object + # for the first result found by the query + def element(css_query) + process_output + @output[css_query].first + end + + # returns an array of Hpricot::Elem objects + # for the results found by the query + def elements(css_query) + process_output + @output[css_query] + end + + # small utility class for working with + # the Hpricot parser class + class DocumentOutput + def initialize(response_body) + @parser = Hpricot.parse(response_body) + end + + def content_for(css_query) + @parser.search(css_query).first.inner_text + end + + def content_for_all(css_query) + @parser.search(css_query).collect(&:inner_text) + end + + def [](css_query) + @parser.search(css_query) + end + end + + protected + # creates a new DocumentOutput object from the response + # body if hasn't already been created. This is + # called automatically by the element and tag methods + def process_output(force=false) + @output = HpricotTestHelper::DocumentOutput.new(@response.body) if @output.nil? || force + end +end diff --git a/test/factories.rb b/test/factories.rb index ecaf6a8..c5be63d 100644 --- a/test/factories.rb +++ b/test/factories.rb @@ -1,5 +1,5 @@ Factory.sequence :page_name do |pn| - "Page #{pn}" + "home#{pn}" end Factory.sequence :user_login do |n| diff --git a/test/fixtures/content_sections.yml b/test/fixtures/content_sections.yml new file mode 100644 index 0000000..b136278 --- /dev/null +++ b/test/fixtures/content_sections.yml @@ -0,0 +1,4 @@ +home_content: + id: 1 + name: home content + contents: These are the contents diff --git a/test/fixtures/page_plugins.yml b/test/fixtures/page_plugins.yml index 0134674..f526362 100644 --- a/test/fixtures/page_plugins.yml +++ b/test/fixtures/page_plugins.yml @@ -1,25 +1,6 @@ -# == Schema Information -# Schema version: 20090125222830 -# -# Table name: page_plugins -# -# id :integer(4) not null, primary key -# page_id :integer(4) -# module_type :string(255) -# module_id :integer(4) -# created_at :datetime -# updated_at :datetime -# position :integer(4) -# - -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html - -one: +home_content: + id: 1 page_id: 1 - module_type: MyString - module_id: - -two: - page_id: 1 - module_type: MyString - module_id: + module_type: "Ansuz::JAdams::ContentSection" + module_id: 1 + position: 1 diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml new file mode 100644 index 0000000..4e33861 --- /dev/null +++ b/test/fixtures/pages.yml @@ -0,0 +1,101 @@ +# == Schema Information +# Schema version: 2 +# +# Table name: pages +# +# id :integer(11) not null, primary key +# name :string(255) +# title :string(255) +# full_title :string(255) +# body :text +# created_at :datetime +# updated_at :datetime +# page_order :integer(11) default(0) +# parent_id :integer(11) +# page_type :string(255) default("page") +# display_title :boolean(1) default(TRUE) +# published :boolean(1) default(TRUE) +# linked :boolean(1) default(TRUE) +# show_sub_menu :boolean(1) +# + +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html +home: + id: 1 + name: home + title: Home + full_title: Home Page + published: true + status: published + linked: true + +second_level: + id: 2 + name: second + title: Second Level + parent_id: 1 + published: true + status: published + linked: true + +third_level: + id: 3 + name: third + title: Third Level + parent_id: 2 + published: true + status: published + linked: true + +fourth_level: + id: 9 + name: fourth + title: Fourth Level + parent_id: 3 + published: true + status: published + linked: true + +unpublished: + id: 4 + name: unpublished + title: Unpublished + parent_id: 2 + published: false + status: draft + linked: false + +swap_test: + id: 5 + name: swap_test + title: Swap Test + parent_id: 1 + +swap_test1: + id: 6 + name: swap1 + title: Swap Test 1 + parent_id: 5 + page_order: 1 + +swap_test2: + id: 7 + name: swap2 + title: Swap Test 2 + parent_id: 5 + page_order: 3 + +swap_test3: + id: 8 + name: swap3 + title: Swap Test 3 + parent_id: 5 + page_order: 4 + +expired: + id: 245 + name: Expired + title: Expired test + parent_id: 9 + page_order: 5 + expires_on: <%= 2.days.ago %> diff --git a/test/fixtures/proto_page_plugins.yml b/test/fixtures/proto_page_plugins.yml deleted file mode 100644 index 292cd7d..0000000 --- a/test/fixtures/proto_page_plugins.yml +++ /dev/null @@ -1,21 +0,0 @@ -# == Schema Information -# Schema version: 20090125222830 -# -# Table name: proto_page_plugins -# -# id :integer(4) not null, primary key -# name :string(255) -# type :string(255) -# created_at :datetime -# updated_at :datetime -# - -# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html - -one: - name: MyString - type: MyString - -two: - name: MyString - type: MyString diff --git a/test/functional/page_controller_test.rb b/test/functional/page_controller_test.rb new file mode 100644 index 0000000..2eb262c --- /dev/null +++ b/test/functional/page_controller_test.rb @@ -0,0 +1,33 @@ +require 'test_helper' + +class PageControllerTest < ActionController::TestCase + context "When hitting /pages/" do + setup do + # set up a page to visit + @page = pages(:home) + end + context "as a public user" do + context "for html" do + setup do + get :indexer, :path => ["home"] + end + + should_respond_with :ok + should "have the content section module's content included" do + assert_select "div.page-plugin-0" + end + end + + context "for xml" do + setup do + get :indexer, :path => ["home.xml"] + end + + should_respond_with :ok + should "have the content section module's content included" do + assert tag("page page-plugins page-plugin contents") + end + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 66a6cfd..09c8470 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -4,11 +4,14 @@ require 'test/role_requirement_test_helper' require 'flexmock/test_unit' require 'exception_macros' +require 'hpricot_test_helper' class Test::Unit::TestCase # RoleRequirementTestHelper must be included to test RoleRequirement include RoleRequirementTestHelper + include HpricotTestHelper + # Transactional fixtures accelerate your tests by wrapping each test method # in a transaction that's rolled back on completion. This ensures that the # test database remains unchanged so your fixtures don't have to be reloaded