holidays 9.1.1 → 9.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +2 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +5 -0
- data/Makefile +17 -2
- data/README.md +1 -2
- data/Rakefile +28 -0
- data/holidays.gemspec +3 -3
- data/lib/generated_definitions/MANIFEST +2 -0
- data/lib/generated_definitions/REGIONS.rb +2 -2
- data/lib/generated_definitions/europe.rb +5 -5
- data/lib/generated_definitions/fr.rb +2 -2
- data/lib/generated_definitions/gb.rb +3 -3
- data/lib/generated_definitions/il.rb +74 -0
- data/lib/generated_definitions/mc.rb +36 -0
- data/lib/generated_definitions/northamerica.rb +3 -2
- data/lib/generated_definitions/us.rb +3 -2
- data/lib/holidays/definition/context/function_processor.rb +1 -1
- data/lib/holidays/definition/context/merger.rb +20 -4
- data/lib/holidays/definition/repository/custom_methods.rb +37 -9
- data/lib/holidays/finder/context/search.rb +43 -24
- data/lib/holidays/version.rb +1 -1
- data/lib/holidays.rb +9 -4
- data/test/coverage_report.rb +3 -5
- data/test/data/test_date_transform_conflict_region_1.yaml +14 -0
- data/test/data/test_date_transform_conflict_region_2.yaml +14 -0
- data/test/defs/test_defs_europe.rb +7 -3
- data/test/defs/test_defs_fr.rb +3 -3
- data/test/defs/test_defs_gb.rb +4 -0
- data/test/defs/test_defs_il.rb +35 -0
- data/test/defs/test_defs_mc.rb +43 -0
- data/test/defs/test_defs_northamerica.rb +6 -1
- data/test/defs/test_defs_us.rb +6 -1
- data/test/e2e/README.md +52 -0
- data/test/e2e/data/test_multiple_regions_with_conflicts_region_3.yaml +38 -0
- data/test/{integration → e2e}/test_holidays.rb +3 -2
- data/test/e2e/test_multiple_regions_with_conflict.rb +228 -0
- data/test/holidays/definition/context/test_function_processor.rb +2 -2
- data/test/holidays/definition/context/test_merger.rb +1 -1
- data/test/holidays/finder/context/test_search.rb +58 -0
- data/test/integration/README.md +45 -6
- data/test/integration/test_custom_holidays.rb +1 -1
- data/test/integration/test_custom_informal_holidays.rb +1 -1
- data/test/smoke/README.md +31 -0
- data/test/{integration → smoke}/test_available_regions.rb +0 -5
- data/test/smoke/test_smoke.rb +74 -0
- metadata +51 -33
- data/test/integration/test_multiple_regions_with_conflict.rb +0 -29
- /data/test/{data → e2e/data}/test_multiple_regions_with_conflicts_region_1.yaml +0 -0
- /data/test/{data → e2e/data}/test_multiple_regions_with_conflicts_region_2.yaml +0 -0
- /data/test/{integration → e2e}/test_all_regions.rb +0 -0
- /data/test/{integration → e2e}/test_any_holidays_during_work_week.rb +0 -0
- /data/test/{integration → e2e}/test_holidays_between.rb +0 -0
- /data/test/{integration → e2e}/test_multiple_regions.rb +0 -0
- /data/test/{integration → e2e}/test_nonstandard_regions.rb +0 -0
- /data/test/{data → integration/data}/test_custom_govt_holiday_defs.yaml +0 -0
- /data/test/{data → integration/data}/test_custom_informal_holidays_defs.yaml +0 -0
- /data/test/{data → integration/data}/test_multiple_custom_holiday_defs.yaml +0 -0
|
@@ -24,14 +24,19 @@ module Holidays
|
|
|
24
24
|
next unless @rules[:year_range].call(year, h[:year_ranges])
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
date
|
|
27
|
+
dates = if h[:function]
|
|
28
|
+
custom_holidays(year, month, h, regions)
|
|
29
|
+
else
|
|
30
|
+
date = build_date(year, month, h, regions)
|
|
31
|
+
date ? [date] : []
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
dates.each do |d|
|
|
35
|
+
if observed_set?(options) && h[:observed]
|
|
36
|
+
d = build_observed_date(d, regions, h)
|
|
37
|
+
end
|
|
38
|
+
holidays << {:date => d, :name => h[:name], :regions => h[:regions]}
|
|
39
|
+
end
|
|
35
40
|
end
|
|
36
41
|
end
|
|
37
42
|
end
|
|
@@ -68,36 +73,50 @@ module Holidays
|
|
|
68
73
|
options && options.include?(:observed) == true
|
|
69
74
|
end
|
|
70
75
|
|
|
71
|
-
def build_date(year, month, h)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#FIXME The result should always be present, see https://github.com/holidays/holidays/issues/204 for more information
|
|
75
|
-
current_month = holiday&.month
|
|
76
|
-
current_day = holiday&.mday
|
|
77
|
-
else
|
|
78
|
-
current_month = month
|
|
79
|
-
current_day = h[:mday] || @day_of_month_calculator.call(year, month, h[:week], h[:wday])
|
|
80
|
-
end
|
|
76
|
+
def build_date(year, month, h, queried_regions)
|
|
77
|
+
current_month = month
|
|
78
|
+
current_day = h[:mday] || @day_of_month_calculator.call(year, month, h[:week], h[:wday])
|
|
81
79
|
|
|
82
80
|
# Silently skip bad mdays
|
|
83
81
|
#TODO Should we be doing something different here? We have no concept of logging right now. Maybe we should add it?
|
|
84
82
|
Date.civil(year, current_month, current_day) rescue nil
|
|
85
83
|
end
|
|
86
84
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
def custom_holidays(year, month, h, queried_regions)
|
|
86
|
+
effective_regions = queried_regions & h[:regions]
|
|
87
|
+
effective_regions = [queried_regions.first] if effective_regions.empty?
|
|
88
|
+
|
|
89
|
+
effective_regions.each_with_object([]) do |region, dates|
|
|
90
|
+
result = @custom_method_processor.call(
|
|
91
|
+
{ year: year, month: month, day: h[:mday], region: region },
|
|
92
|
+
h[:function], h[:function_arguments], h[:function_modifier],
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
#FIXME The result should always be present, see https://github.com/holidays/holidays/issues/204 for more information
|
|
96
|
+
next if result.nil?
|
|
97
|
+
|
|
98
|
+
date = Date.civil(year, result.month, result.mday) rescue nil
|
|
99
|
+
dates << date if date
|
|
100
|
+
end.uniq
|
|
93
101
|
end
|
|
94
102
|
|
|
95
|
-
|
|
103
|
+
# When the queried region is :any (or no holiday_regions are provided), fall back
|
|
104
|
+
# to the holiday's own first region. Otherwise use the first queried region that
|
|
105
|
+
# also appears in the holiday's region list so that region-specific function
|
|
106
|
+
# implementations resolve correctly even when a holiday definition is shared across
|
|
107
|
+
# multiple regions.
|
|
108
|
+
def build_custom_method_input(year, month, day, queried_regions, holiday_regions = nil)
|
|
109
|
+
effective_region = if holiday_regions.nil? || queried_regions.include?(:any)
|
|
110
|
+
queried_regions.first
|
|
111
|
+
else
|
|
112
|
+
(queried_regions & holiday_regions).first || holiday_regions.first
|
|
113
|
+
end
|
|
114
|
+
|
|
96
115
|
{
|
|
97
116
|
year: year,
|
|
98
117
|
month: month,
|
|
99
118
|
day: day,
|
|
100
|
-
region:
|
|
119
|
+
region: effective_region,
|
|
101
120
|
}
|
|
102
121
|
end
|
|
103
122
|
|
data/lib/holidays/version.rb
CHANGED
data/lib/holidays.rb
CHANGED
|
@@ -42,9 +42,8 @@ module Holidays
|
|
|
42
42
|
|
|
43
43
|
raise ArgumentError if end_date < start_date
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
45
|
+
cached_holidays = Factory::Definition.cache_repository.find(start_date, end_date, options)
|
|
46
|
+
return cached_holidays unless cached_holidays.nil?
|
|
48
47
|
|
|
49
48
|
Factory::Finder.between.call(start_date, end_date, options)
|
|
50
49
|
end
|
|
@@ -93,11 +92,17 @@ module Holidays
|
|
|
93
92
|
def load_custom(*files)
|
|
94
93
|
regions, rules_by_month, custom_methods, _ = Factory::Definition.file_parser.parse_definition_files(files)
|
|
95
94
|
|
|
95
|
+
# Capture source code before converting entities to Procs so the merger
|
|
96
|
+
# can detect genuine conflicts (same name, different logic).
|
|
97
|
+
method_sources = custom_methods.each_with_object({}) do |(key, entity), h|
|
|
98
|
+
h[key] = entity.source
|
|
99
|
+
end
|
|
100
|
+
|
|
96
101
|
custom_methods.each do |method_key, method_entity|
|
|
97
102
|
custom_methods[method_key] = Factory::Definition.custom_method_proc_decorator.call(method_entity)
|
|
98
103
|
end
|
|
99
104
|
|
|
100
|
-
Factory::Definition.merger.call(regions, rules_by_month, custom_methods)
|
|
105
|
+
Factory::Definition.merger.call(regions, rules_by_month, custom_methods, method_sources)
|
|
101
106
|
|
|
102
107
|
rules_by_month
|
|
103
108
|
end
|
data/test/coverage_report.rb
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
require 'simplecov'
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# We set the floor based on jruby so that all automated tests pass on Travis CI.
|
|
7
|
-
SimpleCov.minimum_coverage 89
|
|
3
|
+
# JRuby coverage reporting is inaccurate without --debug mode, resulting in
|
|
4
|
+
# artificially low numbers. Skip the minimum coverage check under JRuby.
|
|
5
|
+
SimpleCov.minimum_coverage 90 unless RUBY_PLATFORM == 'java' || RUBY_PATCHLEVEL == -1 || ENV['SMOKE_TEST'] || ENV['CONTRACT_TEST']
|
|
8
6
|
|
|
9
7
|
SimpleCov.add_filter [
|
|
10
8
|
# Apparently simplecov doesn't automatically filter 'spec' or 'test' so we
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
months:
|
|
2
|
+
1:
|
|
3
|
+
- name: Weekend Holiday
|
|
4
|
+
regions: [date_transform_conflict_1]
|
|
5
|
+
mday: 1
|
|
6
|
+
function: to_nearest_upcoming_weekend_day(date)
|
|
7
|
+
|
|
8
|
+
methods:
|
|
9
|
+
to_nearest_upcoming_weekend_day:
|
|
10
|
+
arguments: date
|
|
11
|
+
ruby: |
|
|
12
|
+
days_until = (6 - date.wday) % 7
|
|
13
|
+
days_until = 7 if days_until == 0
|
|
14
|
+
date + days_until
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
months:
|
|
2
|
+
1:
|
|
3
|
+
- name: Weekend Holiday
|
|
4
|
+
regions: [date_transform_conflict_2]
|
|
5
|
+
mday: 1
|
|
6
|
+
function: to_nearest_upcoming_weekend_day(date)
|
|
7
|
+
|
|
8
|
+
methods:
|
|
9
|
+
to_nearest_upcoming_weekend_day:
|
|
10
|
+
arguments: date
|
|
11
|
+
ruby: |
|
|
12
|
+
days_until = (7 - date.wday) % 7
|
|
13
|
+
days_until = 7 if days_until == 0
|
|
14
|
+
date + days_until
|
|
@@ -413,7 +413,7 @@ class EuropeDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
413
413
|
|
|
414
414
|
assert_equal "Ascension", (Holidays.on(Date.civil(2007, 5, 17), [:fr])[0] || {})[:name]
|
|
415
415
|
|
|
416
|
-
|
|
416
|
+
assert_nil (Holidays.on(Date.civil(2007, 5, 27), [:fr])[0] || {})[:name]
|
|
417
417
|
|
|
418
418
|
assert_equal "Fête nationale", (Holidays.on(Date.civil(2007, 7, 14), [:fr])[0] || {})[:name]
|
|
419
419
|
|
|
@@ -427,11 +427,11 @@ class EuropeDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
427
427
|
|
|
428
428
|
assert_nil (Holidays.on(Date.civil(2007, 4, 8), [:fr])[0] || {})[:name]
|
|
429
429
|
|
|
430
|
-
|
|
430
|
+
assert_equal "Lundi de Pentecôte", (Holidays.on(Date.civil(2007, 5, 28), [:fr])[0] || {})[:name]
|
|
431
431
|
|
|
432
432
|
assert_equal "Pâques", (Holidays.on(Date.civil(2007, 4, 8), [:fr], [:informal])[0] || {})[:name]
|
|
433
433
|
|
|
434
|
-
assert_equal "
|
|
434
|
+
assert_equal "Pentecôte", (Holidays.on(Date.civil(2007, 5, 27), [:fr], [:informal])[0] || {})[:name]
|
|
435
435
|
|
|
436
436
|
assert_equal "Saint-Étienne", (Holidays.on(Date.civil(2017, 12, 26), [:fr_a, :fr_m], [:informal])[0] || {})[:name]
|
|
437
437
|
|
|
@@ -575,6 +575,10 @@ class EuropeDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
575
575
|
|
|
576
576
|
assert_equal "Bank Holiday for the Coronation of King Charles III", (Holidays.on(Date.civil(2023, 5, 8), [:gb])[0] || {})[:name]
|
|
577
577
|
|
|
578
|
+
assert_equal "Easter Monday", (Holidays.on(Date.civil(2016, 3, 28), [:gb_con])[0] || {})[:name]
|
|
579
|
+
|
|
580
|
+
assert_equal "Bank Holiday", (Holidays.on(Date.civil(2016, 8, 29), [:gb_con])[0] || {})[:name]
|
|
581
|
+
|
|
578
582
|
assert_nil (Holidays.on(Date.civil(2024, 5, 8), [:gb])[0] || {})[:name]
|
|
579
583
|
|
|
580
584
|
assert_nil (Holidays.on(Date.civil(2022, 5, 8), [:gb])[0] || {})[:name]
|
data/test/defs/test_defs_fr.rb
CHANGED
|
@@ -17,7 +17,7 @@ class FrDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
17
17
|
|
|
18
18
|
assert_equal "Ascension", (Holidays.on(Date.civil(2007, 5, 17), [:fr])[0] || {})[:name]
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
assert_nil (Holidays.on(Date.civil(2007, 5, 27), [:fr])[0] || {})[:name]
|
|
21
21
|
|
|
22
22
|
assert_equal "Fête nationale", (Holidays.on(Date.civil(2007, 7, 14), [:fr])[0] || {})[:name]
|
|
23
23
|
|
|
@@ -31,11 +31,11 @@ class FrDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
31
31
|
|
|
32
32
|
assert_nil (Holidays.on(Date.civil(2007, 4, 8), [:fr])[0] || {})[:name]
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
assert_equal "Lundi de Pentecôte", (Holidays.on(Date.civil(2007, 5, 28), [:fr])[0] || {})[:name]
|
|
35
35
|
|
|
36
36
|
assert_equal "Pâques", (Holidays.on(Date.civil(2007, 4, 8), [:fr], [:informal])[0] || {})[:name]
|
|
37
37
|
|
|
38
|
-
assert_equal "
|
|
38
|
+
assert_equal "Pentecôte", (Holidays.on(Date.civil(2007, 5, 27), [:fr], [:informal])[0] || {})[:name]
|
|
39
39
|
|
|
40
40
|
assert_equal "Saint-Étienne", (Holidays.on(Date.civil(2017, 12, 26), [:fr_a, :fr_m], [:informal])[0] || {})[:name]
|
|
41
41
|
|
data/test/defs/test_defs_gb.rb
CHANGED
|
@@ -147,6 +147,10 @@ class GbDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
|
147
147
|
|
|
148
148
|
assert_equal "Bank Holiday for the Coronation of King Charles III", (Holidays.on(Date.civil(2023, 5, 8), [:gb])[0] || {})[:name]
|
|
149
149
|
|
|
150
|
+
assert_equal "Easter Monday", (Holidays.on(Date.civil(2016, 3, 28), [:gb_con])[0] || {})[:name]
|
|
151
|
+
|
|
152
|
+
assert_equal "Bank Holiday", (Holidays.on(Date.civil(2016, 8, 29), [:gb_con])[0] || {})[:name]
|
|
153
|
+
|
|
150
154
|
assert_nil (Holidays.on(Date.civil(2024, 5, 8), [:gb])[0] || {})[:name]
|
|
151
155
|
|
|
152
156
|
assert_nil (Holidays.on(Date.civil(2022, 5, 8), [:gb])[0] || {})[:name]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
|
3
|
+
|
|
4
|
+
# This file is generated by the Ruby Holiday gem.
|
|
5
|
+
#
|
|
6
|
+
# Definitions loaded: definitions/il.yaml
|
|
7
|
+
class IlDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
8
|
+
|
|
9
|
+
def test_il
|
|
10
|
+
assert_equal "Exodus from Egypt", (Holidays.on(Date.civil(2024, 3, 23), [:il])[0] || {})[:name]
|
|
11
|
+
|
|
12
|
+
assert_equal "Exodus from Egypt (day 7)", (Holidays.on(Date.civil(2023, 3, 12), [:il])[0] || {})[:name]
|
|
13
|
+
|
|
14
|
+
assert_equal "Independence Day", (Holidays.on(Date.civil(2025, 4, 1), [:il])[0] || {})[:name]
|
|
15
|
+
|
|
16
|
+
assert_equal "Thanksgiving", (Holidays.on(Date.civil(2026, 4, 22), [:il])[0] || {})[:name]
|
|
17
|
+
|
|
18
|
+
assert_equal "Thanksgiving (day 2)", (Holidays.on(Date.civil(2024, 5, 13), [:il])[0] || {})[:name]
|
|
19
|
+
|
|
20
|
+
assert_equal "Jewish New Year", (Holidays.on(Date.civil(2023, 9, 16), [:il])[0] || {})[:name]
|
|
21
|
+
|
|
22
|
+
assert_equal "2nd New Year's Day", (Holidays.on(Date.civil(2025, 9, 24), [:il])[0] || {})[:name]
|
|
23
|
+
|
|
24
|
+
assert_equal "Day of Atonement", (Holidays.on(Date.civil(2026, 9, 21), [:il])[0] || {})[:name]
|
|
25
|
+
|
|
26
|
+
assert_equal "Feast of Tabernacles", (Holidays.on(Date.civil(2024, 10, 17), [:il])[0] || {})[:name]
|
|
27
|
+
|
|
28
|
+
assert_equal "Rejoicing of the Torah", (Holidays.on(Date.civil(2025, 10, 15), [:il])[0] || {})[:name]
|
|
29
|
+
|
|
30
|
+
assert_nil (Holidays.on(Date.civil(2024, 7, 9), [:il])[0] || {})[:name]
|
|
31
|
+
|
|
32
|
+
assert_nil (Holidays.on(Date.civil(2026, 8, 15), [:il])[0] || {})[:name]
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
|
3
|
+
|
|
4
|
+
# This file is generated by the Ruby Holiday gem.
|
|
5
|
+
#
|
|
6
|
+
# Definitions loaded: definitions/mc.yaml
|
|
7
|
+
class McDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
8
|
+
|
|
9
|
+
def test_mc
|
|
10
|
+
assert_equal "Jour de l'an", (Holidays.on(Date.civil(2026, 1, 1), [:mc])[0] || {})[:name]
|
|
11
|
+
|
|
12
|
+
assert_equal "Sainte Dévote", (Holidays.on(Date.civil(2026, 1, 27), [:mc])[0] || {})[:name]
|
|
13
|
+
|
|
14
|
+
assert_equal "Lundi de Pâques", (Holidays.on(Date.civil(2026, 4, 6), [:mc])[0] || {})[:name]
|
|
15
|
+
|
|
16
|
+
assert_equal "Fête du Travail", (Holidays.on(Date.civil(2026, 5, 1), [:mc])[0] || {})[:name]
|
|
17
|
+
|
|
18
|
+
assert_equal "Ascension", (Holidays.on(Date.civil(2026, 5, 14), [:mc])[0] || {})[:name]
|
|
19
|
+
|
|
20
|
+
assert_equal "Lundi de Pentecôte", (Holidays.on(Date.civil(2026, 5, 25), [:mc])[0] || {})[:name]
|
|
21
|
+
|
|
22
|
+
assert_equal "Fête Dieu", (Holidays.on(Date.civil(2026, 6, 4), [:mc])[0] || {})[:name]
|
|
23
|
+
|
|
24
|
+
assert_equal "Assomption", (Holidays.on(Date.civil(2026, 8, 15), [:mc])[0] || {})[:name]
|
|
25
|
+
|
|
26
|
+
assert_equal "Toussaint", (Holidays.on(Date.civil(2026, 11, 1), [:mc])[0] || {})[:name]
|
|
27
|
+
|
|
28
|
+
assert_equal "Fête du Prince", (Holidays.on(Date.civil(2026, 11, 19), [:mc])[0] || {})[:name]
|
|
29
|
+
|
|
30
|
+
assert_equal "Immaculée Conception", (Holidays.on(Date.civil(2026, 12, 8), [:mc])[0] || {})[:name]
|
|
31
|
+
|
|
32
|
+
assert_equal "Noël", (Holidays.on(Date.civil(2026, 12, 25), [:mc])[0] || {})[:name]
|
|
33
|
+
|
|
34
|
+
assert_equal "Immaculée Conception", (Holidays.on(Date.civil(2024, 12, 8), [:mc])[0] || {})[:name]
|
|
35
|
+
|
|
36
|
+
assert_equal "Immaculée Conception", (Holidays.on(Date.civil(2024, 12, 9), [:mc], [:observed])[0] || {})[:name]
|
|
37
|
+
|
|
38
|
+
assert_equal "Toussaint", (Holidays.on(Date.civil(2026, 11, 1), [:mc])[0] || {})[:name]
|
|
39
|
+
|
|
40
|
+
assert_equal "Toussaint", (Holidays.on(Date.civil(2026, 11, 2), [:mc], [:observed])[0] || {})[:name]
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -443,7 +443,12 @@ assert_equal "Confederate Memorial Day", (Holidays.on(Date.civil(2026, 4, 27), [
|
|
|
443
443
|
assert_nil (Holidays.on(Date.civil(2021, 4, 26), [:us])[0] || {})[:name]
|
|
444
444
|
|
|
445
445
|
assert_equal "State Holiday", (Holidays.on(Date.civil(2015, 4, 20), [:us_ga])[0] || {})[:name]
|
|
446
|
-
|
|
446
|
+
|
|
447
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2020, 4, 10), [:us_ga])[0] || {})[:name]
|
|
448
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2021, 4, 2), [:us_ga])[0] || {})[:name]
|
|
449
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2022, 4, 15), [:us_ga])[0] || {})[:name]
|
|
450
|
+
|
|
451
|
+
assert_nil (Holidays.on(Date.civil(2021, 4, 26), [:us_ga])[0] || {})[:name]
|
|
447
452
|
|
|
448
453
|
assert_equal "Arbor Day", (Holidays.on(Date.civil(2017, 4, 28), [:us_ne])[0] || {})[:name]
|
|
449
454
|
assert_equal "Arbor Day", (Holidays.on(Date.civil(2025, 4, 25), [:us_ne])[0] || {})[:name]
|
data/test/defs/test_defs_us.rb
CHANGED
|
@@ -163,7 +163,12 @@ assert_equal "Confederate Memorial Day", (Holidays.on(Date.civil(2026, 4, 27), [
|
|
|
163
163
|
assert_nil (Holidays.on(Date.civil(2021, 4, 26), [:us])[0] || {})[:name]
|
|
164
164
|
|
|
165
165
|
assert_equal "State Holiday", (Holidays.on(Date.civil(2015, 4, 20), [:us_ga])[0] || {})[:name]
|
|
166
|
-
|
|
166
|
+
|
|
167
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2020, 4, 10), [:us_ga])[0] || {})[:name]
|
|
168
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2021, 4, 2), [:us_ga])[0] || {})[:name]
|
|
169
|
+
assert_equal "State Holiday", (Holidays.on(Date.civil(2022, 4, 15), [:us_ga])[0] || {})[:name]
|
|
170
|
+
|
|
171
|
+
assert_nil (Holidays.on(Date.civil(2021, 4, 26), [:us_ga])[0] || {})[:name]
|
|
167
172
|
|
|
168
173
|
assert_equal "Arbor Day", (Holidays.on(Date.civil(2017, 4, 28), [:us_ne])[0] || {})[:name]
|
|
169
174
|
assert_equal "Arbor Day", (Holidays.on(Date.civil(2025, 4, 25), [:us_ne])[0] || {})[:name]
|
data/test/e2e/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# End-to-end tests
|
|
2
|
+
|
|
3
|
+
End-user behavioral checks against the **real upstream definitions** in
|
|
4
|
+
`/definitions`. These tests load actual region data and assert specific
|
|
5
|
+
holiday names, dates, counts, and observed-date behavior, the kinds of
|
|
6
|
+
expectations a consumer of the gem would care about.
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
These tests verify that the full pipeline, from upstream YAML through
|
|
11
|
+
generation through gem processing to the public API, produces the results
|
|
12
|
+
an end user expects for real-world regions. They complement fixture-based
|
|
13
|
+
integration tests by catching content regressions in the gem's interaction
|
|
14
|
+
with real definitions.
|
|
15
|
+
|
|
16
|
+
## E2E tests vs. integration vs. smoke
|
|
17
|
+
|
|
18
|
+
- **Smoke** (`test/smoke/`): only asserts nothing crashes. Run from the
|
|
19
|
+
upstream `holidays/definitions` CI.
|
|
20
|
+
- **Integration** (`test/integration/`): verifies gem-wide behavior using
|
|
21
|
+
controlled fixture YAMLs. Stable across definitions changes.
|
|
22
|
+
- **E2E** (this directory): verifies end-user-perceived behavior using real
|
|
23
|
+
upstream definitions. Expected to break when upstream definitions change,
|
|
24
|
+
on purpose.
|
|
25
|
+
|
|
26
|
+
## Important
|
|
27
|
+
|
|
28
|
+
These tests are tightly coupled to the contents of `/definitions`. When you
|
|
29
|
+
update the definitions submodule and an upstream change shifts a holiday name,
|
|
30
|
+
date, or count, the corresponding e2e test must be updated to match. That is
|
|
31
|
+
working as intended: the test is the gem's record of what end users see, so
|
|
32
|
+
updating it is part of accepting the upstream change.
|
|
33
|
+
|
|
34
|
+
This directory is **not** run by the upstream `holidays/definitions` CI. Doing
|
|
35
|
+
so would create a dependency loop where the definitions repo cannot ship a
|
|
36
|
+
legitimate content change without also updating tests in this repo first.
|
|
37
|
+
|
|
38
|
+
## What belongs here
|
|
39
|
+
|
|
40
|
+
- Tests that assert specific holidays exist on specific dates for specific
|
|
41
|
+
regions using real definitions (e.g. `:ca` returns "Labour Day" on Sept 1, 2008).
|
|
42
|
+
- Tests of observed-date behavior against real region rules.
|
|
43
|
+
- Tests of sub-region inheritance, wildcards (`:ca_`), `:any`, and cross-region
|
|
44
|
+
conflicts using real data.
|
|
45
|
+
- Region-count or holiday-count assertions for specific year/region combinations.
|
|
46
|
+
|
|
47
|
+
## What does NOT belong here
|
|
48
|
+
|
|
49
|
+
- Tests that don't depend on real definitions content. Those belong in
|
|
50
|
+
`integration/` (with fixtures) or `smoke/` (structural only).
|
|
51
|
+
- Tests of a single file or class in isolation. Those are unit tests and
|
|
52
|
+
belong next to the code they cover.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
months:
|
|
2
|
+
0:
|
|
3
|
+
- name: With Function Modifier
|
|
4
|
+
regions: [multiple_with_conflict_3]
|
|
5
|
+
function: easter(year)
|
|
6
|
+
function_modifier: 70
|
|
7
|
+
- name: With Function Only Different Function Name
|
|
8
|
+
regions: [multiple_with_conflict_3]
|
|
9
|
+
function: conflict_custom_method_3(year)
|
|
10
|
+
- name: With Function Only Same Function Name
|
|
11
|
+
regions: [multiple_with_conflict_3]
|
|
12
|
+
function: conflict_custom_method_identical_name_between_regions(year)
|
|
13
|
+
- name: With Function Only Same Function Name - Region 3
|
|
14
|
+
regions: [multiple_with_conflict_3]
|
|
15
|
+
function: conflict_custom_method_identical_name_between_regions_but_different_holiday_names(year)
|
|
16
|
+
1:
|
|
17
|
+
- name: New Year's Day
|
|
18
|
+
regions: [multiple_with_conflict_3]
|
|
19
|
+
mday: 1
|
|
20
|
+
observed: to_monday_if_weekend(date)
|
|
21
|
+
10:
|
|
22
|
+
- name: Testing Conflict Month 10
|
|
23
|
+
regions: [multiple_with_conflict_3]
|
|
24
|
+
mday: 9
|
|
25
|
+
|
|
26
|
+
methods:
|
|
27
|
+
conflict_custom_method_3:
|
|
28
|
+
arguments: year
|
|
29
|
+
ruby: |
|
|
30
|
+
Date.civil(year, 4, 1)
|
|
31
|
+
conflict_custom_method_identical_name_between_regions:
|
|
32
|
+
arguments: year
|
|
33
|
+
ruby: |
|
|
34
|
+
Date.civil(year, 3, 1)
|
|
35
|
+
conflict_custom_method_identical_name_between_regions_but_different_holiday_names:
|
|
36
|
+
arguments: year
|
|
37
|
+
ruby: |
|
|
38
|
+
Date.civil(year, 3, 15)
|