holidays 3.3.0 → 4.0.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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/CONTRIBUTING.md +37 -0
  4. data/README.md +16 -25
  5. data/REFERENCES +4 -1
  6. data/Rakefile +38 -8
  7. data/benchmark.rb +8 -0
  8. data/definitions/README.md +187 -8
  9. data/definitions/ar.yaml +2 -1
  10. data/definitions/at.yaml +17 -13
  11. data/definitions/au.yaml +65 -60
  12. data/definitions/be_fr.yaml +14 -10
  13. data/definitions/be_nl.yaml +8 -4
  14. data/definitions/bg.yaml +12 -6
  15. data/definitions/br.yaml +6 -3
  16. data/definitions/ca.yaml +8 -6
  17. data/definitions/ch.yaml +21 -15
  18. data/definitions/cl.yaml +4 -2
  19. data/definitions/cr.yaml +5 -3
  20. data/definitions/cz.yaml +4 -2
  21. data/definitions/de.yaml +25 -14
  22. data/definitions/dk.yaml +26 -17
  23. data/definitions/ecb_target.yaml +4 -2
  24. data/definitions/el.yaml +23 -18
  25. data/definitions/es.yaml +31 -28
  26. data/definitions/federal_reserve.yaml +12 -12
  27. data/definitions/fedex.yaml +6 -6
  28. data/definitions/fi.yaml +26 -25
  29. data/definitions/fr.yaml +8 -4
  30. data/definitions/gb.yaml +9 -7
  31. data/definitions/hr.yaml +8 -6
  32. data/definitions/hu.yaml +8 -6
  33. data/definitions/ie.yaml +17 -16
  34. data/definitions/index.yaml +1 -1
  35. data/definitions/is.yaml +29 -19
  36. data/definitions/it.yaml +10 -9
  37. data/definitions/jp.yaml +92 -44
  38. data/definitions/li.yaml +25 -20
  39. data/definitions/lt.yaml +2 -1
  40. data/definitions/ma.yaml +7 -7
  41. data/definitions/mx.yaml +11 -11
  42. data/definitions/nerc.yaml +6 -6
  43. data/definitions/nl.yaml +22 -18
  44. data/definitions/no.yaml +19 -11
  45. data/definitions/north_america_informal.yaml +6 -6
  46. data/definitions/nyse.yaml +9 -8
  47. data/definitions/nz.yaml +33 -29
  48. data/definitions/ph.yaml +15 -8
  49. data/definitions/pl.yaml +27 -17
  50. data/definitions/pt.yaml +4 -2
  51. data/definitions/ro.yaml +21 -18
  52. data/definitions/se.yaml +24 -18
  53. data/definitions/sg.yaml +10 -9
  54. data/definitions/si.yaml +4 -2
  55. data/definitions/sk.yaml +4 -2
  56. data/definitions/united_nations.yaml +12 -12
  57. data/definitions/ups.yaml +6 -6
  58. data/definitions/us.yaml +12 -11
  59. data/definitions/ve.yaml +8 -4
  60. data/definitions/vi.yaml +6 -6
  61. data/definitions/za.yaml +26 -24
  62. data/holidays.gemspec +3 -1
  63. data/lib/generated_definitions/MANIFEST +1 -1
  64. data/lib/generated_definitions/ar.rb +8 -6
  65. data/lib/generated_definitions/at.rb +11 -9
  66. data/lib/generated_definitions/au.rb +75 -99
  67. data/lib/generated_definitions/be.rb +12 -10
  68. data/lib/generated_definitions/be_fr.rb +12 -10
  69. data/lib/generated_definitions/be_nl.rb +12 -10
  70. data/lib/generated_definitions/bg.rb +14 -13
  71. data/lib/generated_definitions/br.rb +11 -9
  72. data/lib/generated_definitions/ca.rb +20 -20
  73. data/lib/generated_definitions/ch.rb +41 -44
  74. data/lib/generated_definitions/cl.rb +9 -7
  75. data/lib/generated_definitions/cr.rb +9 -7
  76. data/lib/generated_definitions/cz.rb +9 -6
  77. data/lib/generated_definitions/de.rb +25 -25
  78. data/lib/generated_definitions/dk.rb +17 -15
  79. data/lib/generated_definitions/ecb_target.rb +9 -7
  80. data/lib/generated_definitions/el.rb +13 -11
  81. data/lib/generated_definitions/es.rb +35 -33
  82. data/lib/generated_definitions/europe.rb +234 -247
  83. data/lib/generated_definitions/federal_reserve.rb +11 -9
  84. data/lib/generated_definitions/fedex.rb +42 -0
  85. data/lib/generated_definitions/fi.rb +32 -36
  86. data/lib/generated_definitions/fr.rb +12 -10
  87. data/lib/generated_definitions/gb.rb +15 -13
  88. data/lib/generated_definitions/hr.rb +10 -8
  89. data/lib/generated_definitions/hu.rb +9 -7
  90. data/lib/generated_definitions/ie.rb +17 -17
  91. data/lib/generated_definitions/is.rb +26 -26
  92. data/lib/generated_definitions/it.rb +9 -7
  93. data/lib/generated_definitions/jp.rb +112 -89
  94. data/lib/generated_definitions/li.rb +14 -12
  95. data/lib/generated_definitions/lt.rb +9 -7
  96. data/lib/generated_definitions/ma.rb +7 -5
  97. data/lib/generated_definitions/mx.rb +7 -5
  98. data/lib/generated_definitions/nerc.rb +10 -8
  99. data/lib/generated_definitions/nl.rb +15 -13
  100. data/lib/generated_definitions/no.rb +16 -14
  101. data/lib/generated_definitions/north_america.rb +34 -37
  102. data/lib/generated_definitions/nyse.rb +10 -8
  103. data/lib/generated_definitions/nz.rb +40 -40
  104. data/lib/generated_definitions/ph.rb +17 -13
  105. data/lib/generated_definitions/pl.rb +25 -27
  106. data/lib/generated_definitions/pt.rb +10 -8
  107. data/lib/generated_definitions/ro.rb +11 -9
  108. data/lib/generated_definitions/scandinavia.rb +92 -102
  109. data/lib/generated_definitions/se.rb +25 -27
  110. data/lib/generated_definitions/sg.rb +11 -9
  111. data/lib/generated_definitions/si.rb +10 -8
  112. data/lib/generated_definitions/sk.rb +9 -7
  113. data/lib/generated_definitions/united_nations.rb +7 -5
  114. data/lib/generated_definitions/ups.rb +13 -12
  115. data/lib/generated_definitions/us.rb +20 -21
  116. data/lib/generated_definitions/ve.rb +11 -9
  117. data/lib/generated_definitions/vi.rb +7 -5
  118. data/lib/generated_definitions/za.rb +19 -17
  119. data/lib/holidays.rb +20 -83
  120. data/lib/holidays/date_calculator/weekend_modifier.rb +22 -5
  121. data/lib/holidays/definition/context/generator.rb +67 -29
  122. data/lib/holidays/definition/context/merger.rb +8 -8
  123. data/lib/holidays/definition/decorator/custom_method_proc.rb +28 -0
  124. data/lib/holidays/definition/decorator/custom_method_source.rb +30 -0
  125. data/lib/holidays/definition/entity/custom_method.rb +11 -0
  126. data/lib/holidays/definition/parser/custom_method.rb +69 -0
  127. data/lib/holidays/definition/repository/custom_methods.rb +27 -0
  128. data/lib/holidays/definition/repository/holidays_by_month.rb +1 -1
  129. data/lib/holidays/definition/repository/{proc_cache.rb → proc_result_cache.rb} +19 -4
  130. data/lib/holidays/definition/validator/custom_method.rb +31 -0
  131. data/lib/holidays/definition_factory.rb +42 -6
  132. data/lib/holidays/errors.rb +6 -0
  133. data/lib/holidays/load_all_definitions.rb +57 -0
  134. data/lib/holidays/option/context/parse_options.rb +26 -16
  135. data/lib/holidays/option_factory.rb +1 -0
  136. data/lib/holidays/use_case/context/between.rb +41 -14
  137. data/lib/holidays/use_case_factory.rb +2 -1
  138. data/lib/holidays/version.rb +1 -1
  139. data/test/data/test_single_custom_holiday_with_custom_procs.yaml +24 -0
  140. data/test/defs/test_defs_at.rb +1 -1
  141. data/test/defs/test_defs_au.rb +3 -2
  142. data/test/defs/test_defs_cr.rb +1 -0
  143. data/test/defs/test_defs_cz.rb +1 -0
  144. data/test/defs/test_defs_dk.rb +2 -2
  145. data/test/defs/test_defs_el.rb +7 -6
  146. data/test/defs/test_defs_europe.rb +40 -33
  147. data/test/defs/test_defs_fedex.rb +24 -0
  148. data/test/defs/test_defs_fi.rb +4 -3
  149. data/test/defs/test_defs_hr.rb +2 -2
  150. data/test/defs/test_defs_hu.rb +2 -2
  151. data/test/defs/test_defs_is.rb +2 -1
  152. data/test/defs/test_defs_it.rb +2 -1
  153. data/test/defs/test_defs_jp.rb +1 -1
  154. data/test/defs/test_defs_li.rb +1 -1
  155. data/test/defs/test_defs_ma.rb +2 -1
  156. data/test/defs/test_defs_mx.rb +4 -3
  157. data/test/defs/test_defs_nl.rb +7 -6
  158. data/test/defs/test_defs_no.rb +1 -0
  159. data/test/defs/test_defs_north_america.rb +4 -3
  160. data/test/defs/test_defs_nyse.rb +2 -1
  161. data/test/defs/test_defs_pl.rb +1 -0
  162. data/test/defs/test_defs_ro.rb +11 -11
  163. data/test/defs/test_defs_scandinavia.rb +12 -8
  164. data/test/defs/test_defs_se.rb +3 -2
  165. data/test/defs/test_defs_sg.rb +2 -1
  166. data/test/defs/test_defs_vi.rb +1 -1
  167. data/test/defs/test_defs_za.rb +3 -2
  168. data/test/holidays/date_calculator/test_weekend_modifier.rb +11 -0
  169. data/test/holidays/definition/context/test_generator.rb +64 -5
  170. data/test/holidays/definition/context/test_merger.rb +5 -2
  171. data/test/holidays/definition/decorator/test_custom_method_proc.rb +113 -0
  172. data/test/holidays/definition/decorator/test_custom_method_source.rb +96 -0
  173. data/test/holidays/definition/parser/test_custom_method.rb +79 -0
  174. data/test/holidays/definition/repository/test_custom_methods.rb +43 -0
  175. data/test/holidays/definition/repository/test_holidays_by_month.rb +0 -32
  176. data/test/holidays/definition/repository/test_proc_result_cache.rb +84 -0
  177. data/test/holidays/definition/validator/test_custom_method.rb +89 -0
  178. data/test/holidays/option/context/test_parse_options.rb +5 -0
  179. data/test/holidays/test_definition_factory.rb +17 -2
  180. data/test/holidays/use_case/context/test_between.rb +2 -0
  181. data/test/test_all_regions.rb +7 -49
  182. data/test/test_custom_holidays.rb +8 -2
  183. data/test/test_helper.rb +9 -2
  184. data/test/test_holidays.rb +9 -29
  185. metadata +46 -11
  186. data/lib/generated_definitions/fed_ex.rb +0 -41
  187. data/test/holidays/definition/repository/test_proc_cache.rb +0 -29
  188. data/test/test_parse_definitions.rb +0 -30
