web-utils 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/web_utils.rb +153 -69
- data/test/test_web_utils.rb +22 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74c9972b2a2cfeb97d05475c3833378dfe7b83350e5764e281888c3f7e206b67
|
4
|
+
data.tar.gz: 82f8929a62f9b94e130514f9191f0be756b7f7ef49ab1e6e5105113d53068ce4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4488aa8e08eddc957a2626662bc3eda75b59c049435e9f4b37eb2cbd6574335d178373c0cf97e289797b9451966838017753f2c2e15e21f4fe751cb4bde55def
|
7
|
+
data.tar.gz: 144b9995c41472af73386bfe7ffa1a4e0f4df5f5dca6d929dbd10a0118c42a265b0d99ef753f2916935535e182580038b1c51fcf85c679c84a69ffa17f2f4ed1
|
data/lib/web_utils.rb
CHANGED
@@ -5,59 +5,104 @@ require 'uri'
|
|
5
5
|
|
6
6
|
module WebUtils
|
7
7
|
|
8
|
-
VERSION = '0.1.
|
8
|
+
VERSION = '0.1.5'.freeze
|
9
9
|
|
10
10
|
# Most methods are supposed to be as simple as possible
|
11
11
|
# and just cover most cases.
|
12
|
-
# I would rather override specific cases
|
12
|
+
# I would rather override specific cases than making
|
13
13
|
# complicated methods.
|
14
14
|
|
15
15
|
extend Rack::Utils
|
16
16
|
|
17
|
+
# Global string constants
|
18
|
+
EMPTY_STRING = ''.freeze
|
19
|
+
IES_STRING = 'ies'.freeze
|
20
|
+
E_STRING = 'e'.freeze
|
21
|
+
S_STRING = 's'.freeze
|
22
|
+
Y_STRING = 'y'.freeze
|
23
|
+
X_STRING = 'x'.freeze
|
24
|
+
XES_STRING = 'xes'.freeze
|
25
|
+
SPACE = ' '.freeze
|
26
|
+
DASH = '-'.freeze
|
27
|
+
UNDERSCORE = '_'.freeze
|
28
|
+
AMPERSAND = '&'.freeze
|
29
|
+
PERCENT = '%'.freeze
|
30
|
+
PIPE = '|'
|
31
|
+
DOT = '.'.freeze
|
32
|
+
COMMA = ','.freeze
|
33
|
+
CONST_SEP = '::'.freeze
|
34
|
+
ELLIPSIS = '...'
|
35
|
+
AND_STRING = 'and'.freeze
|
36
|
+
SPACE_PERCENT_STRING = ' percent'.freeze
|
37
|
+
TRUE_STRING = 'true'.freeze
|
38
|
+
FALSE_STRING = 'false'.freeze
|
39
|
+
BR_TAG = '<br>'.freeze
|
40
|
+
ARG1_SUB = '\1'.freeze
|
41
|
+
|
42
|
+
# From then on, constants preceed the methods they are
|
43
|
+
# used on.
|
44
|
+
|
45
|
+
BLANK_RE = /\A[[:space:]]*\z/.freeze
|
46
|
+
|
17
47
|
def blank? s
|
18
|
-
s.
|
48
|
+
return true if s.nil?
|
49
|
+
# Not much difference with strip on benchmarks
|
50
|
+
# return (s.empty? or BLANK_RE.match?(s)) if s.is_a?(String)
|
51
|
+
return (s.strip.empty?) if s.is_a?(String)
|
52
|
+
return s.empty? if s.respond_to?(:empty?)
|
53
|
+
return true if s==false
|
54
|
+
false
|
19
55
|
end
|
20
56
|
module_function :blank?
|
21
57
|
|
58
|
+
PLURAL_RE = /([b-df-hj-np-tv-z])ys\z/.freeze
|
59
|
+
PLURAL_SUB = '\1ies'.freeze
|
60
|
+
|
22
61
|
def pluralize s
|
23
|
-
s
|
24
|
-
s<<
|
25
|
-
s
|
62
|
+
s = s.dup
|
63
|
+
s<<E_STRING if s[-1,1]==X_STRING
|
64
|
+
s<<S_STRING
|
65
|
+
s.sub PLURAL_RE, PLURAL_SUB
|
26
66
|
end
|
27
67
|
module_function :pluralize
|
28
68
|
|
69
|
+
SINGULAR_RE = /ies\z/.freeze
|
70
|
+
|
29
71
|
def singularize s
|
30
|
-
|
31
|
-
when /xes$/
|
72
|
+
if s.end_with? XES_STRING
|
32
73
|
s[0..-3]
|
33
|
-
|
34
|
-
s.sub(
|
35
|
-
|
74
|
+
elsif s.end_with? IES_STRING
|
75
|
+
s.sub(SINGULAR_RE, Y_STRING)
|
76
|
+
elsif s.end_with? S_STRING
|
36
77
|
s[0..-2]
|
37
78
|
else
|
38
|
-
s
|
79
|
+
s.dup
|
39
80
|
end
|
40
81
|
end
|
41
82
|
module_function :singularize
|
42
83
|
|
84
|
+
UPPER_OR_NUM_RE = /([A-Z]|\d+)/.freeze
|
85
|
+
|
43
86
|
def dasherize_class_name s
|
44
|
-
s.gsub(
|
87
|
+
s.gsub(UPPER_OR_NUM_RE) {|str| "-#{str.downcase}" }[1..-1].gsub(CONST_SEP, DASH)
|
45
88
|
end
|
46
89
|
module_function :dasherize_class_name
|
47
90
|
|
91
|
+
DASH_LOWER_OR_NUM_RE = /\-([a-z0-9])/.freeze
|
92
|
+
|
48
93
|
def undasherize_class_name s
|
49
|
-
s.capitalize.gsub(
|
94
|
+
s.capitalize.gsub(DASH_LOWER_OR_NUM_RE) {|str| $1.upcase }.gsub(DASH, CONST_SEP)
|
50
95
|
end
|
51
96
|
module_function :undasherize_class_name
|
52
97
|
|
53
98
|
def resolve_class_name s, context=Kernel
|
54
|
-
current, *payload = s.to_s.split(
|
99
|
+
current, *payload = s.to_s.split(CONST_SEP)
|
55
100
|
raise(NameError) if current.nil?
|
56
101
|
const = context.const_get(current)
|
57
102
|
if payload.empty?
|
58
103
|
const
|
59
104
|
else
|
60
|
-
resolve_class_name(payload.join(
|
105
|
+
resolve_class_name(payload.join(CONST_SEP),const)
|
61
106
|
end
|
62
107
|
end
|
63
108
|
module_function :resolve_class_name
|
@@ -67,12 +112,15 @@ module WebUtils
|
|
67
112
|
end
|
68
113
|
module_function :resolve_dasherized_class_name
|
69
114
|
|
115
|
+
START_UPPER_RE = /^[A-Z]/.freeze
|
116
|
+
START_LOWER_RE = /^[a-z]/.freeze
|
117
|
+
|
70
118
|
def guess_related_class_name context, clue
|
71
119
|
context.respond_to?(:name) ? context.name : context.to_s
|
72
120
|
clue = clue.to_s
|
73
|
-
return clue if clue
|
74
|
-
if clue
|
75
|
-
clue = undasherize_class_name singularize(clue).gsub(
|
121
|
+
return clue if clue =~ START_UPPER_RE
|
122
|
+
if clue =~ START_LOWER_RE
|
123
|
+
clue = undasherize_class_name singularize(clue).gsub(UNDERSCORE, DASH)
|
76
124
|
clue = "::#{clue}"
|
77
125
|
end
|
78
126
|
"#{context}#{clue}"
|
@@ -96,39 +144,43 @@ module WebUtils
|
|
96
144
|
module_function :deep_copy
|
97
145
|
|
98
146
|
def ensure_key! h, k, v
|
99
|
-
h
|
100
|
-
h[k]
|
147
|
+
h.fetch(k) {|k| h.store(k, v) }
|
101
148
|
end
|
102
149
|
module_function :ensure_key!
|
103
150
|
|
104
151
|
def ensure_key h, k, v
|
105
|
-
|
106
|
-
self.ensure_key! new_h, k, v
|
107
|
-
new_h
|
152
|
+
{k=>v}.merge h
|
108
153
|
end
|
109
154
|
module_function :ensure_key
|
110
155
|
|
111
|
-
ACCENTS = "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž"
|
112
|
-
WITHOUT_ACCENTS = "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
|
156
|
+
ACCENTS = "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž".freeze
|
157
|
+
WITHOUT_ACCENTS = "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz".freeze
|
158
|
+
DASHIFY_RE = /(\-|[^0-9a-zA-Z])+/.freeze
|
159
|
+
EDGE_DASH_RE = /(\A-|-\z)/.freeze
|
160
|
+
|
113
161
|
def slugify s, force_lower=true
|
114
162
|
s = s.to_s
|
115
163
|
.tr(ACCENTS, WITHOUT_ACCENTS)
|
116
|
-
.gsub(
|
117
|
-
.gsub(
|
118
|
-
.gsub(
|
119
|
-
.gsub(
|
164
|
+
.gsub(AMPERSAND, AND_STRING)
|
165
|
+
.gsub(PERCENT, SPACE_PERCENT_STRING)
|
166
|
+
.gsub(DASHIFY_RE, DASH)
|
167
|
+
.gsub(EDGE_DASH_RE, EMPTY_STRING)
|
120
168
|
s = s.downcase if force_lower
|
121
169
|
escape(s)
|
122
170
|
end
|
123
171
|
module_function :slugify
|
124
172
|
|
173
|
+
ALPHA_NUM_RE = /[a-zA-Z0-9]+/.freeze
|
174
|
+
|
125
175
|
def label_for_field field_name
|
126
|
-
field_name.to_s.scan(
|
176
|
+
field_name.to_s.scan(ALPHA_NUM_RE).map(&:capitalize).join(SPACE)
|
127
177
|
end
|
128
178
|
module_function :label_for_field
|
129
179
|
|
180
|
+
EACH_STUB_ERR_MSG = 'WebUtils.each_stub expects an object which respond to each_with_index.'
|
181
|
+
|
130
182
|
def each_stub obj, &block
|
131
|
-
raise TypeError,
|
183
|
+
raise TypeError, EACH_STUB_ERR_MSG unless obj.respond_to?(:each_with_index)
|
132
184
|
obj.each_with_index do |(k,v),i|
|
133
185
|
value = v || k
|
134
186
|
if value.is_a?(Hash) || value.is_a?(Array)
|
@@ -140,7 +192,10 @@ module WebUtils
|
|
140
192
|
end
|
141
193
|
module_function :each_stub
|
142
194
|
|
143
|
-
TYPECASTABLE = [:bool, :boolean, :nil, :int, :integer, :float]
|
195
|
+
TYPECASTABLE = [:bool, :boolean, :nil, :int, :integer, :float].freeze
|
196
|
+
INT_RE = /\A-?\d+\z/.freeze
|
197
|
+
FLOAT_RE = /\A-?\d*\.\d+\z/.freeze
|
198
|
+
|
144
199
|
def automatic_typecast str, casted=TYPECASTABLE
|
145
200
|
return str unless str.is_a?(String)
|
146
201
|
casted = casted.map do |sym|
|
@@ -153,15 +208,15 @@ module WebUtils
|
|
153
208
|
sym
|
154
209
|
end
|
155
210
|
end
|
156
|
-
if casted.include?(:boolean) and str==
|
211
|
+
if casted.include?(:boolean) and str == TRUE_STRING
|
157
212
|
true
|
158
|
-
elsif casted.include?(:boolean) and str==
|
213
|
+
elsif casted.include?(:boolean) and str == FALSE_STRING
|
159
214
|
false
|
160
|
-
elsif casted.include?(:nil) and str==
|
215
|
+
elsif casted.include?(:nil) and str == EMPTY_STRING
|
161
216
|
nil
|
162
|
-
elsif casted.include?(:integer) and str
|
217
|
+
elsif casted.include?(:integer) and str =~ INT_RE
|
163
218
|
str.to_i
|
164
|
-
elsif casted.include?(:float) and str
|
219
|
+
elsif casted.include?(:float) and str =~ FLOAT_RE
|
165
220
|
str.to_f
|
166
221
|
else
|
167
222
|
str
|
@@ -169,23 +224,29 @@ module WebUtils
|
|
169
224
|
end
|
170
225
|
module_function :automatic_typecast
|
171
226
|
|
172
|
-
ID_CHARS = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
|
227
|
+
ID_CHARS = (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a).freeze.map(&:freeze)
|
173
228
|
ID_SIZE = 16
|
229
|
+
DEPRECATED_RANDOM_ID_STRING = 'WebUtils::generate_random_id is deprecated. Use standard SecureRandom instead.'.freeze
|
230
|
+
|
174
231
|
def generate_random_id size=ID_SIZE
|
175
|
-
warn
|
176
|
-
id =
|
232
|
+
warn DEPRECATED_RANDOM_ID_STRING
|
233
|
+
id = String.new
|
177
234
|
size.times{id << ID_CHARS[rand(ID_CHARS.size)]}
|
178
235
|
id
|
179
236
|
end
|
180
237
|
module_function :generate_random_id
|
181
238
|
|
182
|
-
|
183
|
-
|
239
|
+
RN_RE = /\r?\n/.freeze
|
240
|
+
|
241
|
+
def nl2br s, br=BR_TAG
|
242
|
+
s.to_s.gsub(RN_RE, br)
|
184
243
|
end
|
185
244
|
module_function :nl2br
|
186
245
|
|
246
|
+
COMPLETE_LINK_RE = /^(\/|[a-z]*:)/.freeze
|
247
|
+
|
187
248
|
def complete_link link
|
188
|
-
if blank?(link) or link
|
249
|
+
if blank?(link) or link =~ COMPLETE_LINK_RE
|
189
250
|
link
|
190
251
|
else
|
191
252
|
"//#{link}"
|
@@ -193,14 +254,17 @@ module WebUtils
|
|
193
254
|
end
|
194
255
|
module_function :complete_link
|
195
256
|
|
257
|
+
EXTERNAL_LINK_RE = /\A[a-z]*:?\/\//.freeze
|
258
|
+
|
196
259
|
def external_link? link
|
197
|
-
!!(link =~
|
260
|
+
!!(link =~ EXTERNAL_LINK_RE)
|
198
261
|
end
|
199
262
|
module_function :external_link?
|
200
263
|
|
201
|
-
EMAIL_REGEX = /([^\s]+@[^\s]*[a-zA-Z])
|
202
|
-
LINK_REGEX = /\b((https?:\/\/|ftps?:\/\/|www\.)([A-Za-z0-9\-_=%&@\?\.\/]+))\b
|
203
|
-
|
264
|
+
EMAIL_REGEX = /([^\s]+@[^\s]*[a-zA-Z])/.freeze
|
265
|
+
LINK_REGEX = /\b((https?:\/\/|ftps?:\/\/|www\.)([A-Za-z0-9\-_=%&@\?\.\/]+))\b/.freeze
|
266
|
+
|
267
|
+
def automatic_html s, br=BR_TAG
|
204
268
|
replaced = s.to_s.
|
205
269
|
gsub(LINK_REGEX) do |str|
|
206
270
|
url = complete_link $1
|
@@ -213,51 +277,69 @@ module WebUtils
|
|
213
277
|
end
|
214
278
|
module_function :automatic_html
|
215
279
|
|
216
|
-
TAG_REGEX = /<[^>]
|
217
|
-
|
280
|
+
TAG_REGEX = /<[^>]*>/.freeze
|
281
|
+
NL_RE = /\n/.freeze
|
282
|
+
|
283
|
+
def truncate s, c=320, ellipsis=ELLIPSIS
|
218
284
|
s.to_s
|
219
|
-
.gsub(TAG_REGEX,
|
220
|
-
.gsub(
|
221
|
-
.sub(/^(.{#{c}}\w*).*$/m,
|
285
|
+
.gsub(TAG_REGEX, EMPTY_STRING)
|
286
|
+
.gsub(NL_RE, SPACE)
|
287
|
+
.sub(/^(.{#{c}}\w*).*$/m, ARG1_SUB+ellipsis)
|
222
288
|
end
|
223
289
|
module_function :truncate
|
224
290
|
|
291
|
+
QUERY_SPLITTER = /[^a-zA-Z0-9\&]+/.freeze
|
292
|
+
|
225
293
|
def regex_for_query query, exhaustive=true
|
226
|
-
atoms = query.split(
|
294
|
+
atoms = query.split(QUERY_SPLITTER)
|
227
295
|
atom_patterns = atoms.map{|a| "(?=.*\\b#{a})" }
|
228
|
-
sep = exhaustive ?
|
229
|
-
|
296
|
+
sep = exhaustive ? EMPTY_STRING : PIPE
|
297
|
+
/#{atom_patterns.join(sep)}/i.freeze
|
230
298
|
end
|
231
299
|
module_function :regex_for_query
|
232
300
|
|
301
|
+
PRICE_ERR_MSG = 'The price needs to be the price in cents/pence as an integer'.freeze
|
302
|
+
PRICE_FMT = '%.2f'.freeze
|
303
|
+
NO_CENTS_RE = /\.00/.freeze
|
304
|
+
THOUSANDS_RE = /(\d{3})(?=\d)/.freeze
|
305
|
+
THOUSANDS_SUB = '\1,'.freeze
|
306
|
+
|
233
307
|
def display_price int
|
234
308
|
unless int.is_a?(Integer)
|
235
|
-
raise(TypeError,
|
309
|
+
raise(TypeError, PRICE_ERR_MSG)
|
236
310
|
end
|
237
|
-
(
|
238
|
-
.sub(
|
311
|
+
(PRICE_FMT % (int/100.0))
|
312
|
+
.sub(NO_CENTS_RE, EMPTY_STRING)
|
239
313
|
.reverse
|
240
|
-
.gsub(
|
314
|
+
.gsub(THOUSANDS_RE, THOUSANDS_SUB)
|
241
315
|
.reverse
|
242
316
|
end
|
243
317
|
module_function :display_price
|
244
318
|
|
319
|
+
PRICE_PARSE_ERR_MSG = 'The price needs to be parsed from a String'.freeze
|
320
|
+
SWITCH_DOT_COMMA_TR = ['.,'.freeze, ',.'.freeze].freeze
|
321
|
+
COMMA_BASED_PRICE_RE = /(\.\d\d\d|,\d\d?)\z/.freeze
|
322
|
+
NON_PRICE_CHARS_RE = /[^\d\.\-,]/.freeze
|
323
|
+
|
245
324
|
def parse_price string
|
246
325
|
unless string.is_a?(String)
|
247
|
-
raise(TypeError,
|
326
|
+
raise(TypeError, PRICE_PARSE_ERR_MSG)
|
248
327
|
end
|
249
|
-
string = string.gsub(
|
250
|
-
if string[
|
328
|
+
string = string.gsub(NON_PRICE_CHARS_RE, EMPTY_STRING)
|
329
|
+
if string[COMMA_BASED_PRICE_RE]
|
251
330
|
# comma-based price
|
252
|
-
string = string.tr
|
331
|
+
string = string.tr(*SWITCH_DOT_COMMA_TR)
|
253
332
|
end
|
254
|
-
(
|
333
|
+
(PRICE_FMT % string.gsub(COMMA, EMPTY_STRING)).gsub(DOT, EMPTY_STRING).to_i
|
255
334
|
end
|
256
335
|
module_function :parse_price
|
257
336
|
|
258
|
-
|
337
|
+
DEFAULT_BRAND = self.name
|
338
|
+
START_DOT_SLASH_RE = /\A\.\//.freeze
|
339
|
+
|
340
|
+
def branded_filename path, brand=DEFAULT_BRAND
|
259
341
|
"#{File.dirname(path)}/#{brand}-#{File.basename(path)}"
|
260
|
-
.sub(
|
342
|
+
.sub(START_DOT_SLASH_RE, EMPTY_STRING)
|
261
343
|
end
|
262
344
|
module_function :branded_filename
|
263
345
|
|
@@ -268,12 +350,14 @@ module WebUtils
|
|
268
350
|
module_function :filename_variation
|
269
351
|
|
270
352
|
def initial_request? request
|
271
|
-
return true unless request.referer=~URI.regexp
|
272
353
|
URI.parse(request.referer).host!=request.host
|
354
|
+
rescue URI::InvalidURIError
|
355
|
+
return true
|
273
356
|
end
|
274
357
|
module_function :initial_request?
|
275
358
|
|
276
|
-
BOT_REGEX = /bot|crawl|slurp|spider/i
|
359
|
+
BOT_REGEX = /bot|crawl|slurp|spider/i.freeze
|
360
|
+
|
277
361
|
def being_crawled? request
|
278
362
|
request.user_agent =~ BOT_REGEX
|
279
363
|
end
|
data/test/test_web_utils.rb
CHANGED
@@ -26,6 +26,9 @@ describe WebUtils do
|
|
26
26
|
describe 'with nil' do
|
27
27
|
it('is true') { assert utils.blank?(nil) }
|
28
28
|
end
|
29
|
+
describe 'with false' do
|
30
|
+
it('is true') { assert utils.blank?(false) }
|
31
|
+
end
|
29
32
|
describe 'with non-blank strings' do
|
30
33
|
it 'is false' do
|
31
34
|
['a','abc', ' abc '].each do |s|
|
@@ -54,6 +57,11 @@ describe WebUtils do
|
|
54
57
|
assert_equal 'copies', utils.pluralize('copy')
|
55
58
|
end
|
56
59
|
end
|
60
|
+
it "Does not mutate input" do
|
61
|
+
input = 'bag'
|
62
|
+
utils.pluralize(input)
|
63
|
+
assert_equal 'bag', input
|
64
|
+
end
|
57
65
|
|
58
66
|
end
|
59
67
|
|
@@ -72,6 +80,14 @@ describe WebUtils do
|
|
72
80
|
assert_equal 'copy', utils.singularize('copies')
|
73
81
|
end
|
74
82
|
end
|
83
|
+
describe "The word does not seem plural" do
|
84
|
+
it "Returns the same" do
|
85
|
+
input = 'bag'
|
86
|
+
output = utils.singularize(input)
|
87
|
+
assert_equal 'bag', output
|
88
|
+
refute_same input, output
|
89
|
+
end
|
90
|
+
end
|
75
91
|
|
76
92
|
end
|
77
93
|
|
@@ -350,14 +366,14 @@ describe WebUtils do
|
|
350
366
|
|
351
367
|
describe '#generate_random_id' do
|
352
368
|
it 'Has the correct format' do
|
353
|
-
|
354
|
-
assert_match
|
369
|
+
_, err = capture_io do
|
370
|
+
assert_match(/[a-zA-Z0-9]{16}/, utils.generate_random_id )
|
355
371
|
end
|
356
372
|
assert_match "WebUtils::generate_random_id is deprecated", err
|
357
373
|
end
|
358
374
|
it 'Can have a specific length' do
|
359
|
-
|
360
|
-
assert_match
|
375
|
+
_, err = capture_io do
|
376
|
+
assert_match(/[a-zA-Z0-9]{32}/, utils.generate_random_id(32) )
|
361
377
|
end
|
362
378
|
assert_match "WebUtils::generate_random_id is deprecated", err
|
363
379
|
end
|
@@ -508,13 +524,13 @@ describe WebUtils do
|
|
508
524
|
assert_equal 2800, utils.parse_price('28')
|
509
525
|
end
|
510
526
|
it 'Ignores visual help but works with negative prices' do
|
511
|
-
assert_equal
|
527
|
+
assert_equal(-1234567890, utils.parse_price(' £-12,345,678.90 ') )
|
512
528
|
end
|
513
529
|
it 'Parses comma-based prices - french/german style' do
|
514
530
|
assert_equal 2390, utils.parse_price('23,90')
|
515
531
|
assert_equal 2390, utils.parse_price('23,9')
|
516
532
|
assert_equal 2000000, utils.parse_price('20.000')
|
517
|
-
assert_equal
|
533
|
+
assert_equal(-1234567890, utils.parse_price(' £-12.345.678,90 ') )
|
518
534
|
end
|
519
535
|
it 'Raises when argument is not string' do
|
520
536
|
assert_raises(TypeError) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mickael Riga
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|