rack-rest-rspec 0.0.4 → 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.
- checksums.yaml +4 -4
- data/.debride_whitelist +6 -0
- data/.github/workflows/main.yml +23 -0
- data/.rspec +2 -0
- data/.rubocop.yml +44 -0
- data/Gemfile +2 -17
- data/LICENSE.txt +21 -0
- data/README.md +198 -37
- data/Rakefile +42 -35
- data/VERSION +1 -1
- data/bom.xml +690 -0
- data/lib/rack-rest-rspec/helpers/init.rb +3 -2
- data/lib/rack-rest-rspec/helpers/memorizer.rb +6 -5
- data/lib/rack-rest-rspec/helpers/yml.rb +3 -1
- data/lib/rack-rest-rspec/lib/rest_service.rb +10 -13
- data/lib/rack-rest-rspec/matchers/be_correctly_sent.rb +4 -2
- data/lib/rack-rest-rspec/matchers/init.rb +3 -2
- data/lib/rack-rest-rspec/matchers/respond_a_collection_of_record.rb +13 -5
- data/lib/rack-rest-rspec/matchers/respond_a_record.rb +13 -5
- data/lib/rack-rest-rspec/matchers/respond_with_collection_size.rb +15 -5
- data/lib/rack-rest-rspec/matchers/respond_with_data.rb +23 -25
- data/lib/rack-rest-rspec/matchers/respond_with_status.rb +10 -4
- data/lib/rack-rest-rspec/prepare.rb +5 -3
- data/lib/rack-rest-rspec/version.rb +2 -0
- data/rack-rest-rspec.gemspec +34 -23
- data/samples/.rspec +2 -0
- data/samples/Gemfile +14 -0
- data/samples/Rakefile +8 -0
- data/samples/app.rb +27 -0
- data/samples/config.ru +10 -0
- data/samples/spec/api_spec.rb +40 -0
- data/samples/spec/spec_helper.rb +4 -0
- metadata +116 -14
@@ -1,2 +1,3 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Dir["#{File.dirname(__FILE__)}/*.rb"].each { |file| require file unless File.basename(file) == 'init.rb' }
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pstore'
|
2
4
|
|
3
5
|
def memorize(options)
|
4
|
-
|
5
|
-
$store = PStore.new("/tmp/data.pstore")
|
6
|
+
$store = PStore.new('/tmp/data.pstore')
|
6
7
|
$store.transaction do
|
7
|
-
options.each do |key,val|
|
8
|
+
options.each do |key, val|
|
8
9
|
$store[key] = val
|
9
10
|
end
|
10
11
|
$store.commit
|
@@ -12,6 +13,6 @@ def memorize(options)
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def retrieve(key)
|
15
|
-
$store = PStore.new(
|
16
|
-
|
16
|
+
$store = PStore.new('/tmp/data.pstore')
|
17
|
+
$store.transaction { $store[key] }
|
17
18
|
end
|
@@ -1,29 +1,26 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'forwardable'
|
3
4
|
|
4
5
|
class RestService
|
5
6
|
extend Forwardable
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :path
|
9
|
-
attr_reader :service
|
10
|
-
attr_reader :browser
|
7
|
+
|
8
|
+
attr_reader :path, :service, :browser
|
11
9
|
|
12
10
|
def initialize(params = {})
|
13
11
|
defaults = {
|
14
|
-
:
|
15
|
-
:
|
12
|
+
service: Sinatra::Base,
|
13
|
+
path: '/'
|
16
14
|
}
|
17
15
|
defaults.merge! params
|
18
16
|
@service = defaults[:service]
|
19
17
|
@path = defaults[:path]
|
20
18
|
@browser = Rack::Test::Session.new(Rack::MockSession.new(@service))
|
21
19
|
end
|
22
|
-
|
23
|
-
def_delegators :@browser, :get, :post, :put, :delete
|
24
20
|
|
25
|
-
|
26
|
-
return JSON::parse(@browser.last_response.body, symbolize_names: true)
|
27
|
-
end
|
21
|
+
def_delegators :@browser, :get, :post, :put, :delete
|
28
22
|
|
23
|
+
def returned_data
|
24
|
+
JSON.parse(@browser.last_response.body, symbolize_names: true)
|
25
|
+
end
|
29
26
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec::Matchers.define :be_correctly_sent do
|
2
4
|
match do |actual|
|
3
|
-
actual.
|
5
|
+
actual.instance_of?(Rack::MockResponse)
|
4
6
|
end
|
5
7
|
description do
|
6
|
-
|
8
|
+
'be a valid HTTP verb request with a valid response return'
|
7
9
|
end
|
8
10
|
failure_message do |actual|
|
9
11
|
"expected this HTTP verb request to return a valid response, \nneed : Rack::MockResponse \ngot : #{actual.class}"
|
@@ -1,2 +1,3 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Dir["#{File.dirname(__FILE__)}/*.rb"].each { |file| require file unless File.basename(file) == 'init.rb' }
|
@@ -1,14 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_a_collection_of_record do |options = {}|
|
2
4
|
match do |actual|
|
3
|
-
JSON
|
5
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
6
|
+
result = result[options[:root]] unless options[:root].nil?
|
7
|
+
result.instance_of?(Array)
|
4
8
|
end
|
5
9
|
description do
|
6
|
-
|
10
|
+
'respond with a records collection (Array)'
|
7
11
|
end
|
8
12
|
failure_message do |actual|
|
9
|
-
|
13
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
14
|
+
result = result[options[:root]] unless options[:oot].nil?
|
15
|
+
"expected #{actual} response body would be a collection \nneed : Array, \ngot : #{result.class}"
|
10
16
|
end
|
11
17
|
failure_message_when_negated do |actual|
|
12
|
-
|
18
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
19
|
+
result = result[options[:root]] unless options[:root].nil?
|
20
|
+
"expected #{actual} response body would not be a collection \nneed : Array, \ngot : #{result.class}"
|
13
21
|
end
|
14
22
|
end
|
@@ -1,14 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_a_record do |options = {}|
|
2
4
|
match do |actual|
|
3
|
-
JSON
|
5
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
6
|
+
result = result[options[:root]] unless options[:root].nil?
|
7
|
+
result.instance_of?(Hash)
|
4
8
|
end
|
5
9
|
description do
|
6
|
-
|
10
|
+
'respond with a record (Hash)'
|
7
11
|
end
|
8
12
|
failure_message do |actual|
|
9
|
-
|
13
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
14
|
+
result = result[options[:root]] unless options[:root].nil?
|
15
|
+
"expected #{actual} response body would be a record \nneed : Hash, \ngot : #{result.class}"
|
10
16
|
end
|
11
17
|
failure_message_when_negated do |actual|
|
12
|
-
|
18
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
19
|
+
result = result[options[:root]] unless options[:root].nil?
|
20
|
+
"expected #{actual} response body would not be a record \nneed : Hash, \ngot : #{result.class}"
|
13
21
|
end
|
14
22
|
end
|
@@ -1,14 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_with_collection do |options = {}|
|
4
|
+
expected = options[:size]
|
2
5
|
match do |actual|
|
3
|
-
JSON
|
6
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
7
|
+
result = result[options[:root]] unless options[:root].nil?
|
8
|
+
result.size == expected
|
4
9
|
end
|
5
10
|
description do
|
6
|
-
"respond with a collection of
|
11
|
+
"respond with a collection of records size of #{expected}"
|
7
12
|
end
|
13
|
+
|
8
14
|
failure_message do |actual|
|
9
|
-
|
15
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
16
|
+
result = result[options[:root]] unless options[:root].nil?
|
17
|
+
"expected #{actual} response body collection would have a size of #{expected}, \ngot #{result.size}"
|
10
18
|
end
|
11
19
|
failure_message_when_negated do |actual|
|
12
|
-
|
20
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
21
|
+
result = result[options[:root]] unless options[:root].nil?
|
22
|
+
"expected #{actual} response body collection would not have a size of #{expected}, \ngot #{result.size}"
|
13
23
|
end
|
14
24
|
end
|
@@ -1,45 +1,43 @@
|
|
1
|
-
|
2
|
-
if expected.size == actual.size then
|
3
|
-
res = true
|
4
|
-
actual.each_with_index do |item,index|
|
5
|
-
res = false unless item == expected[index]
|
6
|
-
end
|
7
|
-
return res
|
8
|
-
else
|
9
|
-
return false
|
10
|
-
end
|
11
|
-
end
|
1
|
+
# frozen_string_literal: true
|
12
2
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
def compare_array_of_hash(expected, actual)
|
4
|
+
return false unless expected.size == actual.size
|
5
|
+
|
6
|
+
res = true
|
7
|
+
actual.each_with_index do |item, index|
|
8
|
+
res = false unless item == expected[index]
|
17
9
|
end
|
18
|
-
|
10
|
+
res
|
19
11
|
end
|
20
12
|
|
13
|
+
def prepare_array(data)
|
14
|
+
data.instance_of?(Hash) ? [data] : data
|
15
|
+
end
|
21
16
|
|
22
|
-
RSpec::Matchers.define :
|
23
|
-
|
17
|
+
RSpec::Matchers.define :respond_with do |options = {}|
|
18
|
+
expected = options[:data]
|
24
19
|
match do |actual|
|
25
|
-
result = actual.browser.last_response.body
|
26
|
-
|
27
|
-
|
20
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
21
|
+
result = result[options[:root]] unless options[:root].nil?
|
22
|
+
if result.empty?
|
23
|
+
false
|
28
24
|
else
|
29
|
-
result = JSON::parse(result)
|
30
25
|
result = prepare_array result
|
31
26
|
expected = prepare_array expected
|
32
|
-
compare_array_of_hash expected,result
|
27
|
+
compare_array_of_hash expected, result
|
33
28
|
end
|
34
29
|
end
|
35
30
|
description do
|
36
|
-
|
31
|
+
'respond with corresponding data'
|
37
32
|
end
|
38
33
|
failure_message do |actual|
|
34
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
35
|
+
result = result[options[:root]] unless options[:root].nil?
|
39
36
|
"expected #{actual} response body would be equal \nto : #{expected}, \ngot : #{result}"
|
40
37
|
end
|
41
38
|
failure_message_when_negated do |actual|
|
39
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
40
|
+
result = result[options[:root]] unless options[:root].nil?
|
42
41
|
"expected #{actual} response body would not be equal \nto : #{expected}, \ngot : #{result}"
|
43
42
|
end
|
44
43
|
end
|
45
|
-
|
@@ -1,14 +1,20 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_with_status do |options = {}|
|
4
|
+
expected = options[:code]
|
2
5
|
match do |actual|
|
3
|
-
actual.browser.last_response
|
6
|
+
result = actual.browser.last_response
|
7
|
+
result.status == expected
|
4
8
|
end
|
5
9
|
description do
|
6
10
|
"respond with status code equal to #{expected}"
|
7
11
|
end
|
8
12
|
failure_message do |actual|
|
9
|
-
|
13
|
+
result = actual.browser.last_response
|
14
|
+
"expected #{actual} response would be equal \nto : #{expected} \ngot : #{result.status}"
|
10
15
|
end
|
11
16
|
failure_message_when_negated do |actual|
|
12
|
-
|
17
|
+
result = actual.browser.last_response
|
18
|
+
"expected #{actual} response would not be equal \nto : #{expected} \ngot : #{result.status}"
|
13
19
|
end
|
14
20
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec'
|
2
4
|
require 'rack/test'
|
3
5
|
require 'rspec/expectations'
|
4
6
|
|
5
|
-
require_relative 'lib/rest_service
|
6
|
-
require_relative 'helpers/init
|
7
|
-
require_relative 'matchers/init
|
7
|
+
require_relative 'lib/rest_service'
|
8
|
+
require_relative 'helpers/init'
|
9
|
+
require_relative 'matchers/init'
|
data/rack-rest-rspec.gemspec
CHANGED
@@ -1,31 +1,42 @@
|
|
1
|
-
#
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
3
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
4
|
+
spec.name = 'rack-rest-rspec'
|
8
5
|
spec.version = `cat VERSION`
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
6
|
+
spec.authors = ['Romain GEORGES']
|
7
|
+
spec.email = ['romain@ultragreen.net']
|
8
|
+
spec.summary = 'Rack-rest-rspec: RSpec Matchers for REST Rack webservice '
|
9
|
+
spec.description = 'Rack-rest-rspec: RSpec Matchers for REST Rack webservice '
|
10
|
+
spec.homepage = 'http://github.com/Ultragreen/rack-rest-rspec'
|
11
|
+
spec.license = 'MIT'
|
15
12
|
|
16
|
-
spec.
|
17
|
-
spec.
|
18
|
-
|
19
|
-
spec.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.2.3')
|
14
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
15
|
+
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
20
17
|
|
21
|
-
spec.
|
22
|
-
spec.
|
23
|
-
spec.
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.11"
|
25
|
-
spec.add_development_dependency "yard", "~> 0.9.28"
|
26
|
-
spec.add_development_dependency "yard-rspec", "~> 0.1"
|
27
|
-
|
28
|
-
spec.add_runtime_dependency "rack-test", "~> 2.0"
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
20
|
+
spec.metadata['changelog_uri'] = spec.homepage
|
29
21
|
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ['lib']
|
30
28
|
|
29
|
+
spec.add_development_dependency 'bundle-audit', '~> 0.1.0'
|
30
|
+
spec.add_development_dependency 'code_statistics', '~> 0.2.13'
|
31
|
+
spec.add_development_dependency 'cyclonedx-ruby', '~> 1.1'
|
32
|
+
spec.add_development_dependency 'debride', '~> 1.12'
|
33
|
+
spec.add_development_dependency 'diff-lcs', '~> 1.5.1'
|
34
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
35
|
+
spec.add_development_dependency 'rspec', '~> 3.11'
|
36
|
+
spec.add_development_dependency 'rubocop', '~> 1.32'
|
37
|
+
spec.add_development_dependency 'sinatra', '~> 4.0'
|
38
|
+
spec.add_development_dependency 'yard', '~> 0.9.28'
|
39
|
+
spec.add_development_dependency 'yard-rspec', '~> 0.1'
|
40
|
+
spec.add_runtime_dependency 'rack-test', '~> 2.0'
|
41
|
+
spec.add_runtime_dependency 'version', '~> 1.1'
|
31
42
|
end
|
data/samples/.rspec
ADDED
data/samples/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'puma', '~> 6.4'
|
6
|
+
gem 'rackup', '~> 2.1'
|
7
|
+
gem 'sinatra', '~> 4.0.0'
|
8
|
+
|
9
|
+
group :test, :development do
|
10
|
+
gem 'rack-rest-rspec', '~> 0.0.3'
|
11
|
+
gem 'rack-test', '~> 2.0.2'
|
12
|
+
gem 'rake', '~> 13.0'
|
13
|
+
gem 'rspec', '~> 3.10.0'
|
14
|
+
end
|
data/samples/Rakefile
ADDED
data/samples/app.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sinatra'
|
4
|
+
|
5
|
+
class Application < Sinatra::Base
|
6
|
+
before do
|
7
|
+
content_type 'application/json'
|
8
|
+
end
|
9
|
+
|
10
|
+
get '/status' do
|
11
|
+
status 208
|
12
|
+
return { name: 'Sample App', version: '0.0.1', status: 'OK' }.to_json
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/embeded_status' do
|
16
|
+
status 208
|
17
|
+
return { code: 208, data: { name: 'Sample App', version: '0.0.1', status: 'OK' } }.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/collection' do
|
21
|
+
return [{ one: 1 }, { two: 2 }, { three: 3 }].to_json
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/embeded_collection' do
|
25
|
+
return { code: 200, data: [{ one: 1 }, { two: 2 }, { three: 3 }] }.to_json
|
26
|
+
end
|
27
|
+
end
|
data/samples/config.ru
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe 'Test REST API' do
|
4
|
+
before :all do
|
5
|
+
$service = RestService.new service: Application
|
6
|
+
$data = { name: 'Sample App', version: '0.0.1', status: 'OK' }
|
7
|
+
$collection = [{ one: 1 }, { two: 2 }, { three: 3 }]
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { $service }
|
11
|
+
context 'GET /status : test for status' do
|
12
|
+
it { expect(subject.get('/status')).to be_correctly_sent }
|
13
|
+
it { expect(subject).to respond_with_status code: 208 }
|
14
|
+
it { expect(subject).to respond_a_record }
|
15
|
+
it { expect(subject).to respond_with data: $data }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'GET /embeded_status : test for status' do
|
19
|
+
it { expect(subject.get('/embeded_status')).to be_correctly_sent }
|
20
|
+
it { expect(subject).to respond_with_status code: 208 }
|
21
|
+
it { expect(subject).to respond_a_record root: :data }
|
22
|
+
it { expect(subject).to respond_with data: $data, root: :data }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'GET /collection : test for Array' do
|
26
|
+
it { expect(subject.get('/collection')).to be_correctly_sent }
|
27
|
+
it { expect(subject).to respond_with_status code: 200 }
|
28
|
+
it { expect(subject).to respond_a_collection_of_record }
|
29
|
+
it { expect(subject).to respond_with_collection size: 3 }
|
30
|
+
it { expect(subject).to respond_with data: $collection }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'GET /embeded_collection : test for Array' do
|
34
|
+
it { expect(subject.get('/embeded_collection')).to be_correctly_sent }
|
35
|
+
it { expect(subject).to respond_with_status code: 200 }
|
36
|
+
it { expect(subject).to respond_a_collection_of_record root: :data }
|
37
|
+
it { expect(subject).to respond_with_collection size: 3, root: :data }
|
38
|
+
it { expect(subject).to respond_with data: $collection, root: :data }
|
39
|
+
end
|
40
|
+
end
|