skink 0.2.0 → 0.3.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.
- data/lib/skink/client/base.rb +4 -23
- data/lib/skink/client/response.rb +74 -0
- data/lib/skink/client/utils.rb +28 -0
- data/lib/skink/dsl.rb +5 -1
- data/lib/skink/rack_test_client/rack_test_response.rb +4 -0
- data/lib/skink/resourceful_client/resourceful_response.rb +5 -1
- data/lib/skink/version.rb +1 -1
- data/skink.gemspec +2 -0
- data/spec/skink_dsl_spec.rb +40 -9
- data/spec/test_server.rb +8 -0
- metadata +35 -2
data/lib/skink/client/base.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'skink'
|
2
|
+
require 'skink/client/utils'
|
2
3
|
|
3
4
|
module Skink
|
4
5
|
module Client
|
5
6
|
|
6
7
|
class Base
|
8
|
+
include Utils
|
9
|
+
|
7
10
|
def with_header(name, value)
|
8
11
|
raise NotImplementedError
|
9
12
|
end
|
@@ -56,31 +59,9 @@ class Base
|
|
56
59
|
if name.match(/with_(\w+)_header/)
|
57
60
|
with_header(normalize_header_name($1), *args)
|
58
61
|
else
|
59
|
-
super
|
62
|
+
super(name, *args)
|
60
63
|
end
|
61
64
|
end
|
62
|
-
|
63
|
-
private
|
64
|
-
def normalize_header_name(name)
|
65
|
-
# c.f http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
|
66
|
-
|
67
|
-
case name
|
68
|
-
# special cases
|
69
|
-
when /^content_md5$/i
|
70
|
-
return "Content-MD5"
|
71
|
-
when /^te$/i
|
72
|
-
return "TE"
|
73
|
-
when /^dnt$/i
|
74
|
-
return "DNT"
|
75
|
-
when /^etag$/i
|
76
|
-
return "ETag"
|
77
|
-
when /^www_authenticate$/i
|
78
|
-
return "WWW-Authenticate"
|
79
|
-
end
|
80
|
-
|
81
|
-
# otherwise this should work
|
82
|
-
name.split("_").map(&:capitalize).join("-")
|
83
|
-
end
|
84
65
|
end
|
85
66
|
|
86
67
|
end
|
@@ -1,7 +1,14 @@
|
|
1
|
+
require 'skink/client/utils'
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'jsonpath'
|
5
|
+
|
1
6
|
module Skink
|
2
7
|
module Client
|
3
8
|
|
4
9
|
class Response
|
10
|
+
include Utils
|
11
|
+
|
5
12
|
def status_code
|
6
13
|
raise NotImplementedError
|
7
14
|
end
|
@@ -10,9 +17,76 @@ class Response
|
|
10
17
|
raise NotImplementedError
|
11
18
|
end
|
12
19
|
|
20
|
+
def find_header header
|
21
|
+
case header
|
22
|
+
when String
|
23
|
+
headers[headers.keys.detect {|key| key.match(/^#{header}$/i)}] rescue nil
|
24
|
+
when Symbol
|
25
|
+
headers[headers.keys.detect {|key| key.match(/^#{header.to_s.gsub('_', '-')}$/i)}] rescue nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_header? header
|
30
|
+
if find_header(header)
|
31
|
+
true
|
32
|
+
elsif header.respond_to? :keys
|
33
|
+
header.all? do |key, value|
|
34
|
+
value === find_header(key)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
13
41
|
def body
|
14
42
|
raise NotImplementedError
|
15
43
|
end
|
44
|
+
|
45
|
+
def xml_doc
|
46
|
+
@xml_doc ||= Nokogiri::XML.parse body
|
47
|
+
end
|
48
|
+
|
49
|
+
def xpath path
|
50
|
+
xml_doc.xpath path
|
51
|
+
end
|
52
|
+
|
53
|
+
def has_xpath? path, value = nil
|
54
|
+
elems = xpath(path)
|
55
|
+
if value
|
56
|
+
block = ->(elem) {value === elem.to_s}
|
57
|
+
else
|
58
|
+
block = nil
|
59
|
+
end
|
60
|
+
|
61
|
+
elems.any?(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def json_doc
|
65
|
+
@json_doc ||= MultiJson.load body
|
66
|
+
end
|
67
|
+
|
68
|
+
def jsonpath path
|
69
|
+
JsonPath.new(path).on json_doc
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_jsonpath? path, value = nil
|
73
|
+
elems = jsonpath(path)
|
74
|
+
if value
|
75
|
+
block = ->(elem) {value === elem}
|
76
|
+
else
|
77
|
+
block = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
elems.any?(&block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def method_missing(name, *args)
|
84
|
+
if name.match(/has_(\w+)_header\?/)
|
85
|
+
headers[normalize_header_name($1)] === args.first
|
86
|
+
else
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
16
90
|
end
|
17
91
|
|
18
92
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Skink
|
2
|
+
module Client
|
3
|
+
|
4
|
+
module Utils
|
5
|
+
def normalize_header_name(name)
|
6
|
+
# c.f http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
|
7
|
+
|
8
|
+
case name
|
9
|
+
# special cases
|
10
|
+
when /^content_md5$/i
|
11
|
+
return "Content-MD5"
|
12
|
+
when /^te$/i
|
13
|
+
return "TE"
|
14
|
+
when /^dnt$/i
|
15
|
+
return "DNT"
|
16
|
+
when /^etag$/i
|
17
|
+
return "ETag"
|
18
|
+
when /^www_authenticate$/i
|
19
|
+
return "WWW-Authenticate"
|
20
|
+
end
|
21
|
+
|
22
|
+
# otherwise this should work
|
23
|
+
name.split("_").map(&:capitalize).join("-")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/skink/dsl.rb
CHANGED
@@ -41,7 +41,11 @@ module Skink
|
|
41
41
|
|
42
42
|
Skink::Client::Base.instance_methods(false).each do |method|
|
43
43
|
define_method method do |*args, &block|
|
44
|
-
|
44
|
+
begin
|
45
|
+
Skink.client.send method, *args, &block
|
46
|
+
rescue NoMethodError
|
47
|
+
super(*args) if method == :method_missing
|
48
|
+
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
@@ -13,8 +13,12 @@ class ResourcefulResponse < Client::Response
|
|
13
13
|
native_response.code
|
14
14
|
end
|
15
15
|
|
16
|
+
def has_status_code? code
|
17
|
+
native_response.code == code
|
18
|
+
end
|
19
|
+
|
16
20
|
def headers
|
17
|
-
native_response.headers
|
21
|
+
native_response.headers.to_hash
|
18
22
|
end
|
19
23
|
|
20
24
|
def body
|
data/lib/skink/version.rb
CHANGED
data/skink.gemspec
CHANGED
@@ -14,6 +14,8 @@ Gem::Specification.new do |gem|
|
|
14
14
|
|
15
15
|
gem.add_dependency "rack-test"
|
16
16
|
gem.add_dependency "openlogic-resourceful"
|
17
|
+
gem.add_dependency "nokogiri"
|
18
|
+
gem.add_dependency "jsonpath"
|
17
19
|
|
18
20
|
gem.add_development_dependency "rspec"
|
19
21
|
gem.add_development_dependency "sinatra"
|
data/spec/skink_dsl_spec.rb
CHANGED
@@ -3,13 +3,13 @@ require_relative './spec_helper'
|
|
3
3
|
shared_examples "a REST API test language" do
|
4
4
|
it "is able to test a HEAD" do
|
5
5
|
head "/"
|
6
|
-
response.
|
6
|
+
response.should have_status_code 200
|
7
7
|
response.body.size.should == 0
|
8
8
|
end
|
9
9
|
|
10
10
|
it "is able to test a GET" do
|
11
11
|
get "/"
|
12
|
-
response.
|
12
|
+
response.should have_status_code 200
|
13
13
|
response.body.should == "Hello, world!"
|
14
14
|
end
|
15
15
|
|
@@ -17,7 +17,7 @@ shared_examples "a REST API test language" do
|
|
17
17
|
body = "<ping/>"
|
18
18
|
with_content_type_header "application/xml"
|
19
19
|
post "/", body
|
20
|
-
response.
|
20
|
+
response.should have_status_code 200
|
21
21
|
response.body.should == body
|
22
22
|
end
|
23
23
|
|
@@ -25,39 +25,70 @@ shared_examples "a REST API test language" do
|
|
25
25
|
body = "{\"ping\": \"hello\"}"
|
26
26
|
with_content_type_header "application/json"
|
27
27
|
put "/", body
|
28
|
-
response.
|
28
|
+
response.should have_status_code 200
|
29
29
|
response.body.should == body
|
30
30
|
end
|
31
31
|
|
32
32
|
it "is able to test a DELETE" do
|
33
33
|
delete "/"
|
34
|
-
response.
|
34
|
+
response.should have_status_code 200
|
35
35
|
response.body.should == "Deleted"
|
36
36
|
end
|
37
37
|
|
38
38
|
it "is able to test a request with additional headers" do
|
39
39
|
with_accept_header "application/json"
|
40
40
|
get "/foo"
|
41
|
-
response.
|
41
|
+
response.should have_status_code 200
|
42
42
|
response.body.should == "{\"foo\": 42}"
|
43
43
|
end
|
44
44
|
|
45
45
|
it "is able to test requests which require basic authentication" do
|
46
46
|
with_basic_auth "admin", "admin"
|
47
47
|
get "/protected"
|
48
|
-
response.
|
48
|
+
response.should have_status_code 200
|
49
49
|
response.body.should == "Welcome, authenticated client."
|
50
50
|
end
|
51
51
|
|
52
52
|
it "is able to test requests which require basic authentication for specified realm" do
|
53
53
|
get "/protected"
|
54
|
-
response.
|
54
|
+
response.should have_status_code 401
|
55
55
|
|
56
56
|
with_basic_auth "admin", "admin", "Restricted Area"
|
57
57
|
get "/protected"
|
58
|
-
response.
|
58
|
+
response.should have_status_code 200
|
59
59
|
response.body.should == "Welcome, authenticated client."
|
60
60
|
end
|
61
|
+
|
62
|
+
it "is able to test the presence of specified response headers" do
|
63
|
+
with_accept_header "application/json"
|
64
|
+
get "/json_doc"
|
65
|
+
response.should have_header(:content_type)
|
66
|
+
response.should have_header("Content-Type")
|
67
|
+
response.should_not have_header("This-Is-Not-A-Header-Name")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "is able to test the value of specified response headers" do
|
71
|
+
with_accept_header "application/xml"
|
72
|
+
get "/xml_doc"
|
73
|
+
response.should have_header(content_type: %r{charset})
|
74
|
+
response.should_not have_header(content_type: %r{json})
|
75
|
+
end
|
76
|
+
|
77
|
+
it "is able to test for the presence of elements in the response body" do
|
78
|
+
with_accept_header "application/xml"
|
79
|
+
get "/xml_doc"
|
80
|
+
response.should have_xpath "//foo/foo"
|
81
|
+
response.should_not have_xpath "//bar/foo"
|
82
|
+
response.should have_xpath "//foo", /Some/
|
83
|
+
response.should_not have_xpath "//foo", /bar/
|
84
|
+
|
85
|
+
with_accept_header "application/json"
|
86
|
+
get "/json_doc"
|
87
|
+
response.should have_jsonpath "root.foo.foo"
|
88
|
+
response.should_not have_jsonpath "shazbot.mcgillicuddy"
|
89
|
+
response.should have_jsonpath "root.foo.foo", /ow/
|
90
|
+
response.should_not have_jsonpath "root.foo.foo", /oo/
|
91
|
+
end
|
61
92
|
end
|
62
93
|
|
63
94
|
describe Skink::DSL do
|
data/spec/test_server.rb
CHANGED
@@ -38,3 +38,11 @@ get '/protected' do
|
|
38
38
|
protected!
|
39
39
|
"Welcome, authenticated client."
|
40
40
|
end
|
41
|
+
|
42
|
+
get '/xml_doc', :provides => :xml do
|
43
|
+
"<root><foo attr=\"true\">Some text<foo/></foo></root>"
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/json_doc', :provides => :json do
|
47
|
+
'{"root": {"foo": {"foo": "howdy"}}}'
|
48
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skink
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack-test
|
@@ -43,6 +43,38 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: nokogiri
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: jsonpath
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
46
78
|
- !ruby/object:Gem::Dependency
|
47
79
|
name: rspec
|
48
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +122,7 @@ files:
|
|
90
122
|
- lib/skink.rb
|
91
123
|
- lib/skink/client/base.rb
|
92
124
|
- lib/skink/client/response.rb
|
125
|
+
- lib/skink/client/utils.rb
|
93
126
|
- lib/skink/dsl.rb
|
94
127
|
- lib/skink/integrations/rails.rb
|
95
128
|
- lib/skink/integrations/rspec.rb
|