furi 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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