holidays 4.6.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/CONTRIBUTING.md +5 -5
  4. data/Makefile +29 -0
  5. data/README.md +13 -1
  6. data/Rakefile +2 -2
  7. data/definitions/au.yaml +12 -9
  8. data/definitions/ca.yaml +17 -2
  9. data/definitions/ch.yaml +1 -1
  10. data/definitions/index.yaml +3 -0
  11. data/definitions/is.yaml +1 -1
  12. data/definitions/jp.yaml +19 -14
  13. data/definitions/kr.yaml +282 -0
  14. data/definitions/lu.yaml +56 -0
  15. data/definitions/my.yaml +51 -0
  16. data/definitions/ups.yaml +1 -1
  17. data/definitions/us.yaml +1 -1
  18. data/lib/generated_definitions/MANIFEST +3 -0
  19. data/lib/generated_definitions/REGIONS.rb +1 -1
  20. data/lib/generated_definitions/au.rb +11 -8
  21. data/lib/generated_definitions/ca.rb +1 -1
  22. data/lib/generated_definitions/ch.rb +1 -1
  23. data/lib/generated_definitions/europe.rb +2 -2
  24. data/lib/generated_definitions/is.rb +1 -1
  25. data/lib/generated_definitions/jp.rb +13 -15
  26. data/lib/generated_definitions/kr.rb +248 -0
  27. data/lib/generated_definitions/lu.rb +39 -0
  28. data/lib/generated_definitions/my.rb +36 -0
  29. data/lib/generated_definitions/north_america.rb +2 -2
  30. data/lib/generated_definitions/scandinavia.rb +1 -1
  31. data/lib/generated_definitions/ups.rb +1 -1
  32. data/lib/generated_definitions/us.rb +1 -1
  33. data/lib/holidays.rb +29 -51
  34. data/lib/holidays/core_extensions/date.rb +1 -1
  35. data/lib/holidays/definition/context/function_processor.rb +86 -0
  36. data/lib/holidays/definition/context/generator.rb +31 -6
  37. data/lib/holidays/definition/parser/custom_method.rb +1 -3
  38. data/lib/holidays/definition/repository/holidays_by_month.rb +1 -1
  39. data/lib/holidays/definition/validator/region.rb +1 -3
  40. data/lib/holidays/errors.rb +1 -0
  41. data/lib/holidays/factory/date_calculator.rb +37 -0
  42. data/lib/holidays/factory/definition.rb +96 -0
  43. data/lib/holidays/factory/finder.rb +70 -0
  44. data/lib/holidays/finder/context/between.rb +43 -0
  45. data/lib/holidays/{use_case → finder}/context/dates_driver_builder.rb +6 -4
  46. data/lib/holidays/finder/context/next_holiday.rb +57 -0
  47. data/lib/holidays/{option → finder}/context/parse_options.rb +6 -8
  48. data/lib/holidays/finder/context/search.rb +86 -0
  49. data/lib/holidays/finder/context/year_holiday.rb +57 -0
  50. data/lib/holidays/finder/rules/in_region.rb +23 -0
  51. data/lib/holidays/finder/rules/year_range.rb +82 -0
  52. data/lib/holidays/load_all_definitions.rb +7 -5
  53. data/lib/holidays/version.rb +1 -1
  54. data/test/coverage_report.rb +7 -0
  55. data/test/defs/test_defs_au.rb +1 -1
  56. data/test/defs/test_defs_ca.rb +16 -1
  57. data/test/defs/test_defs_jp.rb +4 -0
  58. data/test/defs/test_defs_kr.rb +26 -0
  59. data/test/defs/test_defs_lu.rb +24 -0
  60. data/test/defs/test_defs_my.rb +20 -0
  61. data/test/defs/test_defs_north_america.rb +16 -1
  62. data/test/holidays/core_extensions/test_date_time.rb +7 -7
  63. data/test/holidays/definition/context/test_function_processor.rb +175 -0
  64. data/test/holidays/definition/context/test_generator.rb +18 -11
  65. data/test/holidays/definition/parser/test_custom_method.rb +2 -2
  66. data/test/holidays/definition/repository/test_proc_result_cache.rb +1 -1
  67. data/test/holidays/{test_date_calculator_factory.rb → factory/test_date_calculator.rb} +3 -3
  68. data/test/holidays/factory/test_definition.rb +53 -0
  69. data/test/holidays/factory/test_finder.rb +25 -0
  70. data/test/holidays/finder/context/test_between.rb +172 -0
  71. data/test/holidays/{use_case → finder}/context/test_dates_driver_builder.rb +2 -2
  72. data/test/holidays/finder/context/test_next_holiday.rb +156 -0
  73. data/test/holidays/{option → finder}/context/test_parse_options.rb +9 -9
  74. data/test/holidays/finder/context/test_search.rb +203 -0
  75. data/test/holidays/finder/context/test_year_holiday.rb +202 -0
  76. data/test/holidays/finder/rules/test_in_region.rb +38 -0
  77. data/test/holidays/finder/rules/test_year_range.rb +170 -0
  78. data/test/integration/README.md +9 -0
  79. data/test/{test_all_regions.rb → integration/test_all_regions.rb} +16 -2
  80. data/test/{test_custom_holidays.rb → integration/test_custom_holidays.rb} +2 -2
  81. data/test/{test_custom_year_range_holidays.rb → integration/test_custom_year_range_holidays.rb} +1 -1
  82. data/test/{test_holidays.rb → integration/test_holidays.rb} +43 -32
  83. data/test/{test_holidays_between.rb → integration/test_holidays_between.rb} +8 -16
  84. data/test/{test_multiple_regions.rb → integration/test_multiple_regions.rb} +1 -1
  85. data/test/test_helper.rb +3 -4
  86. metadata +67 -39
  87. data/benchmark.rb +0 -8
  88. data/lib/holidays/date_calculator_factory.rb +0 -35
  89. data/lib/holidays/definition_factory.rb +0 -86
  90. data/lib/holidays/option_factory.rb +0 -15
  91. data/lib/holidays/use_case/context/between.rb +0 -45
  92. data/lib/holidays/use_case/context/context_common.rb +0 -123
  93. data/lib/holidays/use_case/context/next_holiday.rb +0 -54
  94. data/lib/holidays/use_case/context/year_holiday.rb +0 -51
  95. data/lib/holidays/use_case_factory.rb +0 -41
  96. data/test/holidays/test_definition_factory.rb +0 -49
  97. data/test/holidays/test_option_factory.rb +0 -9
  98. data/test/holidays/test_use_case_factory.rb +0 -13
  99. data/test/holidays/use_case/context/test_between.rb +0 -77
