aitch 0.5.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -5
- data/CHANGELOG.md +38 -0
- data/README.md +50 -14
- data/Rakefile +10 -0
- data/aitch.gemspec +4 -2
- data/lib/aitch.rb +7 -2
- data/lib/aitch/configuration.rb +1 -12
- data/lib/aitch/dsl.rb +1 -0
- data/lib/aitch/errors.rb +1 -0
- data/lib/aitch/ext/to_query.rb +1 -0
- data/lib/aitch/location.rb +3 -2
- data/lib/aitch/namespace.rb +1 -0
- data/lib/aitch/redirect.rb +8 -2
- data/lib/aitch/request.rb +22 -9
- data/lib/aitch/response.rb +4 -13
- data/lib/aitch/response/body.rb +1 -0
- data/lib/aitch/response/description.rb +52 -51
- data/lib/aitch/response/errors.rb +1 -0
- data/lib/aitch/response_parser.rb +29 -0
- data/lib/aitch/response_parser/default_parser.rb +18 -0
- data/lib/aitch/response_parser/html_parser.rb +18 -0
- data/lib/aitch/response_parser/json_parser.rb +18 -0
- data/lib/aitch/response_parser/xml_parser.rb +18 -0
- data/lib/aitch/uri.rb +1 -0
- data/lib/aitch/utils.rb +1 -0
- data/lib/aitch/version.rb +2 -1
- data/test/aitch/aitch_test.rb +27 -0
- data/test/aitch/configuration_test.rb +29 -0
- data/test/aitch/dsl_test.rb +48 -0
- data/test/aitch/execute_test.rb +45 -0
- data/test/aitch/namespace_test.rb +12 -0
- data/test/aitch/request/client_https_test.rb +20 -0
- data/test/aitch/request/follow_redirect_test.rb +64 -0
- data/test/aitch/request/request_class_test.rb +28 -0
- data/test/aitch/request/status_code_validation_test.rb +19 -0
- data/test/aitch/request_test.rb +138 -0
- data/test/aitch/response/custom_response_parser_test.rb +31 -0
- data/test/aitch/response/errors_test.rb +16 -0
- data/test/aitch/response/html_response_test.rb +18 -0
- data/test/aitch/response/json_response_test.rb +18 -0
- data/test/aitch/response/raw_response_test.rb +11 -0
- data/test/aitch/response/status_3xx_test.rb +56 -0
- data/test/aitch/response/status_4xx_test.rb +18 -0
- data/test/aitch/response/status_5xx_test.rb +18 -0
- data/test/aitch/response/xml_response_test.rb +18 -0
- data/test/aitch/response_parser/html_parser_test.rb +9 -0
- data/test/aitch/response_parser/json_parser_test.rb +9 -0
- data/test/aitch/response_parser/xml_parser_test.rb +17 -0
- data/test/aitch/response_test.rb +114 -0
- data/test/aitch/uri_test.rb +37 -0
- data/test/aitch/utils/symbolize_keys_test.rb +9 -0
- data/test/aitch/utils/underscore_test.rb +12 -0
- data/{spec → test}/fixtures/iso8859-1.xml +0 -0
- data/{spec/support/request_uri.rb → test/support/helpers.rb} +12 -3
- data/test/test_helper.rb +15 -0
- metadata +70 -37
- data/.rspec +0 -1
- data/lib/aitch/html_parser.rb +0 -7
- data/lib/aitch/xml_parser.rb +0 -7
- data/spec/aitch/aitch_spec.rb +0 -71
- data/spec/aitch/configuration_spec.rb +0 -33
- data/spec/aitch/dsl_spec.rb +0 -47
- data/spec/aitch/html_parser_spec.rb +0 -8
- data/spec/aitch/namespace_spec.rb +0 -11
- data/spec/aitch/request_spec.rb +0 -261
- data/spec/aitch/response_spec.rb +0 -259
- data/spec/aitch/uri_spec.rb +0 -36
- data/spec/aitch/utils_spec.rb +0 -19
- data/spec/aitch/xml_parser_spec.rb +0 -16
- data/spec/spec_helper.rb +0 -24
- 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,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,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
|
-
|
2
|
-
|
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
|