aitch 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -5
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +50 -14
  5. data/Rakefile +10 -0
  6. data/aitch.gemspec +4 -2
  7. data/lib/aitch.rb +7 -2
  8. data/lib/aitch/configuration.rb +1 -12
  9. data/lib/aitch/dsl.rb +1 -0
  10. data/lib/aitch/errors.rb +1 -0
  11. data/lib/aitch/ext/to_query.rb +1 -0
  12. data/lib/aitch/location.rb +3 -2
  13. data/lib/aitch/namespace.rb +1 -0
  14. data/lib/aitch/redirect.rb +8 -2
  15. data/lib/aitch/request.rb +22 -9
  16. data/lib/aitch/response.rb +4 -13
  17. data/lib/aitch/response/body.rb +1 -0
  18. data/lib/aitch/response/description.rb +52 -51
  19. data/lib/aitch/response/errors.rb +1 -0
  20. data/lib/aitch/response_parser.rb +29 -0
  21. data/lib/aitch/response_parser/default_parser.rb +18 -0
  22. data/lib/aitch/response_parser/html_parser.rb +18 -0
  23. data/lib/aitch/response_parser/json_parser.rb +18 -0
  24. data/lib/aitch/response_parser/xml_parser.rb +18 -0
  25. data/lib/aitch/uri.rb +1 -0
  26. data/lib/aitch/utils.rb +1 -0
  27. data/lib/aitch/version.rb +2 -1
  28. data/test/aitch/aitch_test.rb +27 -0
  29. data/test/aitch/configuration_test.rb +29 -0
  30. data/test/aitch/dsl_test.rb +48 -0
  31. data/test/aitch/execute_test.rb +45 -0
  32. data/test/aitch/namespace_test.rb +12 -0
  33. data/test/aitch/request/client_https_test.rb +20 -0
  34. data/test/aitch/request/follow_redirect_test.rb +64 -0
  35. data/test/aitch/request/request_class_test.rb +28 -0
  36. data/test/aitch/request/status_code_validation_test.rb +19 -0
  37. data/test/aitch/request_test.rb +138 -0
  38. data/test/aitch/response/custom_response_parser_test.rb +31 -0
  39. data/test/aitch/response/errors_test.rb +16 -0
  40. data/test/aitch/response/html_response_test.rb +18 -0
  41. data/test/aitch/response/json_response_test.rb +18 -0
  42. data/test/aitch/response/raw_response_test.rb +11 -0
  43. data/test/aitch/response/status_3xx_test.rb +56 -0
  44. data/test/aitch/response/status_4xx_test.rb +18 -0
  45. data/test/aitch/response/status_5xx_test.rb +18 -0
  46. data/test/aitch/response/xml_response_test.rb +18 -0
  47. data/test/aitch/response_parser/html_parser_test.rb +9 -0
  48. data/test/aitch/response_parser/json_parser_test.rb +9 -0
  49. data/test/aitch/response_parser/xml_parser_test.rb +17 -0
  50. data/test/aitch/response_test.rb +114 -0
  51. data/test/aitch/uri_test.rb +37 -0
  52. data/test/aitch/utils/symbolize_keys_test.rb +9 -0
  53. data/test/aitch/utils/underscore_test.rb +12 -0
  54. data/{spec → test}/fixtures/iso8859-1.xml +0 -0
  55. data/{spec/support/request_uri.rb → test/support/helpers.rb} +12 -3
  56. data/test/test_helper.rb +15 -0
  57. metadata +70 -37
  58. data/.rspec +0 -1
  59. data/lib/aitch/html_parser.rb +0 -7
  60. data/lib/aitch/xml_parser.rb +0 -7
  61. data/spec/aitch/aitch_spec.rb +0 -71
  62. data/spec/aitch/configuration_spec.rb +0 -33
  63. data/spec/aitch/dsl_spec.rb +0 -47
  64. data/spec/aitch/html_parser_spec.rb +0 -8
  65. data/spec/aitch/namespace_spec.rb +0 -11
  66. data/spec/aitch/request_spec.rb +0 -261
  67. data/spec/aitch/response_spec.rb +0 -259
  68. data/spec/aitch/uri_spec.rb +0 -36
  69. data/spec/aitch/utils_spec.rb +0 -19
  70. data/spec/aitch/xml_parser_spec.rb +0 -16
  71. data/spec/spec_helper.rb +0 -24
  72. data/spec/support/webmock.rb +0 -15
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+ require "csv"
4
+
5
+ class CustomResponseParserTest < Minitest::Test
6
+ setup do
7
+ parser = Class.new do
8
+ def self.type
9
+ :csv
10
+ end
11
+
12
+ def self.match?(content_type)
13
+ content_type =~ /csv/
14
+ end
15
+
16
+ def self.load(source)
17
+ CSV.parse(source)
18
+ end
19
+ end
20
+
21
+ Aitch::ResponseParser.prepend(:csv, parser)
22
+ end
23
+
24
+ test "returns csv" do
25
+ register_uri(:get, "http://example.org/file.csv", body: "1,2,3", content_type: "text/csv")
26
+ response = Aitch.get("http://example.org/file.csv")
27
+
28
+ assert_instance_of Array, response.data
29
+ assert_equal [%w[1 2 3]], response.data
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class ErrorsTest < Minitest::Test
5
+ Aitch::Response::ERRORS.each do |code, exception|
6
+ name = Aitch::Utils.underscore(exception.name.split("::").last).gsub("_error", "")
7
+
8
+ test "detects response as #{name}" do
9
+ config = {}
10
+ http_response = stub(code: code)
11
+ response = Aitch::Response.new(config, http_response)
12
+
13
+ assert response.public_send("#{name}?")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class HtmlResponseTest < Minitest::Test
5
+ test "detects as html" do
6
+ register_uri(:get, "http://example.org/", body: "", content_type: "text/html")
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert response.html?
10
+ end
11
+
12
+ test "returns html" do
13
+ register_uri(:get, "http://example.org/", body: "Hello", content_type: "text/html")
14
+ response = Aitch.get("http://example.org/")
15
+
16
+ assert_instance_of Nokogiri::HTML::Document, response.data
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class JsonResponseTest < Minitest::Test
5
+ test "detects as json" do
6
+ register_uri(:get, "http://example.org/", body: "[]", content_type: "application/json")
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert response.json?
10
+ end
11
+
12
+ test "returns json" do
13
+ register_uri(:get, "http://example.org/", body: "[1,2,3]", content_type: "application/json")
14
+ response = Aitch.get("http://example.org/")
15
+
16
+ assert_equal [1,2,3], response.data
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class RawResponseTest < Minitest::Test
5
+ test "returns body as it is (raw)" do
6
+ register_uri(:get, "http://example.org/", body: "HELLO", content_type: "text/plain")
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert_equal "HELLO", response.body
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class Status3xxTest < Minitest::Test
5
+ setup { Aitch.configuration.follow_redirect = false }
6
+
7
+ test "sets default redirected from" do
8
+ assert_equal [], Aitch::Response.new({}, stub("response")).redirected_from
9
+ end
10
+
11
+ test "uses provided redirected from" do
12
+ assert_equal ["URL"], Aitch::Response.new({redirected_from: ["URL"]}, stub("response")).redirected_from
13
+ end
14
+
15
+ test "has body" do
16
+ register_uri(:get, "http://example.org/", body: "Hello", status: 301)
17
+ response = Aitch.get("http://example.org/")
18
+ assert_equal "Hello", response.body
19
+ end
20
+
21
+ test "detects as successful response" do
22
+ register_uri(:get, "http://example.org/", status: 301)
23
+ response = Aitch.get("http://example.org/")
24
+
25
+ assert response.success?
26
+ assert response.ok?
27
+ end
28
+
29
+ test "detects as redirect" do
30
+ register_uri(:get, "http://example.org/", status: 301)
31
+ response = Aitch.get("http://example.org/")
32
+
33
+ assert response.redirect?
34
+ end
35
+
36
+ test "returns location" do
37
+ register_uri(:get, "http://example.org/", status: 301, location: "https://example.com/")
38
+ response = Aitch.get("http://example.org/")
39
+ assert_equal "https://example.com/", response.location
40
+ end
41
+
42
+ test "follows absolute paths" do
43
+ Aitch.configuration.follow_redirect = true
44
+ Aitch.configuration.redirect_limit = 5
45
+
46
+ register_uri(:get, "http://example.org/", status: 301, location: "/hello")
47
+ register_uri(:get, "http://example.org/hello", status: 301, location: "/hi")
48
+ register_uri(:get, "http://example.org/hi", status: 200, body: "Hi")
49
+
50
+ response = Aitch.get("http://example.org/")
51
+
52
+ assert_equal ["http://example.org/", "http://example.org/hello"], response.redirected_from
53
+ assert_equal "http://example.org/hi", response.url
54
+ assert_equal "Hi", response.body
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class Status4xxTest < Minitest::Test
5
+ test "detects as error" do
6
+ register_uri(:get, "http://example.org/", status: 404)
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert response.error?
10
+ end
11
+
12
+ test "sets error" do
13
+ register_uri(:get, "http://example.org/", status: 404)
14
+ response = Aitch.get("http://example.org/")
15
+
16
+ assert_equal Aitch::NotFoundError, response.error
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class Status5xxTest < Minitest::Test
5
+ test "detects as error" do
6
+ register_uri(:get, "http://example.org/", status: 500)
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert response.error?
10
+ end
11
+
12
+ test "sets error" do
13
+ register_uri(:get, "http://example.org/", status: 500)
14
+ response = Aitch.get("http://example.org/")
15
+
16
+ assert_equal Aitch::InternalServerErrorError, response.error
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class XmlResponseTest < Minitest::Test
5
+ test "detects as xml" do
6
+ register_uri(:get, "http://example.org/", body: "[]", content_type: "application/xml")
7
+ response = Aitch.get("http://example.org/")
8
+
9
+ assert response.xml?
10
+ end
11
+
12
+ test "returns xml" do
13
+ register_uri(:get, "http://example.org/", body: "<foo/>", content_type: "application/xml")
14
+ response = Aitch.get("http://example.org/")
15
+
16
+ assert_instance_of Nokogiri::XML::Document, response.data
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class HtmlParserTest < Minitest::Test
5
+ test "instantiates Nokogiri" do
6
+ Nokogiri.expects(:HTML).with("HTML")
7
+ Aitch::ResponseParser::HTMLParser.load("HTML")
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class JsonParserTest < Minitest::Test
5
+ test "loads JSON" do
6
+ JSON.expects(:load).with(%[{"a":1}])
7
+ Aitch::ResponseParser::JSONParser.load(%[{"a":1}])
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+ require "test_helper"
4
+
5
+ class XmlParserTest < Minitest::Test
6
+ test "instantiates Nokogiri" do
7
+ Nokogiri.expects(:XML).with("XML", nil, "utf-8")
8
+ Aitch::ResponseParser::XMLParser.load("XML")
9
+ end
10
+
11
+ test "converts ISO-8859-1 to UTF-8" do
12
+ xml = Aitch::ResponseParser::XMLParser.load(File.read("./test/fixtures/iso8859-1.xml"))
13
+
14
+ assert_equal "utf-8", xml.encoding
15
+ assert_includes xml.to_xml, %[<?xml version="1.0" encoding="utf-8"?>]
16
+ end
17
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class ResponseTest < Minitest::Test
5
+ test "has body" do
6
+ register_uri(:get, "http://example.org/", body: "Hello")
7
+ response = Aitch.get("http://example.org/")
8
+ assert_equal "Hello", response.body
9
+ end
10
+
11
+ test "sets current url" do
12
+ register_uri(:get, "http://example.org/", body: "Hello")
13
+ response = Aitch.get("http://example.org/")
14
+ assert_equal "http://example.org/", response.url
15
+ end
16
+
17
+ test "parses gzip response" do
18
+ stdio = StringIO.new
19
+ gzipped = Zlib::GzipWriter.new(stdio)
20
+ gzipped.write("Hello")
21
+ gzipped.finish
22
+
23
+ register_uri(:get, "http://example.org/", body: stdio.string, content_encoding: "gzip")
24
+ response = Aitch.get("http://example.org/")
25
+
26
+ assert_equal "Hello", response.body
27
+ end
28
+
29
+ test "deflates response" do
30
+ stdio = StringIO.new
31
+ deflated = Zlib::Deflate.deflate("Hello")
32
+
33
+ register_uri(:get, "http://example.org/", body: deflated, content_encoding: "deflate")
34
+ response = Aitch.get("http://example.org/")
35
+
36
+ assert_equal "Hello", response.body
37
+ end
38
+
39
+ test "returns status code" do
40
+ register_uri(:get, "http://example.org/", body: "")
41
+ response = Aitch.get("http://example.org/")
42
+ assert_equal 200, response.code
43
+ end
44
+
45
+ test "returns content type" do
46
+ register_uri(:get, "http://example.org/", content_type: "text/html")
47
+ response = Aitch.get("http://example.org/")
48
+ assert_equal "text/html", response.content_type
49
+ end
50
+
51
+ test "detects as successful response" do
52
+ register_uri(:get, "http://example.org/", content_type: "text/html")
53
+ response = Aitch.get("http://example.org/")
54
+ assert response.success?
55
+ end
56
+
57
+ test "returns headers" do
58
+ register_uri(:get, "http://example.org/", content_type: "text/html")
59
+ headers = Aitch.get("http://example.org/").headers
60
+
61
+ assert_instance_of Hash, headers
62
+ assert_equal "text/html", headers["content-type"]
63
+ end
64
+
65
+ test "normalizes custom headers" do
66
+ register_uri(:get, "http://example.org/", headers: {"X-Runtime" => "0.003"})
67
+ headers = Aitch.get("http://example.org/").headers
68
+
69
+ assert_equal "0.003", headers["runtime"]
70
+ end
71
+
72
+ test "maps missing methods to headers" do
73
+ register_uri(:get, "http://example.org/", headers: {"X-Runtime" => "0.003"})
74
+ response = Aitch.get("http://example.org/")
75
+
76
+ assert_equal "0.003", response.runtime
77
+ assert response.respond_to?(:runtime)
78
+ end
79
+
80
+ test "raises when have no method" do
81
+ register_uri(:get, "http://example.org/")
82
+ response = Aitch.get("http://example.org/")
83
+
84
+ assert_raises(NoMethodError) { response.runtime }
85
+ end
86
+
87
+ test "returns description for 200 OK" do
88
+ register_uri(:get, "http://example.org/", status: 200)
89
+ response = Aitch.get("http://example.org/")
90
+
91
+ assert_equal "200 OK", response.description
92
+ end
93
+
94
+ test "returns description for 101 Switch Protocol" do
95
+ register_uri(:get, "http://example.org/", status: 101)
96
+ response = Aitch.get("http://example.org/")
97
+
98
+ assert_equal "101 Switch Protocol", response.description
99
+ end
100
+
101
+ test "returns description for 444 No Response (nginx)" do
102
+ register_uri(:get, "http://example.org/", status: 444)
103
+ response = Aitch.get("http://example.org/")
104
+
105
+ assert_equal "444", response.description
106
+ end
107
+
108
+ test "overrides inspect" do
109
+ register_uri(:get, "http://example.org/", status: 101, content_type: "text/html")
110
+ response = Aitch.get("http://example.org/")
111
+
112
+ assert_equal "#<Aitch::Response 101 Switch Protocol (text/html)>", response.inspect
113
+ end
114
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class UriTest < Minitest::Test
5
+ test "returns default path" do
6
+ assert_equal "/", Aitch::URI.new("http://example.org").path
7
+ end
8
+
9
+ test "returns defined path" do
10
+ assert_equal "/some/path", Aitch::URI.new("http://example.org/some/path").path
11
+ end
12
+
13
+ test "returns fragment" do
14
+ assert_equal "#top", Aitch::URI.new("http://example.org/#top").fragment
15
+ end
16
+
17
+ test "returns query string" do
18
+ assert_equal "?a=1&b=2", Aitch::URI.new("http://example.org/?a=1&b=2").query
19
+ end
20
+
21
+ test "converts data into query string" do
22
+ assert_equal "?a=1&b=2", Aitch::URI.new("http://example.org", a: 1, b: 2).query
23
+ end
24
+
25
+ test "merges data into query string" do
26
+ assert_equal "?a=1&b=2&c=3", Aitch::URI.new("http://example.org/?a=1&b=2", c: 3).query
27
+ end
28
+
29
+ test "ignores data when request has body" do
30
+ assert_equal nil, Aitch::URI.new("http://example.org/", {c: 3}, true).query
31
+ end
32
+
33
+ test "returns request uri" do
34
+ uri = Aitch::URI.new("http://example.org/some/path?a=1&b=2#hello", c: 3)
35
+ assert_equal "/some/path?a=1&b=2&c=3#hello", uri.request_uri
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class SymbolizeKeysTest < Minitest::Test
5
+ test "converts keys to symbols" do
6
+ expected = {a: 1}
7
+ assert_equal expected, Aitch::Utils.symbolize_keys("a" => 1)
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require "test_helper"
3
+
4
+ class UnderscoreTest < Minitest::Test
5
+ test "replaces capital letters by underscores" do
6
+ assert_equal "some_constant_name", Aitch::Utils.underscore("SomeConstantName")
7
+ end
8
+
9
+ test "considers URI acronym" do
10
+ assert_equal "request_uri_too_long", Aitch::Utils.underscore("RequestURITooLong")
11
+ end
12
+ end
File without changes
@@ -1,5 +1,6 @@
1
- RSpec.configure do |config|
2
- config.include Module.new {
1
+ # frozen_string_literal: true
2
+ module Minitest
3
+ class Test
3
4
  def add_hash_entry(source, target, from, to)
4
5
  target[to] = source[from] if source[from]
5
6
  end
@@ -20,5 +21,13 @@ RSpec.configure do |config|
20
21
  def last_request
21
22
  WebMock.requests.last
22
23
  end
23
- }
24
+
25
+ def build_request(options = {})
26
+ Aitch::Request.new({
27
+ request_method: "get",
28
+ url: "http://example.org",
29
+ options: {}
30
+ }.merge(options))
31
+ end
32
+ end
24
33
  end