furi 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b454ab79a6ac9b95fc85b8b8b2381c8e93715af
4
- data.tar.gz: d84272345cd55a7aad224ce2b124423806f38301
3
+ metadata.gz: e9c81dc7acc1ab6c12a180cf8722a10e4bad93b8
4
+ data.tar.gz: 88787eb5df40194b9373c14375e94523cb9a0191
5
5
  SHA512:
6
- metadata.gz: cc4227555a121e3c25d7c4ba32765659fa78678ff7aa2b500f0f6cbe384f9507e11bac3828bfd9eae097879e786395ac9b8113049447b5d1a1aff6a834a91108
7
- data.tar.gz: 4b8d902ab961bff2d68a369da05c96f1cc142e6d71980a3cd24691de930807057b65016aa9ec16e8d7e52e2cdd5173068d108ac2d0128ced4ac9d497e671adbb
6
+ metadata.gz: 92ae36c027f8f38d9c9617595b6aedade9db5b7f652021660a3502813e63ba6b4062669fed3b1ba7c7d01846a0ab0251ff77752ca7f47a15e3d8482353743ad2
7
+ data.tar.gz: 8e756624ec091e58981ed3c1d8c0e998b22168fef6c1a1b0e41cf31a3d39037efad32fb9a62fe725322c7efa65600fcff8824efbc321b0bd79d7af95ca327b13
data/README.md CHANGED
@@ -36,9 +36,9 @@ Furi.port!("http://gusiev.com") # => 80
36
36
 
37
37
  Furi.update("http://gusiev.com", protocol: '') # => "//gusiev.com"
38
38
  Furi.update("http://gusiev.com?source=google", query: {email: "a@b.com"})
39
- # => "http://gusiev.com?email=a@b.com"
40
- Furi.merge("http://gusiev.com?source=google", query: {email: "a@b.com"})
41
39
  # => "http://gusiev.com?source=google&email=a@b.com"
40
+ Furi.replace("http://gusiev.com?source=google", query: {email: "a@b.com"})
41
+ # => "http://gusiev.com?email=a@b.com"
42
42
 
43
43
  Furi.build(protocol: '//', host: 'gusiev.com', path: '/assets/application.js')
44
44
  # => "//gusiev.com/assets/application.js"
@@ -113,14 +113,6 @@ Giving credit...
113
113
  * rfc3986 validation
114
114
  * mailto protocol
115
115
  * escaping in path
116
- * case insensetivity:
117
- * domain
118
- * protocol
119
- * case sensitivity:
120
- * path
121
- * query
122
- * anchor
123
- * basic auth data ?
124
116
 
125
117
  ## Contributing
126
118
 
@@ -21,5 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.7"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "rspec"
24
- spec.add_development_dependency "byebug"
24
+ spec.add_development_dependency "pry-byebug"
25
25
  end
@@ -35,6 +35,7 @@ module Furi
35
35
  "tftp" => {port: 69},
36
36
  "sftp" => {port: 22},
37
37
  "ssh" => {port: 22, ssl: true},
38
+ "svn" => {port: 3690},
38
39
  "svn+ssh" => {port: 22, ssl: true},
39
40
  "telnet" => {port: 23},
40
41
  "nntp" => {port: 119},
@@ -42,6 +43,10 @@ module Furi
42
43
  "wais" => {port: 210},
43
44
  "ldap" => {port: 389},
44
45
  "prospero" => {port: 1525},
46
+ "file" => {port: nil},
47
+ "postgres" => {port: 5432},
48
+ "mysql" => {port: 3306},
49
+ "mailto" => {port: nil}
45
50
  }
46
51
 
47
52
 
@@ -56,8 +61,9 @@ module Furi
56
61
  ROOT = '/'
57
62
 
58
63
  # Parses a given string and return an URL object
59
- def self.parse(argument)
60
- Uri.new(argument)
64
+ # Optionally accepts parts to update the parsed URL object
65
+ def self.parse(argument, parts = nil)
66
+ Uri.new(argument).update(parts)
61
67
  end
62
68
 
63
69
  # Builds an URL from given parts
@@ -83,6 +89,9 @@ module Furi
83
89
  def self.update(string, parts)
84
90
  parse(string).update(parts).to_s
