ndr_support 3.1.1

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 (67) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +14 -0
  3. data/.rubocop.yml +27 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +22 -0
  6. data/CODE_OF_CONDUCT.md +13 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +16 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +91 -0
  11. data/Rakefile +12 -0
  12. data/code_safety.yml +258 -0
  13. data/gemfiles/Gemfile.rails32 +6 -0
  14. data/gemfiles/Gemfile.rails32.lock +108 -0
  15. data/gemfiles/Gemfile.rails41 +6 -0
  16. data/gemfiles/Gemfile.rails41.lock +111 -0
  17. data/gemfiles/Gemfile.rails42 +6 -0
  18. data/gemfiles/Gemfile.rails42.lock +111 -0
  19. data/lib/ndr_support.rb +21 -0
  20. data/lib/ndr_support/array.rb +52 -0
  21. data/lib/ndr_support/concerns/working_days.rb +94 -0
  22. data/lib/ndr_support/date_and_time_extensions.rb +103 -0
  23. data/lib/ndr_support/daterange.rb +196 -0
  24. data/lib/ndr_support/fixnum/calculations.rb +15 -0
  25. data/lib/ndr_support/fixnum/julian_date_conversions.rb +14 -0
  26. data/lib/ndr_support/hash.rb +52 -0
  27. data/lib/ndr_support/integer.rb +12 -0
  28. data/lib/ndr_support/nil.rb +38 -0
  29. data/lib/ndr_support/ourdate.rb +97 -0
  30. data/lib/ndr_support/ourtime.rb +51 -0
  31. data/lib/ndr_support/regexp_range.rb +65 -0
  32. data/lib/ndr_support/safe_file.rb +185 -0
  33. data/lib/ndr_support/safe_path.rb +268 -0
  34. data/lib/ndr_support/string/cleaning.rb +136 -0
  35. data/lib/ndr_support/string/conversions.rb +137 -0
  36. data/lib/ndr_support/tasks.rb +1 -0
  37. data/lib/ndr_support/time/conversions.rb +13 -0
  38. data/lib/ndr_support/utf8_encoding.rb +72 -0
  39. data/lib/ndr_support/utf8_encoding/control_characters.rb +53 -0
  40. data/lib/ndr_support/utf8_encoding/force_binary.rb +44 -0
  41. data/lib/ndr_support/utf8_encoding/object_support.rb +31 -0
  42. data/lib/ndr_support/version.rb +5 -0
  43. data/lib/ndr_support/yaml/serialization_migration.rb +65 -0
  44. data/lib/tasks/audit_code.rake +423 -0
  45. data/ndr_support.gemspec +39 -0
  46. data/test/array_test.rb +20 -0
  47. data/test/concerns/working_days_test.rb +122 -0
  48. data/test/daterange_test.rb +194 -0
  49. data/test/fixnum/calculations_test.rb +28 -0
  50. data/test/hash_test.rb +84 -0
  51. data/test/integer_test.rb +14 -0
  52. data/test/nil_test.rb +40 -0
  53. data/test/ourdate_test.rb +27 -0
  54. data/test/ourtime_test.rb +27 -0
  55. data/test/regexp_range_test.rb +135 -0
  56. data/test/resources/filesystem_paths.yml +37 -0
  57. data/test/safe_file_test.rb +597 -0
  58. data/test/safe_path_test.rb +168 -0
  59. data/test/string/cleaning_test.rb +176 -0
  60. data/test/string/conversions_test.rb +353 -0
  61. data/test/test_helper.rb +41 -0
  62. data/test/time/conversions_test.rb +15 -0
  63. data/test/utf8_encoding/control_characters_test.rb +84 -0
  64. data/test/utf8_encoding/force_binary_test.rb +64 -0
  65. data/test/utf8_encoding_test.rb +170 -0
  66. data/test/yaml/serialization_test.rb +145 -0
  67. metadata +295 -0
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ndr_support/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ndr_support'
8
+ spec.version = NdrSupport::VERSION
9
+ spec.authors = ['NCRS Development Team']
10
+ spec.email = []
11
+ spec.summary = 'NDR Support library'
12
+ spec.description = 'Provides NDR classes and class extensions'
13
+ spec.homepage = 'https://github.com/PublicHealthEngland/ndr_support'
14
+ spec.license = 'MIT'
15
+
16
+ # Exclude older versions of this gem from the package.
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |s| s =~ /^pkg\// }
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'activerecord', '>= 3.2.18', '< 5.0.0'
23
+ spec.add_dependency 'activesupport', '>= 3.2.18', '< 5.0.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.7'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+
28
+ spec.required_ruby_version = '>= 1.9.3'
29
+
30
+ # Avoid std-lib minitest (which has different namespace)
31
+ spec.add_development_dependency 'minitest', '>= 5.0.0'
32
+ spec.add_development_dependency 'mocha', '~> 1.1'
33
+
34
+ spec.add_development_dependency 'guard'
35
+ spec.add_development_dependency 'guard-rubocop'
36
+ spec.add_development_dependency 'guard-minitest'
37
+ spec.add_development_dependency 'terminal-notifier-guard' if RUBY_PLATFORM =~ /darwin/
38
+ spec.add_development_dependency 'simplecov'
39
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our Array extension
4
+ class ArrayTest < Minitest::Test
5
+ test 'Arrays should be extended with #permutations' do
6
+ assert [].respond_to?(:permutations)
7
+ end
8
+
9
+ test 'Array#permutations should calculate permutations correctly' do
10
+ array = [1, 2, 3]
11
+ permutations = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
12
+ assert_equal array.length.factorial, array.permutations.length
13
+ assert_equal permutations.sort, array.permutations.sort
14
+ end
15
+
16
+ test 'Array#permutations should permute duplicates' do
17
+ array = [1, 1]
18
+ assert_equal [[1, 1], [1, 1]], array.permutations
19
+ end
20
+ end
@@ -0,0 +1,122 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our WorkingDays Time/Date/DateTime extension
4
+ class WorkingDaysTest < Minitest::Test
5
+ def setup
6
+ @normal_date = Date.parse('2015-02-02') # Monday 2nd Feb 2015
7
+ @normal_time = Time.parse('2015-02-02 2pm') # Monday 2nd Feb 2015
8
+ @normal_date_time = DateTime.parse('2015-02-02 11am') # Monday 2nd Feb 2015
9
+
10
+ @easter_date = Date.parse('2015-04-06') # Easter Monday, 2015
11
+ @easter_time = Time.parse('2015-04-06 2pm') # Easter Monday, 2015
12
+ @easter_date_time = DateTime.parse('2015-04-06 11am') # Easter Monday, 2015
13
+ end
14
+
15
+ test 'should identify weekdays' do
16
+ assert Date.parse('2015-12-25').weekday?
17
+ assert Time.parse('2015-12-25 3pm').weekday?
18
+ assert DateTime.parse('2015-12-25 3pm').weekday?
19
+
20
+ refute Date.parse('2015-12-26').weekday?
21
+ refute Time.parse('2015-12-26 3pm').weekday?
22
+ refute DateTime.parse('2015-12-26 3pm').weekday?
23
+ end
24
+
25
+ test 'should identify bank holidays' do
26
+ assert Date.parse('2015-12-25').public_holiday?
27
+ assert Time.parse('2015-12-25 3pm').public_holiday?
28
+ assert DateTime.parse('2015-12-25 3pm').public_holiday?
29
+
30
+ # Boxing Day 2015 is a Saturday; the bank holiday a
31
+ # substitute day, on the following Monday:
32
+ refute Date.parse('2015-12-26').public_holiday?
33
+ refute Time.parse('2015-12-26 3pm').public_holiday?
34
+ refute DateTime.parse('2015-12-26 3pm').public_holiday?
35
+
36
+ assert Date.parse('2015-12-28').public_holiday?
37
+ assert Time.parse('2015-12-28 3pm').public_holiday?
38
+ assert DateTime.parse('2015-12-28 3pm').public_holiday?
39
+ end
40
+
41
+ test 'should allow comparison of Time and DateTime' do
42
+ @normal_time.working_days_until(@normal_date_time)
43
+ @normal_date_time.working_days_until(@normal_time)
44
+ end
45
+
46
+ test 'should allow comparison of DateTime and Date' do
47
+ @normal_date_time.working_days_until(@normal_date)
48
+ @normal_date.working_days_until(@normal_date_time)
49
+ end
50
+
51
+ test 'should be zero working days between same normal day' do
52
+ assert_equal 0, @normal_date.working_days_until(@normal_date)
53
+ assert_equal 0, @normal_time.working_days_until(@normal_time + 6.hours)
54
+ assert_equal 0, @normal_date_time.working_days_until(@normal_date_time + 6.hours)
55
+ end
56
+
57
+ test 'Monday -> Friday should be 4 working days' do
58
+ assert_equal 4, @normal_date.working_days_until(@normal_date + 4.days)
59
+ assert_equal 4, @normal_time.working_days_until(@normal_time + 4.days)
60
+ assert_equal 4, @normal_date_time.working_days_until(@normal_date_time + 4.days)
61
+ end
62
+
63
+ test 'Friday <- Monday should be -4 working days' do
64
+ assert_equal(-4, (@normal_date + 4.days).working_days_until(@normal_date))
65
+ assert_equal(-4, (@normal_time + 4.days).working_days_until(@normal_time))
66
+ assert_equal(-4, (@normal_date_time + 4.days).working_days_until(@normal_date_time))
67
+ end
68
+
69
+ test 'Saturday -> Sunday should be 0 working days' do
70
+ assert_equal 0, (@normal_date - 2.days).working_days_until(@normal_date - 1.day)
71
+ assert_equal 0, (@normal_time - 2.days).working_days_until(@normal_time - 1.day)
72
+ assert_equal 0, (@normal_date_time - 2.days).working_days_until(@normal_date_time - 1.day)
73
+ end
74
+
75
+ test 'Sunday <- Saturday should be 0 working days' do
76
+ assert_equal 0, (@normal_date - 1.day).working_days_until(@normal_date - 2.days)
77
+ assert_equal 0, (@normal_time - 1.day).working_days_until(@normal_time - 2.days)
78
+ assert_equal 0, (@normal_date_time - 1.day).working_days_until(@normal_date_time - 2.days)
79
+ end
80
+
81
+ test 'Monday -> next Monday should be 5 working days' do
82
+ assert_equal 5, @normal_date.working_days_until(@normal_date + 7.days)
83
+ assert_equal 5, @normal_time.working_days_until(@normal_time + 7.days)
84
+ assert_equal 5, @normal_date_time.working_days_until(@normal_date_time + 7.days)
85
+ end
86
+
87
+ test 'Monday -> Easter Monday should be 3 working days' do
88
+ assert_equal 3, (@easter_date - 7.days).working_days_until(@easter_date)
89
+ assert_equal 3, (@easter_time - 7.days).working_days_until(@easter_time)
90
+ assert_equal 3, (@easter_date_time - 7.days).working_days_until(@easter_date_time)
91
+ end
92
+
93
+ test 'Tuesday -> Tuesday over Easter should be 3 working days' do
94
+ assert_equal 3, (@easter_date - 6.days).working_days_until(@easter_date + 1.day)
95
+ assert_equal 3, (@easter_time - 6.days).working_days_until(@easter_time + 1.day)
96
+ assert_equal 3, (@easter_date_time - 6.days).working_days_until(@easter_date_time + 1.day)
97
+ end
98
+
99
+ test 'Good Friday -> Friday should be 4 working days' do
100
+ assert_equal 4, (@easter_date - 3.days).working_days_until(@easter_date + 4.day)
101
+ assert_equal 4, (@easter_time - 3.days).working_days_until(@easter_time + 4.day)
102
+ assert_equal 4, (@easter_date_time - 3.days).working_days_until(@easter_date_time + 4.day)
103
+ end
104
+
105
+ test 'Friday -> Monday should be 1 working day' do
106
+ assert_equal 1, (@normal_date - 3.days).working_days_until(@normal_date)
107
+ assert_equal 1, (@normal_time - 3.days).working_days_until(@normal_time)
108
+ assert_equal 1, (@normal_date_time - 3.days).working_days_until(@normal_date_time)
109
+ end
110
+
111
+ test 'A year of week days' do
112
+ assert_equal 261, @normal_date.weekdays_until(@normal_date + 1.year)
113
+ assert_equal 261, @normal_time.weekdays_until(@normal_time + 1.year)
114
+ assert_equal 261, @normal_date_time.weekdays_until(@normal_date_time + 1.year)
115
+ end
116
+
117
+ test 'A year of working days' do
118
+ assert_equal 253, @normal_date.working_days_until(@normal_date + 1.year)
119
+ assert_equal 253, @normal_time.working_days_until(@normal_time + 1.year)
120
+ assert_equal 253, @normal_date_time.working_days_until(@normal_date_time + 1.year)
121
+ end
122
+ end
@@ -0,0 +1,194 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our Daterange class
4
+ class DaterangeTest < Minitest::Test
5
+ def test_basic_creation
6
+ dr = Daterange.new
7
+ assert_equal '', dr.to_s
8
+ assert_nil dr.date1
9
+ assert_nil dr.date2
10
+ assert dr.empty?
11
+ assert dr.blank? # delegates to dr.empty?
12
+ end
13
+
14
+ def test_creation_from_dates
15
+ d = Date.today
16
+ dr = Daterange.new d, d
17
+ assert_nil dr.source
18
+ refute_nil dr.date1
19
+ refute_nil dr.date2
20
+ refute dr.empty?
21
+ assert_equal d.to_s, dr.to_s # because just one day
22
+ # assert_match(/\d\d\.\d\d\.\d\d\d\d/, dr.to_s) # default format
23
+ # dr = Daterange.new d, d + 1
24
+ # assert_match(/\d\d\.\d\d\.\d\d\d\d to \d\d.\d\d.\d\d\d\d/, dr.to_s)
25
+ end
26
+
27
+ def test_dates_in_reverse_order
28
+ d = Date.today
29
+ dr = Daterange.new d, d + 1
30
+ dr2 = Daterange.new d + 1, d
31
+ assert_equal(dr.to_s, dr2.to_s)
32
+ end
33
+
34
+ def test_illegal_strings
35
+ dr = Daterange.new('01/o1/2000')
36
+ assert_equal '', dr.to_s
37
+ assert_nil dr.date1
38
+ assert_nil dr.date2
39
+ refute dr.empty? # Illegal dates do not count as empty / blank,
40
+ refute_nil dr.source # but the illegal string is preserved
41
+ end
42
+
43
+ def test_out_of_range
44
+ dr = Daterange.new('31/12/1879')
45
+ assert_equal '', dr.to_s
46
+ assert_nil dr.date1
47
+ assert_nil dr.date2
48
+ end
49
+
50
+ def test_year_attributes
51
+ dr = Daterange.new('2000')
52
+ assert_equal '2000', dr.source
53
+ assert_equal '2000', dr.to_s
54
+ assert_equal '01.01.2000', dr.date1.to_s
55
+ assert_equal '31.12.2000', dr.date2.to_s
56
+ end
57
+
58
+ def test_year_range_attributes
59
+ dr = Daterange.new('1880 2020')
60
+ assert_equal '01.01.1880 to 31.12.2020', dr.to_s
61
+ assert_equal '01.01.1880', dr.date1.to_s
62
+ assert_equal '31.12.2020', dr.date2.to_s
63
+ assert_equal '1880 2020', dr.source
64
+ end
65
+
66
+ def test_hyphen_month_input_style
67
+ dr = Daterange.new('2000-05')
68
+ assert_equal '05.2000', dr.to_s
69
+ end
70
+
71
+ def test_dot_month_input_style
72
+ dr = Daterange.new('06.2000')
73
+ assert_equal '01.06.2000', dr.date1.to_s
74
+ assert_equal '30.06.2000', dr.date2.to_s
75
+ assert_equal '06.2000', dr.to_s
76
+ end
77
+
78
+ def test_forwardslash_month_input_style
79
+ dr = Daterange.new('07/2000')
80
+ assert_equal '07.2000', dr.to_s
81
+ assert_equal '01.07.2000', dr.date1.to_s
82
+ assert_equal '31.07.2000', dr.date2.to_s
83
+ end
84
+
85
+ def test_noseparator_month_input_style
86
+ dr = Daterange.new('082000')
87
+ assert_equal '08.2000', dr.to_s
88
+ assert_equal '01.08.2000', dr.date1.to_s
89
+ assert_equal '31.08.2000', dr.date2.to_s
90
+ end
91
+
92
+ def test_date_to_date_input_style
93
+ dr = Daterange.new('01.05.2000 to 31.05.2000')
94
+ assert_equal '05.2000', dr.to_s
95
+ assert_equal '01.05.2000', dr.date1.to_s
96
+ assert_equal '31.05.2000', dr.date2.to_s
97
+ dr = Daterange.new('2000 TO 2001')
98
+ assert_equal '01.01.2000 to 31.12.2001', dr.to_s
99
+ end
100
+
101
+ def test_hyphen_date_input_style
102
+ dr = Daterange.new('2000-09-12')
103
+ assert_equal '12.09.2000', dr.to_s
104
+ end
105
+
106
+ def test_forwardslash_date_input_style
107
+ dr = Daterange.new('13/09/2000')
108
+ assert_equal '13.09.2000', dr.to_s
109
+ end
110
+
111
+ def test_dot_date_input_style
112
+ dr = Daterange.new('14.09.2000')
113
+ assert_equal '14.09.2000', dr.to_s
114
+ end
115
+
116
+ def test_noseparator_date_input_style
117
+ dr = Daterange.new('15092000')
118
+ assert_equal '15.09.2000', dr.to_s
119
+ end
120
+
121
+ def test_spen_daylight_saving
122
+ dr = Daterange.new('03.2010') # Span time zones (daylight saving)
123
+ assert_equal '03.2010', dr.to_s # Ideally '03.2010'
124
+ end
125
+
126
+ def test_year_intersection
127
+ dr1 = Daterange.new('2001')
128
+ dr2 = Daterange.new('2002')
129
+ refute dr1.intersects?(dr2)
130
+ refute dr2.intersects?(dr1)
131
+
132
+ dr1 = Daterange.new('2001')
133
+ dr2 = Daterange.new('2001')
134
+ assert dr1.intersects?(dr2)
135
+ assert dr2.intersects?(dr1)
136
+ end
137
+
138
+ def test_year_range_intersection
139
+ dr1 = Daterange.new('2001 to 2003')
140
+ dr2 = Daterange.new('2002 to 2004')
141
+ assert dr1.intersects?(dr2)
142
+ assert dr2.intersects?(dr1)
143
+ end
144
+
145
+ def test_subset_intersection
146
+ dr1 = Daterange.new('01.05.2000 to 31.05.2000')
147
+ dr2 = Daterange.new('02.05.2000 to 30.05.2000')
148
+ assert dr1.intersects?(dr2)
149
+ assert dr2.intersects?(dr1)
150
+ end
151
+
152
+ def test_smallest_inhabited_intersection
153
+ dr1 = Daterange.new('01.05.2000 to 31.05.2000')
154
+ dr2 = Daterange.new('01.04.2000 to 01.05.2000')
155
+ assert dr1.intersects?(dr2)
156
+ assert dr2.intersects?(dr1)
157
+
158
+ dr1 = Daterange.new('01.05.2000 to 31.05.2000')
159
+ dr2 = Daterange.new('31.05.2000 to 01.06.2000')
160
+ assert dr1.intersects?(dr2)
161
+ assert dr2.intersects?(dr1)
162
+ end
163
+
164
+ def test_disjointed_intersection
165
+ dr1 = Daterange.new('02.05.2000 to 31.05.2000')
166
+ dr2 = Daterange.new('01.04.2000 to 01.05.2000')
167
+ refute dr1.intersects?(dr2)
168
+ refute dr2.intersects?(dr1)
169
+ end
170
+
171
+ def test_real_empty_intersection
172
+ dr1 = Daterange.new
173
+ dr2 = Daterange.new('01.04.2000 to 01.05.2000')
174
+ refute dr1.intersects?(dr2)
175
+ refute dr2.intersects?(dr1)
176
+
177
+ dr1 = Daterange.new('01.04.2000 to 01.05.2000')
178
+ dr2 = Daterange.new
179
+ refute dr1.intersects?(dr2)
180
+ refute dr2.intersects?(dr1)
181
+ end
182
+
183
+ def test_empty_empty_intersection
184
+ dr1 = Daterange.new
185
+ dr2 = Daterange.new
186
+ refute dr1.intersects?(dr2)
187
+ refute dr2.intersects?(dr1)
188
+ end
189
+
190
+ def test_merge
191
+ dr = Daterange.merge('2001, 30.04.2005, 2003,,')
192
+ assert_equal '01.01.2001 to 30.04.2005', dr.to_s
193
+ end
194
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our Fixnum calculations extension
4
+ class Fixnum::CalculationsTest < Minitest::Test
5
+ test 'Fixnums should be extended with #factorial' do
6
+ assert 1.respond_to?(:factorial)
7
+ end
8
+
9
+ test 'Fixnums#factorial should behave correctly' do
10
+ assert_equal 1, 0.factorial
11
+ assert_equal 24, 4.factorial
12
+ assert_raises(RuntimeError) { -1.factorial }
13
+ end
14
+
15
+ test 'Fixnums should be extended with #choose' do
16
+ assert 1.respond_to?(:choose)
17
+ end
18
+
19
+ test 'Fixnum#choose should behave correctly' do
20
+ pascal_row = [1, 5, 10, 10, 5, 1]
21
+ pascal_row.each_with_index do |target, index|
22
+ assert_equal target, 5.choose(index)
23
+ end
24
+
25
+ assert_raises(ArgumentError) { 10.choose(11) }
26
+ assert_raises(ArgumentError) { 10.choose(-1) }
27
+ end
28
+ end
data/test/hash_test.rb ADDED
@@ -0,0 +1,84 @@
1
+ require 'test_helper'
2
+
3
+ # This tests our Hash extension
4
+ class HashTest < Minitest::Test
5
+ test 'value_by_path' do
6
+ my_hash = { 'one' => '1', 'two' => { 'twopointone' => '2.1', 'twopointtwo' => '2.2' } }
7
+ assert_equal my_hash['one'], my_hash.value_by_path('one')
8
+ assert_equal my_hash['two']['twopointone'], my_hash.value_by_path('two', 'twopointone')
9
+ end
10
+
11
+ test 'intersection' do
12
+ my_hash = { :a => 1, :b => :two, 'c' => '3' }
13
+ assert_equal({ :a => 1, 'c' => '3' }, my_hash & [:a, :c])
14
+ assert_equal({ :b => :two }, my_hash & [:b])
15
+ assert_equal({}, my_hash & [:d, :e])
16
+ end
17
+
18
+ test 'rawtext_merge without prevent_overwrite' do
19
+ first_hash = { :a => 1, :b => :two, :rawtext => { 'x' => 'apples', 'y' => 'pears' } }
20
+ second_hash = { :b => 2, 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }
21
+ assert_equal(
22
+ {
23
+ :a => 1, :b => 2, 'c' => '3',
24
+ :rawtext => { 'x' => 'apples', 'y' => 'pears', 'z' => 'oranges' }
25
+ },
26
+ first_hash.rawtext_merge(second_hash, false)
27
+ )
28
+ # Ensure original hashes are preserved
29
+ assert_equal(
30
+ { :a => 1, :b => :two, :rawtext => { 'x' => 'apples', 'y' => 'pears' } }, first_hash
31
+ )
32
+ assert_equal(
33
+ { :b => 2, 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }, second_hash
34
+ )
35
+ end
36
+
37
+ test 'rawtext_merge with prevent_overwrite on rawtext' do
38
+ first_hash = { :a => 1, :b => :two, :rawtext => { 'x' => 'apples', 'y' => 'pears' } }
39
+ second_hash = { 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }
40
+ assert_raises RuntimeError do
41
+ first_hash.rawtext_merge(second_hash, true)
42
+ end
43
+ # Ensure original hashes are preserved
44
+ assert_equal(
45
+ { :a => 1, :b => :two, :rawtext => { 'x' => 'apples', 'y' => 'pears' } }, first_hash
46
+ )
47
+ assert_equal({ 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }, second_hash)
48
+ end
49
+
50
+ test 'rawtext_merge with prevent_overwrite on non-rawtext' do
51
+ first_hash = { :a => 1, :b => :two, :rawtext => { 'x' => 'apples' } }
52
+ second_hash = { :b => 2, 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }
53
+ assert_raises RuntimeError do
54
+ first_hash.rawtext_merge(second_hash, true)
55
+ end
56
+ # Ensure original hashes are preserved
57
+ assert_equal({ :a => 1, :b => :two, :rawtext => { 'x' => 'apples' } }, first_hash)
58
+ assert_equal(
59
+ { :b => 2, 'c' => '3', :rawtext => { 'y' => 'pears', 'z' => 'oranges' } }, second_hash
60
+ )
61
+ end
62
+
63
+ test 'rawtext_merge with one rawtext missing' do
64
+ first_hash = { :a => 1, :b => :two }
65
+ second_hash = { 'c' => '3', :rawtext => { 'x' => 'apples' } }
66
+ assert_equal({ :a => 1, :b => :two, 'c' => '3', :rawtext => { 'x' => 'apples' } },
67
+ first_hash.rawtext_merge(second_hash, false))
68
+ assert_equal({ :a => 1, :b => :two, 'c' => '3', :rawtext => { 'x' => 'apples' } },
69
+ second_hash.rawtext_merge(first_hash, false))
70
+ # Ensure original hashes are preserved
71
+ assert_equal({ :a => 1, :b => :two }, first_hash)
72
+ assert_equal({ 'c' => '3', :rawtext => { 'x' => 'apples' } }, second_hash)
73
+ end
74
+
75
+ test 'rawtext_merge with rawtext missing' do
76
+ first_hash = { :a => 1, :b => :two }
77
+ second_hash = { 'c' => '3' }
78
+ assert_equal({ :a => 1, :b => :two, 'c' => '3', :rawtext => {} },
79
+ first_hash.rawtext_merge(second_hash, false))
80
+ # Ensure original hashes are preserved
81
+ assert_equal({ :a => 1, :b => :two }, first_hash)
82
+ assert_equal({ 'c' => '3' }, second_hash)
83
+ end
84
+ end