furi 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +19 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +7 -0
- data/README.md +30 -25
- data/Rakefile +5 -10
- data/furi.gemspec +13 -14
- data/lib/furi.rb +3 -1
- data/lib/furi/uri.rb +15 -10
- data/lib/furi/version.rb +1 -1
- metadata +17 -75
- data/spec/furi/uri_spec.rb +0 -12
- data/spec/furi_spec.rb +0 -761
- data/spec/spec_helper.rb +0 -75
data/spec/furi/uri_spec.rb
DELETED
data/spec/furi_spec.rb
DELETED
@@ -1,761 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Furi do
|
4
|
-
|
5
|
-
class PartsMatcher
|
6
|
-
|
7
|
-
def initialize(expectation)
|
8
|
-
@expectation = expectation
|
9
|
-
end
|
10
|
-
|
11
|
-
def matches?(text)
|
12
|
-
@uri = Furi.parse(text)
|
13
|
-
@expectation.each do |part, value|
|
14
|
-
if @uri.send(part) != value
|
15
|
-
@unmatched_part = part
|
16
|
-
return false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
return true
|
20
|
-
end
|
21
|
-
|
22
|
-
def failure_message
|
23
|
-
"Expected #{@unmatched_part.inspect} to equal #{@expectation[@unmatched_part].inspect}, but it was #{@uri.send(@unmatched_part).inspect}"
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
class SerializeAs
|
29
|
-
def initialize(expectation)
|
30
|
-
@expectation = expectation
|
31
|
-
if @expectation.is_a?(Array)
|
32
|
-
@expectation = @expectation.map do |item|
|
33
|
-
item.split("=").map {|z| CGI.escape(z.to_s)}.join("=")
|
34
|
-
end.join("&")
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def matches?(hash)
|
39
|
-
@hash = hash
|
40
|
-
Furi.serialize(hash) == @expectation
|
41
|
-
end
|
42
|
-
|
43
|
-
def failure_message
|
44
|
-
"Expected #{@hash.inspect} to serialize as #{@expectation.inspect}, but was serialized as #{Furi.serialize(@hash)}.\n" +
|
45
|
-
"Debug: #{unserialize(@expectation)}, but was serialized as #{unserialize(Furi.serialize(@hash))}"
|
46
|
-
end
|
47
|
-
|
48
|
-
def unserialize(string)
|
49
|
-
string.split("&").map do |z|
|
50
|
-
z.split("=").map do |q|
|
51
|
-
CGI.unescape(q)
|
52
|
-
end
|
53
|
-
end.inspect
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def have_parts(parts)
|
58
|
-
PartsMatcher.new(parts)
|
59
|
-
end
|
60
|
-
|
61
|
-
def serialize_as(value)
|
62
|
-
SerializeAs.new(value)
|
63
|
-
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
describe ".parse" do
|
68
|
-
|
69
|
-
it "raises on empty string" do
|
70
|
-
expect {
|
71
|
-
Furi.parse("")
|
72
|
-
}.to raise_error(Furi::FormattingError)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "parses URL with everything" do
|
76
|
-
expect("http://user:pass@www.gusiev.com:8080/articles/index.html?a=1&b=2#header").to have_parts(
|
77
|
-
location: 'http://user:pass@www.gusiev.com:8080',
|
78
|
-
protocol: 'http',
|
79
|
-
schema: 'http',
|
80
|
-
authority: 'user:pass@www.gusiev.com:8080',
|
81
|
-
hostinfo: 'www.gusiev.com:8080',
|
82
|
-
host: 'www.gusiev.com',
|
83
|
-
subdomain: 'www',
|
84
|
-
domain: 'gusiev.com',
|
85
|
-
domainzone: 'com',
|
86
|
-
port: 8080,
|
87
|
-
userinfo: 'user:pass',
|
88
|
-
username: 'user',
|
89
|
-
password: 'pass',
|
90
|
-
|
91
|
-
resource: '/articles/index.html?a=1&b=2#header',
|
92
|
-
path: "/articles/index.html",
|
93
|
-
file: 'index.html',
|
94
|
-
extension: 'html',
|
95
|
-
query_string: "a=1&b=2",
|
96
|
-
query_tokens: [['a', '1'], ['b', '2']],
|
97
|
-
query: {'a' => '1', 'b' => '2'},
|
98
|
-
request: '/articles/index.html?a=1&b=2',
|
99
|
-
anchor: 'header',
|
100
|
-
fragment: 'header',
|
101
|
-
home_page?: false,
|
102
|
-
)
|
103
|
-
|
104
|
-
end
|
105
|
-
it "parses URL without path" do
|
106
|
-
expect("http://gusiev.com").to have_parts(
|
107
|
-
protocol: 'http',
|
108
|
-
hostname: 'gusiev.com',
|
109
|
-
query_string: nil,
|
110
|
-
query: {},
|
111
|
-
path: nil,
|
112
|
-
path!: '/',
|
113
|
-
port: nil,
|
114
|
-
request: nil,
|
115
|
-
request!: '/',
|
116
|
-
resource: nil,
|
117
|
-
resource!: '/',
|
118
|
-
location: 'http://gusiev.com',
|
119
|
-
home_page?: true,
|
120
|
-
)
|
121
|
-
end
|
122
|
-
|
123
|
-
it "parses URL with root path" do
|
124
|
-
expect("http://gusiev.com/?a=b").to have_parts(
|
125
|
-
hostname: 'gusiev.com',
|
126
|
-
path: '/',
|
127
|
-
path!: '/',
|
128
|
-
request: '/?a=b',
|
129
|
-
home_page?: true,
|
130
|
-
)
|
131
|
-
end
|
132
|
-
it "extracts anchor" do
|
133
|
-
expect("http://gusiev.com/posts/index.html?a=b#zz").to have_parts(
|
134
|
-
anchor: 'zz',
|
135
|
-
query_string: 'a=b',
|
136
|
-
path: '/posts/index.html',
|
137
|
-
port: nil,
|
138
|
-
protocol: 'http',
|
139
|
-
resource: '/posts/index.html?a=b#zz',
|
140
|
-
request: '/posts/index.html?a=b',
|
141
|
-
location: 'http://gusiev.com',
|
142
|
-
file: 'index.html',
|
143
|
-
extension: 'html',
|
144
|
-
)
|
145
|
-
end
|
146
|
-
|
147
|
-
it "works with path without URL" do
|
148
|
-
expect("/posts/index.html").to have_parts(
|
149
|
-
path: '/posts/index.html',
|
150
|
-
hostname: nil,
|
151
|
-
port: nil,
|
152
|
-
protocol: nil,
|
153
|
-
location: nil,
|
154
|
-
extension: 'html',
|
155
|
-
home_page?: false,
|
156
|
-
)
|
157
|
-
end
|
158
|
-
|
159
|
-
it "works with path ending at slash" do
|
160
|
-
|
161
|
-
expect("/posts/").to have_parts(
|
162
|
-
path: '/posts/',
|
163
|
-
directory: '/posts',
|
164
|
-
file: nil,
|
165
|
-
'file!' => '',
|
166
|
-
extension: nil,
|
167
|
-
home_page?: false,
|
168
|
-
)
|
169
|
-
end
|
170
|
-
|
171
|
-
it "parses uri with user and password" do
|
172
|
-
expect("http://user:pass@gusiev.com").to have_parts(
|
173
|
-
username: 'user',
|
174
|
-
password: 'pass',
|
175
|
-
hostname: 'gusiev.com',
|
176
|
-
query_string: nil,
|
177
|
-
anchor: nil,
|
178
|
-
location: 'http://user:pass@gusiev.com',
|
179
|
-
)
|
180
|
-
end
|
181
|
-
|
182
|
-
it "parses uri with user and without password" do
|
183
|
-
expect("http://user@gusiev.com").to have_parts(
|
184
|
-
username: 'user',
|
185
|
-
password: nil,
|
186
|
-
hostname: 'gusiev.com',
|
187
|
-
query_string: nil,
|
188
|
-
anchor: nil,
|
189
|
-
location: 'http://user@gusiev.com',
|
190
|
-
)
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
it "supports aliases" do
|
195
|
-
expect("http://gusiev.com#zz").to have_parts(
|
196
|
-
location: 'http://gusiev.com',
|
197
|
-
)
|
198
|
-
end
|
199
|
-
|
200
|
-
it "parses uri with explicit port and auth data" do
|
201
|
-
expect("http://user:pass@gusiev.com:80").to have_parts(
|
202
|
-
username: 'user',
|
203
|
-
password: 'pass',
|
204
|
-
userinfo: 'user:pass',
|
205
|
-
protocol: 'http',
|
206
|
-
port: 80,
|
207
|
-
query_string: nil,
|
208
|
-
)
|
209
|
-
end
|
210
|
-
|
211
|
-
it "parses custom port" do
|
212
|
-
expect("http://gusiev.com:8080").to have_parts(
|
213
|
-
hostname: 'gusiev.com',
|
214
|
-
hostinfo: 'gusiev.com:8080',
|
215
|
-
protocol: 'http',
|
216
|
-
port: 8080,
|
217
|
-
)
|
218
|
-
|
219
|
-
end
|
220
|
-
it "parses url with query" do
|
221
|
-
expect("/index.html?a=b&c=d").to have_parts(
|
222
|
-
host: nil,
|
223
|
-
host!: '',
|
224
|
-
query_string: 'a=b&c=d',
|
225
|
-
query: {'a' => 'b', 'c' => 'd'},
|
226
|
-
request: '/index.html?a=b&c=d',
|
227
|
-
home_page?: true,
|
228
|
-
)
|
229
|
-
end
|
230
|
-
|
231
|
-
it "finds out port if not explicitly defined`" do
|
232
|
-
expect("http://gusiev.com").to have_parts(
|
233
|
-
protocol: 'http',
|
234
|
-
port: nil,
|
235
|
-
"port!" => 80
|
236
|
-
)
|
237
|
-
end
|
238
|
-
it "parses nested query" do
|
239
|
-
expect("gusiev.com?a[]=1&a[]=2&b[c]=1&b[d]=2").to have_parts(
|
240
|
-
host: 'gusiev.com',
|
241
|
-
query: {"a" => ["1","2"], "b" => {"c" => "1", "d" => "2"}},
|
242
|
-
)
|
243
|
-
end
|
244
|
-
|
245
|
-
it "find out protocol security" do
|
246
|
-
expect("gusiev.com:443").to have_parts(
|
247
|
-
host: 'gusiev.com',
|
248
|
-
:"ssl" => false
|
249
|
-
)
|
250
|
-
expect("https://gusiev.com:443").to have_parts(
|
251
|
-
host: 'gusiev.com',
|
252
|
-
:"ssl" => true
|
253
|
-
)
|
254
|
-
end
|
255
|
-
|
256
|
-
it "parses host into parts" do
|
257
|
-
expect("http://www.gusiev.com.ua").to have_parts(
|
258
|
-
domain: 'gusiev.com.ua',
|
259
|
-
subdomain: 'www',
|
260
|
-
domainname: 'gusiev',
|
261
|
-
domainzone: 'com.ua'
|
262
|
-
)
|
263
|
-
expect("http://www.com.ua").to have_parts(
|
264
|
-
domain: 'www.com.ua',
|
265
|
-
subdomain: nil,
|
266
|
-
domainname: 'www',
|
267
|
-
domainzone: 'com.ua'
|
268
|
-
)
|
269
|
-
expect("http://com.ua").to have_parts(
|
270
|
-
domain: 'com.ua',
|
271
|
-
subdomain: nil,
|
272
|
-
domainname: 'com',
|
273
|
-
domainzone: 'ua'
|
274
|
-
)
|
275
|
-
expect("http://www.blog.gusiev.com.ua").to have_parts(
|
276
|
-
domain: 'gusiev.com.ua',
|
277
|
-
subdomain: 'www.blog',
|
278
|
-
domainname: 'gusiev',
|
279
|
-
domainzone: 'com.ua'
|
280
|
-
)
|
281
|
-
end
|
282
|
-
|
283
|
-
it "parses double # in anchor" do
|
284
|
-
expect("/index?a=1#c#d").to have_parts(
|
285
|
-
anchor: 'c#d',
|
286
|
-
query_string: "a=1",
|
287
|
-
path: '/index',
|
288
|
-
)
|
289
|
-
end
|
290
|
-
it "parses blank port with protocol" do
|
291
|
-
expect("http://gusiev.com:/hello").to have_parts(
|
292
|
-
path: '/hello',
|
293
|
-
port: nil,
|
294
|
-
host: 'gusiev.com',
|
295
|
-
protocol: 'http',
|
296
|
-
)
|
297
|
-
end
|
298
|
-
it "parses blank port without protocol" do
|
299
|
-
expect("gusiev.com:/hello").to have_parts(
|
300
|
-
path: '/hello',
|
301
|
-
port: nil,
|
302
|
-
host: 'gusiev.com',
|
303
|
-
protocol: nil,
|
304
|
-
)
|
305
|
-
end
|
306
|
-
|
307
|
-
it "parses 0 port as blank port" do
|
308
|
-
expect("http://gusiev.com:0/hello").to have_parts(
|
309
|
-
path: '/hello',
|
310
|
-
port: 0,
|
311
|
-
host: 'gusiev.com',
|
312
|
-
protocol: 'http',
|
313
|
-
)
|
314
|
-
end
|
315
|
-
|
316
|
-
it "downcases only protocol and host" do
|
317
|
-
expect("HTTP://GUSIEV.cOM/About").to have_parts(
|
318
|
-
protocol: 'http',
|
319
|
-
host: 'gusiev.com',
|
320
|
-
path: "/About",
|
321
|
-
)
|
322
|
-
end
|
323
|
-
|
324
|
-
describe "ipv6 host" do
|
325
|
-
it "parses host and port" do
|
326
|
-
expect("http://[2406:da00:ff00::6b14:8d43]:8080/").to have_parts(
|
327
|
-
path: '/',
|
328
|
-
port: 8080,
|
329
|
-
host: '[2406:da00:ff00::6b14:8d43]',
|
330
|
-
protocol: 'http',
|
331
|
-
)
|
332
|
-
end
|
333
|
-
it "parses host and nil port" do
|
334
|
-
|
335
|
-
expect("http://[2406:da00:ff00::6b14:8d43]:/hello").to have_parts(
|
336
|
-
path: '/hello',
|
337
|
-
port: nil,
|
338
|
-
host: '[2406:da00:ff00::6b14:8d43]',
|
339
|
-
protocol: 'http',
|
340
|
-
)
|
341
|
-
end
|
342
|
-
|
343
|
-
it "parses host without protocol and port" do
|
344
|
-
expect("[2406:da00:ff00::6b14:8d43]/hello").to have_parts(
|
345
|
-
path: '/hello',
|
346
|
-
port: nil,
|
347
|
-
host: '[2406:da00:ff00::6b14:8d43]',
|
348
|
-
protocol: nil,
|
349
|
-
)
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
|
-
describe "mailto" do
|
354
|
-
it "without email" do
|
355
|
-
expect("mailto:?subject=Talkable%20is%20Hiring&body=https%3A%2F%2Fwww.talkable.com%2Fjobs").to have_parts(
|
356
|
-
protocol: 'mailto',
|
357
|
-
email: nil,
|
358
|
-
query: {
|
359
|
-
"subject" => "Talkable is Hiring",
|
360
|
-
"body" => "https://www.talkable.com/jobs"
|
361
|
-
}
|
362
|
-
)
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
describe ".replace" do
|
367
|
-
|
368
|
-
it "support replace for query" do
|
369
|
-
expect(Furi.replace("/index.html?a=b", query: {c: 'd'})).to eq('/index.html?c=d')
|
370
|
-
end
|
371
|
-
|
372
|
-
it "replace hostname" do
|
373
|
-
expect(Furi.replace("www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
374
|
-
expect(Furi.replace("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
375
|
-
expect(Furi.replace("http://www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('http://gusiev.com/index.html')
|
376
|
-
expect(Furi.replace("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
|
377
|
-
expect(Furi.replace("gusiev.com/index.html?a=b", hostname: nil)).to eq('/index.html?a=b')
|
378
|
-
expect(Furi.replace("gusiev.com?a=b", hostname: nil)).to eq('/?a=b')
|
379
|
-
end
|
380
|
-
|
381
|
-
it "replace port" do
|
382
|
-
expect(Furi.replace("gusiev.com", port: 33)).to eq('gusiev.com:33')
|
383
|
-
expect(Furi.replace("gusiev.com/index.html", port: 33)).to eq('gusiev.com:33/index.html')
|
384
|
-
expect(Furi.replace("gusiev.com:33/index.html", port: 80)).to eq('gusiev.com:80/index.html')
|
385
|
-
expect(Furi.replace("http://gusiev.com:33/index.html", port: 80)).to eq('http://gusiev.com/index.html')
|
386
|
-
expect(Furi.replace("http://gusiev.com:33/index.html", port: nil)).to eq('http://gusiev.com/index.html')
|
387
|
-
expect(Furi.replace("http://gusiev.com:33/index.html", port: 0)).to eq('http://gusiev.com:0/index.html')
|
388
|
-
expect(Furi.replace("http://gusiev.com:33/index.html", port: '')).to eq('http://gusiev.com/index.html')
|
389
|
-
end
|
390
|
-
it "replace directory" do
|
391
|
-
expect(Furi.replace("gusiev.com", directory: 'articles')).to eq('gusiev.com/articles')
|
392
|
-
expect(Furi.replace("gusiev.com/", directory: 'articles')).to eq('gusiev.com/articles')
|
393
|
-
expect(Furi.replace("gusiev.com/index#header", directory: '/posts')).to eq('gusiev.com/posts/index#header')
|
394
|
-
expect(Furi.replace("gusiev.com/articles/#header", directory: nil)).to eq('gusiev.com/#header')
|
395
|
-
expect(Furi.replace("gusiev.com/articles/index?a=b", directory: 'posts')).to eq('gusiev.com/posts/index?a=b')
|
396
|
-
expect(Furi.replace("/articles/index?a=b", directory: '/posts')).to eq('/posts/index?a=b')
|
397
|
-
expect(Furi.replace("/articles/index.html?a=b", directory: '/posts/')).to eq('/posts/index.html?a=b')
|
398
|
-
end
|
399
|
-
it "replace file" do
|
400
|
-
expect(Furi.replace("gusiev.com", file: 'article')).to eq('gusiev.com/article')
|
401
|
-
expect(Furi.replace("gusiev.com/", file: 'article')).to eq('gusiev.com/article')
|
402
|
-
expect(Furi.replace("gusiev.com/article1#header", file: '/article2')).to eq('gusiev.com/article2#header')
|
403
|
-
expect(Furi.replace("gusiev.com/article#header", file: nil)).to eq('gusiev.com/#header')
|
404
|
-
expect(Furi.replace("gusiev.com/articles/article1?a=b", file: 'article2')).to eq('gusiev.com/articles/article2?a=b')
|
405
|
-
expect(Furi.replace("/articles/article1?a=b", file: '/article2')).to eq('/articles/article2?a=b')
|
406
|
-
expect(Furi.replace("/articles/article1.xml?a=b", file: 'article2.html')).to eq('/articles/article2.html?a=b')
|
407
|
-
end
|
408
|
-
it "replace extension" do
|
409
|
-
expect(->{
|
410
|
-
Furi.replace("gusiev.com/", extension: 'xml')
|
411
|
-
}).to raise_error(Furi::FormattingError)
|
412
|
-
expect(Furi.replace("gusiev.com/article#header", extension: 'html')).to eq('gusiev.com/article.html#header')
|
413
|
-
expect(Furi.replace("gusiev.com/article.html?header", extension: nil)).to eq('gusiev.com/article?header')
|
414
|
-
expect(Furi.replace("gusiev.com/article.xml?a=b", extension: 'html')).to eq('gusiev.com/article.html?a=b')
|
415
|
-
end
|
416
|
-
it "replace resource" do
|
417
|
-
expect(Furi.replace("gusiev.com", resource: '/article?a=1#hello')).to eq('gusiev.com/article?a=1#hello')
|
418
|
-
expect(Furi.replace("gusiev.com/article1#header", resource: '/article2')).to eq('gusiev.com/article2')
|
419
|
-
expect(Furi.replace("gusiev.com/article#header", resource: nil)).to eq('gusiev.com')
|
420
|
-
expect(Furi.replace("gusiev.com/article1?a=b", resource: 'article2')).to eq('gusiev.com/article2')
|
421
|
-
end
|
422
|
-
it "replace path" do
|
423
|
-
expect(Furi.replace("gusiev.com", path: '/article')).to eq('gusiev.com/article')
|
424
|
-
expect(Furi.replace("gusiev.com/article1#header", path: '/article2')).to eq('gusiev.com/article2#header')
|
425
|
-
expect(Furi.replace("gusiev.com/article#header", path: nil)).to eq('gusiev.com#header')
|
426
|
-
expect(Furi.replace("gusiev.com/article1?a=b", path: 'article2')).to eq('gusiev.com/article2?a=b')
|
427
|
-
end
|
428
|
-
|
429
|
-
it "replace ssl" do
|
430
|
-
expect(Furi.replace("http://gusiev.com", ssl: true)).to eq('https://gusiev.com')
|
431
|
-
expect(Furi.replace("https://gusiev.com", ssl: true)).to eq('https://gusiev.com')
|
432
|
-
expect(Furi.replace("https://gusiev.com", ssl: false)).to eq('http://gusiev.com')
|
433
|
-
expect(Furi.replace("http://gusiev.com", ssl: false)).to eq('http://gusiev.com')
|
434
|
-
end
|
435
|
-
|
436
|
-
it "replace protocol" do
|
437
|
-
expect(Furi.replace("http://gusiev.com", protocol: '')).to eq('//gusiev.com')
|
438
|
-
expect(Furi.replace("http://gusiev.com", protocol: nil)).to eq('gusiev.com')
|
439
|
-
expect(Furi.replace("http://gusiev.com", protocol: 'https')).to eq('https://gusiev.com')
|
440
|
-
expect(Furi.replace("gusiev.com", protocol: 'http')).to eq('http://gusiev.com')
|
441
|
-
expect(Furi.replace("gusiev.com", protocol: 'http:')).to eq('http://gusiev.com')
|
442
|
-
expect(Furi.replace("gusiev.com", protocol: 'http:/')).to eq('http://gusiev.com')
|
443
|
-
expect(Furi.replace("gusiev.com", protocol: 'http://')).to eq('http://gusiev.com')
|
444
|
-
end
|
445
|
-
|
446
|
-
it "replace userinfo" do
|
447
|
-
expect(Furi.replace("http://gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
448
|
-
expect(Furi.replace("http://aa:bb@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
449
|
-
expect(Furi.replace("http://aa:bb@gusiev.com", userinfo: nil)).to eq('http://gusiev.com')
|
450
|
-
expect(Furi.replace("http://aa@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
|
451
|
-
end
|
452
|
-
|
453
|
-
it "replace authority" do
|
454
|
-
expect(Furi.replace("http://user:pass@gusiev.com:8080/index.html", authority: 'gusiev.com')).to eq('http://gusiev.com/index.html')
|
455
|
-
end
|
456
|
-
|
457
|
-
it "replace request" do
|
458
|
-
expect(Furi.replace("http://gusiev.com:8080/index.html?c=d", request: '/blog.html?a=b')).to eq('http://gusiev.com:8080/blog.html?a=b')
|
459
|
-
end
|
460
|
-
|
461
|
-
it "replace domainzone" do
|
462
|
-
expect(Furi.replace("http://gusiev.com:8080", domainzone: 'com.ua')).to eq('http://gusiev.com.ua:8080')
|
463
|
-
expect(Furi.replace("http://gusiev.com.ua:8080", domainzone: 'com')).to eq('http://gusiev.com:8080')
|
464
|
-
expect(Furi.replace("http://gusiev.com.ua:8080", domainzone: nil)).to eq('http://gusiev:8080')
|
465
|
-
end
|
466
|
-
|
467
|
-
it "replace domainname" do
|
468
|
-
expect(Furi.replace("http://gusiev.com", domainname: 'google')).to eq('http://google.com')
|
469
|
-
expect(Furi.replace("http://gusiev.com", domainname: nil)).to eq('http://com')
|
470
|
-
end
|
471
|
-
it "replace subdomain" do
|
472
|
-
expect(Furi.replace("http://gusiev.com", subdomain: 'blog')).to eq('http://blog.gusiev.com')
|
473
|
-
expect(Furi.replace("http://blog.gusiev.com", subdomain: nil)).to eq('http://gusiev.com')
|
474
|
-
end
|
475
|
-
|
476
|
-
it "replace location" do
|
477
|
-
expect(Furi.replace("/index.html", location: 'http://gusiev.com')).to eq('http://gusiev.com/index.html')
|
478
|
-
expect(Furi.replace("/index.html", location: 'http://gusiev.com/')).to eq('http://gusiev.com/index.html')
|
479
|
-
expect(Furi.replace("gusiev.com:433/index.html", location: 'gusiev.com:80')).to eq('gusiev.com:80/index.html')
|
480
|
-
expect(Furi.replace("gusiev.com:433/index.html", location: nil)).to eq('/index.html')
|
481
|
-
expect(Furi.replace("http://gusiev.com:433/index.html", location: nil)).to eq('/index.html')
|
482
|
-
end
|
483
|
-
|
484
|
-
it "replace query" do
|
485
|
-
expect(Furi.replace("/", query: {a: 1})).to eq('/?a=1')
|
486
|
-
expect(Furi.replace("/", query: {a: [1,2]})).to eq('/?a%5B%5D=1&a%5B%5D=2')
|
487
|
-
expect(Furi.replace("/", query: {a: 1, b: 2})).to eq('/?a=1&b=2')
|
488
|
-
expect(Furi.replace("/?a=1", query: {a: 2})).to eq('/?a=2')
|
489
|
-
expect(Furi.replace("/?a=1&a=1", query: true)).to eq('/?a=1')
|
490
|
-
end
|
491
|
-
|
492
|
-
end
|
493
|
-
|
494
|
-
describe ".build" do
|
495
|
-
it "should work correctly" do
|
496
|
-
expect(Furi.build(hostname: 'hello.com')).to eq('hello.com')
|
497
|
-
expect(Furi.build(hostname: 'hello.com', port: 88)).to eq('hello.com:88')
|
498
|
-
expect(Furi.build(hostname: 'hello.com', port: 88)).to eq('hello.com:88')
|
499
|
-
expect(Furi.build(schema: 'https', hostname: 'hello.com', port: 88)).to eq('https://hello.com:88')
|
500
|
-
expect(Furi.build(schema: 'http', hostname: 'hello.com', port: 80)).to eq('http://hello.com')
|
501
|
-
expect(Furi.build(path: '/index.html', query: {a: 1, b: 2})).to eq('/index.html?a=1&b=2')
|
502
|
-
expect(Furi.build(path: '/', host: 'gusiev.com', query: {a: 1})).to eq('gusiev.com/?a=1')
|
503
|
-
expect(Furi.build(path: '/articles/', host: 'gusiev.com', query: {a: 1})).to eq('gusiev.com/articles/?a=1')
|
504
|
-
expect(Furi.build(user: 'user', hostname: 'hello.com')).to eq('user@hello.com')
|
505
|
-
expect(Furi.build(protocol: 'http', host: 'hello.com', port: 80)).to eq('http://hello.com')
|
506
|
-
expect(Furi.build(query: 'a=b')).to eq('/?a=b')
|
507
|
-
|
508
|
-
expect(->{
|
509
|
-
Furi.build(host: nil, port: 80)
|
510
|
-
}).to raise_error(Furi::FormattingError)
|
511
|
-
expect(->{
|
512
|
-
Furi.build(host: 'localhost', password: 'pass')
|
513
|
-
}).to raise_error(Furi::FormattingError)
|
514
|
-
end
|
515
|
-
|
516
|
-
it "builds protocol" do
|
517
|
-
expect(Furi.build(protocol: 'http', host: 'hello.com', port: 80)).to eq('http://hello.com')
|
518
|
-
expect(Furi.build(protocol: 'mailto', username: "bogdan", host: 'gusiev.com')).to eq('mailto:bogdan@gusiev.com')
|
519
|
-
expect(Furi.build(email: "bogdan@gusiev.com")).to eq('mailto:bogdan@gusiev.com')
|
520
|
-
expect(Furi.build(protocol: 'mailto', query: {subject: 'Hello', body: "Welcome"})).to eq('mailto:?subject=Hello&body=Welcome')
|
521
|
-
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
describe ".update" do
|
526
|
-
it "updates query" do
|
527
|
-
expect(Furi.update("//gusiev.com", query: {a: 1})).to eq('//gusiev.com?a=1')
|
528
|
-
expect(Furi.update("//gusiev.com?a=1", query: {b: 2})).to eq('//gusiev.com?a=1&b=2')
|
529
|
-
expect(Furi.update("//gusiev.com?a=1", query: {a: 2})).to eq('//gusiev.com?a=2')
|
530
|
-
expect(Furi.update("//gusiev.com?a=1", query: [['a', 2], ['b', 3]])).to eq('//gusiev.com?a=1&a=2&b=3')
|
531
|
-
expect(Furi.update("//gusiev.com?a=1&b=2", query: '?a=3')).to eq('//gusiev.com?a=1&b=2&a=3')
|
532
|
-
end
|
533
|
-
it "updates query_string" do
|
534
|
-
expect(Furi.update("//gusiev.com?a=1&b=2", query_string: '?a=3')).to eq('//gusiev.com?a=1&b=2&a=3')
|
535
|
-
end
|
536
|
-
end
|
537
|
-
|
538
|
-
describe ".defaults" do
|
539
|
-
it "should set protocol" do
|
540
|
-
expect(Furi.defaults("gusiev.com", protocol: 'http')).to eq('http://gusiev.com')
|
541
|
-
expect(Furi.defaults("gusiev.com", protocol: '//')).to eq('//gusiev.com')
|
542
|
-
expect(Furi.defaults("//gusiev.com", protocol: 'http')).to eq('//gusiev.com')
|
543
|
-
expect(Furi.defaults("https://gusiev.com", protocol: 'http')).to eq('https://gusiev.com')
|
544
|
-
end
|
545
|
-
it "should set host" do
|
546
|
-
expect(Furi.defaults("https://gusiev.com", subdomain: 'www')).to eq('https://www.gusiev.com')
|
547
|
-
expect(Furi.defaults("https://blog.gusiev.com", subdomain: 'www')).to eq('https://blog.gusiev.com')
|
548
|
-
expect(Furi.defaults("/index.html", host: 'gusiev.com', protocol: 'http')).to eq('http://gusiev.com/index.html')
|
549
|
-
end
|
550
|
-
it "should set query" do
|
551
|
-
expect(Furi.defaults("gusiev.com?a=1", query: {a: 2})).to eq('gusiev.com?a=1')
|
552
|
-
expect(Furi.defaults("gusiev.com?a=1", query: {b: 2})).to eq('gusiev.com?a=1&b=2')
|
553
|
-
expect(Furi.defaults("//gusiev.com?a=1", query_string: 'b=2')).to eq('//gusiev.com?a=1')
|
554
|
-
expect(Furi.defaults("//gusiev.com", query_string: 'b=2')).to eq('//gusiev.com?b=2')
|
555
|
-
expect(Furi.defaults("//gusiev.com?a=1&b=2", query: '?a=3')).to eq('//gusiev.com?a=1&b=2')
|
556
|
-
end
|
557
|
-
it "should set file" do
|
558
|
-
expect(Furi.defaults("gusiev.com?a=1", file: 'index.html')).to eq('gusiev.com/index.html?a=1')
|
559
|
-
expect(Furi.defaults("gusiev.com/posts?a=1", file: 'index.html')).to eq('gusiev.com/posts?a=1')
|
560
|
-
expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
561
|
-
expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
562
|
-
end
|
563
|
-
it "should set extension" do
|
564
|
-
expect {
|
565
|
-
Furi.defaults("gusiev.com?a=1", extension: 'html')
|
566
|
-
}.to raise_error(Furi::FormattingError)
|
567
|
-
expect(Furi.defaults("gusiev.com?a=1", file: 'index.html', extension: 'html')).to eq('gusiev.com/index.html?a=1')
|
568
|
-
expect(Furi.defaults("gusiev.com/posts?a=1", extension: 'html')).to eq('gusiev.com/posts.html?a=1')
|
569
|
-
#expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
570
|
-
#expect(Furi.defaults("gusiev.com/posts/?a=1", file: 'index.html')).to eq('gusiev.com/posts/index.html?a=1')
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
describe "#==" do
|
575
|
-
it "should work" do
|
576
|
-
expect(Furi.parse('http://gusiev.com:80') == Furi.parse('http://gusiev.com')).to be_truthy
|
577
|
-
expect(Furi.parse('http://gusiev.com') == Furi.parse('https://gusiev.com')).to be_falsey
|
578
|
-
expect(Furi.parse('http://gusiev.com') == Furi.parse('http://gusiev.com')).to be_truthy
|
579
|
-
expect(Furi.parse('http://gusiev.com.ua') == Furi.parse('http://gusiev.com')).to be_falsey
|
580
|
-
expect(Furi.parse('http://gusiev.com?a=1&a=1') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
|
581
|
-
end
|
582
|
-
|
583
|
-
it "works with query parameters" do
|
584
|
-
expect(Furi.parse('/?b=1&a=1') == Furi.parse('/?b=1&a=1')).to be_truthy
|
585
|
-
expect(Furi.parse('/?a=1&a=1') == Furi.parse('/?a=1')).to be_falsey
|
586
|
-
expect(Furi.parse('/') == Furi.parse('/?a=1')).to be_falsey
|
587
|
-
expect(Furi.parse('/') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
|
588
|
-
|
589
|
-
end
|
590
|
-
|
591
|
-
it "ignores case only on protocol and host" do
|
592
|
-
expect(Furi.parse('hTTp://gUSiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
|
593
|
-
expect(Furi.parse('/hello') == Furi.parse('/Hello')).to be_falsey
|
594
|
-
expect(Furi.parse('/hello?a=1') == Furi.parse('/hello?A=1')).to be_falsey
|
595
|
-
expect(Furi.parse('hTTp://gusiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
|
596
|
-
expect(Furi.parse('/#h1') == Furi.parse('/#H1')).to be_falsey
|
597
|
-
expect(Furi.parse('hello@gusiev.com') == Furi.parse('Hello@gusiev.com')).to be_falsey
|
598
|
-
expect(Furi.parse('hello:psswd@gusiev.com') == Furi.parse('hello:Psswd@gusiev.com')).to be_falsey
|
599
|
-
end
|
600
|
-
|
601
|
-
end
|
602
|
-
|
603
|
-
describe "#abstract_protocol" do
|
604
|
-
it "works" do
|
605
|
-
expect(Furi.parse('http://gUSiev.cOm')).to_not be_abstract_protocol
|
606
|
-
expect(Furi.parse('//gUSiev.cOm')).to be_abstract_protocol
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
describe "#clone" do
|
611
|
-
it "should work" do
|
612
|
-
|
613
|
-
uri = Furi.parse('http://gusiev.com')
|
614
|
-
expect(uri.clone == uri).to be_truthy
|
615
|
-
expect(uri.clone.merge_query([[:a, 1]]) == uri).to be_falsey
|
616
|
-
end
|
617
|
-
end
|
618
|
-
|
619
|
-
describe "serialize" do
|
620
|
-
it "should work" do
|
621
|
-
expect({a: 'b'}).to serialize_as("a=b")
|
622
|
-
expect(a: nil).to serialize_as("a")
|
623
|
-
expect(nil).to serialize_as("")
|
624
|
-
expect(b: 2, a: 1).to serialize_as("b=2&a=1")
|
625
|
-
expect(a: {b: {c: []}}).to serialize_as("")
|
626
|
-
expect({:a => {:b => 'c'}}).to serialize_as("a%5Bb%5D=c")
|
627
|
-
expect(q: [1,2]).to serialize_as("q%5B%5D=1&q%5B%5D=2")
|
628
|
-
expect(a: {b: [1,2]}).to serialize_as("a%5Bb%5D%5B%5D=1&a%5Bb%5D%5B%5D=2")
|
629
|
-
expect(q: "cowboy hat?").to serialize_as("q=cowboy+hat%3F")
|
630
|
-
expect(a: true).to serialize_as("a=true")
|
631
|
-
expect(a: false).to serialize_as("a=false")
|
632
|
-
expect(a: [nil, 0]).to serialize_as("a%5B%5D&a%5B%5D=0")
|
633
|
-
expect({f: ["b", 42, "your base"] }).to serialize_as("f%5B%5D=b&f%5B%5D=42&f%5B%5D=your+base")
|
634
|
-
expect({"a[]" => 1 }).to serialize_as("a%5B%5D=1")
|
635
|
-
expect({"a[b]" => [1] }).to serialize_as(["a[b][]=1"])
|
636
|
-
expect("a" => [1, 2], "b" => "blah" ).to serialize_as("a%5B%5D=1&a%5B%5D=2&b=blah")
|
637
|
-
|
638
|
-
expect(a: [1,{c: 2, b: 3}, 4]).to serialize_as(["a[]=1", "a[][c]=2", "a[][b]=3", "a[]=4"])
|
639
|
-
expect(->{
|
640
|
-
Furi.serialize([1,2])
|
641
|
-
}).to raise_error(Furi::FormattingError)
|
642
|
-
expect(->{
|
643
|
-
Furi.serialize(a: [1,[2]])
|
644
|
-
}).to raise_error(Furi::FormattingError)
|
645
|
-
|
646
|
-
|
647
|
-
params = { b:{ c:3, d:[4,5], e:{ x:[6], y:7, z:[8,9] }}};
|
648
|
-
expect(CGI.unescape(Furi.serialize(params))).to eq("b[c]=3&b[d][]=4&b[d][]=5&b[e][x][]=6&b[e][y]=7&b[e][z][]=8&b[e][z][]=9")
|
649
|
-
|
650
|
-
end
|
651
|
-
end
|
652
|
-
|
653
|
-
describe ".query_tokens" do
|
654
|
-
it "should work" do
|
655
|
-
Furi.query_tokens("a=1").should eq [['a', 1]]
|
656
|
-
Furi.query_tokens("a==").should eq [['a', '=']]
|
657
|
-
Furi.query_tokens("a==1").should eq [['a', '=1']]
|
658
|
-
Furi.query_tokens("a=1&").should eq [['a', 1], ["", nil]]
|
659
|
-
Furi.query_tokens("&a=1").should eq [["", nil], ['a', 1]]
|
660
|
-
Furi.query_tokens("=").should eq [["", ""], ]
|
661
|
-
Furi.query_tokens(" ").should eq [[" ", nil], ]
|
662
|
-
Furi.query_tokens(" =").should eq [[" ", ''], ]
|
663
|
-
Furi.query_tokens("= ").should eq [["", ' '], ]
|
664
|
-
Furi.query_tokens("a=1&b").should eq [['a', 1], ["b", nil]]
|
665
|
-
Furi.query_tokens("a=&b").should eq [['a', ''], ['b', nil]]
|
666
|
-
Furi.query_tokens("a=1&b=2").should eq [['a', 1], ['b', 2]]
|
667
|
-
end
|
668
|
-
end
|
669
|
-
|
670
|
-
describe ".parse_query" do
|
671
|
-
it "should work" do
|
672
|
-
Furi.parse_query("foo").
|
673
|
-
should eq "foo" => nil
|
674
|
-
Furi.parse_query("foo=").
|
675
|
-
should eq "foo" => ""
|
676
|
-
Furi.parse_query("foo=bar").
|
677
|
-
should eq "foo" => "bar"
|
678
|
-
Furi.parse_query("foo=\"bar\"").
|
679
|
-
should eq "foo" => "\"bar\""
|
680
|
-
|
681
|
-
Furi.parse_query("foo=bar&foo=quux").
|
682
|
-
should eq "foo" => "quux"
|
683
|
-
Furi.parse_query("foo&foo=").
|
684
|
-
should eq "foo" => ""
|
685
|
-
Furi.parse_query("foo=1&bar=2").
|
686
|
-
should eq "foo" => "1", "bar" => "2"
|
687
|
-
Furi.parse_query("&foo=1&&bar=2").
|
688
|
-
should eq "foo" => "1", "bar" => "2"
|
689
|
-
Furi.parse_query("foo&bar=").
|
690
|
-
should eq "foo" => nil, "bar" => ""
|
691
|
-
Furi.parse_query("foo=bar&baz=").
|
692
|
-
should eq "foo" => "bar", "baz" => ""
|
693
|
-
Furi.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
|
694
|
-
should eq "my weird field" => "q1!2\"'w$5&7/z8)?"
|
695
|
-
|
696
|
-
Furi.parse_query("a=b&pid%3D1234=1023").
|
697
|
-
should eq "pid=1234" => "1023", "a" => "b"
|
698
|
-
|
699
|
-
Furi.parse_query("foo[]").
|
700
|
-
should eq "foo" => [nil]
|
701
|
-
Furi.parse_query("foo[]=").
|
702
|
-
should eq "foo" => [""]
|
703
|
-
Furi.parse_query("foo[]=bar").
|
704
|
-
should eq "foo" => ["bar"]
|
705
|
-
|
706
|
-
Furi.parse_query("foo[]=1&foo[]=2").
|
707
|
-
should eq "foo" => ["1", "2"]
|
708
|
-
Furi.parse_query("foo=bar&baz[]=1&baz[]=2&baz[]=3").
|
709
|
-
should eq "foo" => "bar", "baz" => ["1", "2", "3"]
|
710
|
-
Furi.parse_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3").
|
711
|
-
should eq "foo" => ["bar"], "baz" => ["1", "2", "3"]
|
712
|
-
|
713
|
-
Furi.parse_query("x[y][z]=1").
|
714
|
-
should eq "x" => {"y" => {"z" => "1"}}
|
715
|
-
Furi.parse_query("x[y][z][]=1").
|
716
|
-
should eq "x" => {"y" => {"z" => ["1"]}}
|
717
|
-
Furi.parse_query("x[y][z]=1&x[y][z]=2").
|
718
|
-
should eq "x" => {"y" => {"z" => "2"}}
|
719
|
-
Furi.parse_query("x[y][z][]=1&x[y][z][]=2").
|
720
|
-
should eq "x" => {"y" => {"z" => ["1", "2"]}}
|
721
|
-
|
722
|
-
Furi.parse_query("x[y][][z]=1").
|
723
|
-
should eq "x" => {"y" => [{"z" => "1"}]}
|
724
|
-
Furi.parse_query("x[y][][z][]=1").
|
725
|
-
should eq "x" => {"y" => [{"z" => ["1"]}]}
|
726
|
-
Furi.parse_query("x[y][][z]=1&x[y][][w]=2").
|
727
|
-
should eq "x" => {"y" => [{"z" => "1", "w" => "2"}]}
|
728
|
-
|
729
|
-
Furi.parse_query("x[y][][v][w]=1").
|
730
|
-
should eq "x" => {"y" => [{"v" => {"w" => "1"}}]}
|
731
|
-
Furi.parse_query("x[y][][z]=1&x[y][][v][w]=2").
|
732
|
-
should eq "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}
|
733
|
-
|
734
|
-
Furi.parse_query("x[y][][z]=1&x[y][][z]=2").
|
735
|
-
should eq "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}
|
736
|
-
Furi.parse_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3").
|
737
|
-
should eq "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
|
738
|
-
|
739
|
-
lambda { Furi.parse_query("x[y]=1&x[y]z=2") }.
|
740
|
-
should raise_error(Furi::QueryParseError, "expected Hash (got String) for param `y'")
|
741
|
-
|
742
|
-
lambda { Furi.parse_query("x[y]=1&x[]=1") }.
|
743
|
-
should raise_error(Furi::QueryParseError, /expected Array \(got [^)]*\) for param `x'/)
|
744
|
-
|
745
|
-
lambda { Furi.parse_query("x[y]=1&x[y][][w]=2") }.
|
746
|
-
should raise_error(Furi::QueryParseError, "expected Array (got String) for param `y'")
|
747
|
-
end
|
748
|
-
|
749
|
-
end
|
750
|
-
|
751
|
-
it "should support inspect" do
|
752
|
-
expect(Furi.parse('http://google.com').inspect).to eq("#<Furi::Uri \"http://google.com\">")
|
753
|
-
end
|
754
|
-
|
755
|
-
|
756
|
-
describe ".join" do
|
757
|
-
it "works" do
|
758
|
-
expect(Furi.join("http://gusiev.com/slides", "../photos")).to eq("http://gusiev.com/photos")
|
759
|
-
end
|
760
|
-
end
|
761
|
-
end
|