turkish_support 1.1.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,15 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TurkishSupport
4
+ # :nodoc:
2
5
  refine Array do
3
6
  def sort
4
- sort_by do |item|
5
- item.chars.map do |ch|
6
- if ALPHABET.include?(ch)
7
- ASCII_ALPHABET[ch]
8
- else
9
- ch.ord
10
- end
11
- end
12
- end
7
+ return super if block_given?
8
+
9
+ sort_by { _1.chars.map { |ch| TurkishRanges::TrText.new(ch).code } }
13
10
  end
14
11
 
15
12
  def sort!
@@ -1,56 +1,30 @@
1
- module TurkishSupportHelpers
2
- ALPHA = {
3
- lower: 'abcçdefgğhıijklmnoöpqrsştuüvwxyz',
4
- upper: 'ABCÇDEFGĞHIİJKLMNOÖPQRSŞTUÜVWXYZ',
5
- tr_lower: 'çğıiöşü',
6
- tr_upper: 'ÇĞIİÖŞÜ'
7
- }.freeze
1
+ # frozen_string_literal: true
8
2
 
9
- ALPHABET = ALPHA[:upper] + ALPHA[:lower]
10
-
11
- ASCII_ALPHABET = ALPHABET.chars.map.with_index do |ch, i|
12
- # Add 65 to put special chars and numbers in correct order
13
- [ch, i + 65]
14
- end.to_h
15
-
16
- META_CHARS = {
17
- '\w' => '[\p{Latin}\d_]',
18
- '\W' => '[^\p{Latin}\d_]'
19
- }.freeze
3
+ module TurkishSupport
4
+ CASE_METHODS = %i[downcase
5
+ downcase!
6
+ upcase
7
+ upcase!
8
+ capitalize
9
+ capitalize!
10
+ swapcase
11
+ swapcase!].freeze
20
12
 
