ndr_support 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
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