contracto 0.4.1 → 0.4.2
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/contracto.gemspec +1 -0
- data/lib/contracto/command/start/remote.rb +2 -4
- data/lib/contracto/command.rb +3 -0
- data/lib/contracto/config.rb +5 -1
- data/lib/contracto/constants.rb +3 -1
- data/lib/contracto/contract/response.rb +47 -7
- data/lib/contracto/contract.rb +21 -6
- data/lib/contracto/parser.rb +7 -2
- data/lib/contracto/server/ruby/server.rb +45 -1
- data/lib/contracto/stats.rb +17 -0
- data/lib/contracto/system_action.rb +14 -25
- data/lib/contracto/version.rb +1 -1
- data/spec/fixtures/get_users.con.json +33 -0
- data/spec/fixtures/get_users_by_id.con.json +28 -0
- data/spec/fixtures/my_data.con.json +23 -0
- data/spec/fixtures/post_users.con.json +22 -0
- data/spec/fixtures/{users.json → users/get_users.json} +0 -0
- data/spec/fixtures/users/get_users.xml +14 -0
- data/spec/fixtures/users/{1.json → get_users_by_id_id_1.json} +1 -1
- data/spec/fixtures/users/{2.json → get_users_by_id_id_2.json} +1 -1
- data/spec/fixtures/users/get_users_by_search_search_albert.json +7 -0
- data/spec/fixtures/users/post_users.json +6 -0
- data/spec/spec_helper.rb +18 -3
- data/spec/unit/contract_spec.rb +40 -27
- metadata +37 -18
- data/spec/fixtures/contract.con.json +0 -54
- data/spec/fixtures/posts.con.json +0 -36
- data/spec/fixtures/users/1/posts.json +0 -7
- data/spec/fixtures/users/2/posts.json +0 -7
- data/spec/unit/parser_spec.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c35eed00df100a4c4a2117e8a0d239cb20dcd117
|
4
|
+
data.tar.gz: a55bf9e05603df1c4b03cc354d34096945795d02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43d467496a10704a35fec13b81d11b1a2ccf4d7e502a371748ae637df018e022191a8af6ef0fd3bcbf056c7730172b4d8ac04484341b4adbfc66512c11919143
|
7
|
+
data.tar.gz: bd325007dca162ebc8f9ae2e4d8c5455c9429ac0bacff26a4fdb003c0fef5a900449874cce5845815b719934d0eeb39466360e3fc3069d295d393ff8c1e33c6e
|
data/contracto.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_runtime_dependency 'daemons', '~> 1.2'
|
25
25
|
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3.2'
|
27
|
+
spec.add_development_dependency 'callapi', '~> 0.9'
|
27
28
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
28
29
|
spec.add_development_dependency 'rake', '~> 10.0'
|
29
30
|
end
|
@@ -4,7 +4,7 @@ class Contracto::Command::Start::Remote
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def execute
|
7
|
-
puts "downloading contract from #{Contracto::Config.repo_url}"
|
7
|
+
puts "downloading contract from #{Contracto::Config.repo_url} to #{Contracto::Config.root_dir}"
|
8
8
|
Contracto::SystemActionChain.new(*actions).execute
|
9
9
|
end
|
10
10
|
|
@@ -12,9 +12,7 @@ class Contracto::Command::Start::Remote
|
|
12
12
|
|
13
13
|
def actions
|
14
14
|
[
|
15
|
-
:
|
16
|
-
:move_tmp_dir_files_to_root_dir,
|
17
|
-
:remove_tmp_contracto_dir,
|
15
|
+
:clone_repo,
|
18
16
|
:start_server
|
19
17
|
]
|
20
18
|
end
|
data/lib/contracto/command.rb
CHANGED
@@ -12,6 +12,9 @@ class Contracto::Command
|
|
12
12
|
Contracto::Command::Start.new(args).execute
|
13
13
|
when 'stop'
|
14
14
|
Contracto::Command::Stop.new(args).execute
|
15
|
+
when 'restart'
|
16
|
+
Contracto::Command::Stop.new(args).execute
|
17
|
+
Contracto::Command::Start.new(args).execute
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
data/lib/contracto/config.rb
CHANGED
data/lib/contracto/constants.rb
CHANGED
@@ -2,7 +2,8 @@ module Contracto::Constants
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
GEM_DIR = Gem::Specification.find_by_name('contracto').gem_dir
|
5
|
-
|
5
|
+
CURRENT_DIR = FileUtils.pwd
|
6
|
+
DEFAULT_ROOT_DIR = CURRENT_DIR + '/.contract'
|
6
7
|
CONTRACTO_DIR = '.contracto'
|
7
8
|
CONTRACTO_TMP_DIR = '.tmp.contracto'
|
8
9
|
RUBY_SERVER_DIR = "#{GEM_DIR}/lib/contracto/server/ruby"
|
@@ -13,6 +14,7 @@ module Contracto::Constants
|
|
13
14
|
|
14
15
|
%w(
|
15
16
|
gem_dir
|
17
|
+
current_dir
|
16
18
|
default_root_dir
|
17
19
|
contracto_dir
|
18
20
|
contracto_tmp_dir
|
@@ -6,22 +6,49 @@ class Contracto::Contract::Response
|
|
6
6
|
@hash = hash
|
7
7
|
end
|
8
8
|
|
9
|
+
def request
|
10
|
+
@hash['request'] || {}
|
11
|
+
end
|
12
|
+
|
9
13
|
def params
|
10
|
-
|
14
|
+
request['params'] || {} #TODO: should it be optional or required?
|
15
|
+
end
|
16
|
+
|
17
|
+
def headers
|
18
|
+
request['headers'] || {} #TODO: should it be optional or required?
|
11
19
|
end
|
12
20
|
|
13
21
|
def body_path
|
14
22
|
@hash.fetch('response').fetch('body_path')
|
15
23
|
end
|
16
24
|
|
17
|
-
def params_matches?(
|
18
|
-
return true if params.
|
25
|
+
def params_matches?(request_params)
|
26
|
+
return true if params.empty?
|
19
27
|
|
20
28
|
params.keys.all? do |key|
|
21
|
-
|
29
|
+
value_from_contract = params[key]
|
30
|
+
value_from_request = request_params[key]
|
31
|
+
|
32
|
+
if value_from_contract.is_a?(Numeric)
|
33
|
+
value_from_request = string_to_number(value_from_contract, value_from_request)
|
34
|
+
end
|
35
|
+
|
36
|
+
value_from_request == value_from_contract
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def headers_matches?(other_headers)
|
41
|
+
return true if headers.empty?
|
42
|
+
|
43
|
+
headers.keys.all? do |key|
|
44
|
+
other_headers[human_header_key_to_http_header_key(key)] == headers[key]
|
22
45
|
end
|
23
46
|
end
|
24
47
|
|
48
|
+
def conditions_number
|
49
|
+
params.keys.size + headers.keys.size
|
50
|
+
end
|
51
|
+
|
25
52
|
def body
|
26
53
|
set_body
|
27
54
|
@body.tap do
|
@@ -31,13 +58,26 @@ class Contracto::Contract::Response
|
|
31
58
|
|
32
59
|
private
|
33
60
|
|
61
|
+
def string_to_number(number, string)
|
62
|
+
if number.is_a?(Integer)
|
63
|
+
string.to_i
|
64
|
+
elsif number.is_a?(Float)
|
65
|
+
string.to_f
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
34
69
|
def set_body
|
35
70
|
@body = File.read(Contracto::Config.root_dir + body_path)
|
36
71
|
end
|
37
72
|
|
73
|
+
def human_header_key_to_http_header_key(key)
|
74
|
+
key = key.upcase
|
75
|
+
key = key.gsub('-', '_')
|
76
|
+
key = 'HTTP_' + key
|
77
|
+
key
|
78
|
+
end
|
79
|
+
|
38
80
|
def replace_params_placeholders_with_params_value
|
39
|
-
|
40
|
-
@body.gsub!(":#{key}", value.to_s) if value
|
41
|
-
end
|
81
|
+
# TODO
|
42
82
|
end
|
43
83
|
end
|
data/lib/contracto/contract.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
class Contracto::Contract
|
2
2
|
require_relative 'contract/response'
|
3
|
+
require_relative 'stats'
|
4
|
+
|
5
|
+
attr_reader :responses
|
3
6
|
|
4
7
|
def initialize(hash)
|
5
8
|
@hash = hash
|
@@ -15,19 +18,31 @@ class Contracto::Contract
|
|
15
18
|
@request.url_pattern
|
16
19
|
end
|
17
20
|
|
18
|
-
def response_body(params)
|
19
|
-
response = @responses.
|
21
|
+
def response_body(params, headers)
|
22
|
+
response = @responses.find_by_params_and_headers(params, headers)
|
20
23
|
raise Contracto::ResponseNotFoundError.new(params) unless response
|
21
|
-
response.body
|
24
|
+
response.body.tap do
|
25
|
+
Contracto::Stats.used_contracts << self unless Contracto::Stats.used_contracts.include?(self)
|
26
|
+
end
|
22
27
|
end
|
23
28
|
|
24
29
|
class Contracto::Contract::Responses
|
25
30
|
def initialize(responses)
|
26
|
-
@responses = responses.map
|
31
|
+
@responses = responses.map do |response|
|
32
|
+
Contracto::Contract::Response.new(response)
|
33
|
+
end.sort_by(&:conditions_number).reverse
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_by_params_and_headers(params, headers)
|
37
|
+
@responses.find do |response|
|
38
|
+
response.params_matches?(params) && response.headers_matches?(headers)
|
39
|
+
end.tap do |response|
|
40
|
+
Contracto::Stats.used_responses << response if response && !Contracto::Stats.used_responses.include?(response)
|
41
|
+
end
|
27
42
|
end
|
28
43
|
|
29
|
-
def
|
30
|
-
@responses.
|
44
|
+
def count
|
45
|
+
@responses.count
|
31
46
|
end
|
32
47
|
end
|
33
48
|
|
data/lib/contracto/parser.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
class Contracto::Parser
|
4
|
+
require_relative 'stats'
|
5
|
+
|
4
6
|
def initialize(strings_with_json)
|
5
7
|
@json_collection = strings_with_json.map { |string| JSON.parse(string) }
|
6
8
|
end
|
7
9
|
|
8
10
|
def contracts
|
9
11
|
@json_collection.map do |json|
|
10
|
-
|
12
|
+
json = [json] unless json.is_a?(Array)
|
13
|
+
json.map do |json|
|
11
14
|
Contracto::Contract.new(json)
|
12
15
|
end
|
13
|
-
end.flatten
|
16
|
+
end.flatten.tap do |contracts|
|
17
|
+
Contracto::Stats.all_contracts = contracts
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
|
3
3
|
class Contracto::Server < Sinatra::Base
|
4
|
+
require_relative '../../stats'
|
4
5
|
|
5
6
|
set :port, Contracto::Constants::PORT
|
6
7
|
|
@@ -8,15 +9,58 @@ class Contracto::Server < Sinatra::Base
|
|
8
9
|
"*** Contracto server is working! [#{Gem::Specification.find_by_name('contracto').version}] ***"
|
9
10
|
end
|
10
11
|
|
12
|
+
get '/contracto_terminate' do
|
13
|
+
Thread.new { sleep 1; Process.kill 'INT', Process.pid }
|
14
|
+
status 200
|
15
|
+
body_on_terminate
|
16
|
+
end
|
17
|
+
|
11
18
|
jsons_with_contracts = Dir["#{Contracto::Config.root_dir}/**/*.con.json"].map do |file_with_contract|
|
12
19
|
File.read file_with_contract
|
13
20
|
end
|
14
21
|
|
15
22
|
Contracto::Parser.new(jsons_with_contracts).contracts.each do |contract|
|
16
23
|
send(contract.http_method, contract.url_pattern) do
|
17
|
-
|
24
|
+
begin
|
25
|
+
contract.response_body(params, http_headers)
|
26
|
+
rescue StandardError => ex
|
27
|
+
status 500
|
28
|
+
error_response(ex)
|
29
|
+
end
|
18
30
|
end
|
19
31
|
end
|
20
32
|
|
33
|
+
def http_headers
|
34
|
+
env.select {|k,v| k.start_with? 'HTTP_'}
|
35
|
+
end
|
36
|
+
|
37
|
+
def error_response(ex)
|
38
|
+
["#{ex.class}: #{ex.message}", ex.backtrace[0, 15].join("\n")].join("\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
def body_on_terminate
|
42
|
+
used_contracts_count = Contracto::Stats.used_contracts.size
|
43
|
+
all_contracts_count = Contracto::Stats.all_contracts.size
|
44
|
+
used_responses_count = Contracto::Stats.used_responses.size
|
45
|
+
all_responses_count = Contracto::Stats.all_responses.size
|
46
|
+
|
47
|
+
contracts_usage = if all_contracts_count.zero?
|
48
|
+
'N/A'
|
49
|
+
else
|
50
|
+
"#{(used_contracts_count / all_contracts_count.to_f).round(2)}%"
|
51
|
+
end
|
52
|
+
|
53
|
+
responses_usage = if all_responses_count.zero?
|
54
|
+
'N/A'
|
55
|
+
else
|
56
|
+
"#{(used_responses_count / all_responses_count.to_f).round(2)}%"
|
57
|
+
end
|
58
|
+
|
59
|
+
[
|
60
|
+
"Used contracts: #{used_contracts_count}/#{all_contracts_count} (#{contracts_usage})",
|
61
|
+
"Used responses: #{used_responses_count}/#{all_responses_count} (#{responses_usage})",
|
62
|
+
''
|
63
|
+
].join("\n")
|
64
|
+
end
|
21
65
|
end
|
22
66
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Contracto::Stats
|
2
|
+
class << self
|
3
|
+
attr_accessor :all_contracts
|
4
|
+
|
5
|
+
def used_contracts
|
6
|
+
@used_contracts ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def used_responses
|
10
|
+
@used_responses ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def all_responses
|
14
|
+
@all_responses ||= all_contracts.map(&:responses).map(&:count).inject(&:+)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,20 +4,18 @@ class Contracto::SystemAction
|
|
4
4
|
class << self
|
5
5
|
include Contracto::Constants
|
6
6
|
|
7
|
-
def remove_tmp_contracto_dir
|
8
|
-
FileUtils.rm_rf contracto_tmp_dir
|
9
|
-
end
|
10
|
-
|
11
7
|
def create_sample_contract
|
12
|
-
if
|
8
|
+
if Dir.exists?(Contracto::Config.root_dir)
|
13
9
|
puts 'contract already exists, creating sample contract skipped'
|
14
10
|
else
|
15
|
-
FileUtils.cp_r sample_contract_dir,
|
16
|
-
move_tmp_dir_files_to_root_dir
|
17
|
-
puts "created: #{contract_filename}"
|
11
|
+
FileUtils.cp_r sample_contract_dir, Contracto::Config.root_dir
|
18
12
|
end
|
19
13
|
end
|
20
14
|
|
15
|
+
def revert_create_sample_contract
|
16
|
+
remove_root_dir
|
17
|
+
end
|
18
|
+
|
21
19
|
def start_server
|
22
20
|
raise Contracto::ServerAlreadyRunningError if server_already_running?
|
23
21
|
|
@@ -43,10 +41,8 @@ class Contracto::SystemAction
|
|
43
41
|
|
44
42
|
def stop_server
|
45
43
|
puts 'killing server...'
|
46
|
-
|
44
|
+
system "curl 0.0.0.0:#{port}/contracto_terminate"
|
47
45
|
puts '...server killed'
|
48
|
-
rescue Errno::ENOENT
|
49
|
-
puts 'could not kill server (pidfile not found)'
|
50
46
|
end
|
51
47
|
|
52
48
|
def revert_start_server
|
@@ -54,27 +50,20 @@ class Contracto::SystemAction
|
|
54
50
|
rescue StandardError
|
55
51
|
end
|
56
52
|
|
57
|
-
def
|
58
|
-
|
53
|
+
def clone_repo
|
54
|
+
FileUtils.rm_rf Contracto::Config.root_dir
|
55
|
+
success = system "git clone -q --depth 1 --single-branch --branch master #{Contracto::Config.repo_url} #{Contracto::Config.root_dir}"
|
59
56
|
raise(Contracto::CouldNotDownloadContractError.new(Contracto::Config.repo_url)) unless success
|
60
57
|
end
|
61
58
|
|
62
|
-
def
|
63
|
-
|
59
|
+
def revert_clone_repo
|
60
|
+
remove_root_dir
|
64
61
|
end
|
65
62
|
|
66
|
-
def move_tmp_dir_files_to_root_dir
|
67
|
-
move_dir_files_to_root_dir(contracto_tmp_dir)
|
68
|
-
end
|
69
|
-
|
70
63
|
private
|
71
64
|
|
72
|
-
def
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
def contract_already_exists?
|
77
|
-
File.exist?("#{Contracto::Config.root_dir}/#{contract_filename}")
|
65
|
+
def remove_root_dir
|
66
|
+
FileUtils.rm_rf Contracto::Config.root_dir
|
78
67
|
end
|
79
68
|
|
80
69
|
def server_already_running?
|
data/lib/contracto/version.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"request": {
|
3
|
+
"http_method": "get",
|
4
|
+
"path": "/users"
|
5
|
+
},
|
6
|
+
"responses": [
|
7
|
+
{
|
8
|
+
"request": {
|
9
|
+
"params": {
|
10
|
+
"search": "Albert"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
"response": {
|
14
|
+
"body_path": "/users/get_users_by_search_search_albert.json"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"request": {
|
19
|
+
"headers": {
|
20
|
+
"Content-Type": "application/xml"
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"response": {
|
24
|
+
"body_path": "/users/get_users.xml"
|
25
|
+
}
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"response": {
|
29
|
+
"body_path": "/users/get_users.json"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
]
|
33
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"request": {
|
3
|
+
"http_method": "get",
|
4
|
+
"path": "/users/:id"
|
5
|
+
},
|
6
|
+
"responses": [
|
7
|
+
{
|
8
|
+
"request": {
|
9
|
+
"params": {
|
10
|
+
"id": 1
|
11
|
+
}
|
12
|
+
},
|
13
|
+
"response": {
|
14
|
+
"body_path": "/users/get_users_by_id_id_1.json"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"request": {
|
19
|
+
"params": {
|
20
|
+
"id": 2
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"response": {
|
24
|
+
"body_path": "/users/get_users_by_id_id_2.json"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
]
|
28
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"request": {
|
3
|
+
"http_method": "get",
|
4
|
+
"path": "/my/data",
|
5
|
+
"meta": {
|
6
|
+
"request": {
|
7
|
+
|
8
|
+
},
|
9
|
+
"response": {
|
10
|
+
"body": {
|
11
|
+
"type": "object",
|
12
|
+
"embedded": [
|
13
|
+
{
|
14
|
+
"name": "id",
|
15
|
+
"type": "string"
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"responses": []
|
23
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"request": {
|
3
|
+
"http_method": "post",
|
4
|
+
"path": "/users"
|
5
|
+
},
|
6
|
+
"responses": [
|
7
|
+
{
|
8
|
+
"request": {
|
9
|
+
"params": {
|
10
|
+
"user": {
|
11
|
+
"first_name": "New",
|
12
|
+
"last_name": "User",
|
13
|
+
"age": "30"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
},
|
17
|
+
"response": {
|
18
|
+
"body_path": "/users/post_users.json"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
]
|
22
|
+
}
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<users type="array">
|
2
|
+
<user>
|
3
|
+
<id type="integer">1</id>
|
4
|
+
<first-name>Albert</first-name>
|
5
|
+
<last-name>Einstein</last-name>
|
6
|
+
<age type="integer">30</age>
|
7
|
+
</user>
|
8
|
+
<user>
|
9
|
+
<id type="integer">2</id>
|
10
|
+
<first-name>Kurt</first-name>
|
11
|
+
<last-name>Godel</last-name>
|
12
|
+
<age type="integer">35</age>
|
13
|
+
</user>
|
14
|
+
</users>
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,24 @@
|
|
1
1
|
require_relative '../lib/contracto'
|
2
|
+
require 'callapi'
|
2
3
|
|
3
|
-
|
4
|
+
Contracto::Config.root_dir = 'spec/fixtures'
|
5
|
+
Contracto::Command.run('start', [])
|
4
6
|
|
5
7
|
RSpec.configure do |config|
|
6
|
-
config.before(:
|
7
|
-
|
8
|
+
config.before(:suite) do
|
9
|
+
|
10
|
+
Callapi::Config.api_host = 'http://0.0.0.0:54321'
|
11
|
+
Callapi::Config.log_level = :none
|
12
|
+
|
13
|
+
Callapi::Routes.draw do
|
14
|
+
get 'users'
|
15
|
+
post 'users'
|
16
|
+
get 'users/:id'
|
17
|
+
get 'users/:id/posts'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after(:suite) do
|
22
|
+
Contracto::Command.run('stop', [])
|
8
23
|
end
|
9
24
|
end
|
data/spec/unit/contract_spec.rb
CHANGED
@@ -1,43 +1,56 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
RSpec.describe Contracto
|
3
|
+
RSpec.describe 'Contracto' do
|
4
4
|
|
5
|
-
context '
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
it { expect(subject).to eq 'get' }
|
10
|
-
end
|
11
|
-
|
12
|
-
context '#url_pattern' do
|
13
|
-
let(:contract) { contracts[1] }
|
14
|
-
subject { contract.url_pattern }
|
5
|
+
context 'HTTP methods' do
|
6
|
+
it 'should return response with GET' do
|
7
|
+
expect(get_users_call.data).to eq [{"first_name"=>"Albert", "last_name"=>"Einstein", "age"=>30}, {"first_name"=>"Kurt", "last_name"=>"Godel", "age"=>35}]
|
8
|
+
end
|
15
9
|
|
16
|
-
it
|
10
|
+
it 'should return response with POST' do
|
11
|
+
# TODO
|
12
|
+
end
|
17
13
|
end
|
18
14
|
|
19
|
-
context '
|
20
|
-
|
15
|
+
context 'selecting response' do
|
21
16
|
context 'by params' do
|
17
|
+
it 'should find response by one string param' do
|
18
|
+
expect(get_users_call(search: 'Albert').data).to eq [{"first_name"=>"Albert", "last_name"=>"Einstein", "age"=>30}]
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
let(:response_1) { JSON.parse contract.response_body('id' => '2') }
|
26
|
-
|
27
|
-
it 'should return body based on params' do
|
28
|
-
expect(response_0).to eq('first_name' => 'Albert', 'last_name' => 'Einstein', 'age' => 30)
|
29
|
-
expect(response_1).to eq('first_name' => 'Kurt', 'last_name' => 'Godel', 'age' => 35)
|
21
|
+
it 'should find response by one integer param' do
|
22
|
+
expect(get_users_by_id_call(id: 1).data).to eq("id"=>1, "first_name"=>"Albert", "last_name"=>"Einstein", "age"=>30)
|
30
23
|
end
|
31
24
|
|
32
|
-
it 'should
|
33
|
-
expect
|
25
|
+
it 'should find response by one hash param' do
|
26
|
+
expect(post_users_call('user[first_name]' => 'New', 'user[last_name]' => 'User', 'user[age]' => '30').data).to eq("id"=>111, "first_name"=>"New", "last_name"=>"User", "age"=>30)
|
34
27
|
end
|
35
28
|
end
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
context 'by headers' do
|
31
|
+
it 'should find response by header' do
|
32
|
+
expected = <<XML
|
33
|
+
<users type="array">
|
34
|
+
<user>
|
35
|
+
<id type="integer">1</id>
|
36
|
+
<first-name>Albert</first-name>
|
37
|
+
<last-name>Einstein</last-name>
|
38
|
+
<age type="integer">30</age>
|
39
|
+
</user>
|
40
|
+
<user>
|
41
|
+
<id type="integer">2</id>
|
42
|
+
<first-name>Kurt</first-name>
|
43
|
+
<last-name>Godel</last-name>
|
44
|
+
<age type="integer">35</age>
|
45
|
+
</user>
|
46
|
+
</users>
|
47
|
+
XML
|
48
|
+
|
49
|
+
given = get_users_call.add_headers({"Content_Type" => "application/xml"}).body.gsub!(/\s+/, "")
|
50
|
+
expected = expected.gsub!(/\s+/, "")
|
51
|
+
expect(given).to eq expected
|
52
|
+
end
|
53
|
+
end
|
41
54
|
end
|
42
55
|
|
43
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contracto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kacper Walanus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: callapi
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.9'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.9'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,22 +124,25 @@ files:
|
|
110
124
|
- lib/contracto/parser.rb
|
111
125
|
- lib/contracto/server/ruby/config.ru
|
112
126
|
- lib/contracto/server/ruby/server.rb
|
127
|
+
- lib/contracto/stats.rb
|
113
128
|
- lib/contracto/system_action.rb
|
114
129
|
- lib/contracto/system_action_chain.rb
|
115
130
|
- lib/contracto/version.rb
|
116
131
|
- script/send_test_requests.sh
|
117
132
|
- script/start_from_remote.sh
|
118
133
|
- script/start_locally.sh
|
119
|
-
- spec/fixtures/
|
120
|
-
- spec/fixtures/
|
121
|
-
- spec/fixtures/
|
122
|
-
- spec/fixtures/
|
123
|
-
- spec/fixtures/users/
|
124
|
-
- spec/fixtures/users/
|
125
|
-
- spec/fixtures/users/
|
134
|
+
- spec/fixtures/get_users.con.json
|
135
|
+
- spec/fixtures/get_users_by_id.con.json
|
136
|
+
- spec/fixtures/my_data.con.json
|
137
|
+
- spec/fixtures/post_users.con.json
|
138
|
+
- spec/fixtures/users/get_users.json
|
139
|
+
- spec/fixtures/users/get_users.xml
|
140
|
+
- spec/fixtures/users/get_users_by_id_id_1.json
|
141
|
+
- spec/fixtures/users/get_users_by_id_id_2.json
|
142
|
+
- spec/fixtures/users/get_users_by_search_search_albert.json
|
143
|
+
- spec/fixtures/users/post_users.json
|
126
144
|
- spec/spec_helper.rb
|
127
145
|
- spec/unit/contract_spec.rb
|
128
|
-
- spec/unit/parser_spec.rb
|
129
146
|
homepage: ''
|
130
147
|
licenses:
|
131
148
|
- MIT
|
@@ -151,13 +168,15 @@ signing_key:
|
|
151
168
|
specification_version: 4
|
152
169
|
summary: XXX
|
153
170
|
test_files:
|
154
|
-
- spec/fixtures/
|
155
|
-
- spec/fixtures/
|
156
|
-
- spec/fixtures/
|
157
|
-
- spec/fixtures/
|
158
|
-
- spec/fixtures/users/
|
159
|
-
- spec/fixtures/users/
|
160
|
-
- spec/fixtures/users/
|
171
|
+
- spec/fixtures/get_users.con.json
|
172
|
+
- spec/fixtures/get_users_by_id.con.json
|
173
|
+
- spec/fixtures/my_data.con.json
|
174
|
+
- spec/fixtures/post_users.con.json
|
175
|
+
- spec/fixtures/users/get_users.json
|
176
|
+
- spec/fixtures/users/get_users.xml
|
177
|
+
- spec/fixtures/users/get_users_by_id_id_1.json
|
178
|
+
- spec/fixtures/users/get_users_by_id_id_2.json
|
179
|
+
- spec/fixtures/users/get_users_by_search_search_albert.json
|
180
|
+
- spec/fixtures/users/post_users.json
|
161
181
|
- spec/spec_helper.rb
|
162
182
|
- spec/unit/contract_spec.rb
|
163
|
-
- spec/unit/parser_spec.rb
|
@@ -1,54 +0,0 @@
|
|
1
|
-
[
|
2
|
-
{
|
3
|
-
"request": {
|
4
|
-
"http_method": "get",
|
5
|
-
"path": "/users"
|
6
|
-
},
|
7
|
-
"responses": [
|
8
|
-
{
|
9
|
-
"request": {
|
10
|
-
"headers": {
|
11
|
-
"Content-Type": "application/json"
|
12
|
-
}
|
13
|
-
},
|
14
|
-
"response": {
|
15
|
-
"body_path": "/users.json"
|
16
|
-
}
|
17
|
-
}
|
18
|
-
]
|
19
|
-
},
|
20
|
-
{
|
21
|
-
"request": {
|
22
|
-
"http_method": "get",
|
23
|
-
"path": "/users/:id"
|
24
|
-
},
|
25
|
-
"responses": [
|
26
|
-
{
|
27
|
-
"request": {
|
28
|
-
"headers": {
|
29
|
-
"Content-Type": "application/json"
|
30
|
-
},
|
31
|
-
"params": {
|
32
|
-
"id": 1
|
33
|
-
}
|
34
|
-
},
|
35
|
-
"response": {
|
36
|
-
"body_path": "/users/1.json"
|
37
|
-
}
|
38
|
-
},
|
39
|
-
{
|
40
|
-
"request": {
|
41
|
-
"headers": {
|
42
|
-
"Content-Type": "application/json"
|
43
|
-
},
|
44
|
-
"params": {
|
45
|
-
"id": 2
|
46
|
-
}
|
47
|
-
},
|
48
|
-
"response": {
|
49
|
-
"body_path": "/users/2.json"
|
50
|
-
}
|
51
|
-
}
|
52
|
-
]
|
53
|
-
}
|
54
|
-
]
|
@@ -1,36 +0,0 @@
|
|
1
|
-
[
|
2
|
-
{
|
3
|
-
"request": {
|
4
|
-
"http_method": "get",
|
5
|
-
"path": "/users/:id/posts"
|
6
|
-
},
|
7
|
-
"responses": [
|
8
|
-
{
|
9
|
-
"request": {
|
10
|
-
"headers": {
|
11
|
-
"Content-Type": "application/json"
|
12
|
-
},
|
13
|
-
"params": {
|
14
|
-
"id": 1
|
15
|
-
}
|
16
|
-
},
|
17
|
-
"response": {
|
18
|
-
"body_path": "/users/1/posts.json"
|
19
|
-
}
|
20
|
-
},
|
21
|
-
{
|
22
|
-
"request": {
|
23
|
-
"headers": {
|
24
|
-
"Content-Type": "application/json"
|
25
|
-
},
|
26
|
-
"params": {
|
27
|
-
"id": 2
|
28
|
-
}
|
29
|
-
},
|
30
|
-
"response": {
|
31
|
-
"body_path": "/users/2/posts.json"
|
32
|
-
}
|
33
|
-
}
|
34
|
-
]
|
35
|
-
}
|
36
|
-
]
|
data/spec/unit/parser_spec.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Contracto::Parser do
|
4
|
-
context '#contracts' do
|
5
|
-
subject { described_class.new(STRINGS_WITH_JSON).contracts }
|
6
|
-
|
7
|
-
it do
|
8
|
-
expect(subject).to be_a Array
|
9
|
-
expect(subject.first).to be_a Contracto::Contract
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|