85
91
  end
92
+ class << self
93
+ alias :merge :update
94
+ end
86
95
 
87
96
  # Puts the default values for given URL that are not defined
88
97
  #
@@ -94,16 +103,17 @@ module Furi
94
103
 
95
104
  # Replaces a given URL string with given parts.
96
105
  # Same as update but works different for URL query parameter:
97
- # merges newly specified parameters instead of replacing existing ones
106
+ # replaces newly specified parameters instead of merging to existing ones
98
107
  #
99
- # Furi.merge("/hello.html?a=1", host: 'gusiev.com', query: {b: 2})
108
+ # Furi.update("/hello.html?a=1", host: 'gusiev.com', query: {b: 2})
100
109
  # # => "gusiev.com/hello.html?a=1&b=2"
101
110
  #
102
- def self.merge(string, parts)
103
- parse(string).merge(parts).to_s
111
+ def self.replace(string, parts)
112
+ parse(string).replace(parts).to_s
104
113
  end
105
114
 
106
115
 
116
+
107
117
  # Parses a query into nested paramters hash using a rack convension with square brackets.
108
118
  #
109
119
  # Furi.parse_query("a[]=1&a[]=2") # => {a: [1,2]}
@@ -159,6 +169,12 @@ module Furi
159
169
  serialize_tokens(query, namespace).join("&")
160
170
  end
161
171
 
172
+ def self.join(*uris)
173
+ uris.map do |uri|
174
+ Furi.parse(uri)
175
+ end.reduce(:join)
176
+ end
177
+
162
178
  class FormattingError < StandardError
163
179
  end
164
180
 
@@ -21,21 +21,28 @@ module Furi
21
21
  when String
22
22
  parse_uri_string(argument)
23
23
  when Hash
24
- update(argument)
24
+ replace(argument)
25
+ when ::URI::Generic
26
+ parse_uri_string(argument.to_s)
27
+ else
28
+ raise ArgumentError, "wrong Uri argument"
25
29
  end
26
30
  end
27
31
 
28
- def update(parts)
29
- parts.each do |part, value|
30
- self[part] = value
32
+ def replace(parts)
33
+ if parts
34
+ parts.each do |part, value|
35
+ self[part] = value
36
+ end
31
37
  end
32
38
  self
33
39
  end
34
40
 
35
- def merge(parts)
41
+ def update(parts)
42
+ return self unless parts
36
43
  parts.each do |part, value|
37
44
  case part.to_sym
38
- when :query, :query_tokens
45
+ when :query, :query_tokens, :query_string
39
46
  merge_query(value)
40
47
  else
41
48
  self[part] = value
@@ -91,7 +98,7 @@ module Furi
91
98
  when "", nil
92
99
  nil
93
100
  else
94
- host.to_s
101
+ host.to_s.downcase
95
102
  end
96
103
  end
97
104
 
@@ -166,7 +173,7 @@ module Furi
166
173
  def to_s
167
174
  result = []
168
175
  result << location
169
- result << (host ? path : path!)
176
+ result << (host || mailto? ? path : path!)
170
177
  if query_tokens.any?
171
178
  result << "?" << query_string
172
179
  end
@@ -178,10 +185,12 @@ module Furi
178
185
 
179
186
  def location
180
187
  if protocol
181
- unless host
188
+ if !host && !mailto?
182
189
  raise Furi::FormattingError, "can not build URI with protocol but without host"
183
190
  end
184
- [protocol.empty? ? "" : "#{protocol}:", authority].join("//")
191
+ [
192
+ protocol.empty? ? "" : "#{protocol}:", authority
193
+ ].join(mailto? ? "" : "//")
185
194
  else
186
195
  authority
187
196
  end
@@ -196,12 +205,17 @@ module Furi
196
205
  end
197
206
 
198
207
  def request
208
+ return nil if !path && query_tokens.empty?
199
209
  result = []
200
210
  result << path!
201
211
  result << "?" << query_string if query_tokens.any?
202
212
  result.join
203
213
  end
204
214
 
215
+ def request!
216
+ request || path!
217
+ end
218
+
205
219
  def request=(string)
206
220
  string = parse_anchor_and_query(string)
207
221
  self.path = string
@@ -218,11 +232,13 @@ module Furi
218
232
 
