spaceborne 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d7e3361faaa6b37ac545afafdf24df2e6b918f62
4
+ data.tar.gz: 8d68d8cb74c1623e35d48fd95a233b112e7a3d7a
5
+ SHA512:
6
+ metadata.gz: 1cb4c4fb2fa7f220101dddfce7a1081b5af2c5001cf2a72101cdab49d1b9f4240bc1aa743f08802c3cd61acfeaa057590e9fc5c86de0ba36067446b512eaddcb
7
+ data.tar.gz: b53ca43bbe086026693037ca45ce914eece1b29ff064566af1fedfc6ba035f815fc621d47bacd28af2e8b8b0594e18094ae5baa98efcd623a54cca2d0fd271d9
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spaceborne.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Keith Williams
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Spaceborne
2
+
3
+ Welcome to spaceborne. Your new tool for testing of RESTful APIs. This builds on the great work of brooklyn/airborne, which I think is very useful, but has some major shortcomings. It also leverages curlyrest which allows easily adding a header parameter to an API request, and causes the request to be processed/exposed as a curl command.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'spaceborne'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install spaceborne
20
+
21
+ ## Creating API tests
22
+
23
+ ```ruby
24
+ require 'spaceborne'
25
+
26
+ describe 'sample spec' do
27
+ it 'should validate types' do
28
+ wrap_request do
29
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
30
+ expect_json_types(name: :string)
31
+ end
32
+ end
33
+
34
+ it 'should validate values' do
35
+ wrap_request do
36
+ get 'http://example.com/api/v1/simple_get' #json api that returns { "name" : "John Doe" }
37
+ expect_json(name: 'John Doe')
38
+ end
39
+ end
40
+ end
41
+ ```
42
+
43
+ ## Development
44
+
45
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
46
+
47
+ ## Extensions to Airborne
48
+
49
+ 1. Uses curlyrest to allow extension of rest-client with curl requests
50
+ 2. Bundles groups of expectations so that if any fail, you will actually see the request and response printed out, rather than just seeing the expectation that failed
51
+ 3. json_body is only calculated once after request rather than on each call
52
+ 4. Expectations for headers use the same form as the expectations for json bodies
53
+ * `expect_header same arguments/handling as expect_json`
54
+ * `expect_header_types same arguments/handling as expect_json_types`
55
+ 5. Expectations returning a hash with keys that are unknown, but that have a defined structure are supported
56
+ 6. It is possible to use non-json data in a request
57
+
58
+ ## Contributing
59
+
60
+ Bug reports and pull requests are welcome on GitHub at https://github.com/keithrw54/spaceborne.
61
+
62
+ ## License
63
+
64
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,127 @@
1
+ require "spaceborne/version"
2
+ require 'rest-client'
3
+ require 'byebug'
4
+ require 'json'
5
+
6
+ module Spaceborne
7
+ def wrap_request(&block)
8
+ block.call
9
+ rescue Exception => e
10
+ puts "REQUEST: #{response.request.method.upcase} #{response.request.url}"
11
+ puts " HEADERS:\n#{JSON::pretty_generate(response.request.headers)}"
12
+ puts " PAYLOAD:\n#{response.request.payload}" if response.request.payload
13
+ puts "RESPONSE: #{response.code}"
14
+ puts " HEADERS:\n#{JSON::pretty_generate(response.headers)}"
15
+ is_json = response.headers[:content_type].include?('application/json')
16
+ puts " JSON_BODY\n#{JSON::pretty_generate(json_body)}" if is_json
17
+ puts " BODY\n#{response.body}" unless is_json
18
+ raise e
19
+ end
20
+ end
21
+
22
+ module Airborne
23
+ def json_body
24
+ @json_body ||= JSON.parse(response.body, symbolize_names: true)
25
+ rescue
26
+ fail InvalidJsonError, 'Api request returned invalid json'
27
+ end
28
+ module RestClientRequester
29
+ def make_request(method, url, options = {})
30
+ @json_body = nil
31
+ headers = base_headers.merge(options[:headers] || {})
32
+ res = if method == :post || method == :patch || method == :put
33
+ begin
34
+ request_body = options[:body].nil? ? '' : options[:body]
35
+ request_body = request_body.to_json if options[:body].is_a?(Hash)
36
+ RestClient.send(method, get_url(url), request_body, headers)
37
+ rescue RestClient::Exception => e
38
+ e.response
39
+ end
40
+ else
41
+ begin
42
+ RestClient.send(method, get_url(url), headers)
43
+ rescue RestClient::Exception => e
44
+ e.response
45
+ end
46
+ end
47
+ res
48
+ end
49
+ end
50
+ module RequestExpectations
51
+ def call_with_relative_path(data, args)
52
+ if args.length == 2
53
+ get_by_path(args[0], data) do |json_chunk|
54
+ yield(args[1], json_chunk)
55
+ end
56
+ else
57
+ yield(args[0], data)
58
+ end
59
+ end
60
+
61
+ def expect_json_types(*args)
62
+ call_with_relative_path(json_body, args) do |param, body|
63
+ expect_json_types_impl(param, body)
64
+ end
65
+ end
66
+
67
+ def expect_json(*args)
68
+ call_with_relative_path(json_body, args) do |param, body|
69
+ expect_json_impl(param, body)
70
+ end
71
+ end
72
+
73
+ def expect_header_types(*args)
74
+ call_with_relative_path(response.headers, args) do |param, body|
75
+ expect_json_types_impl(param, body)
76
+ end
77
+ end
78
+
79
+ def expect_header(*args)
80
+ call_with_relative_path(response.headers, args) do |param, body|
81
+ expect_json_impl(param, body)
82
+ end
83
+ end
84
+ end
85
+
86
+ module PathMatcher
87
+ def get_by_path(path, json, &block)
88
+ fail PathError, "Invalid Path, contains '..'" if /\.\./ =~ path
89
+ type = false
90
+ parts = path.split('.')
91
+ parts.each_with_index do |part, index|
92
+ if part == '*' || part == '?'
93
+ ensure_array_or_hash(path, json)
94
+ type = part
95
+ if index < parts.length.pred
96
+ walk_with_path(type, index, path, parts, json, &block) && return
97
+ end
98
+ next
99
+ end
100
+ begin
101
+ json = process_json(part, json)
102
+ rescue
103
+ raise PathError, "Expected #{json.class}\nto be an object with property #{part}"
104
+ end
105
+ end
106
+ if type == '*'
107
+ case json.class.name
108
+ when 'Array'
109
+ expect_all(json, &block)
110
+ when 'Hash'
111
+ json.each do |k,v|
112
+ yield json[k]
113
+ end
114
+ end
115
+ elsif type == '?'
116
+ expect_one(path, json, &block)
117
+ else
118
+ yield json
119
+ end
120
+ end
121
+
122
+ def ensure_array_or_hash(path, json)
123
+ fail RSpec::Expectations::ExpectationNotMetError, "Expected #{path} to be array or hash, got #{json.class} from JSON response" unless
124
+ json.class == Array || json.class == Hash
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module Spaceborne
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'spaceborne/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "spaceborne"
8
+ spec.version = Spaceborne::VERSION
9
+ spec.authors = ["Keith Williams"]
10
+ spec.email = ["keithrw@comcast.net"]
11
+
12
+ spec.summary = 'Gem supporting API testing'
13
+ spec.description = 'Extends brooklynDev/airborne'
14
+ spec.homepage = "https://github.com/keithrw54/spaceborne.git"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+ spec.add_development_dependency "rest-client", "~> 2.0"
26
+ spec.add_development_dependency "byebug", "~> 2.0"
27
+ spec.add_development_dependency "airborne", "~> 0.2.13"
28
+ spec.add_development_dependency "curlyrest", "~> 0.1.0"
29
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spaceborne
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Keith Williams
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: airborne
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.13
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.13
97
+ - !ruby/object:Gem::Dependency
98
+ name: curlyrest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.0
111
+ description: Extends brooklynDev/airborne
112
+ email:
113
+ - keithrw@comcast.net
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - lib/spaceborne.rb
125
+ - lib/spaceborne/version.rb
126
+ - spaceborne.gemspec
127
+ homepage: https://github.com/keithrw54/spaceborne.git
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.5.2.1
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Gem supporting API testing
151
+ test_files: []