21
- # Regexp required methods
22
- RE_RE_METHS = %i(match scan).freeze
23
-
24
- # Regexp optional methods
25
- RE_OP_METHS = %i(
26
- []
27
- []=
28
- =~
29
- index
30
- rindex
31
- partition
32
- rpartition
33
- slice
34
- slice!
35
- split
36
- sub
37
- sub!
38
- gsub
39
- gsub!
40
- ).freeze
41
-
42
- CASE_RELATED_METHS = %i(
43
- downcase
44
- downcase!
45
- upcase
46
- upcase!
47
- capitalize
48
- capitalize!
49
- ).freeze
50
-
51
- RANGE_REGEXP = /\[[^\]]*?([#{ALPHABET}]-[#{ALPHABET}])[^\[]*?\]/
52
-
53
- CONJUCTIONS = %w(ve ile veya).freeze
54
-
55
- SPECIAL_CHARS = %q{("'}.freeze
13
+ REGEX_METHODS = %i[[]
14
+ []=
15
+ index
16
+ gsub
17
+ gsub!
18
+ match
19
+ rindex
20
+ partition
21
+ rpartition
22
+ scan
23
+ slice
24
+ slice!
25
+ split
26
+ sub
27
+ sub!
28
+ gsub
29
+ gsub!].freeze
56
30
  end
@@ -1,78 +1,56 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module TurkishSupport
2
4
  refine String do # rubocop:disable Metrics/BlockLength
3
- (RE_RE_METHS + RE_OP_METHS).each do |meth|
5
+ REGEX_METHODS.each do |meth|
4
6
  define_method meth do |*args|
5
- extend(TurkishSupportHelpers)
6
-
7
- if RE_RE_METHS.include?(meth) || args[0].is_a?(Regexp)
8
- args[0] = translate_regexp(args[0])
7
+ if args[0].is_a?(Regexp) || %i[match scan].include?(meth)
8
+ args[0] = TurkishRegexps::TrRegexp.new(args[0]).translate
9
9
  end
10
10
 
11
- super(*args)
11
+ instance_exec { super(*args) }
12
12
  end
13
13
  end
14
14
 
15
- CASE_RELATED_METHS.each do |meth|
16
- non_destructive = meth.to_s.chomp('!').to_sym
17
- define_method(meth) do
18
- extend(TurkishSupportHelpers)
19
- str = prepare_for(non_destructive, self).public_send(non_destructive)
20
- return meth.to_s.end_with?('!') ? public_send(:replace, str) : str
21
- end
22
- end
15
+ CASE_METHODS.each { define_method(_1) { super(:turkic) } }
23
16
 
24
- def titleize(conjuctions = true) # rubocop:disable Metrics/AbcSize
25
- split.map do |word|
26
- word.downcase!
27
- if conjuction?(word) && !conjuctions
28
- word
29
- elsif start_with_a_special_char?(word)
30
- word.size > 1 ? word[0] + word[1..-1].capitalize : word.chr
31
- else
32
- word.capitalize
33
- end
34
- end.join(' ')
17
+ # capitalize all words and returns a copy of the string
18
+ #
19
+ # @return [String]
20
+ def titleize
21
+ downcase.gsub(/\b\S/u).each { _1.upcase }
35
22
  end
36
23
 
37
- def titleize!(conjuctions = true)
38
- replace(titleize(conjuctions))
24
+ # capitalize all words in place
25
+ # @return [String]
26
+ def titleize!
27
+ replace(titleize)
39
28
  end
40
29
 
41
- def swapcase
42
- extend(TurkishSupportHelpers)
43
- chars.map do |ch|
44
- if tr_char?(ch)
45
- tr_lower?(ch) ? ch.upcase : ch.downcase
46
- else
47
- ch.public_send(:swapcase)
48
- end
49
- end.join
30
+ def casecmp(other) # :nodoc:
31
+ upcase.instance_exec { super(other.upcase) }
50
32
  end
51
33
 
52
- def swapcase!
53
- replace(swapcase)
54
- end
34
+ def <=>(other) # :nodoc:
35
+ return nil unless other.is_a? String
55
36
 
56
- def casecmp(other_string)
57
- upcase.public_send(:casecmp, other_string.upcase)
37
+ TurkishRanges::TrText.new(to_s) <=> TurkishRanges::TrText.new(other)
58
38
  end
59
39
 
60
- def <=>(other_string)
61
- return nil unless other_string.is_a? String
40
+ def >(other) # :nodoc:
41
+ (self <=> other) == 1
42
+ end
62
43
 
63
- each_char.with_index do |ch, i|
64
- position1 = ASCII_ALPHABET[ch]
65
- position2 = ASCII_ALPHABET[other_string[i]]
44
+ def <(other) # :nodoc:
45
+ (self <=> other) == -1
46
+ end
66
47
 
67
- return (position2.nil? ? 0 : -1) if position1.nil?
68
- return 1 if position2.nil?
69
- return (position1 < position2 ? -1 : 1) if position1 != position2
70
- end
48
+ def >=(other) # :nodoc:
49
+ (self <=> other) != -1
50
+ end
71
51
 
72
- return 0 if length == other_string.length
73
- return -1 if length < other_string.length
74
- return 1
75
-
52
+ def <=(other) # :nodoc:
53
+ (self <=> other) != 1
76
54
  end
77
55
  end
78
56
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TurkishSupport
2
- VERSION = '1.1.0'.freeze
4
+ VERSION = '2.1.0'
3
5
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: false
2
+
3
+ using TurkishSupport
4
+
5
+ describe 'Array' do
6
+ describe '#sort' do
7
+ let(:samples) do
8
+ [{ mixed: %w[bağcılar bahçelievler şimdi çüNKÜ olmalı üç\ kere düş ılık duy],
9
+ sorted: %w[bağcılar bahçelievler çüNKÜ duy düş ılık olmalı şimdi üç\ kere] },
10
+ { mixed: %w[iki Üç dört ılık İğne iyne Ul],
11
+ sorted: %w[İğne Ul Üç dört ılık iki iyne] },
12
+ { mixed: %w[Sıtkı1\ Bağdat Sıtkı\ Bağdat a 3s 2\ b ab\ ],
13
+ sorted: %w[2\ b 3s Sıtkı\ Bağdat Sıtkı1\ Bağdat a ab\ ] }]
14
+ end
15
+ let(:block_samples) do
16
+ [{ mixed: %w[ağa aça aşa aöa aüa aua afa aba],
17
+ sorted: { "a[1]<=>b[1]": %w[aba aça afa ağa aöa aşa aua aüa],
18
+ "b[1]<=>a[1]": %w[aüa aua aşa aöa ağa afa aça aba] } },
19
+ { mixed: %w[iki Üç dört ılık İğne iyne Ul],
20
+ sorted: { "a.length<=>b.length": %w[Üç Ul iki dört ılık İğne iyne],
21
+ "b.length<=>a.length": %w[dört ılık İğne iyne iki Üç Ul] } },
22
+ { mixed: [['Şakir', 2], ['İsmet', 0], ['Zeliha', 1]],
23
+ sorted: { "a[1]<=>b[1]": [['İsmet', 0], ['Zeliha', 1], ['Şakir', 2]],
24
+ "b[0]<=>a[0]": [['Zeliha', 1], ['Şakir', 2], ['İsmet', 0]] } }]
25
+ end
26
+
27
+ context 'nondestructive version' do
28
+ context 'no block given' do
29
+ it 'does not change the original value of the array' do
30
+ samples.each do |sample|
31
+ expect { sample[:mixed].sort }.to_not(change { sample[:mixed] })
32
+ end
33
+ end
34
+
35
+ it 'sorts array in alphabetical order' do
36
+ samples.each do |sample|
37
+ expect(sample[:mixed].sort).to eq(sample[:sorted])
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'block given' do
43
+ it 'sorts array for random conditions' do
44
+ sample = block_samples.first
45
+ expect(sample[:mixed].sort { |a, b| a[1] <=> b[1] })
46
+ .to eq(sample[:sorted][:"a[1]<=>b[1]"])
47
+ expect(sample[:mixed].sort { |a, b| b[1] <=> a[1] })
48
+ .to eq(sample[:sorted][:"b[1]<=>a[1]"])
49
+ sample = block_samples[1]
50
+ expect(sample[:mixed].sort { |a, b| a.length <=> b.length })
51
+ .to eq(sample[:sorted][:"a.length<=>b.length"])
52
+ expect(sample[:mixed].sort { |a, b| b.length <=> a.length })
53
+ .to eq(sample[:sorted][:"b.length<=>a.length"])
54
+ end
55
+
56
+ it 'sorts nested arrays' do
57
+ sample = block_samples[2]
58
+ expect(sample[:mixed].sort { |a, b| a[1] <=> b[1] })
59
+ .to eq(sample[:sorted][:"a[1]<=>b[1]"])
60
+ expect(sample[:mixed].sort { |a, b| b[0] <=> a[0] })
61
+ .to eq(sample[:sorted][:"b[0]<=>a[0]"])
62
+ end
63
+ end
64
+ end
65
+
66
+ context 'with destructive version' do
67
+ it 'changes the original value of the array' do
68
+ samples.each do |sample|
69
+ expect { sample[:mixed].sort! }.to(change { sample[:mixed] })
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,2 +1,4 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
2
4
  require 'turkish_support'
@@ -0,0 +1,467 @@
1
+ # frozen_string_literal: false
2
+
3
+ using TurkishSupport
4
+
5
+ module TurkishSupport # rubocop:disable Metrics/ModuleLength
6
+ describe String do
7
+ let(:downcased_turkish_alphabet) { 'abcçdefgğhıijklmnoöprsştuüvyz' }
8
+ let(:upcased_turkish_alphabet) { 'ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ' }
9
+ let(:downcased_english_alphabet) { ('a'..'z').to_a.join }
10
+ let(:upcased_english_alphabet) { ('A'..'Z').to_a.join }
11
+ let(:turkish_words) { %w[çamur ıhlamur insan ördek şahika ümraniye] }
12
+
13
+ describe '#[]' do
14
+ context 'with non-destructive version' do
15
+ it 'does not change the original value of the string' do
16
+ word = turkish_words.sample
17
+
18
+ expect { word[/\w+/] }.to_not(change { word })
19
+ end
20
+
21
+ it 'is able to capture Turkish characters' do
22
+ expect(turkish_words.all? { |w| w[/\w+/] == w }).to be true
23
+ expect(turkish_words.all? { |w| w[/[a-z]+/] == w }).to be true
24
+ expect(turkish_words.map(&:upcase).all? { |w| w[/[a-z]+/i] == w }).to be true
25
+ end
26
+ end
27
+
28
+ context 'with destructive version' do
29
+ it 'changes the original value of the string' do
30
+ word = turkish_words.sample
31
+
32
+ expect { word[/\w+/] = 'new value' }.to(change { word })
33
+ expect(word).to eq('new value')
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#index' do
39
+ it 'does not change the original value of the string' do
40
+ word = turkish_words.sample
41
+
42
+ expect { word.index(/\w+/) }.to_not(change { word })
43
+ end
44
+
45
+ it 'is able to capture Turkish characters' do
46
+ expect(turkish_words.all? { |w| w.index(/\w+/).zero? }).to be true
47
+ expect(turkish_words.all? { |w| w.index(/[a-z]+/).zero? }).to be true
48
+ expect(turkish_words.map(&:upcase).all? { |w| w.index(/[a-z]+/i).zero? }).to be true
49
+ end
50
+
51
+ it 'begins to search from the right position' do
52
+ expect('şç-!+*/-ğüı'.index(/\w+/, 2)).to be 8
53
+ end
54
+ end
55
+
56
+ describe '#rindex' do
57
+ it 'does not change the original value of the string' do
58
+ word = turkish_words.sample
59
+
60
+ expect { word.rindex(/\w+/) }.to_not(change { word })
61
+ end
62
+
63
+ it 'is able to capture Turkish characters' do
64
+ expect(turkish_words.map(&:reverse).all? { |w| w.rindex(/\w+/) == w.size - 1 }).to be true
65
+ expect(turkish_words.map(&:reverse).all? { |w| w.rindex(/[a-z]+/) == w.size - 1 }).to be true
66
+ expect(turkish_words.map { |w| w.upcase.reverse }.all? { |w| w.rindex(/[a-z]+/i) == w.size - 1 }).to be true
67
+ end
68
+
69
+ it 'finishes the searching to the right position' do
70
+ expect('şç-!+*/-ğüı'.rindex(/\w+/, 7)).to be 1
71
+ end
72
+ end
73
+
74
+ describe '#partition' do
75
+ let(:word1) { turkish_words.sample }
76
+ let(:word2) { turkish_words.sample }
77
+ let(:two_words) { "#{word1} #{word2}" }
78
+
79
+ it 'does not change the original value of the string' do
80
+ expect { two_words.partition(/\W+/) }.to_not(change { two_words })
81
+ end
82
+
83
+ it 'is able to capture Turkish characters' do
84
+ expect(two_words.partition(/\W+/)).to(eq([word1, ' ', word2]))
85
+ end
86
+ end
87
+
88
+ describe '#rpartition' do
89
+ let(:word1) { turkish_words.sample }
90
+ let(:word2) { turkish_words.sample }
91
+ let(:word3) { turkish_words.sample }
92
+ let(:three_words) { "#{word1} #{word2} #{word3}" }
93
+
94
+ it 'does not change the original value of the string' do
95
+ expect { three_words.rpartition(/\W+/) }.to_not(change { three_words })
96
+ end
97
+
98
+ it 'is able to capture Turkish characters' do
99
+ expect(three_words.rpartition(/\W+/)).to(eq(["#{word1} #{word2}", ' ', word3]))
100
+ end
101
+ end
102
+
103
+ describe '#slice' do
104
+ context 'with non-destructive version' do
105
+ it 'does not change the original value of the string' do
106
+ sentence = turkish_words * ' '
107
+
108
+ expect { sentence.slice(/\w+/) }.to_not(change { sentence })
109
+ end
110
+
111
+ it 'is able to capture Turkish characters' do
112
+ expect(turkish_words.all? { |w| w.slice(/\w+/) == w }).to be true
113
+ expect(turkish_words.all? { |w| w.slice(/[a-z]+/) == w }).to be true
114
+ expect(turkish_words.map(&:upcase).all? { |w| w.slice(/[a-z]+/i) == w }).to be true
115
+ end
116
+ end
117
+
118
+ context 'with destructive version' do
119
+ it 'changes the original value of the string' do
120
+ sentence = turkish_words * ' '
121
+
122
+ expect { sentence.slice!(/\w+/) }.to(change { sentence })
123
+ expect(sentence).to eq(" #{turkish_words[1..] * ' '}")
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '#split' do
129
+ it 'is able to capture Turkish characters' do
130
+ expect(turkish_words.join(' ').split(/\w+/).join.strip.empty?).to be true
131
+ expect(turkish_words.join(' ').split(/[a-z]+/).join.strip.empty?).to be true
132
+ expect(turkish_words.join(' ').upcase.split(/[a-z]+/i).join.strip.empty?).to be true
133
+ end
134
+ end
135
+
136
+ describe '#upcase' do
137
+ context 'with non-destructive version' do
138
+ it 'does not change the original value of the string' do
139
+ expect { downcased_turkish_alphabet.upcase }.to_not(change { downcased_turkish_alphabet })
140
+ end
141
+
142
+ it 'upcases all of Turkish characters' do
143
+ upcased_string = downcased_turkish_alphabet.upcase
144
+
145
+ expect(upcased_string).to(eq(upcased_turkish_alphabet))
146
+ end
147
+
148
+ it 'upcases English characters except i as I' do
149
+ upcased_string = downcased_english_alphabet.upcase
150
+
151
+ expect(upcased_string).to eq upcased_english_alphabet.tr('I', 'İ')
152
+ end
153
+ end
154
+
155
+ context 'with destructive version' do
156
+ it 'changes the original value of the string' do
157
+ expect { downcased_turkish_alphabet.upcase! }.to(change { downcased_turkish_alphabet })
158
+ expect(downcased_turkish_alphabet).to(eq(upcased_turkish_alphabet))
159
+ end
160
+ end
161
+ end
162
+
163
+ describe '#downcase' do
164
+ context 'with non-destructive version' do
165
+ it 'does not change the original value of the string' do
166
+ expect { upcased_turkish_alphabet.downcase }.to_not(change { upcased_turkish_alphabet })
167
+ end
168
+
169
+ it 'downcases all of Turkish characters' do
170
+ downcased_string = upcased_turkish_alphabet.downcase
171
+ expect(downcased_string).to eq downcased_turkish_alphabet
172
+ end
173
+
174
+ it 'downcases English characters except I as ı' do
175
+ downcased_string = upcased_english_alphabet.downcase
176
+ expect(downcased_string).to eq downcased_english_alphabet.tr('i', 'ı')
177
+ end
178
+ end
179
+
180
+ context 'with destructive version' do
181
+ it 'changes the original value of the string' do
182
+ expect { upcased_turkish_alphabet.downcase! }.to(change { upcased_turkish_alphabet })
183
+ expect(upcased_turkish_alphabet).to(eq(downcased_turkish_alphabet))
184
+ end
185
+ end
186
+ end
187
+
188
+ describe '#capitalize' do
189
+ context 'with non-destructive version' do
190
+ it 'does not change the original value of the string' do
191
+ turkish_word = turkish_words.sample
192
+
193
+ expect { turkish_word.capitalize }.to_not(change { turkish_word })
194
+ end
195
+
196
+ it 'capitalizes the leading first Turkish character' do
197
+ capitalized_words = turkish_words.map(&:capitalize)
198
+
199
+ expect(capitalized_words).to eq %w[Çamur Ihlamur İnsan Ördek Şahika Ümraniye]
200
+ end
201
+
202
+ it 'capitalizes the first character of a string and downcase others' do
203
+ expect('türkÇE desteĞİ'.capitalize).to eq 'Türkçe desteği'
204
+ end
205
+
206
+ it 'capitalizes the first character of an English string' do
207
+ english_word = 'spy'
208
+
209
+ expect(english_word.capitalize).to eq 'Spy'
210
+ end
211
+ end
212
+
213
+ context 'with destructive version' do
214
+ it 'changes the original value of the string' do
215
+ turkish_word = 'çamur'
216
+
217
+ expect { turkish_word.capitalize! }.to(change { turkish_word })
218
+ expect(turkish_word).to eq('Çamur')
219
+ end
220
+ end
221
+ end
222
+
223
+ describe '#casecmp' do
224
+ it 'compares Turkish characters correctly' do
225
+ result = downcased_turkish_alphabet.casecmp(upcased_turkish_alphabet)
226
+
227
+ expect(result.zero?).to be true
228
+ end
229
+
230
+ it 'compares Turkish characters correctly' do
231
+ expect('sıtkı'.casecmp('SıTKI')&.zero?).to be true
232
+ end
233
+ end
234
+
235
+ describe '#titleize' do
236
+ context 'with non-destructive version' do
237
+ it 'does not change the original value of the string' do
238
+ word = 'mERHABA çAMUR iSMETOĞULLARI'
239
+
240
+ expect { word.titleize }.to_not(change { word })
241
+ end
242
+
243
+ it 'upcases first character of all words' do
244
+ titleized = 'merhaba çamur ismet'.titleize
245
+
246
+ expect(titleized).to(eq('Merhaba Çamur İsmet'))
247
+ end
248
+
249
+ it 'no problem with words that consist of special chars only' do
250
+ titleized = '(( merhaba çamur ismet'.titleize
251
+
252
+ expect(titleized).to(eq('(( Merhaba Çamur İsmet'))
253
+ end
254
+
255
+ it 'downcases characters other than first characters of all words' do
256
+ titleized = 'mERHABA çAMUR iSMETOĞULLARI'.titleize
257
+
258
+ expect(titleized).to(eq('Merhaba Çamur İsmetoğulları'))
259
+ end
260
+
261
+ it 'support strings that include paranthesis, quotes, etc.' do
262
+ titleized = "rUBY roCkS... (really! 'tRUSt' ME)".titleize
263
+
264
+ expect(titleized).to(eq("Ruby Rocks... (Really! 'Trust' Me)"))
265
+ end
266
+ end
267
+
268
+ context 'with destructive version' do
269
+ it 'changes the original value of the string' do
270
+ word = 'mERHABA çAMUR iSMETOĞULLARI'
271
+
272
+ expect { word.titleize! }.to(change { word })
273
+ expect(word).to(eq('Merhaba Çamur İsmetoğulları'))
274
+ end
275
+ end
276
+ end
277
+
278
+ describe '#swapcase' do
279
+ context 'with non-destructive version' do
280
+ it 'does not change the original value of the string' do
281
+ word = 'mErHaba çamur ismetoğullarI'
282
+
283
+ expect { word.swapcase }.to_not(change { word })
284
+ end
285
+
286
+ it 'swaps characters correctly' do
287
+ word = 'mErHaba çamur ismetoğullarI'.swapcase
288
+
289
+ expect(word).to(eq('MeRhABA ÇAMUR İSMETOĞULLARı'))
290
+ end
291
+ end
292
+
293
+ context 'with destructive version' do
294
+ it 'changes the original value of the string' do
295
+ word = 'mErHaba çamur ismetoğullarI'
296
+
297
+ expect { word.swapcase! }.to(change { word })
298
+ expect(word).to(eq('MeRhABA ÇAMUR İSMETOĞULLARı'))
299
+ end
300
+ end
301
+ end
302
+
303
+ describe '#match' do
304
+ it "matches Turkish characters when regex include '\\w'" do
305
+ expect('Aşağı'.match(/\w+/).to_s).to(eq('Aşağı'))
306
+ expect('Aşağı Ayrancı'.match(/^\w+\s\w+$/).to_s).to(eq('Aşağı Ayrancı'))
307
+ end
308
+
309
+ it 'matches Turkish characters when regex include lowercase range' do
310
+ expect('aüvvağğ öövvaağ'.match(/^[a-z]+\s[a-z]+$/).to_s).to(eq('aüvvağğ öövvaağ'))
311
+ end
312
+
313
+ it 'matches Turkish characters when regex include uppercase range' do
314
+ expect('BAĞCIlar'.match(/[A-Z]+/).to_s).to(eq('BAĞCI'))
315
+ end
316
+
317
+ it "doesn't match Turkish characters when regex include '\\W'" do
318
+ expect('Aşağı Ayrancı'.match(/\W+/).to_s).to(eq(' '))
319
+ end
320
+ end
321
+
322
+ describe '#scan' do
323
+ it "matches Turkish characters when regex include '\\w'" do
324
+ expect(turkish_words.join(' ').scan(/\w+/)).to eq(turkish_words)
325
+ end
326
+
327
+ it 'matches Turkish characters when regex include lowercase range' do
328
+ expect(turkish_words.join(' ').scan(/^[a-z\s]+$/)).to(eq([turkish_words.join(' ')]))
329
+ end
330
+
331
+ it 'matches Turkish characters when regex include uppercase range' do
332
+ expect(turkish_words.join(' ').upcase.scan(/^[A-Z\s]+$/)).to(eq([turkish_words.join(' ').upcase]))
333
+ end
334
+
335
+ it "matches Turkish characters when regex include '\\w'" do
336
+ expect(turkish_words.join(' ').scan(/\W+/).map(&:strip).all?(&:empty?)).to be true
337
+ end
338
+ end
339
+
340
+ describe '#sub' do
341
+ context 'non-destructive version' do
342
+ it 'does not affect the object' do
343
+ word = 'ağapaşa ağa'
344
+
345
+ expect { word.sub(/\w+/, 'bey') }.to_not(change { word })
346
+ end
347
+
348
+ it 'matches Turkish characters, and replaces them' do
349
+ expect('ağapaşa ağa'.sub(/\w+/, 'bey')).to(eq('bey ağa'))
350
+ expect('ağapaşa ağa şapka'.sub(/\W+/, 'bey')).to(eq('ağapaşabeyağa şapka'))
351
+ expect('ağapaşaağa'.sub(/[a-h]+/, 'bey')).to(eq('beypaşaağa'))
352
+ end
353
+ end
354
+
355
+ context 'destructive version' do
356
+ it 'affects the object' do
357
+ word = 'ağapaşa ağa'
358
+
359
+ expect { word.sub!(/\w+/, 'bey') }.to(change { word }.from('ağapaşa ağa').to('bey ağa'))
360
+ end
361
+ end
362
+ end
363
+
364
+ describe '#gsub' do
365
+ context 'non-destructive version' do
366
+ it 'does not affect the object' do
367
+ word = 'ağapaşa ağa'
368
+
369
+ expect { word.gsub(/\w+/, 'bey') }.to_not(change { word })
370
+ end
371
+
372
+ it 'matches Turkish characters, and replaces them' do
373
+ expect('ağapaşa ağa'.gsub(/\w+/, 'bey')).to(eq('bey bey'))
374
+ expect('ağapaşa ağa şapka'.gsub(/\W+/, 'bey')).to(eq('ağapaşabeyağabeyşapka'))
375
+ expect('ağapaşaağa'.gsub(/[a-h]+/, 'bey')).to(eq('beypbeyşbey'))
376
+ end
377
+ end
378
+
379
+ context 'destructive version' do
380
+ it 'affects the object' do
381
+ word = 'ağapaşa ağa'
382
+
383
+ expect { word.gsub!(/\w+/, 'bey') }.to(change { word }.from('ağapaşa ağa').to('bey bey'))
384
+ end
385
+ end
386
+ end
387
+
388
+ describe '#>' do
389
+ it 'should compares turkish cars correctly' do
390
+ expect('d' > 'ç').to be true
391
+ expect('ağa' > 'aga').to be true
392
+ expect('ğ' > 'h').to be false
393
+ end
394
+ end
395
+
396
+ describe '#>=' do
397
+ it 'should compares turkish cars correctly' do
398
+ expect('d' >= 'ç').to be true
399
+ expect('aha' >= 'ağa').to be true
400
+ expect('ğ.' >= 'ğ').to be true
401
+ end
402
+ end
403
+
404
+ describe '#<' do
405
+ it 'should compares turkish cars correctly' do
406
+ expect('d' < 'ç').to be false
407
+ expect('ağa' < 'aga').to be false
408
+ expect('ğ' < 'h').to be true
409
+ end
410
+ end
411
+
412
+ describe '#<=' do
413
+ it 'should compares turkish cars correctly' do
414
+ expect('d' <= 'ç').to be false
415
+ expect('aha' <= 'ağa').to be false
416
+ expect('ğ.' <= 'ğ').to be false
417
+ end
418
+ end
419
+
420
+ describe '#<=>' do
421
+ let(:sorted_equal_length_strings) { %w[Cahit Çağla Ömer Sıtkı Şakir] }
422
+ let(:sorted_different_length_strings) { %w[c ca falan om saki sıt] }
423
+ context 'with equal length strings' do
424
+ it 'works for smaller test' do
425
+ 0.upto(sorted_equal_length_strings.length - 2) do |i|
426
+ expect(sorted_equal_length_strings[i] <=> sorted_equal_length_strings[i + 1]).to(eq(-1))
427
+ end
428
+ end
429
+
430
+ it 'works for bigger test' do
431
+ (sorted_equal_length_strings.length - 1).downto(1) do |i|
432
+ expect(sorted_equal_length_strings[i] <=> sorted_equal_length_strings[i - 1]).to(eq(1))
433
+ end
434
+ end
435
+
436
+ it 'works for equals test' do
437
+ sorted_equal_length_strings.each do |str|
438
+ expect(str <=> str).to eq(0) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
439
+ end
440
+ end
441
+ end
442
+
443
+ context 'with different length strings' do
444
+ it 'works for smaller test' do
445
+ 0.upto(sorted_different_length_strings.length - 2) do |i|
446
+ expect(sorted_different_length_strings[i] <=> sorted_different_length_strings[i + 1]).to eq(-1)
447
+ end
448
+ end
449
+
450
+ it 'works for bigger test' do
451
+ (sorted_different_length_strings.length - 1).downto(1) do |i|
452
+ expect(sorted_different_length_strings[i] <=> sorted_different_length_strings[i - 1]).to eq(1)
453
+ end
454
+ end
455
+ end
456
+
457
+ context 'invalid comparisons' do
458
+ it 'returns nil' do
459
+ expect('a' <=> 3.5).to be nil
460
+ expect('a' <=> true).to be nil
461
+ expect('a' <=> Object.new).to be nil
462
+ expect('a' <=> 1).to be nil
463
+ end
464
+ end
465
+ end
466
+ end
467
+ end