@@ -0,0 +1,96 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/definition/decorator/custom_method_source'
4
+ require 'holidays/definition/entity/custom_method'
5
+
6
+ class DecoratorCustomMethodSourceTests < Test::Unit::TestCase
7
+ def setup
8
+ @decorator = Holidays::Definition::Decorator::CustomMethodSource.new
9
+ end
10
+
11
+ def test_call_generates_source_from_entity
12
+ entity = Holidays::Definition::Entity::CustomMethod.new(
13
+ name: "test",
14
+ arguments: ["year"],
15
+ source: "Date.civil(year, 1, 1)"
16
+ )
17
+
18
+ source = @decorator.call(entity)
19
+ expected_source = "\"#{entity.name}(#{entity.arguments[0]})\" => Proc.new { |year|\n#{entity.source}}"
20
+
21
+ assert_equal expected_source, source
22
+ end
23
+
24
+ def test_call_generates_source_from_entity_with_multiple_arguments
25
+ entity = Holidays::Definition::Entity::CustomMethod.new(
26
+ name: "test",
27
+ arguments: ["year", "month"],
28
+ source: "Date.civil(year, month, 1)"
29
+ )
30
+
31
+ source = @decorator.call(entity)
32
+ expected_args = "#{entity.arguments[0]}, #{entity.arguments[1]}"
33
+
34
+ expected_source = "\"#{entity.name}(#{expected_args})\" => Proc.new { |#{expected_args}|\n#{entity.source}}"
35
+
36
+ assert_equal expected_source, source
37
+ end
38
+
39
+ def test_call_generates_source_from_entity_when_source_is_multiple_lines
40
+ entity = Holidays::Definition::Entity::CustomMethod.new(
41
+ name: "test",
42
+ arguments: ["year"],
43
+ source: "d = Date.civil(year, 1, 1)\nd + 2"
44
+ )
45
+
46
+ source = @decorator.call(entity)
47
+ expected_source = "\"#{entity.name}(#{entity.arguments[0]})\" => Proc.new { |year|\n#{entity.source}}"
48
+
49
+ assert_equal expected_source, source
50
+ end
51
+
52
+ def test_call_raises_error_if_missing_name
53
+ entity = Holidays::Definition::Entity::CustomMethod.new(
54
+ arguments: ["year", "month"],
55
+ source: "Date.civil(year, month, 1)"
56
+ )
57
+
58
+ assert_raises ArgumentError do
59
+ @decorator.call(entity)
60
+ end
61
+ end
62
+
63
+ def test_call_raises_error_if_missing_arguments
64
+ entity = Holidays::Definition::Entity::CustomMethod.new(
65
+ name: "test",
66
+ source: "Date.civil(year, month, 1)"
67
+ )
68
+
69
+ assert_raises ArgumentError do
70
+ @decorator.call(entity)
71
+ end
72
+ end
73
+
74
+ def test_call_raises_error_if_arguments_is_not_an_array
75
+ entity = Holidays::Definition::Entity::CustomMethod.new(
76
+ name: "test",
77
+ arguments: "test",
78
+ source: "Date.civil(year, month, 1)"
79
+ )
80
+
81
+ assert_raises ArgumentError do
82
+ @decorator.call(entity)
83
+ end
84
+ end
85
+
86
+ def test_call_raises_error_if_missing_source
87
+ entity = Holidays::Definition::Entity::CustomMethod.new(
88
+ name: "test",
89
+ arguments: ["year", "month"],
90
+ )
91
+
92
+ assert_raises ArgumentError do
93
+ @decorator.call(entity)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/definition/parser/custom_method'
4
+ require 'holidays/definition/entity/custom_method'
5
+
6
+ class ParserCustomMethodTests < Test::Unit::TestCase
7
+ def setup
8
+ @validator = mock()
9
+
10
+ @parser = Holidays::Definition::Parser::CustomMethod.new(@validator)
11
+ end
12
+
13
+ def test_parse_happy_single_method
14
+ input = {"custom_method"=>{"arguments"=>"year", "source"=>"d = Date.civil(year, 1, 1)\nd + 2\n"}}
15
+ @validator.expects(:valid?).with({:name => "custom_method", :arguments => "year", :source => "d = Date.civil(year, 1, 1)\nd + 2\n"}).returns(true)
16
+
17
+ result = @parser.call(input)
18
+
19
+ assert_equal(1, result.size)
20
+
21
+ custom_method = result["custom_method(year)"]
22
+ assert(custom_method)
23
+
24
+ assert(custom_method.is_a?(Holidays::Definition::Entity::CustomMethod))
25
+ assert_equal("custom_method", custom_method.name)
26
+ assert_equal(["year"], custom_method.arguments)
27
+ assert_equal("d = Date.civil(year, 1, 1)\nd + 2\n", custom_method.source)
28
+ end
29
+
30
+ def test_call_happy_with_multiple_methods
31
+ input = {"custom_method"=>{"arguments"=>"year", "source"=>"d = Date.civil(year, 1, 1)\nd + 2\n"}, "second_method"=>{"arguments"=>"month","source"=>"source"}}
32
+ @validator.expects(:valid?).with({:name => "custom_method", :arguments => "year", :source => "d = Date.civil(year, 1, 1)\nd + 2\n"}).returns(true)
33
+ @validator.expects(:valid?).with({:name => "second_method", :arguments => "month", :source => "source"}).returns(true)
34
+
35
+ result = @parser.call(input)
36
+
37
+ assert_equal(2, result.size)
38
+
39
+ custom_method = result["custom_method(year)"]
40
+ assert(custom_method)
41
+
42
+ assert(custom_method.is_a?(Holidays::Definition::Entity::CustomMethod))
43
+ assert_equal("custom_method", custom_method.name)
44
+ assert_equal(["year"], custom_method.arguments)
45
+ assert_equal("d = Date.civil(year, 1, 1)\nd + 2\n", custom_method.source)
46
+
47
+ second_method= result["second_method(month)"]
48
+ assert(second_method)
49
+
50
+ assert(second_method.is_a?(Holidays::Definition::Entity::CustomMethod))
51
+ assert_equal("second_method", second_method.name)
52
+ assert_equal(["month"], second_method.arguments)
53
+ assert_equal("source", second_method.source)
54
+ end
55
+
56
+ def test_call_returns_empty_hash_if_methods_are_missing
57
+ assert_equal({}, @parser.call(nil))
58
+ assert_equal({}, @parser.call({}))
59
+ end
60
+
61
+ def test_call_raises_error_if_validator_returns_false_for_single_method
62
+ input = {"custom_method"=>{"arguments"=>"year", "source"=>"d = Date.civil(year, 1, 1)\nd + 2\n"}}
63
+ @validator.expects(:valid?).with({:name => "custom_method", :arguments => "year", :source => "d = Date.civil(year, 1, 1)\nd + 2\n"}).returns(false)
64
+
65
+ assert_raises ArgumentError do
66
+ result = @parser.call(input)
67
+ end
68
+ end
69
+
70
+ def test_call_raises_error_if_validator_returns_false_for_one_of_multiple_methods
71
+ input = {"custom_method"=>{"arguments"=>"year", "source"=>"d = Date.civil(year, 1, 1)\nd + 2\n"}, "second_method"=>{"arguments"=>"month","source"=>"source"}}
72
+ @validator.expects(:valid?).with({:name => "custom_method", :arguments => "year", :source => "d = Date.civil(year, 1, 1)\nd + 2\n"}).returns(true)
73
+ @validator.expects(:valid?).with({:name => "second_method", :arguments => "month", :source => "source"}).returns(false)
74
+
75
+ assert_raises ArgumentError do
76
+ result = @parser.call(input)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/definition/repository/custom_methods'
4
+
5
+ class CustomMethodsRepoTests < Test::Unit::TestCase
6
+ def setup
7
+ @subject = Holidays::Definition::Repository::CustomMethods.new
8
+ end
9
+
10
+ def test_add_raises_error_if_input_is_nil
11
+ assert_raise ArgumentError do
12
+ @subject.add(nil)
13
+ end
14
+ end
15
+
16
+ def test_find_returns_nil_if_method_id_does_not_exist
17
+ assert_nil @subject.find("some-method-id")
18
+ end
19
+
20
+ def test_add_successfully_adds_new_custom_methods
21
+ new_custom_methods = {
22
+ "some-method-id" => Proc.new { |year|
23
+ Date.civil(year, 1, 1)
24
+ }
25
+ }
26
+
27
+ @subject.add(new_custom_methods)
28
+
29
+ target_method = @subject.find("some-method-id")
30
+
31
+ assert_equal new_custom_methods["some-method-id"], target_method
32
+ end
33
+
34
+ def test_find_raises_error_if_target_method_id_is_nil_or_empty
35
+ assert_raise ArgumentError do
36
+ @subject.find(nil)
37
+ end
38
+
39
+ assert_raise ArgumentError do
40
+ @subject.find("")
41
+ end
42
+ end
43
+ end
@@ -93,22 +93,6 @@ class HolidaysByMonthRepoTests < Test::Unit::TestCase
93
93
  assert_equal(expected, @subject.all)
