File: monthly_rule_spec.rb

package info (click to toggle)
ruby-ice-cube 0.16.4-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 800 kB
  • sloc: ruby: 7,823; makefile: 6
file content (177 lines) | stat: -rw-r--r-- 7,002 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
require File.dirname(__FILE__) + '/../spec_helper'

module IceCube
  describe MonthlyRule, 'interval validation' do
    it 'converts a string integer to an actual int when using the interval method' do
      rule = Rule.monthly.interval("2")
      expect(rule.validations_for(:interval).first.interval).to eq(2)
    end

    it 'converts a string integer to an actual int when using the initializer' do
      rule = Rule.monthly("3")
      expect(rule.validations_for(:interval).first.interval).to eq(3)
    end

    it 'converts a string integer to an actual int' do
      rule = Rule.monthly("1")
      expect(rule.instance_variable_get(:@interval)).to eq(1)
    end

    it 'raises an argument error when a bad value is passed' do
      expect {
        Rule.monthly("invalid")
      }.to raise_error(ArgumentError, "'invalid' is not a valid input for interval. Please pass a postive integer.")
    end

    it 'raises an argument error when a bad value is passed using the interval method' do
      expect {
        Rule.monthly.interval("invalid")
      }.to raise_error(ArgumentError, "'invalid' is not a valid input for interval. Please pass a postive integer.")
    end
  end

  describe MonthlyRule do

    it 'should update previous interval' do
      t0 = Time.utc(2013, 5, 17)
      rule = Rule.monthly(3)
      rule.interval(1)
      expect(rule.next_time(t0 + 1, t0, nil)).to eq(t0 + (IceCube::ONE_DAY * 31))
    end

    it 'should produce the correct number of days for @interval = 1' do
      schedule = Schedule.new(t0 = Time.now)
      schedule.add_recurrence_rule Rule.monthly
      #check assumption
      expect(schedule.occurrences(t0 + 50 * ONE_DAY).size).to eq(2)
    end

    it 'should produce the correct number of days for @interval = 2' do
      schedule = Schedule.new(t0 = Time.now)
      schedule.add_recurrence_rule Rule.monthly(2)
      expect(schedule.occurrences(t0 + 50 * ONE_DAY).size).to eq(1)
    end

    it 'should produce the correct number of days for @interval = 1 with only the 1st and 15th' do
      schedule = Schedule.new(t0 = Time.utc(2010, 1, 1))
      schedule.add_recurrence_rule Rule.monthly.day_of_month(1, 15)
      #check assumption (1) (15) (1) (15)
      expect(schedule.occurrences(t0 + 50 * ONE_DAY).map(&:day)).to eq([1, 15, 1, 15])
    end

    it 'should produce the correct number of days for @interval = 1 with only the 1st and last' do
      schedule = Schedule.new(t0 = Time.utc(2010, 1, 1))
      schedule.add_recurrence_rule Rule.monthly.day_of_month(1, -1)
      #check assumption (1) (31) (1)
      expect(schedule.occurrences(t0 + 60 * ONE_DAY).map(&:day)).to eq([1, 31, 1, 28, 1])
    end

    it 'should produce the correct number of days for @interval = 1 with only the first mondays' do
      schedule = Schedule.new(t0 = Time.utc(2010, 1, 1))
      schedule.add_recurrence_rule Rule.monthly.day_of_week(:monday => [1])
      #check assumption (month 1 monday) (month 2 monday)
      expect(schedule.occurrences(t0 + 50 * ONE_DAY).size).to eq(2)
    end

    it 'should produce the correct number of days for @interval = 1 with only the last mondays' do
      schedule = Schedule.new(t0 = Time.utc(2010, 1, 1))
      schedule.add_recurrence_rule Rule.monthly.day_of_week(:monday => [-1])
      #check assumption (month 1 monday)
      expect(schedule.occurrences(t0 + 40 * ONE_DAY).size).to eq(1)
    end

    it 'should produce the correct number of days for @interval = 1 with only the first and last mondays' do
      t0 = Time.utc(2010,  1,  1)
      t1 = Time.utc(2010, 12, 31)
      schedule = Schedule.new(t0)
      schedule.add_recurrence_rule Rule.monthly.day_of_week(:monday => [1, -2])
      #check assumption (12 months - 2 dates each)
      expect(schedule.occurrences(t1).size).to eq(24)
    end

    [:sunday, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday].each_with_index do |weekday, wday|
      context "for every first #{weekday} of a month" do
        let(:schedule) {
          Schedule.new(Time.local(2011, 8, 1)) do |s|
            s.add_recurrence_rule Rule.monthly.day_of_week(weekday => [1])
          end
        }

        it "should not skip a month when DST ends" do
          schedule.first(48).each_cons(2) do |t0, t1|
            expect(month_interval(t1, t0)).to eq(1)
          end
        end

        it "should not change day when DST ends" do
          schedule.first(48).each do |date|
            expect(date.wday).to eq(wday)
          end
        end

        it "should not change hour when DST ends" do
          schedule.first(48).each do |time|
            expect(time.hour).to eq(0)
          end
        end
      end
    end

    it 'should produce dates on a monthly interval for the last day of the month' do
      schedule = Schedule.new(Time.utc(2010, 3, 31, 0, 0, 0))
      schedule.add_recurrence_rule Rule.monthly
      expect(schedule.first(10)).to eq([
        Time.utc(2010,  3, 31, 0, 0, 0), Time.utc(2010,  4, 30, 0, 0, 0),
        Time.utc(2010,  5, 31, 0, 0, 0), Time.utc(2010,  6, 30, 0, 0, 0),
        Time.utc(2010,  7, 31, 0, 0, 0), Time.utc(2010,  8, 31, 0, 0, 0),
        Time.utc(2010,  9, 30, 0, 0, 0), Time.utc(2010, 10, 31, 0, 0, 0),
        Time.utc(2010, 11, 30, 0, 0, 0), Time.utc(2010, 12, 31, 0, 0, 0)
      ])
    end

    it 'should produce dates on a monthly interval for latter days in the month near February' do
      schedule = Schedule.new(Time.utc(2010, 1, 29, 0, 0, 0))
      schedule.add_recurrence_rule Rule.monthly
      expect(schedule.first(3)).to eq([
        Time.utc(2010, 1, 29, 0, 0, 0),
        Time.utc(2010, 2, 28, 0, 0, 0),
        Time.utc(2010, 3, 29, 0, 0, 0)
      ])
    end

    it 'should restrict to available days of month when specified' do
      schedule = Schedule.new(Time.utc(2013,1,31))
      schedule.add_recurrence_rule Rule.monthly.day_of_month(31)
      expect(schedule.first(3)).to eq([
        Time.utc(2013, 1, 31),
        Time.utc(2013, 3, 31),
        Time.utc(2013, 5, 31)
      ])
    end

    def month_interval(current_date, last_date)
      current_month = current_date.year * 12 + current_date.month
      last_month    = last_date.year * 12 + last_date.month
      current_month - last_month
    end

    describe "month_of_year validation" do
      it "allows multiples of 12" do
        expect { IceCube::Rule.monthly(24).month_of_year(3, 6) }.to_not raise_error
      end

      it "raises errors for misaligned interval and month_of_year values" do
        expect {
          IceCube::Rule.monthly(10).month_of_year(3, 6)
        }.to raise_error(ArgumentError, "month_of_year can only be used with interval(1) or multiples of interval(12)")
      end

      it "raises errors for misaligned month_of_year values when changing interval" do
        expect {
          IceCube::Rule.monthly.month_of_year(3, 6).interval(5)
        }.to raise_error(ArgumentError, "month_of_year can only be used with interval(1) or multiples of interval(12)")
      end
    end

  end
end