219
233
 
220
234
  def query=(value)
221
- @query = nil
222
- @query_tokens = []
223
235
  case value
236
+ when true
237
+ # Assuming that current query needs to be parsed to Hash
238
+ query
224
239
  when String, Array
225
240
  self.query_tokens = value
241
+ @query = nil
226
242
  when Hash
227
243
  self.query_tokens = value
228
244
  @query = value
@@ -283,9 +299,12 @@ module Furi
283
299
  end
284
300
 
285
301
  def protocol=(protocol)
286
- @protocol = protocol ? protocol.gsub(%r{:?/?/?\Z}, "") : nil
302
+ @protocol = protocol ? protocol.gsub(%r{:?/?/?\Z}, "").downcase : nil
287
303
  end
288
304
 
305
+ def protocol!
306
+ protocol || default_protocol_for_port || 'http' # Web Rules Them All!
307
+ end
289
308
 
290
309
  def directory
291
310
  path_tokens[0..-2].join("/")
@@ -361,11 +380,11 @@ module Furi
361
380
  end
362
381
 
363
382
  def default_port
364
- protocol && Furi::PROTOCOLS[protocol] ? Furi::PROTOCOLS[protocol][:port] : nil
383
+ Furi::PROTOCOLS.fetch(protocol, {})[:port]
365
384
  end
366
385
 
367
386
  def ssl?
368
- !!(protocol && Furi::PROTOCOLS[protocol][:ssl])
387
+ !!(Furi::PROTOCOLS.fetch(protocol, {})[:ssl])
369
388
  end
370
389
 
371
390
  def ssl
@@ -395,7 +414,12 @@ module Furi
395
414
  Furi::WEB_PROTOCOL.include?(protocol)
396
415
  end
397
416
 
417
+ def abstract_protocol?
418
+ protocol == ""
419
+ end
420
+
398
421
  def resource
422
+ return nil unless request
399
423
  [request, anchor].compact.join("#")
400
424
  end
401
425
 
@@ -412,7 +436,7 @@ module Furi
412
436
  end
413
437
 
414
438
  def resource!
415
- [request]
439
+ resource || request!
416
440
  end
417
441
 
418
442
  def host!
@@ -440,12 +464,25 @@ module Furi
440
464
  send(:"#{part}=", value)
441
465
  end
442
466
 
467
+ def rfc?
468
+ rfc3986?
469
+ end
470
+
443
471
  def rfc3986?
444
472
  uri = to_s
445
- !!(uri.match(URI::RFC3986_Parser::RFC3986_Parser) ||
473
+ !!(uri.match(URI::RFC3986_Parser::RFC3986_URI) ||
446
474
  uri.match(URI::RFC3986_Parser::RFC3986_relative_ref))
447
475
  end
448
476
 
477
+ def email=(email)
478
+ self.protocol ||= "mailto"
479
+ self.authority = email
480
+ end
481
+
482
+ def email
483
+ authority
484
+ end
485
+
449
486
  protected
450
487
 
451
488
  def file_tokens
@@ -461,6 +498,9 @@ module Furi
461
498
  end
462
499
 
463
500
  def parse_uri_string(string)
501
+ if string.empty?
502
+ raise Furi::FormattingError, "can not be an empty string"
503
+ end
464
504
  string = parse_anchor_and_query(string)
465
505
 
466
506
  string = parse_protocol(string)
@@ -499,8 +539,12 @@ module Furi
499
539
  string
500
540
  end
501
541
 
542
+ def join(uri)
543
+ Uri.new(::URI.join(to_s, uri.to_s))
544
+ end
545
+
502
546
  def parse_protocol(string)
503
- if string.include?("://")
547
+ if string.include?("://") || string.start_with?("mailto:")
504
548
  protocol, string = string.split(":", 2)
505
549
  self.protocol = protocol
506
550
  end
@@ -529,5 +573,18 @@ module Furi
529
573
  def host_tokens
530
574
  host.split(".")
531
575
  end
576
+
577
+ def default_protocol_for_port
578
+ return nil unless port
579
+ PROTOCOLS.each do |protocol, data|
580
+ if data[:port] == port
581
+ return protocol
582
+ end
583
+ end
584
+ end
585
+
586
+ def mailto?
587
+ protocol == "mailto"
588
+ end
532
589
  end
533
590
  end
@@ -1,3 +1,3 @@
1
1
  module Furi
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Furi::Uri do
4
+
5
+ describe ".rfc3986?" do
6
+
7
+ it "works" do
8
+ expect(Furi.parse("http://goo gl.com") ).to_not be_rfc
9
+ expect(Furi.parse("http://googl.com") ).to be_rfc
10
+ end
11
+ end
12
+ end
@@ -64,7 +64,13 @@ describe Furi do
64
64
 
65
65
 
66
66
 
67
- describe "#parse" do
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
68
74
 
69
75
  it "parses URL with everything" do
70
76
  expect("http://user:pass@www.gusiev.com:8080/articles/index.html?a=1&b=2#header").to have_parts(
@@ -105,8 +111,10 @@ describe Furi do
105
111
  path: nil,
106
112
  path!: '/',
107
113
  port: nil,
108
- request: '/',
109
- resource: '/',
114
+ request: nil,
115
+ request!: '/',
116
+ resource: nil,
117
+ resource!: '/',
110
118
  location: 'http://gusiev.com',
111
119
  home_page?: true,
112
120
  )
@@ -305,6 +313,14 @@ describe Furi do
305
313
  )
