require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")

describe "A paginated dataset" do
  before do
    @d = Sequel.mock.dataset.extension(:pagination)
    @d.meta_def(:count) {153}
    
    @paginated = @d.paginate(1, 20)
  end
  
  specify "should raise an error if the dataset already has a limit" do
    proc{@d.limit(10).paginate(1,10)}.should raise_error(Sequel::Error)
    proc{@paginated.paginate(2,20)}.should raise_error(Sequel::Error)
    proc{@d.limit(10).each_page(10){|ds|}}.should raise_error(Sequel::Error)
    proc{@d.limit(10).each_page(10)}.should raise_error(Sequel::Error)
  end
  
  specify "should set the limit and offset options correctly" do
    @paginated.opts[:limit].should == 20
    @paginated.opts[:offset].should == 0
  end
  
  specify "should set the page count correctly" do
    @paginated.page_count.should == 8
    @d.paginate(1, 50).page_count.should == 4

    @d.meta_def(:count) {0}
    @d.paginate(1, 50).page_count.should == 1
  end
  
  specify "should set the current page number correctly" do
    @paginated.current_page.should == 1
    @d.paginate(3, 50).current_page.should == 3
  end
  
  specify "should return the next page number or nil if we're on the last" do
    @paginated.next_page.should == 2
    @d.paginate(4, 50).next_page.should be_nil
  end
  
  specify "should return the previous page number or nil if we're on the first" do
    @paginated.prev_page.should be_nil
    @d.paginate(4, 50).prev_page.should == 3
  end
  
  specify "should return the page range" do
    @paginated.page_range.should == (1..8)
    @d.paginate(4, 50).page_range.should == (1..4)
  end
  
  specify "should return the record range for the current page" do
    @paginated.current_page_record_range.should == (1..20)
    @d.paginate(4, 50).current_page_record_range.should == (151..153)
    @d.paginate(5, 50).current_page_record_range.should == (0..0)
  end

  specify "should return the record count for the current page" do
    @paginated.current_page_record_count.should == 20
    @d.paginate(3, 50).current_page_record_count.should == 50
    @d.paginate(4, 50).current_page_record_count.should == 3
    @d.paginate(5, 50).current_page_record_count.should == 0
  end

  specify "should know if current page is last page" do
    @paginated.last_page?.should == false
    @d.paginate(2, 20).last_page?.should == false
    @d.paginate(5, 30).last_page?.should == false
    @d.paginate(6, 30).last_page?.should == true

    @d.meta_def(:count) {0}
    @d.paginate(1, 30).last_page?.should == true
    @d.paginate(2, 30).last_page?.should == false
  end

  specify "should know if current page is first page" do
    @paginated.first_page?.should == true
    @d.paginate(1, 20).first_page?.should == true
    @d.paginate(2, 20).first_page?.should == false
  end

  specify "should work with fixed sql" do
    ds = @d.clone(:sql => 'select * from blah')
    ds.meta_def(:count) {150}
    ds.paginate(2, 50).sql.should == 'SELECT * FROM (select * from blah) AS t1 LIMIT 50 OFFSET 50'
  end
end

describe "Dataset#each_page" do
  before do
    @d = Sequel.mock.dataset.from(:items).extension(:pagination)
    @d.meta_def(:count) {153}
  end
  
  specify "should raise an error if the dataset already has a limit" do
    proc{@d.limit(10).each_page(10){}}.should raise_error(Sequel::Error)
  end
  
  specify "should iterate over each page in the resultset as a paginated dataset" do
    a = []
    @d.each_page(50) {|p| a << p}
    a.map {|p| p.sql}.should == [
      'SELECT * FROM items LIMIT 50 OFFSET 0',
      'SELECT * FROM items LIMIT 50 OFFSET 50',
      'SELECT * FROM items LIMIT 50 OFFSET 100',
      'SELECT * FROM items LIMIT 50 OFFSET 150',
    ]
  end

  specify "should return an enumerator if no block is given" do
    enum = @d.each_page(50)
    enum.map {|p| p.sql}.should == [
      'SELECT * FROM items LIMIT 50 OFFSET 0',
      'SELECT * FROM items LIMIT 50 OFFSET 50',
      'SELECT * FROM items LIMIT 50 OFFSET 100',
      'SELECT * FROM items LIMIT 50 OFFSET 150',
    ]
  end
end
