require 'router/spec_helper'

describe "RestfulRouter" do  
  before :all do
    class ::BlogControllerSpec
      def show; end
    end    
  end
  
  after :all do
    remove_constants %w(BlogControllerSpec)
  end
      
  before :each do
    @router = Rad::RestfulRouter.new
  end
  
  describe 'core API' do      
    it "singleton resource" do
      @router.add :blogs, class: BlogControllerSpec
    
      @router.encode(BlogControllerSpec, :show, {}).should == ["/blogs/show", {}]
      @router.encode_method('show_blog_path').should == [BlogControllerSpec, :show]
      @router.encode_method('show_blogs_path').should == [BlogControllerSpec, :show]
      @router.decode("/blogs/show", {}).should == [BlogControllerSpec, :show, {}]
    end
    
    it "object resource" do
      @router.add :blogs, class: BlogControllerSpec
      
      @router.encode(BlogControllerSpec, :show, id: '10', view: 'full').should == ["/blogs/10/show", {view: 'full'}]
      @router.encode_method('show_blog_path').should == [BlogControllerSpec, :show]
      @router.encode_method('show_blogs_path').should == [BlogControllerSpec, :show]
      @router.decode("/blogs/10/show", {view: 'full'}).should == [BlogControllerSpec, :show, {id: '10', view: 'full'}]
    end    
  end
  
  describe "prefixes" do
    it "singleton resource" do
      @router.add :blogs, class: BlogControllerSpec, prefix: [:l, :space]
      
      @router.encode(BlogControllerSpec, :show, l: 'en', space: 'personal').should == ["/l/en/space/personal/blogs/show", {}]
      @router.decode("/l/en/space/personal/blogs/show", {}).should == [BlogControllerSpec, :show, {l: 'en', space: 'personal'}]
    end
    
    it "object resource" do
      @router.add :blogs, class: BlogControllerSpec, prefix: [:l, :space]
      
      @router.encode(BlogControllerSpec, :show, id: '10', l: 'en', space: 'personal').should == ["/l/en/space/personal/blogs/10/show", {}]
      @router.decode("/l/en/space/personal/blogs/10/show", {}).should == [BlogControllerSpec, :show, {id: '10', l: 'en', space: 'personal'}]
    end
        
    it "should raise error or return nil if prefixes not provided" do      
      @router.add :blogs, class: BlogControllerSpec, prefix: [:l]
      
      lambda{@router.encode(BlogControllerSpec, :show, {})}.should raise_error(/prefix/)      
      @router.decode('/blogs/show', {}).should be_nil
      
      lambda{@router.encode(BlogControllerSpec, :show, id: '10')}.should raise_error(/prefix/)      
      @router.decode('/blogs/10/show', {}).should be_nil
    end
    
    it "should works with :url_root" do
      @router.add :blogs, class: BlogControllerSpec, prefix: [:l], url_root: '/users'
            
      @router.encode(BlogControllerSpec, :show, l: 'en').should == ["/users/l/en/blogs/show", {}]
      @router.decode("/users/l/en/blogs/show", {}).should == [BlogControllerSpec, :show, {l: 'en'}]
      
      @router.encode(BlogControllerSpec, :show, id: '10', l: 'en').should == ["/users/l/en/blogs/10/show", {}]
      @router.decode("/users/l/en/blogs/10/show", {}).should == [BlogControllerSpec, :show, {id: '10', l: 'en'}]
    end
    
    it "should be able to use alias for prefix parameter" do
      @router.add :blogs, class: BlogControllerSpec, prefix: [:l, [:space_id, 'space']]
      
      @router.encode(BlogControllerSpec, :show, l: 'en', space_id: 'personal').should == ["/l/en/space/personal/blogs/show", {}]
      @router.decode("/l/en/space/personal/blogs/show", {}).should == [BlogControllerSpec, :show, {l: 'en', space_id: 'personal'}]
    end
  end
  
  describe "micelaneous check" do    
    it "should allow only plural form in resource definition" do      
      lambda{@router.add :blog, class: BlogControllerSpec}.should raise_error(/plural/)
      @router.add :blogs, class: BlogControllerSpec
    end
    
    it "shouldn't allow slashes in resource name" do
      lambda{@router.add '/admin/blogs', class: BlogControllerSpec}.should raise_error(/\//)
    end
    
    it "should correctly works with unknown routes" do
      @router.encode(BlogControllerSpec, :show, {}).should be_nil
      @router.encode_method('show_blog_path').should be_nil
      @router.encode_method('show_blogs_path').should be_nil
      @router.decode("/blogs/show", {}).should be_nil
            
      @router.encode(BlogControllerSpec, :show, id: '10', view: 'full').should be_nil
      @router.encode_method('show_blog_path').should be_nil
      @router.encode_method('show_blogs_path').should be_nil
      @router.decode("/blogs/10/show", view: 'full').should be_nil
    end
  end
  
  it "should use :url_root" do
    @router.add :blogs, class: BlogControllerSpec, url_root: '/users'
    
    @router.encode(BlogControllerSpec, :show, {}).should == ["/users/blogs/show", {}]
    @router.decode("/users/blogs/show", {}).should == [BlogControllerSpec, :show, {}]
        
    @router.encode(BlogControllerSpec, :show, id: '10').should == ["/users/blogs/10/show", {}]
    @router.decode("/users/blogs/10/show", {}).should == [BlogControllerSpec, :show, {id: '10'}]
  end  
  
  it "input validation" do
    lambda{@router.add :blogs, class: BlogControllerSpec, invalid: 'value'}.should raise_error(/unknown/)
    lambda{@router.add :blogs}.should raise_error(/class/)    
    lambda{@router.add :blogs, class: BlogControllerSpec, url_root: 'users'}.should raise_error(/\//)
    lambda{@router.add :blogs, class: BlogControllerSpec, prefix: []}.should raise_error(/empty/)
  end
end