94
94
  end
95
95
 
96
- def test_add_is_successful_if_function_id_is_different
97
- target_holidays = {0 => [:mday => 1, :name => "Test", :function_id => 'test', :regions => [:test]]}
98
-
99
- @subject.add(@existing_holidays_by_month)
100
- @subject.add(target_holidays)
101
-
102
- expected = {
103
- 0 => [
104
- {:mday=>1, :name=>"Test", :regions=>[:test]},
105
- {:mday=>1, :name=>"Test", :function_id => 'test', :regions=>[:test]}
106
- ]
107
- }
108
-
109
- assert_equal(expected, @subject.all)
110
- end
111
-
112
96
  def test_add_is_successful_if_type_is_different
113
97
  target_holidays = {0 => [:mday => 1, :name => "Test", :type => :informal, :regions => [:test]]}
114
98
 
@@ -125,22 +109,6 @@ class HolidaysByMonthRepoTests < Test::Unit::TestCase
125
109
  assert_equal(expected, @subject.all)
126
110
  end
127
111
 
128
- def test_add_is_successful_if_observed_id_is_different
129
- target_holidays = {0 => [:mday => 1, :name => "Test", :observed_id => :informal, :regions => [:test]]}
130
-
131
- @subject.add(@existing_holidays_by_month)
132
- @subject.add(target_holidays)
133
-
134
- expected = {
135
- 0 => [
136
- {:mday=>1, :name=>"Test", :regions=>[:test]},
137
- {:mday=>1, :name=>"Test", :observed_id => :informal, :regions=>[:test]}
138
- ]
139
- }
140
-
141
- assert_equal(expected, @subject.all)
142
- end
143
-
144
112
  def test_add_is_successful_and_updates_regions_to_existing_matching_definitions