@@ -1,6 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
2
 
3
- require 'holidays/option/context/parse_options'
3
+ require 'holidays/finder/context/parse_options'
4
4
 
5
5
  #TODO This set of tests need love. Since the class itself requires actual
6
6
  # definition files we have real defs in here, meaning that these tests
@@ -17,9 +17,9 @@ class ParseOptionsTests < Test::Unit::TestCase
17
17
 
18
18
  # As mentioned above, this set of tests is NOT isolated. We need
19
19
  # the real merger code here.
20
- @definition_merger = Holidays::DefinitionFactory.merger
20
+ @definition_merger = Holidays::Factory::Definition.merger
21
21
 
22
- @subject = Holidays::Option::Context::ParseOptions.new(
22
+ @subject = Holidays::Finder::Context::ParseOptions.new(
23
23
  @regions_repo,
24
24
  @region_validator,
25
25
  @definition_merger,
@@ -28,30 +28,30 @@ class ParseOptionsTests < Test::Unit::TestCase
28
28
 
29
29
  def test_returns_observed_true_if_options_contains_observed_flag
30
30
  @regions_repo.expects(:exists?).returns(false)
31
- regions, observed, informal = @subject.call([:ca, :observed])
31
+ observed = @subject.call([:ca, :observed])[1]
32
32
  assert_equal(true, observed)
33
33
  end
34
34
 
35
35
  def test_returns_observed_false_if_options_contains_observed_flag
36
36
  @regions_repo.expects(:exists?).returns(false)
37
- regions, observed, informal = @subject.call([:ca])
37
+ observed = @subject.call([:ca])[1]
38
38
  assert_equal(false, observed)
39
39
  end
40
40
 
41
41
  def test_returns_informal_true_if_options_contains_informal_flag
42
42
  @regions_repo.expects(:exists?).returns(false)
43
- regions, observed, informal = @subject.call([:ca, :informal])
43
+ informal = @subject.call([:ca, :informal])[2]
44
44
  assert_equal(true, informal)
45
45
  end
46
46
 
47
47
  def test_returns_informal_false_if_options_contains_informal_flag
48
48
  @regions_repo.expects(:exists?).returns(false)
49
- regions, observed, informal = @subject.call([:ca])
49
+ informal = @subject.call([:ca])[2]
50
50
  assert_equal(false, informal)
51
51
  end
52
52
 
53
53
  def test_returns_any_if_no_regions_are_provided
54
- regions, observed, informal = @subject.call(:informal)
54
+ regions = @subject.call(:informal)[0]
55
55
  assert_equal([:any], regions)
56
56
  end
57
57
 
@@ -60,7 +60,7 @@ class ParseOptionsTests < Test::Unit::TestCase
60
60
  @regions_repo.expects(:exists?).with(:ch_zh).returns(true)
61
61
  @regions_repo.expects(:search).with('ch_').returns([:ch_zh])
62
62
 
63
- regions, observed, informal = @subject.call([:ch_])
63
+ regions = @subject.call([:ch_])[0]
64
64
  assert_equal(false, regions.include?(:ch_))
65
65
  end
66
66
 
@@ -0,0 +1,203 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/finder/context/search'
4
+
5
+ class FinderSearchTests < Test::Unit::TestCase
6
+ def setup
7
+ @holidays_by_month_repo = mock()
8
+ @custom_method_processor = mock()
9
+ @day_of_month_calculator = mock()
10
+
11
+ @in_region_rule = mock()
12
+ @year_range_rule = mock()
13
+ @rules = {:in_region => @in_region_rule, :year_range => @year_range_rule}
14
+
15
+ @custom_method_repo = mock()
16
+ @proc_cache_repo = mock()
17
+
18
+ @subject = Holidays::Finder::Context::Search.new(
19
+ @holidays_by_month_repo,
20
+ @custom_method_processor,
21
+ @day_of_month_calculator,
22
+ @rules,
23
+ )
24
+
25
+ @start_date = Date.civil(2015, 1, 1)
26
+ @end_date = Date.civil(2015, 1, 1)
27
+ @dates_driver = {2015 => [1]}
28
+ @regions = [:us]
29
+ @options = []
30
+
31
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 1, :name => "Test", :regions=>@regions])
32
+ @in_region_rule.expects(:call).at_most_once.returns(true)
33
+ @year_range_rule.expects(:call).at_most_once.returns(false)
34
+ end
35
+
36
+ def test_raises_error_if_dates_driver_is_empty
37
+ @dates_driver = {}
38
+ assert_raises ArgumentError do
39
+ @subject.call(@dates_driver, @regions, @options)
40
+ end
41
+ end
42
+
43
+ def test_raises_error_if_dates_driver_contains_bad_month
44
+ @dates_driver = {2015 => [100]}
45
+ assert_raises ArgumentError do
46
+ @subject.call(@dates_driver, @regions, @options)
47
+ end
48
+ end
49
+
50
+ def test_raises_error_if_dates_driver_contains_bad_month_mixed_with_valid_months
51
+ @dates_driver = {2015 => [1, 12], 2020 => [1, 200]}
52
+ assert_raises ArgumentError do
53
+ @subject.call(@dates_driver, @regions, @options)
54
+ end
55
+ end
56
+
57
+ def test_returns_nothing_if_holidays_repo_returns_nil
58
+ @holidays_by_month_repo.expects(:find_by_month).with(1).returns(nil)
59
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
60
+ end
61
+
62
+ def test_returns_nothing_if_holidays_repo_returns_empty_array
63
+ @holidays_by_month_repo.expects(:find_by_month).with(1).returns([])
64
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
65
+ end
66
+
67
+ def test_returns_nothing_if_holidays_not_in_region
68
+ @holidays_by_month_repo.expects(:find_by_month).returns([:regions=>[:other_region]])
69
+ @in_region_rule.expects(:call).with(@regions, [:other_region]).returns(false)
70
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
71
+ end
72
+
73
+ def test_returns_nothing_if_only_informal_holidays_are_returned_and_no_informal_flag_set
74
+ @holidays_by_month_repo.expects(:find_by_month).returns([:type => :informal, :regions=>@regions])
75
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
76
+ end
77
+
78
+ def test_year_rule_set_but_not_in_required_years_returns_nothing
79
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 1, :name => "Test", :regions=>@regions, :year_ranges => [:after => 2000]])
80
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
81
+ end
82
+
83
+ def test_function_present_returns_date
84
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 1, :name => "Test", :regions=> @regions, :function => "func-id", :function_arguments => [:year], :function_modifier => 1])
85
+
86
+ returned_date = Date.civil(2015, 3, 10)
87
+ @custom_method_processor.expects(:call).with(
88
+ 2015,
89
+ 1,
90
+ 1,
91
+ "func-id",
92
+ [:year],
93
+ 1,
94
+ ).returns(returned_date)
95
+
96
+ assert_equal(
97
+ [{
98
+ :date => Date.civil(2015, 3, 10),
99
+ :name => "Test",
100
+ :regions => [:us],
101
+ }],
102
+ @subject.call(@dates_driver, @regions, @options)
103
+ )
104
+ end
105
+
106
+ #FIXME This is a test that reflects how the current system works
107
+ # but this is NOT valid. See https://github.com/holidays/holidays/issues/204
108
+ def test_function_returns_nil_date_should_not_be_returned
109
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 1, :name => "Test", :regions=> @regions, :function => "func-id", :function_arguments => [:year], :function_modifier => 1])
110
+
111
+ @custom_method_processor.expects(:call).with(
112
+ 2015,
113
+ 1,
114
+ 1,
115
+ "func-id",
116
+ [:year],
117
+ 1,
118
+ ).returns(nil)
119
+
120
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
121
+ end
122
+
123
+ def test_function_not_present_mday_set
124
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 15, :name => "Test", :regions=> @regions])
125
+
126
+ assert_equal(
127
+ [{
128
+ :date => Date.civil(2015, 1, 15),
129
+ :name => "Test",
130
+ :regions => [:us],
131
+ }],
132
+ @subject.call(@dates_driver, @regions, @options)
133
+ )
134
+ end
135
+
136
+ def test_function_not_present_mday_not_set
137
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:name => "Test", :week => 1, :wday => 1, :regions=> @regions])
138
+
139
+ @day_of_month_calculator.expects(:call).with(2015, 1, 1, 1).returns(20)
140
+
141
+ assert_equal(
142
+ [{
143
+ :date => Date.civil(2015, 1, 20),
144
+ :name => "Test",
145
+ :regions => [:us],
146
+ }],
147
+ @subject.call(@dates_driver, @regions, @options)
148
+ )
149
+ end
150
+
151
+ def test_returns_holiday_if_informal_and_informal_flag_set
152
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 13, :name => "Test", :type => :informal, :regions=>@regions])
153
+
154
+ assert_equal(
155
+ [{
156
+ :date => Date.civil(2015, 1, 13),
157
+ :name => "Test",
158
+ :regions => [:us],
159
+ }],
160
+ @subject.call(@dates_driver, @regions, [:informal])
161
+ )
162
+ end
163
+
164
+ def test_does_not_return_holiday_if_informal_and_informal_flag_not_set
165
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 13, :name => "Test", :type => :informal, :regions=>@regions])
166
+
167
+ assert_equal([], @subject.call(@dates_driver, @regions, @options))
168
+ end
169
+
170
+ def test_returns_observed_result_if_observed_set_and_observed_function_present
171
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 8, :name => "Test", :type => :observed, :observed => "SOME_OBSERVED_FUNC_ID", :regions=>@regions])
172
+
173
+ @custom_method_processor.expects(:call).with(
174
+ 2015,
175
+ 1,
176
+ 8,
177
+ "SOME_OBSERVED_FUNC_ID",
178
+ [:date],
179
+ ).returns(Date.civil(2015, 10, 1))
180
+
181
+ assert_equal(
182
+ [{
183
+ :date => Date.civil(2015, 10, 1),
184
+ :name => "Test",
185
+ :regions => [:us],
186
+ }],
187
+ @subject.call(@dates_driver, @regions, [:observed])
188
+ )
189
+ end
190
+
191
+ def test_returns_unobserved_date_if_observed_method_not_set_but_flag_is_present
192
+ @holidays_by_month_repo.expects(:find_by_month).at_most_once.returns([:mday => 14, :name => "Test", :type => :observed, :observed => "SOME_OBSERVED_FUNC_ID", :regions=>@regions])
193
+
194
+ assert_equal(
195
+ [{
196
+ :date => Date.civil(2015, 1, 14),
197
+ :name => "Test",
198
+ :regions => [:us],
199
+ }],
200
+ @subject.call(@dates_driver, @regions, @options)
201
+ )
202
+ end
203
+ end
@@ -0,0 +1,202 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/finder/context/year_holiday'
4
+
5
+ class YearHolidayTests < Test::Unit::TestCase
6
+ def setup
7
+ @regions = [:us]
8
+ @observed = false
9
+ @informal = false
10
+
11
+ @definition_search = mock()
12
+ @dates_driver_builder = mock()
13
+ @options_parser = mock()
14
+
15
+ @subject = Holidays::Finder::Context::YearHoliday.new(
16
+ @definition_search,
17
+ @dates_driver_builder,
18
+ @options_parser,
19
+ )
20
+
21
+ @from_date= Date.civil(2015, 1, 1)
22
+ @dates_driver = {2015 => [0, 1, 2], 2014 => [0, 12]}
23
+ @options = [@regions, @observed, @informal]
24
+
25
+ @definition_search.expects(:call).at_most_once.with(
26
+ @dates_driver,
27
+ @regions,
28
+ [],
29
+ ).returns([{
30
+ :date => Date.civil(2015, 1, 1),
31
+ :name => "Test",
32
+ :regions => [:us],
33
+ }])
34
+
35
+ @dates_driver_builder.expects(:call).at_most_once.with(
36
+ @from_date, @from_date >> 12,
37
+ ).returns(
38
+ @dates_driver,
39
+ )
40
+
41
+ @options_parser.expects(:call).at_most_once.with(@options).returns(@options)
42
+ end
43
+
44
+ def test_returns_error_if_from_date_is_missing
45
+ assert_raise ArgumentError do
46
+ @subject.call(nil, @options)
47
+ end
48
+ end
49
+
50
+ def test_returns_error_if_from_date_is_not_a_date
51
+ assert_raise ArgumentError do
52
+ @subject.call("2015-1-1", @options)
53
+ end
54
+ end
55
+
56
+ def test_returns_single_holiday
57
+ assert_equal(
58
+ [
59
+ {
60
+ :date => Date.civil(2015, 1, 1),
61
+ :name => "Test",
62
+ :regions => [:us],
63
+ }
64
+ ],
65
+ @subject.call(@from_date, @options)
66
+ )
67
+ end
68
+
69
+ def test_returns_multiple_holidays_in_a_year
70
+ @definition_search.expects(:call).at_most_once.with(
71
+ @dates_driver,
72
+ @regions,
73
+ [],
74
+ ).returns([
75
+ {
76
+ :date => Date.civil(2015, 1, 1),
77
+ :name => "Test",
78
+ :regions => [:us],
79
+ },
80
+ {
81
+ :date => Date.civil(2015, 2, 1),
82
+ :name => "Test",
83
+ :regions => [:us],
84
+ },
85
+ {
86
+ :date => Date.civil(2015, 12, 1),
87
+ :name => "Test",
88
+ :regions => [:us],
89
+ },
90
+ ]
91
+ )
92
+
93
+ assert_equal(
94
+ [
95
+ {
96
+ :date => Date.civil(2015, 1, 1),
97
+ :name => "Test",
98
+ :regions => [:us],
99
+ },
100
+ {
101
+ :date => Date.civil(2015, 2, 1),
102
+ :name => "Test",
103
+ :regions => [:us],
104
+ },
105
+ {
106
+ :date => Date.civil(2015, 12, 1),
107
+ :name => "Test",
108
+ :regions => [:us],
109
+ }
110
+ ],
111
+ @subject.call(@from_date, @options)
112
+ )
113
+ end
114
+
115
+ def test_returns_multiple_holidays_filters_dates_outside_of_year
116
+ @definition_search.expects(:call).at_most_once.with(
117
+ @dates_driver,
118
+ @regions,
119
+ [],
120
+ ).returns([
121
+ {
122
+ :date => Date.civil(2015, 1, 1),
123
+ :name => "Test",
124
+ :regions => [:us],
125
+ },
126
+ {
127
+ :date => Date.civil(2015, 2, 1),
128
+ :name => "Test",
129
+ :regions => [:us],
130
+ },
131
+ {
132
+ :date => Date.civil(2016, 12, 1),
133
+ :name => "Test",
134
+ :regions => [:us],
135
+ },
136
+ ]
137
+ )
138
+
139
+ assert_equal(
140
+ [
141
+ {
142
+ :date => Date.civil(2015, 1, 1),
143
+ :name => "Test",
144
+ :regions => [:us],
145
+ },
146
+ {
147
+ :date => Date.civil(2015, 2, 1),
148
+ :name => "Test",
149
+ :regions => [:us],
150
+ },
151
+ ],
152
+ @subject.call(@from_date, @options)
153
+ )
154
+ end
155
+
156
+ def test_returns_sorted_multiple_holidays
157
+ @definition_search.expects(:call).at_most_once.with(
158
+ @dates_driver,
159
+ @regions,
160
+ [],
161
+ ).returns(
162
+ [
163
+ {
164
+ :date => Date.civil(2015, 1, 1),
165
+ :name => "Test",
166
+ :regions => [:us],
167
+ },
168
+ {
169
+ :date => Date.civil(2015, 12, 1),
170
+ :name => "Test",
171
+ :regions => [:us],
172
+ },
173
+ {
174
+ :date => Date.civil(2015, 2, 1),
175
+ :name => "Test",
176
+ :regions => [:us],
177
+ },
178
+ ]
179
+ )
180
+
181
+ assert_equal(
182
+ [
183
+ {
184
+ :date => Date.civil(2015, 1, 1),
185
+ :name => "Test",
186
+ :regions => [:us],
187
+ },
188
+ {
189
+ :date => Date.civil(2015, 2, 1),
190
+ :name => "Test",
191
+ :regions => [:us],
192
+ },
193
+ {
194
+ :date => Date.civil(2015, 12, 1),
195
+ :name => "Test",
196
+ :regions => [:us],
197
+ }
198
+ ],
199
+ @subject.call(@from_date, @options)
200
+ )
201
+ end
202
+ end