added extension to DateTime to easily convert it into a ReportingPeriod, fixed bugs for MySQL and PostgreSQL, added specs for all groupings - reportable - Fork of reportable required by WarVox, from hdm/reportable.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit c1e1f6626fa5fb21ddae68c25d89855d1f74f2ef
 (DIR) parent 686d110e727d3a6144e037d4791f520c434409df
 (HTM) Author: marcoow <marco.otte-witte@simplabs.com>
       Date:   Wed, 10 Dec 2008 23:05:44 +0800
       
       added extension to DateTime to easily convert it into a ReportingPeriod, fixed bugs for MySQL and PostgreSQL, added specs for all groupings
       
       Signed-off-by: Marco Otte-Witte <marco.otte-witte@simplabs.com>
       Diffstat:
         A lib/kvlr/core_extensions/date_time… |      19 +++++++++++++++++++
         M lib/kvlr/reports_as_sparkline/cumu… |      10 ++++++----
         M lib/kvlr/reports_as_sparkline/grou… |      23 +++++++++++++++++++----
         M lib/kvlr/reports_as_sparkline/repo… |       2 +-
         M lib/kvlr/reports_as_sparkline/repo… |       2 +-
         A lib/kvlr/reports_as_sparkline/repo… |      83 +++++++++++++++++++++++++++++++
         M spec/boot.rb                        |       2 +-
         M spec/db/schema.rb                   |       2 +-
         M spec/other/cumulated_report_spec.rb |      82 ++++++++++++++++++++-----------
         M spec/other/grouping_spec.rb         |      43 +++++++++++++++++++++++++++----
         M spec/other/report_cache_spec.rb     |      18 +++++++++---------
         M spec/other/report_spec.rb           |     104 ++++++++++++++++++-------------
         A spec/other/reporting_period_spec.rb |     208 +++++++++++++++++++++++++++++++
       
       13 files changed, 502 insertions(+), 96 deletions(-)
       ---
 (DIR) diff --git a/lib/kvlr/core_extensions/date_time.rb b/lib/kvlr/core_extensions/date_time.rb
       @@ -0,0 +1,19 @@
       +module Simplabs
       +
       +  module CoreExtensions
       +
       +    module DateTime
       +
       +      ::DateTime.class_eval do
       +
       +        def to_reporting_period(grouping)
       +          Kvlr::ReportsAsSparkline::ReportsAsSparkline.new(grouping, self)
       +        end
       +
       +      end
       +
       +    end
       +
       +  end
       +
       +end
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/cumulated_report.rb b/lib/kvlr/reports_as_sparkline/cumulated_report.rb
       @@ -11,11 +11,13 @@ module Kvlr #:nodoc:
              protected
        
                def cumulate(data)
       -          acc = 0
       -          data.collect do |element|
       -            acc += element[1].to_i
       -            [element[0], acc]
       +          acc = 0.0
       +          result = []
       +          data.reverse_each do |element|
       +            acc += element[1].to_f
       +            result << [element[0], acc]
                  end
       +          result.reverse
                end
        
            end
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/grouping.rb b/lib/kvlr/reports_as_sparkline/grouping.rb
       @@ -14,11 +14,26 @@ module Kvlr #:nodoc:
              end
        
              def date_parts_from_db_string(db_string)
       -        parts = db_string.split('/').map(&:to_i)
       -        if @identifier == :week
       -          parts[1] += 1
       +        if ActiveRecord::Base.connection.class.to_s == 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter'
       +          if @identifier == :hour
       +            return (db_string[0..9].split('-') + db_string[11..12]).map(&:to_i)
       +          elsif @identifier == :day
       +            return db_string[0..9].split('-').map(&:to_i)
       +          elsif @identifier == :week
       +            parts = db_string[0..9].split('-').map(&:to_i)
       +            date = Date.new(parts[0], parts[1], parts[2])
       +            return [date.year, date.cweek]
       +          elsif @identifier == :month
       +            return db_string[0..6].split('-')[0..1].map(&:to_i)
       +          end
       +        else
       +          parts = db_string.split('/').map(&:to_i)
       +          return parts if ActiveRecord::Base.connection.class.to_s == 'ActiveRecord::ConnectionAdapters::MysqlAdapter'
       +          if @identifier == :week
       +            parts[1] += 1
       +          end
       +          parts
                end
       -        parts
              end
        
              def to_sql(date_column_name)
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/report.rb b/lib/kvlr/reports_as_sparkline/report.rb
       @@ -25,7 +25,7 @@ module Kvlr #:nodoc:
                ensure_valid_options(options, :run)
                custom_conditions = options.key?(:conditions)
                options.reverse_merge!(@options)
       -        ReportCache.cached_transaction(self, options[:limit], custom_conditions) do |begin_at|
       +        ReportCache.process(self, options[:limit], custom_conditions) do |begin_at|
                  read_data(begin_at, options[:conditions])
                end
              end
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/report_cache.rb b/lib/kvlr/reports_as_sparkline/report_cache.rb
       @@ -6,7 +6,7 @@ module Kvlr #:nodoc:
        
              serialize :reporting_period, Kvlr::ReportsAsSparkline::ReportingPeriod
        
       -      def self.cached_transaction(report, limit, no_cache = false, &block)
       +      def self.process(report, limit, no_cache = false, &block)
                raise ArgumentError.new('A block must be given') unless block_given?
                self.transaction do
                  cached_data = if no_cache
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/reporting_period.rb b/lib/kvlr/reports_as_sparkline/reporting_period.rb
       @@ -0,0 +1,83 @@
       +module Kvlr #:nodoc:
       +
       +  module ReportsAsSparkline #:nodoc:
       +
       +    class ReportingPeriod
       +
       +      attr_reader :date_time, :grouping
       +
       +      def initialize(grouping, date_time = DateTime.now)
       +        @grouping  = grouping
       +        @date_time = parse_date_time(date_time)
       +      end
       +
       +      def self.first(grouping, limit)
       +        return case grouping.identifier
       +          when :hour
       +            self.new(grouping, DateTime.now - limit.hours)
       +          when :day
       +            self.new(grouping, DateTime.now - limit.days)
       +          when :week
       +            self.new(grouping, DateTime.now - limit.weeks)
       +          when :month
       +            date = DateTime.now - limit.months
       +            self.new(grouping, Date.new(date.year, date.month, 1))
       +        end
       +      end
       +
       +      def self.from_db_string(grouping, db_string)
       +        parts = grouping.date_parts_from_db_string(db_string)
       +        result = case grouping.identifier
       +          when :hour
       +            self.new(grouping, DateTime.new(parts[0], parts[1], parts[2], parts[3], 0, 0))
       +          when :day
       +            self.new(grouping, Date.new(parts[0], parts[1], parts[2]))
       +          when :week
       +            self.new(grouping, Date.commercial(parts[0], parts[1]))
       +          when :month
       +            self.new(grouping, Date.new(parts[0], parts[1], 1))
       +        end
       +        result
       +      end
       +
       +      def previous
       +        return case @grouping.identifier
       +          when :hour
       +            self.class.new(@grouping, @date_time - 1.hour)
       +          when :day
       +            self.class.new(@grouping, @date_time - 1.day)
       +          when :week
       +            self.class.new(@grouping, @date_time - 1.week)
       +          when :month
       +            self.class.new(@grouping, @date_time - 1.month)
       +        end
       +      end
       +
       +      def ==(other)
       +        if other.class == Kvlr::ReportsAsSparkline::ReportingPeriod
       +          return @date_time.to_s == other.date_time.to_s && @grouping.identifier.to_s == other.grouping.identifier.to_s
       +        end
       +        false
       +      end
       +
       +      private
       +
       +        def parse_date_time(date_time)
       +          return case @grouping.identifier
       +            when :hour
       +              DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour)
       +            when :day
       +              date_time.to_date
       +            when :week
       +              date_time = (date_time - date_time.wday.days) + 1
       +              Date.new(date_time.year, date_time.month, date_time.day)
       +            when :month
       +              Date.new(date_time.year, date_time.month, 1)
       +          end
       +        end
       +
       +    end
       +
       +  end
       +
       +end
 (DIR) diff --git a/spec/boot.rb b/spec/boot.rb
       @@ -19,5 +19,5 @@ FileUtils.mkdir_p File.join(File.dirname(__FILE__), 'log')
        ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'log', 'spec.log'))
        
        databases = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
       -ActiveRecord::Base.establish_connection(databases['sqlite3'])
       +ActiveRecord::Base.establish_connection(databases['postgresql'])
        load(File.join(File.dirname(__FILE__), 'db', 'schema.rb'))
 (DIR) diff --git a/spec/db/schema.rb b/spec/db/schema.rb
       @@ -14,7 +14,7 @@ ActiveRecord::Schema.define(:version => 1) do
            t.string   :grouping,         :null => false
            t.string   :aggregation,      :null => false
            t.float    :value,            :null => false, :default => 0
       -    t.datetime :reporting_period, :null => false
       +    t.string   :reporting_period, :null => false
        
            t.timestamps
          end
 (DIR) diff --git a/spec/other/cumulated_report_spec.rb b/spec/other/cumulated_report_spec.rb
       @@ -8,46 +8,72 @@ describe Kvlr::ReportsAsSparkline::CumulatedReport do
        
          describe '.run' do
        
       -    before(:all) do
       -      User.create!(:login => 'test 1', :created_at => Time.now - 1.week,  :profile_visits => 1)
       -      User.create!(:login => 'test 2', :created_at => Time.now - 2.weeks, :profile_visits => 2)
       -      User.create!(:login => 'test 3', :created_at => Time.now - 2.weeks, :profile_visits => 3)
       -    end
       -
            it 'should cumulate the data' do
              @report.should_receive(:cumulate).once
        
              @report.run
            end
        
       -    it 'should return correct data for :aggregation => :count' do
       -      result = @report.run.to_a
       +    for grouping in [:hour, :day, :week, :month] do
        
       -      result[7][1].should == 1
       -      result[14][1].should == 3
       -    end
       +      describe "for grouping #{grouping.to_s}" do
        
       -    it 'should return correct data for :aggregation => :sum' do
       -      @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :sum, :value_column_name => :profile_visits)
       -      result = @report.run().to_a
       +        before(:all) do
       +          User.create!(:login => 'test 1', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       +          User.create!(:login => 'test 2', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       +          User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +        end
        
       -      result[7][1].should == 1
       -      result[14][1].should == 6
       -    end
       +        it 'should return correct data for :aggregation => :count' do
       +          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :count, :grouping => grouping)
       +          result = @report.run
        
       -    it 'should return correct data with custom conditions' do
       -      result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +          result[0][1].should == 3
       +          result[1][1].should == 3
       +          result[2][1].should == 2
       +          result[3][1].should == 2
       +        end
        
       -      result[7][1].should == 1
       -      result[14][1].should == 2
       -    end
       +        it 'should return correct data for :aggregation => :sum' do
       +          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column_name => :profile_visits)
       +          result = @report.run().to_a
        
       -    after(:all) do
       -      User.destroy_all
       -    end
       +          result[0][1].should == 6
       +          result[1][1].should == 6
       +          result[2][1].should == 5
       +          result[3][1].should == 5
       +        end
       +
       +        it 'should return correct data with custom conditions for :aggregation => :count' do
       +          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :count, :grouping => grouping)
       +          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +
       +          result[0][1].should == 2
       +          result[1][1].should == 2
       +          result[2][1].should == 1
       +          result[3][1].should == 1
       +        end
       +
       +        it 'should return correct data with custom conditions for :aggregation => :sum' do
       +          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column_name => :profile_visits)
       +          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +
       +          result[0][1].should == 3
       +          result[1][1].should == 3
       +          result[2][1].should == 2
       +          result[3][1].should == 2
       +        end
       +
       +        after(:all) do
       +          User.destroy_all
       +        end
       +
       +        after(:each) do
       +          Kvlr::ReportsAsSparkline::ReportCache.destroy_all
       +        end
       +
       +      end
        
       -    after do
       -      Kvlr::ReportsAsSparkline::ReportCache.destroy_all
            end
        
          end
       @@ -59,7 +85,7 @@ describe Kvlr::ReportsAsSparkline::CumulatedReport do
              second = (Time.now - 1.week).to_s
              data = [[first, 1], [second, 2]]
        
       -      @report.send(:cumulate, data).should == [[first, 1], [second, 3]]
       +      @report.send(:cumulate, data).should == [[first, 3.0], [second, 2.0]]
            end
        
          end
 (DIR) diff --git a/spec/other/grouping_spec.rb b/spec/other/grouping_spec.rb
       @@ -87,7 +87,7 @@ describe Kvlr::ReportsAsSparkline::Grouping do
          end
        
          describe '#date_parts_from_db_string' do
       -
       +=begin
            for grouping in [[:hour, '2008/12/31/12'], [:day, '2008/12/31'], [:month, '2008/12']] do
        
              it "should split the string with '/' for grouping :#{grouping[0].to_s}" do
       @@ -97,12 +97,45 @@ describe Kvlr::ReportsAsSparkline::Grouping do
              end
        
            end
       +=end
       +    describe 'for SQLite3' do
       +
       +      it 'should split the string with "/" and increment the week by 1 for grouping :week' do
       +        ActiveRecord::Base.connection.stub!(:class).and_return(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
       +        db_string = '2008/2'
       +        expected = [2008, 3]
        
       -    it 'should split the string with "/" and increment the week by 1 for grouping :week' do
       -      db_string = '2008/2'
       -      expected = [2008, 3]
       +        Kvlr::ReportsAsSparkline::Grouping.new(:week).date_parts_from_db_string(db_string).should == expected
       +      end
       +
       +    end
       +
       +    describe 'for PostgreSQL' do
       +
       +      before do
       +        ActiveRecord::Base.connection.stub!(:class).and_return(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
       +      end
       +
       +      it 'should split the date part of the string with "-" for grouping :day' do
       +        Kvlr::ReportsAsSparkline::Grouping.new(:day).date_parts_from_db_string('2008-12-03 00:00:00').should == [2008, 12, 03]
       +      end
       +
       +      it 'should split the date part of the string with "-" for grouping :week' do
       +        Kvlr::ReportsAsSparkline::Grouping.new(:week).date_parts_from_db_string('2008-12-01 00:00:00').should == [2008, 49]
       +      end
       +
       +    end
       +
       +    describe 'for MySQL' do
       +
       +      it 'should split the string with "/" for grouping :week' do
       +        ActiveRecord::Base.connection.stub!(:class).and_return(ActiveRecord::ConnectionAdapters::MysqlAdapter)
       +        db_string = '2008/2'
       +        expected = [2008, 2]
       +
       +        Kvlr::ReportsAsSparkline::Grouping.new(:week).date_parts_from_db_string(db_string).should == expected
       +      end
        
       -      Kvlr::ReportsAsSparkline::Grouping.new(:week).date_parts_from_db_string(db_string).should == expected
            end
        
          end
 (DIR) diff --git a/spec/other/report_cache_spec.rb b/spec/other/report_cache_spec.rb
       @@ -2,7 +2,7 @@ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
        
        describe Kvlr::ReportsAsSparkline::ReportCache do
        
       -  describe '#cached_transaction' do
       +  describe '#process' do
        
            before do
              @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations)
       @@ -12,19 +12,19 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
        
            it 'should raise an ArgumentError if no block is given' do
              lambda do
       -        Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100)
       +        Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100)
              end.should raise_error(ArgumentError)
            end
        
            it 'sould start a transaction' do
              Kvlr::ReportsAsSparkline::ReportCache.should_receive(:transaction)
        
       -      Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) {}
       +      Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) {}
            end
        
            it 'should yield to the given block' do
              lambda {
       -        Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) { raise YieldMatchException.new }
       +        Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) { raise YieldMatchException.new }
              }.should raise_error(YieldMatchException)
            end
        
       @@ -41,17 +41,17 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
                :order => "reporting_period DESC"
              )
        
       -      Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) { [] }
       +      Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) { [] }
            end
        
            it 'should update the cache' do
              Kvlr::ReportsAsSparkline::ReportCache.should_receive(:update_cache)
        
       -      Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) { [] }
       +      Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) { [] }
            end
        
            it 'should yield the first reporting period if the cache is empty' do
       -      Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) do |begin_at|
       +      Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) do |begin_at|
                begin_at.should == Kvlr::ReportsAsSparkline::ReportingPeriod.first(@report.grouping, 100).date_time
                []
              end
       @@ -69,7 +69,7 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              })
              Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
        
       -      Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100) do |begin_at|
       +      Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100) do |begin_at|
                begin_at.should == reporting_period.date_time
                []
              end
       @@ -80,7 +80,7 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              it 'should not read any data from cache' do
                Kvlr::ReportsAsSparkline::ReportCache.should_not_receive(:find)
        
       -        Kvlr::ReportsAsSparkline::ReportCache.cached_transaction(@report, 100, true) {}
       +        Kvlr::ReportsAsSparkline::ReportCache.process(@report, 100, true) {}
              end
        
            end
 (DIR) diff --git a/spec/other/report_spec.rb b/spec/other/report_spec.rb
       @@ -8,69 +8,82 @@ describe Kvlr::ReportsAsSparkline::Report do
        
          describe '.run' do
        
       -    it 'should run a cached transaction' do
       -      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:cached_transaction).once.with(@report, 100, false)
       +    it 'should process the data with the report cache' do
       +      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:process).once.with(@report, 100, false)
        
              @report.run
            end
        
       -    it 'should run a cached transaction but specify no_cache when custom conditions are given' do
       -      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:cached_transaction).once.with(@report, 100, true)
       +    it 'should process the data with the report cache and specify no_cache when custom conditions are given' do
       +      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:process).once.with(@report, 100, true)
        
              @report.run(:conditions => { :some => :condition })
            end
        
       -    describe do
       +    it 'should validate the specified options for the :run context' do
       +      @report.should_receive(:ensure_valid_options).once.with({ :limit => 3 }, :run)
        
       -      before(:all) do
       -        User.create!(:login => 'test 1', :created_at => Time.now - 1.week,  :profile_visits => 1)
       -        User.create!(:login => 'test 2', :created_at => Time.now - 2.weeks, :profile_visits => 2)
       -        User.create!(:login => 'test 3', :created_at => Time.now - 2.weeks, :profile_visits => 3)
       -      end
       +      result = @report.run(:limit => 3)
       +    end
        
       -      it 'should validate the specified options for the :run context' do
       -        @report.should_receive(:ensure_valid_options).once.with({ :limit => 3 }, :run)
       +    for grouping in [:hour, :day, :week, :month] do
        
       -        result = @report.run(:limit => 3)
       -      end
       +      describe "for grouping #{grouping.to_s}" do
        
       -      it 'should return correct data for :aggregation => :count and grouping :day' do
       -        @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => :day)
       -        result = @report.run.to_a
       +        before(:all) do
       +          User.create!(:login => 'test 1', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       +          User.create!(:login => 'test 2', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       +          User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +        end
        
       -        result[7][1].should == 1
       -        result[14][1].should == 2
       -      end
       +        it 'should return correct data for :aggregation => :count' do
       +          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => grouping)
       +          result = @report.run.to_a
        
       -      it 'should return correct data for :aggregation => :count and grouping :week' do
       -        @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => :week)
       -        result = @report.run.to_a
       +          result[0][1].should == 0
       +          result[1][1].should == 1
       +          result[2][1].should == 0
       +          result[3][1].should == 2
       +        end
        
       -        result[1][1].should == 1
       -        result[2][1].should == 2
       -      end
       +        it 'should return correct data for :aggregation => :sum' do
       +          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column_name => :profile_visits)
       +          result = @report.run().to_a
        
       -      it 'should return correct data for :aggregation => :sum' do
       -        @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :sum, :value_column_name => :profile_visits)
       -        result = @report.run().to_a
       +          result[0][1].should == 0
       +          result[1][1].should == 1
       +          result[2][1].should == 0
       +          result[3][1].should == 5
       +        end
        
       -        result[7][1].should == 1
       -        result[14][1].should == 5
       -      end
       +        it 'should return correct data with custom conditions for :aggregation => :count' do
       +          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => grouping)
       +          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
        
       -      it 'should return correct data with custom conditions' do
       -        result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +          result[0][1].should == 0
       +          result[1][1].should == 1
       +          result[2][1].should == 0
       +          result[3][1].should == 1
       +        end
        
       -        result[7][1].should == 1
       -        result[14][1].should == 1
       -      end
       +        it 'should return correct data with custom conditions for :aggregation => :sum' do
       +          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column_name => :profile_visits)
       +          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
        
       -      after(:all) do
       -        User.destroy_all
       -      end
       +          result[0][1].should == 0
       +          result[1][1].should == 1
       +          result[2][1].should == 0
       +          result[3][1].should == 2
       +        end
       +
       +        after(:all) do
       +          User.destroy_all
       +        end
       +
       +        after(:each) do
       +          Kvlr::ReportsAsSparkline::ReportCache.destroy_all
       +        end
        
       -      after do
       -        Kvlr::ReportsAsSparkline::ReportCache.destroy_all
              end
        
            end
       @@ -80,11 +93,18 @@ describe Kvlr::ReportsAsSparkline::Report do
          describe '.read_data' do
        
            it 'should invoke the aggregation method on the model' do
       +      @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count)
              User.should_receive(:count).once.and_return([])
        
              @report.send(:read_data, Time.now)
            end
        
       +    it 'should build the conditions' do
       +      @report.should_receive(:setup_conditions).once.and_return([])
       +
       +      @report.send(:read_data, Time.now)
       +    end
       +
          end
        
          describe '.setup_conditions' do
 (DIR) diff --git a/spec/other/reporting_period_spec.rb b/spec/other/reporting_period_spec.rb
       @@ -0,0 +1,208 @@
       +require File.join(File.dirname(__FILE__), '..', 'spec_helper')
       +
       +describe Kvlr::ReportsAsSparkline::ReportingPeriod do
       +
       +  describe '.date_time' do
       +
       +    describe 'for grouping :hour' do
       +
       +      it 'should return the date and time with minutes = seconds = 0 for grouping :hour' do
       +        date_time = DateTime.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:hour), date_time)
       +
       +        reporting_period.date_time.should == DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour, 0, 0)
       +      end
       +
       +    end
       +
       +    describe 'for grouping :day' do
       +
       +      it 'should return the date part only for grouping :day' do
       +        date_time = DateTime.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:day), date_time)
       +
       +        reporting_period.date_time.should == date_time.to_date
       +      end
       +
       +    end
       +
       +    describe 'for grouping :week' do
       +
       +      it 'should return the date of the monday of the week date_time is in for any day in that the week' do
       +        date_time = DateTime.new(2008, 11, 27)
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.date_time.should == DateTime.new(date_time.year, date_time.month, 24)
       +      end
       +
       +      it 'should return the date of the monday of the week date_time is in when the specified date is a monday already' do
       +        date_time = DateTime.new(2008, 11, 24) #this is a monday already, should not change
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.date_time.should == DateTime.new(date_time.year, date_time.month, 24) # expect to get monday 24th again
       +      end
       +
       +      it 'should return the date of the monday of the week date_time is in when the monday is in a different month than the specified date' do
       +        date_time = DateTime.new(2008, 11, 1) #this is a saturday
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.date_time.should == DateTime.new(date_time.year, 10, 27) # expect to get the monday before the 1st, which is in october
       +      end
       +
       +      it 'should return the date of the monday of the week date_time is in when the monday is in a different year than the specified date' do
       +        date_time = DateTime.new(2009, 1, 1) #this is a thursday
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.date_time.should == DateTime.new(2008, 12, 29) # expect to get the monday before the 1st, which is in december 2008
       +      end
       +
       +    end
       +
       +    describe 'for grouping :month' do
       +
       +      it 'should return the date with day = 1 for grouping :month' do
       +        date_time = Time.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:month), date_time)
       +
       +        reporting_period.date_time.should == Date.new(date_time.year, date_time.month, 1)
       +      end
       +
       +    end
       +
       +  end
       +
       +  describe '#from_db_string' do
       +
       +    it 'should return a reporting period with the correct date and time and with minutes = seconds = 0 for grouping :hour' do
       +      grouping = Kvlr::ReportsAsSparkline::Grouping.new(:hour)
       +      grouping.stub!(:date_parts_from_db_string).and_return([2008, 1, 1, 12])
       +
       +      Kvlr::ReportsAsSparkline::ReportingPeriod.from_db_string(grouping, '').date_time.should == DateTime.new(2008, 1, 1, 12, 0, 0)
       +    end
       +
       +    it 'should return a reporting period with the date part only for grouping :day' do
       +      grouping = Kvlr::ReportsAsSparkline::Grouping.new(:day)
       +      grouping.stub!(:date_parts_from_db_string).and_return([2008, 1, 1])
       +
       +      Kvlr::ReportsAsSparkline::ReportingPeriod.from_db_string(grouping, '').date_time.should == Date.new(2008, 1, 1)
       +    end
       +
       +    it 'should return a reporting period with the date part of the monday of the week the date is in for grouping :week' do
       +      grouping = Kvlr::ReportsAsSparkline::Grouping.new(:week)
       +      grouping.stub!(:date_parts_from_db_string).and_return([2008, 1])
       +
       +      Kvlr::ReportsAsSparkline::ReportingPeriod.from_db_string(grouping, '').date_time.should == Date.new(2007, 12, 31)
       +    end
       +
       +    it 'should return a reporting period with the correct date and with day = 1 for grouping :month' do
       +      grouping = Kvlr::ReportsAsSparkline::Grouping.new(:month)
       +      grouping.stub!(:date_parts_from_db_string).and_return([2008, 1])
       +
       +      Kvlr::ReportsAsSparkline::ReportingPeriod.from_db_string(grouping, '').date_time.should == Date.new(2008, 1, 1)
       +    end
       +
       +  end
       +
       +  describe '.previous' do
       +
       +    describe 'for grouping :hour' do
       +
       +      it 'should return a reporting period with date and time one hour before the current period' do
       +        now = Time.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:hour), now)
       +        expected = now - 1.hour
       +
       +        reporting_period.previous.date_time.should == DateTime.new(expected.year, expected.month, expected.day, expected.hour)
       +      end
       +
       +    end
       +
       +    describe 'for grouping :day' do
       +
       +      it 'should return a reporting period with date one day before the current period' do
       +        now = Time.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:day), now)
       +        expected = now - 1.day
       +
       +        reporting_period.previous.date_time.should == Date.new(expected.year, expected.month, expected.day)
       +      end
       +
       +    end
       +
       +    describe 'for grouping :week' do
       +
       +      it 'should return a reporting period with date one week before the current period' do
       +        now = DateTime.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:week), now)
       +        expected = reporting_period.date_time - 1.week
       +
       +        reporting_period.previous.date_time.should == Date.new(expected.year, expected.month, expected.day)
       +      end
       +
       +    end
       +
       +    describe 'for grouping :month' do
       +
       +      it 'should return a reporting period with date one month before the current period' do
       +        now = Time.now
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:month), now)
       +        expected = reporting_period.date_time - 1.month
       +
       +        reporting_period.previous.date_time.should == Date.new(expected.year, expected.month, 1)
       +      end
       +
       +    end
       +
       +  end
       +
       +  describe '.==' do
       +
       +    it 'should return true for 2 reporting periods with the same date_time and grouping' do
       +      now = DateTime.now
       +      reporting_period1 = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:month), now)
       +      reporting_period2 = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:month), now)
       +
       +      (reporting_period1 == reporting_period2).should == true
       +    end
       +
       +    it 'should return false for 2 reporting periods with the same date_time but different groupings' do
       +      now = Time.now
       +      reporting_period1 = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:month), now)
       +      reporting_period2 = Kvlr::ReportsAsSparkline::ReportingPeriod.new(Kvlr::ReportsAsSparkline::Grouping.new(:day), now)
       +
       +      (reporting_period1 == reporting_period2).should == false
       +    end
       +
       +  end
       +
       +  describe '#first' do
       +
       +    before do
       +      @now = DateTime.now
       +      DateTime.stub!(:now).and_return(@now)
       +    end
       +
       +    it 'should return a reporting period with the date part of (DateTime.now - limit.hours) for grouping :hour' do
       +      reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:hour), 3)
       +      expected = @now - 3.hours
       +
       +      reporting_period.date_time.should == DateTime.new(expected.year, expected.month, expected.day, expected.hour, 0, 0)
       +    end
       +
       +    it 'should return a reporting period with the date part of (DateTime.now - limit.days) for grouping :day' do
       +      reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:day), 3)
       +      expected = @now - 3.days
       +
       +      reporting_period.date_time.should == Date.new(expected.year, expected.month, expected.day)
       +    end
       +
       +    it 'should return a reporting period with the date of monday of the week at (DateTime.now - limit.weeks) for grouping :week' do
       +      DateTime.stub!(:now).and_return(DateTime.new(2008, 12, 31, 0, 0, 0)) #wednesday
       +      reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:week), 3)
       +
       +      reporting_period.date_time.should == DateTime.new(2008, 12, 8) #the monday 3 weeks earlier
       +    end
       +
       +  end
       +
       +end