145
113
  target_holidays = {0 => [:mday => 1, :name => "Test", :regions => [:test2]]}
146
114
 
@@ -0,0 +1,84 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/definition/repository/proc_result_cache'
4
+
5
+ class ProcResultCacheRepoTests < Test::Unit::TestCase
6
+ def setup
7
+ @subject = Holidays::Definition::Repository::ProcResultCache.new
8
+ end
9
+
10
+ def test_lookup_stores_and_returns_result_of_function_if_it_is_not_present
11
+ function = lambda { |year| Date.civil(year, 2, 1) - 1 }
12
+ function_argument = 2015
13
+
14
+ assert_equal(Date.civil(2015, 1, 31), @subject.lookup(function, function_argument))
15
+ end
16
+
17
+ #FIXME This test stinks. I don't know how to show that the second invocation
18
+ # doesn't call the function. In rspec I could just do an expect().not_to
19
+ # but it doesn't seem like Mocha can do that? I'm punting.
20
+ def test_lookup_simply_returns_result_of_cache_if_present_after_first_call
21
+ function = lambda { |year| Date.civil(year, 2, 1) - 1 }
22
+ function_argument = 2015
23
+
24
+ assert_equal(Date.civil(2015, 1, 31), @subject.lookup(function, function_argument))
25
+ end
26
+
27
+ def test_lookup_raises_error_if_function_is_not_a_proc
28
+ function = "Holidays.easter(year)"
29
+ function_argument = 2015
30
+
31
+ assert_raise ArgumentError do
32
+ @subject.lookup(function, function_argument)
33
+ end
34
+ end
35
+
36
+ def test_lookup_accepts_date_as_function_argument
37
+ function = lambda { |date| date - 1 }
38
+ function_argument = Date.civil(2015, 2, 1)
39
+
40
+ assert_equal(Date.civil(2015, 1, 31), @subject.lookup(function, function_argument))
41
+ end
42
+
43
+ def test_accepts_multiple_arguments_for_functions
44
+ function = lambda { |year, month, day| Date.civil(year, month, day) + 1 }
45
+ year = 2016
46
+ month = 1
47
+ day = 1
48
+
49
+ assert_equal(Date.civil(2016, 1, 2), @subject.lookup(function, year, month, day))
50
+ end
51
+
52
+ def test_raises_error_if_one_of_multiple_arguments_is_not_an_int_or_date
53
+ function = lambda { |year, month, day| Date.civil(year, month, day) + 1 }
54
+ year = 2016
55
+ month = 1
56
+ day = "1"
57
+
58
+ assert_raise ArgumentError do
59
+ @subject.lookup(function, year, month, day)
60
+ end
61
+ end
62
+
63
+ def test_accepts_mix_of_integers_and_dates_for_multiple_function_arguments
64
+ function = lambda { |date, modifier| date + modifier }
65
+ date = Date.civil(2016, 1, 1)
66
+ modifier = 5
67
+
68
+ assert_equal(Date.civil(2016, 1, 6), @subject.lookup(function, date, modifier))
69
+ end
70
+
71
+ def test_lookup_raises_error_if_function_argument_is_not_valid
72
+ function = lambda { |year| Date.civil(year, 2, 1) - 1 }
73
+ function_argument = "2015"
74
+
75
+ assert_raise ArgumentError do
76
+ @subject.lookup(function, function_argument)
77
+ end
78
+
79
+ funtion_argument = Proc.new { |arg1| "arg1" + "something"}
80
+ assert_raise ArgumentError do
81
+ @subject.lookup(function, function_argument)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,89 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
2
+
3
+ require 'holidays/definition/validator/custom_method'
4
+
5
+ class CustomMethodValidatorTests < Test::Unit::TestCase
6
+ def setup
7
+ @subject = Holidays::Definition::Validator::CustomMethod.new
8
+ end
9
+
10
+ def test_valid_returns_true_if_valid
11
+ m = {:name => "good_method", :arguments => "year", :source => "source"}
12
+ assert @subject.valid?(m)
13
+ end
14
+
15
+ def test_valid_returns_true_with_multiple_arguments
16
+ m = {:name => "good_method", :arguments => "year,month", :source => "source"}
17
+ assert @subject.valid?(m)
18
+ end
19
+
20
+ def test_valid_returns_true_with_date_argument
21
+ m = {:name => "good_method", :arguments => "date", :source => "source"}
22
+ assert @subject.valid?(m)
23
+ end
24
+
25
+ def test_valid_returns_true_with_year_argument
26
+ m = {:name => "good_method", :arguments => "year", :source => "source"}
27
+ assert @subject.valid?(m)
28
+ end
29
+
30
+ def test_valid_returns_true_with_month_argument
31
+ m = {:name => "good_method", :arguments => "month", :source => "source"}
32
+ assert @subject.valid?(m)
33
+ end
34
+
35
+ def test_valid_returns_true_with_day_argument
36
+ m = {:name => "good_method", :arguments => "day", :source => "source"}
37
+ assert @subject.valid?(m)
38
+ end
39
+
40
+ def test_valid_returns_true_multiple_arguments_with_whitespace
41
+ m = {:name => "good_method", :arguments => "year , month", :source => "source"}
42
+ assert @subject.valid?(m)
43
+ end
44
+
45
+ def test_valid_returns_false_if_single_argument_contain_carriage_return
46
+ m = {:name => "bad_method", :arguments =>"year\n", :source =>"d = Date.civil(year, 1, 1)\nd + 2\n"}
47
+ assert_false @subject.valid?(m)
48
+ end
49
+
50
+ def test_valid_returns_false_if_multiple_arguments_contain_carriage_return
51
+ m = {:name => "bad_method", :arguments =>"year,month\n", :source =>"d = Date.civil(year, 1, 1)\nd + 2\n"}
52
+ assert_false @subject.valid?(m)
53
+ end
54
+
55
+ def test_valid_returns_false_if_multiple_arguments_contain_carriage_return_with_whitespace
56
+ m = {:name => "bad_method", :arguments =>"year , month\n", :source =>"d = Date.civil(year, 1, 1)\nd + 2\n"}
57
+ assert_false @subject.valid?(m)
58
+ end
59
+
60
+ def test_valid_returns_false_if_no_source
61
+ m = {:name => "bad_method", :arguments => "day"}
62
+ assert_false @subject.valid?(m)
63
+ end
64
+
65
+ def test_valid_returns_false_if_source_is_empty
66
+ m = {:name => "bad_method", :arguments => "day", :source => ""}
67
+ assert_false @subject.valid?(m)
68
+ end
69
+
70
+ def test_valid_returns_false_if_name_is_missing
71
+ m = {:arguments => "day", :source => "source"}
72
+ assert_false @subject.valid?(m)
73
+ end
74
+
75
+ def test_valid_returns_false_if_name_is_empty
76
+ m = {:name => "", :arguments => "day", :source => "source"}
77
+ assert_false @subject.valid?(m)
78
+ end
79
+
80
+ def test_returns_false_if_multiple_arguments_contain_unrecognized_value
81
+ m = {:name => "bad_method", :arguments => "year,month,day,date,unknown", :source => "source"}
82
+ assert_false @subject.valid?(m)
83
+ end
84
+
85
+ def test_returns_false_if_single_argument_contains_unrecognized_value
86
+ m = {:name => "bad_method", :arguments => "unknown", :source => "source"}
87
+ assert_false @subject.valid?(m)
88
+ end
89
+ end
@@ -15,9 +15,14 @@ class ParseOptionsTests < Test::Unit::TestCase
15
15
  @region_validator = mock()
16
16
  @region_validator.stubs(:valid?).returns(true)
17
17
 
18
+ # As mentioned above, this set of tests is NOT isolated. We need
19
+ # the real merger code here.
20
+ @definition_merger = Holidays::DefinitionFactory.merger
21
+
18
22
  @subject = Holidays::Option::Context::ParseOptions.new(
19
23
  @regions_repo,
20
24
  @region_validator,
25
+ @definition_merger,
21
26
  )
22
27
  end
23
28