rack-rest-rspec 0.0.5 → 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/.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 +100 -6
- 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 +11 -10
- data/lib/rack-rest-rspec/matchers/respond_a_record.rb +11 -9
- data/lib/rack-rest-rspec/matchers/respond_with_collection_size.rb +9 -7
- data/lib/rack-rest-rspec/matchers/respond_with_data.rb +22 -24
- data/lib/rack-rest-rspec/matchers/respond_with_status.rb +4 -2
- 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 +115 -13
@@ -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,21 +1,22 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_a_collection_of_record do |options = {}|
|
3
4
|
match do |actual|
|
4
|
-
result = JSON
|
5
|
-
result
|
6
|
-
result.
|
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)
|
7
8
|
end
|
8
9
|
description do
|
9
|
-
|
10
|
+
'respond with a records collection (Array)'
|
10
11
|
end
|
11
12
|
failure_message do |actual|
|
12
|
-
result = JSON
|
13
|
-
result
|
13
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
14
|
+
result = result[options[:root]] unless options[:oot].nil?
|
14
15
|
"expected #{actual} response body would be a collection \nneed : Array, \ngot : #{result.class}"
|
15
16
|
end
|
16
17
|
failure_message_when_negated do |actual|
|
17
|
-
result = JSON
|
18
|
-
result
|
18
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
19
|
+
result = result[options[:root]] unless options[:root].nil?
|
19
20
|
"expected #{actual} response body would not be a collection \nneed : Array, \ngot : #{result.class}"
|
20
21
|
end
|
21
22
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_a_record do |options = {}|
|
2
4
|
match do |actual|
|
3
|
-
result = JSON
|
4
|
-
result
|
5
|
-
result.
|
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)
|
6
8
|
end
|
7
9
|
description do
|
8
|
-
|
10
|
+
'respond with a record (Hash)'
|
9
11
|
end
|
10
12
|
failure_message do |actual|
|
11
|
-
result = JSON
|
12
|
-
result
|
13
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
14
|
+
result = result[options[:root]] unless options[:root].nil?
|
13
15
|
"expected #{actual} response body would be a record \nneed : Hash, \ngot : #{result.class}"
|
14
16
|
end
|
15
17
|
failure_message_when_negated do |actual|
|
16
|
-
result = JSON
|
17
|
-
result
|
18
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
19
|
+
result = result[options[:root]] unless options[:root].nil?
|
18
20
|
"expected #{actual} response body would not be a record \nneed : Hash, \ngot : #{result.class}"
|
19
21
|
end
|
20
22
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_with_collection do |options = {}|
|
2
4
|
expected = options[:size]
|
3
5
|
match do |actual|
|
4
|
-
result = JSON
|
5
|
-
result
|
6
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
7
|
+
result = result[options[:root]] unless options[:root].nil?
|
6
8
|
result.size == expected
|
7
9
|
end
|
8
10
|
description do
|
@@ -10,13 +12,13 @@ RSpec::Matchers.define :respond_with_collection do |options={}|
|
|
10
12
|
end
|
11
13
|
|
12
14
|
failure_message do |actual|
|
13
|
-
result = JSON
|
14
|
-
result
|
15
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
16
|
+
result = result[options[:root]] unless options[:root].nil?
|
15
17
|
"expected #{actual} response body collection would have a size of #{expected}, \ngot #{result.size}"
|
16
18
|
end
|
17
19
|
failure_message_when_negated do |actual|
|
18
|
-
result = JSON
|
19
|
-
result
|
20
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
21
|
+
result = result[options[:root]] unless options[:root].nil?
|
20
22
|
"expected #{actual} response body collection would not have a size of #{expected}, \ngot #{result.size}"
|
21
23
|
end
|
22
24
|
end
|
@@ -1,45 +1,43 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
return false
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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]
|
10
9
|
end
|
10
|
+
res
|
11
11
|
end
|
12
12
|
|
13
|
-
def prepare_array
|
14
|
-
|
13
|
+
def prepare_array(data)
|
14
|
+
data.instance_of?(Hash) ? [data] : data
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
RSpec::Matchers.define :respond_with do |options={}|
|
17
|
+
RSpec::Matchers.define :respond_with do |options = {}|
|
19
18
|
expected = options[:data]
|
20
19
|
match do |actual|
|
21
|
-
result = JSON
|
22
|
-
result
|
23
|
-
if result.empty?
|
24
|
-
false
|
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
|
25
24
|
else
|
26
25
|
result = prepare_array result
|
27
26
|
expected = prepare_array expected
|
28
|
-
compare_array_of_hash expected,result
|
27
|
+
compare_array_of_hash expected, result
|
29
28
|
end
|
30
29
|
end
|
31
30
|
description do
|
32
|
-
|
31
|
+
'respond with corresponding data'
|
33
32
|
end
|
34
33
|
failure_message do |actual|
|
35
|
-
result = JSON
|
36
|
-
result
|
34
|
+
result = JSON.parse(actual.browser.last_response.body, symbolize_names: true)
|
35
|
+
result = result[options[:root]] unless options[:root].nil?
|
37
36
|
"expected #{actual} response body would be equal \nto : #{expected}, \ngot : #{result}"
|
38
37
|
end
|
39
38
|
failure_message_when_negated do |actual|
|
40
|
-
result = JSON
|
41
|
-
result
|
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,7 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec::Matchers.define :respond_with_status do |options = {}|
|
2
4
|
expected = options[:code]
|
3
5
|
match do |actual|
|
4
|
-
result = actual.browser.last_response
|
6
|
+
result = actual.browser.last_response
|
5
7
|
result.status == expected
|
6
8
|
end
|
7
9
|
description do
|
@@ -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
|