306
314
  end
307
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
+
308
324
  describe "ipv6 host" do
309
325
  it "parses host and port" do
310
326
  expect("http://[2406:da00:ff00::6b14:8d43]:8080/").to have_parts(
@@ -333,123 +349,144 @@ describe Furi do
333
349
  )
334
350
  end
335
351
  end
336
- end
337
- describe ".update" do
338
352
 
339
- it "support update for query" do
340
- expect(Furi.update("/index.html?a=b", query: {c: 'd'})).to eq('/index.html?c=d')
341
- end
342
-
343
- it "updates hostname" do
344
- expect(Furi.update("www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
345
- expect(Furi.update("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
346
- expect(Furi.update("http://www.gusiev.com/index.html", hostname: 'gusiev.com')).to eq('http://gusiev.com/index.html')
347
- expect(Furi.update("/index.html", hostname: 'gusiev.com')).to eq('gusiev.com/index.html')
348
- expect(Furi.update("gusiev.com/index.html?a=b", hostname: nil)).to eq('/index.html?a=b')
349
- expect(Furi.update("gusiev.com?a=b", hostname: nil)).to eq('/?a=b')
350
- end
351
-
352
- it "updates port" do
353
- expect(Furi.update("gusiev.com", port: 33)).to eq('gusiev.com:33')
354
- expect(Furi.update("gusiev.com/index.html", port: 33)).to eq('gusiev.com:33/index.html')
355
- expect(Furi.update("gusiev.com:33/index.html", port: 80)).to eq('gusiev.com:80/index.html')
356
- expect(Furi.update("http://gusiev.com:33/index.html", port: 80)).to eq('http://gusiev.com/index.html')
357
- expect(Furi.update("http://gusiev.com:33/index.html", port: nil)).to eq('http://gusiev.com/index.html')
358
- expect(Furi.update("http://gusiev.com:33/index.html", port: 0)).to eq('http://gusiev.com:0/index.html')
359
- expect(Furi.update("http://gusiev.com:33/index.html", port: '')).to eq('http://gusiev.com/index.html')
360
- end
361
- it "updates directory" do
362
- expect(Furi.update("gusiev.com", directory: 'articles')).to eq('gusiev.com/articles')
363
- expect(Furi.update("gusiev.com/", directory: 'articles')).to eq('gusiev.com/articles')
364
- expect(Furi.update("gusiev.com/index#header", directory: '/posts')).to eq('gusiev.com/posts/index#header')
365
- expect(Furi.update("gusiev.com/articles/#header", directory: nil)).to eq('gusiev.com/#header')
366
- expect(Furi.update("gusiev.com/articles/index?a=b", directory: 'posts')).to eq('gusiev.com/posts/index?a=b')
367
- expect(Furi.update("/articles/index?a=b", directory: '/posts')).to eq('/posts/index?a=b')
368
- expect(Furi.update("/articles/index.html?a=b", directory: '/posts/')).to eq('/posts/index.html?a=b')
369
- end
370
- it "updates filename" do
371
- expect(Furi.update("gusiev.com", filename: 'article')).to eq('gusiev.com/article')
372
- expect(Furi.update("gusiev.com/", filename: 'article')).to eq('gusiev.com/article')
373
- expect(Furi.update("gusiev.com/article1#header", filename: '/article2')).to eq('gusiev.com/article2#header')
374
- expect(Furi.update("gusiev.com/article#header", filename: nil)).to eq('gusiev.com/#header')
375
- expect(Furi.update("gusiev.com/articles/article1?a=b", filename: 'article2')).to eq('gusiev.com/articles/article2?a=b')
376
- expect(Furi.update("/articles/article1?a=b", filename: '/article2')).to eq('/articles/article2?a=b')
377
- expect(Furi.update("/articles/article1.xml?a=b", filename: 'article2.html')).to eq('/articles/article2.html?a=b')
378
- end
379
- it "updates extension" do
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 filename" do
400
+ expect(Furi.replace("gusiev.com", filename: 'article')).to eq('gusiev.com/article')
401
+ expect(Furi.replace("gusiev.com/", filename: 'article')).to eq('gusiev.com/article')
402
+ expect(Furi.replace("gusiev.com/article1#header", filename: '/article2')).to eq('gusiev.com/article2#header')
403
+ expect(Furi.replace("gusiev.com/article#header", filename: nil)).to eq('gusiev.com/#header')
404
+ expect(Furi.replace("gusiev.com/articles/article1?a=b", filename: 'article2')).to eq('gusiev.com/articles/article2?a=b')
405
+ expect(Furi.replace("/articles/article1?a=b", filename: '/article2')).to eq('/articles/article2?a=b')
406
+ expect(Furi.replace("/articles/article1.xml?a=b", filename: 'article2.html')).to eq('/articles/article2.html?a=b')
407
+ end
408
+ it "replace extension" do
380
409
  expect(->{
381
- Furi.update("gusiev.com/", extension: 'xml')
410
+ Furi.replace("gusiev.com/", extension: 'xml')
382
411
  }).to raise_error(Furi::FormattingError)
383
- expect(Furi.update("gusiev.com/article#header", extension: 'html')).to eq('gusiev.com/article.html#header')
384
- expect(Furi.update("gusiev.com/article.html?header", extension: nil)).to eq('gusiev.com/article?header')
385
- expect(Furi.update("gusiev.com/article.xml?a=b", extension: 'html')).to eq('gusiev.com/article.html?a=b')
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')
386
415
  end
387
- it "updates resource" do
388
- expect(Furi.update("gusiev.com", resource: '/article?a=1#hello')).to eq('gusiev.com/article?a=1#hello')
389
- expect(Furi.update("gusiev.com/article1#header", resource: '/article2')).to eq('gusiev.com/article2')
390
- expect(Furi.update("gusiev.com/article#header", resource: nil)).to eq('gusiev.com')
391
- expect(Furi.update("gusiev.com/article1?a=b", resource: 'article2')).to eq('gusiev.com/article2')
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')
392
421
  end
393
- it "updates path" do
394
- expect(Furi.update("gusiev.com", path: '/article')).to eq('gusiev.com/article')
395
- expect(Furi.update("gusiev.com/article1#header", path: '/article2')).to eq('gusiev.com/article2#header')
396
- expect(Furi.update("gusiev.com/article#header", path: nil)).to eq('gusiev.com#header')
397
- expect(Furi.update("gusiev.com/article1?a=b", path: 'article2')).to eq('gusiev.com/article2?a=b')
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')
398
427
  end
399
428
 
400
- it "updates ssl" do
401
- expect(Furi.update("http://gusiev.com", ssl: true)).to eq('https://gusiev.com')
402
- expect(Furi.update("https://gusiev.com", ssl: true)).to eq('https://gusiev.com')
403
- expect(Furi.update("https://gusiev.com", ssl: false)).to eq('http://gusiev.com')
404
- expect(Furi.update("http://gusiev.com", ssl: false)).to eq('http://gusiev.com')
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')
405
434
  end
406
435
 
407
- it "updates protocol" do
408
- expect(Furi.update("http://gusiev.com", protocol: '')).to eq('//gusiev.com')
409
- expect(Furi.update("http://gusiev.com", protocol: nil)).to eq('gusiev.com')
410
- expect(Furi.update("http://gusiev.com", protocol: 'https')).to eq('https://gusiev.com')
411
- expect(Furi.update("gusiev.com", protocol: 'http')).to eq('http://gusiev.com')
412
- expect(Furi.update("gusiev.com", protocol: 'http:')).to eq('http://gusiev.com')
413
- expect(Furi.update("gusiev.com", protocol: 'http:/')).to eq('http://gusiev.com')
414
- expect(Furi.update("gusiev.com", protocol: 'http://')).to eq('http://gusiev.com')
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')
415
444
  end
416
445
 
417
- it "updates userinfo" do
418
- expect(Furi.update("http://gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
419
- expect(Furi.update("http://aa:bb@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
420
- expect(Furi.update("http://aa:bb@gusiev.com", userinfo: nil)).to eq('http://gusiev.com')
421
- expect(Furi.update("http://aa@gusiev.com", userinfo: 'hello:world')).to eq('http://hello:world@gusiev.com')
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')
422
451
  end
423
452
 
424
- it "updates authority" do
425
- expect(Furi.update("http://user:pass@gusiev.com:8080/index.html", authority: 'gusiev.com')).to eq('http://gusiev.com/index.html')
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')
426
455
  end
427
456
 
428
- it "updates request" do
429
- expect(Furi.update("http://gusiev.com:8080/index.html?c=d", request: '/blog.html?a=b')).to eq('http://gusiev.com:8080/blog.html?a=b')
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')
430
459
  end
431
460
 
432
- it "updates domainzone" do
433
- expect(Furi.update("http://gusiev.com:8080", domainzone: 'com.ua')).to eq('http://gusiev.com.ua:8080')
434
- expect(Furi.update("http://gusiev.com.ua:8080", domainzone: 'com')).to eq('http://gusiev.com:8080')
435
- expect(Furi.update("http://gusiev.com.ua:8080", domainzone: nil)).to eq('http://gusiev:8080')
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')
436
465
  end
437
466
 
438
- it "updates domainname" do
439
- expect(Furi.update("http://gusiev.com", domainname: 'google')).to eq('http://google.com')
440
- expect(Furi.update("http://gusiev.com", domainname: nil)).to eq('http://com')
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')
441
470
  end
442
- it "updates subdomain" do
443
- expect(Furi.update("http://gusiev.com", subdomain: 'blog')).to eq('http://blog.gusiev.com')
444
- expect(Furi.update("http://blog.gusiev.com", subdomain: nil)).to eq('http://gusiev.com')
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')
445
474
  end
446
475
 
447
- it "updates location" do
448
- expect(Furi.update("/index.html", location: 'http://gusiev.com')).to eq('http://gusiev.com/index.html')
449
- expect(Furi.update("/index.html", location: 'http://gusiev.com/')).to eq('http://gusiev.com/index.html')
450
- expect(Furi.update("gusiev.com:433/index.html", location: 'gusiev.com:80')).to eq('gusiev.com:80/index.html')
451
- expect(Furi.update("gusiev.com:433/index.html", location: nil)).to eq('/index.html')
452
- expect(Furi.update("http://gusiev.com:433/index.html", location: nil)).to eq('/index.html')
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')
453
490
  end
454
491
 
455
492
  end
@@ -475,15 +512,26 @@ describe Furi do
475
512
  Furi.build(host: 'localhost', password: 'pass')
476
513
  }).to raise_error(Furi::FormattingError)
477
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
478
523
  end
479
524
 
480
- describe ".merge" do
481
- it "should work" do
482
- expect(Furi.merge("//gusiev.com", query: {a: 1})).to eq('//gusiev.com?a=1')
483
- expect(Furi.merge("//gusiev.com?a=1", query: {b: 2})).to eq('//gusiev.com?a=1&b=2')
484
- expect(Furi.merge("//gusiev.com?a=1", query: {a: 2})).to eq('//gusiev.com?a=2')
485
- expect(Furi.merge("//gusiev.com?a=1", query: [['a', 2], ['b', 3]])).to eq('//gusiev.com?a=1&a=2&b=3')
486
- expect(Furi.merge("//gusiev.com?a=1&b=2", query: '?a=3')).to eq('//gusiev.com?a=1&b=2&a=3')
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')
487
535
  end
488
536
  end
489
537
 
@@ -515,8 +563,32 @@ describe Furi do
515
563
  expect(Furi.parse('http://gusiev.com') == Furi.parse('http://gusiev.com')).to be_truthy
516
564
  expect(Furi.parse('http://gusiev.com.ua') == Furi.parse('http://gusiev.com')).to be_falsey
517
565
  expect(Furi.parse('http://gusiev.com?a=1&a=1') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
518
- pending
519
- expect(Furi.parse('http://gUSiev.cOm?A=1') == Furi.parse('http://gusiev.com?a=1')).to be_truthy
566
+ end
567
+
568
+ it "works with query parameters" do
569
+ expect(Furi.parse('/?b=1&a=1') == Furi.parse('/?b=1&a=1')).to be_truthy
570
+ expect(Furi.parse('/?a=1&a=1') == Furi.parse('/?a=1')).to be_falsey
571
+ expect(Furi.parse('/') == Furi.parse('/?a=1')).to be_falsey
572
+ expect(Furi.parse('/') == Furi.parse('http://gusiev.com?a=1')).to be_falsey
573
+
574
+ end
575
+
576
+ it "ignores case only on protocol and host" do
577
+ expect(Furi.parse('hTTp://gUSiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
578
+ expect(Furi.parse('/hello') == Furi.parse('/Hello')).to be_falsey
579
+ expect(Furi.parse('/hello?a=1') == Furi.parse('/hello?A=1')).to be_falsey
580
+ expect(Furi.parse('hTTp://gusiev.cOm') == Furi.parse('http://gusiev.com')).to be_truthy
581
+ expect(Furi.parse('/#h1') == Furi.parse('/#H1')).to be_falsey
582
+ expect(Furi.parse('hello@gusiev.com') == Furi.parse('Hello@gusiev.com')).to be_falsey
583
+ expect(Furi.parse('hello:psswd@gusiev.com') == Furi.parse('hello:Psswd@gusiev.com')).to be_falsey
584
+ end
585
+
586
+ end
587
+
588
+ describe "#abstract_protocol" do
589
+ it "works" do
590
+ expect(Furi.parse('http://gUSiev.cOm')).to_not be_abstract_protocol
591
+ expect(Furi.parse('//gUSiev.cOm')).to be_abstract_protocol
520
592
  end
521
593
  end
522
594
 
@@ -580,7 +652,7 @@ describe Furi do
580
652
  end
581
653
  end
582
654
 
583
- describe "parse_query" do
655
+ describe ".parse_query" do
584
656
  it "should work" do
585
657
  Furi.parse_query("foo").
586
658
  should eq "foo" => nil
@@ -665,4 +737,10 @@ describe Furi do
665
737
  expect(Furi.parse('http://google.com').inspect).to eq("#<Furi::Uri \"http://google.com\">")
666
738
  end
667
739
 
740
+
741
+ describe ".join" do
742
+ it "works" do
743
+ expect(Furi.join("http://gusiev.com/slides", "../photos")).to eq("http://gusiev.com/photos")
744
+ end
745
+ end
668
746
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: furi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdan Gusiev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-30 00:00:00.000000000 Z
11
+ date: 2016-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: byebug
56
+ name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -86,6 +86,7 @@ files:
86
86
  - lib/furi/uri.rb
87
87
  - lib/furi/utils.rb
88
88
  - lib/furi/version.rb
89
+ - spec/furi/uri_spec.rb
89
90
  - spec/furi_spec.rb
90
91
  - spec/spec_helper.rb
91
92
  homepage: ''
@@ -108,10 +109,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
109
  version: '0'
109
110
  requirements: []
110
111
  rubyforge_project:
111
- rubygems_version: 2.4.5
112
+ rubygems_version: 2.6.7
112
113
  signing_key:
113
114
  specification_version: 4
114
115
  summary: Make URI processing as easy as it should be
115
116
  test_files:
117
+ - spec/furi/uri_spec.rb
116
118
  - spec/furi_spec.rb
117
119
  - spec/spec_helper.rb