aitch 0.5.0 → 1.0.0

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.
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