agile-proxy 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.bowerrc +3 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.rubocop.yml +36 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +267 -0
- data/Guardfile +20 -0
- data/LICENSE +22 -0
- data/README.md +93 -0
- data/Rakefile +13 -0
- data/agile-proxy.gemspec +50 -0
- data/assets/index.html +39 -0
- data/assets/ui/app/HttpFlexibleProxyApi.js +31 -0
- data/assets/ui/app/app.js +1 -0
- data/assets/ui/app/controller/Stubs.js +64 -0
- data/assets/ui/app/controller/main.js +12 -0
- data/assets/ui/app/directive/AppEnhancedFormElement.js +21 -0
- data/assets/ui/app/directive/AppFor.js +16 -0
- data/assets/ui/app/directive/AppResponseEditor.js +54 -0
- data/assets/ui/app/model/RequestSpec.js +6 -0
- data/assets/ui/app/routes.js +10 -0
- data/assets/ui/app/service/Dialog.js +49 -0
- data/assets/ui/app/service/DomId.js +10 -0
- data/assets/ui/app/service/Error.js +7 -0
- data/assets/ui/app/service/Stub.js +36 -0
- data/assets/ui/app/view/404.html +2 -0
- data/assets/ui/app/view/dialog/error.html +10 -0
- data/assets/ui/app/view/dialog/yesNo.html +8 -0
- data/assets/ui/app/view/responses/editForm.html +78 -0
- data/assets/ui/app/view/status.html +1 -0
- data/assets/ui/app/view/stubs.html +19 -0
- data/assets/ui/app/view/stubs/edit.html +58 -0
- data/assets/ui/css/main.css +3 -0
- data/bin/agile_proxy +113 -0
- data/bower.json +27 -0
- data/config.yml +6 -0
- data/db.yml +10 -0
- data/db/migrations/20140818110800_create_users.rb +9 -0
- data/db/migrations/20140818134700_create_applications.rb +10 -0
- data/db/migrations/20140818135200_create_request_specs.rb +13 -0
- data/db/migrations/20140821115300_create_responses.rb +14 -0
- data/db/migrations/20140823082900_add_method_to_request_specs.rb +7 -0
- data/db/migrations/20140823083900_rename_request_spec_columns.rb +8 -0
- data/db/migrations/20141031072100_add_url_type_to_request_specs.rb +8 -0
- data/db/migrations/20141105125600_add_conditions_to_request_specs.rb +7 -0
- data/db/migrations/20141106083100_add_username_and_password_to_applications.rb +8 -0
- data/db/migrations/20141119143800_add_record_to_applications.rb +7 -0
- data/db/migrations/20141119174300_create_recordings.rb +18 -0
- data/db/schema.rb +78 -0
- data/examples/README.md +1 -0
- data/examples/facebook_api.html +59 -0
- data/examples/tumblr_api.html +22 -0
- data/lib/agile_proxy.rb +8 -0
- data/lib/agile_proxy/api/applications.rb +77 -0
- data/lib/agile_proxy/api/recordings.rb +52 -0
- data/lib/agile_proxy/api/request_specs.rb +85 -0
- data/lib/agile_proxy/api/root.rb +41 -0
- data/lib/agile_proxy/config.rb +63 -0
- data/lib/agile_proxy/handlers/handler.rb +43 -0
- data/lib/agile_proxy/handlers/proxy_handler.rb +110 -0
- data/lib/agile_proxy/handlers/request_handler.rb +57 -0
- data/lib/agile_proxy/handlers/stub_handler.rb +113 -0
- data/lib/agile_proxy/mitm.crt +22 -0
- data/lib/agile_proxy/mitm.key +27 -0
- data/lib/agile_proxy/model/application.rb +20 -0
- data/lib/agile_proxy/model/recording.rb +16 -0
- data/lib/agile_proxy/model/request_spec.rb +47 -0
- data/lib/agile_proxy/model/response.rb +56 -0
- data/lib/agile_proxy/model/user.rb +17 -0
- data/lib/agile_proxy/proxy_connection.rb +113 -0
- data/lib/agile_proxy/route.rb +106 -0
- data/lib/agile_proxy/router.rb +99 -0
- data/lib/agile_proxy/server.rb +85 -0
- data/lib/agile_proxy/servers/api.rb +41 -0
- data/lib/agile_proxy/servers/request_spec.rb +30 -0
- data/lib/agile_proxy/version.rb +6 -0
- data/load_proxy.js +39 -0
- data/log/.gitkeep +0 -0
- data/spec/common_helper.rb +32 -0
- data/spec/fixtures/test-server.crt +15 -0
- data/spec/fixtures/test-server.key +15 -0
- data/spec/integration/helpers/request_spec_helper.rb +60 -0
- data/spec/integration/specs/lib/server_spec.rb +407 -0
- data/spec/integration_spec_helper.rb +18 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/test_server.rb +75 -0
- data/spec/unit/agile_proxy/api/applications_spec.rb +102 -0
- data/spec/unit/agile_proxy/api/common_helper.rb +31 -0
- data/spec/unit/agile_proxy/api/recordings_spec.rb +115 -0
- data/spec/unit/agile_proxy/api/request_specs_spec.rb +159 -0
- data/spec/unit/agile_proxy/handlers/handler_spec.rb +8 -0
- data/spec/unit/agile_proxy/handlers/proxy_handler_spec.rb +138 -0
- data/spec/unit/agile_proxy/handlers/request_handler_spec.rb +55 -0
- data/spec/unit/agile_proxy/handlers/stub_handler_spec.rb +154 -0
- data/spec/unit/agile_proxy/model/recording_spec.rb +0 -0
- data/spec/unit/agile_proxy/model/request_spec_spec.rb +45 -0
- data/spec/unit/agile_proxy/model/response_spec.rb +38 -0
- data/spec/unit/agile_proxy/server_spec.rb +88 -0
- data/spec/unit/agile_proxy/servers/api_spec.rb +31 -0
- data/spec/unit/agile_proxy/servers/request_spec_spec.rb +32 -0
- metadata +618 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'require_all'
|
2
|
+
require 'airborne'
|
3
|
+
|
4
|
+
require 'agile_proxy'
|
5
|
+
require_all 'spec/support/**/*.rb'
|
6
|
+
require_all 'lib/agile_proxy/model'
|
7
|
+
require_all 'spec/integration/helpers'
|
8
|
+
require 'faker'
|
9
|
+
RSpec.configure do |config|
|
10
|
+
include AgileProxy::TestServer
|
11
|
+
config.before :all do
|
12
|
+
start_test_servers
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
Airborne.configure do |config|
|
17
|
+
config.base_url = 'http://localhost:3020'
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
|
2
|
+
ENV['RACK_ENV'] ||= 'test'
|
3
|
+
require 'pry'
|
4
|
+
require 'active_record'
|
5
|
+
require 'shoulda-matchers'
|
6
|
+
require 'rack'
|
7
|
+
require 'logger'
|
8
|
+
require_relative './unit/agile_proxy/api/common_helper'
|
9
|
+
require_relative './common_helper'
|
10
|
+
require_relative '../lib/agile_proxy'
|
11
|
+
environment = 'test'
|
12
|
+
dbconfig = YAML.load(File.read(AgileProxy.config.database_config_file))
|
13
|
+
ActiveRecord::Base.establish_connection dbconfig[environment]
|
14
|
+
|
15
|
+
AgileProxy.configure do |config|
|
16
|
+
config.logger = Logger.new(File.expand_path('../../log/test.log', __FILE__))
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
include AgileProxy::TestServer
|
21
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
22
|
+
config.run_all_when_everything_filtered = true
|
23
|
+
config.filter_run :focus
|
24
|
+
config.order = 'random'
|
25
|
+
|
26
|
+
config.before :all do
|
27
|
+
start_test_servers
|
28
|
+
end
|
29
|
+
|
30
|
+
config.after :each do
|
31
|
+
AgileProxy.config.reset
|
32
|
+
end
|
33
|
+
|
34
|
+
config.mock_with :rspec do |mocks|
|
35
|
+
mocks.syntax = :expect
|
36
|
+
end
|
37
|
+
config.include AgileProxy::Test::Api::Common, api_test: true
|
38
|
+
config.include AgileProxy::Test::Common
|
39
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'thin'
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module Thin
|
6
|
+
module Backends
|
7
|
+
class TcpServer
|
8
|
+
def get_port
|
9
|
+
# seriously, eventmachine, how hard does getting a port have to be?
|
10
|
+
Socket.unpack_sockaddr_in(EM.get_sockname(@signature)).first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module AgileProxy
|
17
|
+
module TestServer
|
18
|
+
def initialize
|
19
|
+
Thin::Logging.silent = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_test_servers
|
23
|
+
q = Queue.new
|
24
|
+
Thread.new do
|
25
|
+
EM.run do
|
26
|
+
echo = echo_app_setup
|
27
|
+
|
28
|
+
http_server = start_server(echo)
|
29
|
+
q.push http_server.backend.get_port
|
30
|
+
|
31
|
+
https_server = start_server(echo, true)
|
32
|
+
q.push https_server.backend.get_port
|
33
|
+
|
34
|
+
echo_error = echo_app_setup(500)
|
35
|
+
error_server = start_server(echo_error)
|
36
|
+
q.push error_server.backend.get_port
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
@http_url = "http://localhost:#{q.pop}"
|
41
|
+
@https_url = "https://localhost:#{q.pop}"
|
42
|
+
@error_url = "http://localhost:#{q.pop}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def echo_app_setup(response_code = 200)
|
46
|
+
counter = 0
|
47
|
+
proc do |env|
|
48
|
+
req_body = env['rack.input'].read
|
49
|
+
request_info = "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
|
50
|
+
res_body = request_info
|
51
|
+
res_body += "\n#{req_body}" unless req_body.empty?
|
52
|
+
counter += 1
|
53
|
+
[
|
54
|
+
response_code,
|
55
|
+
{ 'HTTP-X-EchoServer' => request_info,
|
56
|
+
'HTTP-X-EchoCount' => "#{counter}" },
|
57
|
+
[res_body]
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def start_server(echo, ssl = false)
|
63
|
+
http_server = Thin::Server.new '127.0.0.1', 0, echo
|
64
|
+
if ssl
|
65
|
+
http_server.ssl = true
|
66
|
+
http_server.ssl_options = {
|
67
|
+
private_key_file: File.expand_path('../../fixtures/test-server.key', __FILE__),
|
68
|
+
cert_chain_file: File.expand_path('../../fixtures/test-server.crt', __FILE__)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
http_server.start
|
72
|
+
http_server
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative './common_helper'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe AgileProxy::Api::Applications, api_test: true do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
include AgileProxy::Test::Api::Common
|
8
|
+
let(:applications_assoc_class) { Class.new }
|
9
|
+
|
10
|
+
describe 'GET /users/1/applications' do
|
11
|
+
let(:applications_result) do
|
12
|
+
[
|
13
|
+
{ username: 'user1', password: 'password1', name: 'application1', record_requests: true, user_id: current_user.id }.stringify_keys,
|
14
|
+
{ username: 'user1', password: 'password2', name: 'application2', record_requests: true, user_id: current_user.id }.stringify_keys,
|
15
|
+
{ username: 'user1', password: 'password3', name: 'application3', record_requests: true, user_id: current_user.id }.stringify_keys
|
16
|
+
]
|
17
|
+
end
|
18
|
+
before :each do
|
19
|
+
expect(current_user).to receive(:applications).and_return(applications_assoc_class)
|
20
|
+
expect(applications_assoc_class).to receive(:page).and_return applications_assoc_class
|
21
|
+
expect(applications_assoc_class).to receive(:per).and_return applications_assoc_class
|
22
|
+
expect(applications_assoc_class).to receive(:padding).and_return applications_assoc_class
|
23
|
+
expect(applications_assoc_class).to receive(:total_count).and_return 3
|
24
|
+
expect(applications_assoc_class).to receive(:num_pages).and_return 1
|
25
|
+
expect(applications_assoc_class).to receive(:current_page).and_return 1
|
26
|
+
expect(applications_assoc_class).to receive(:next_page).and_return 1
|
27
|
+
expect(applications_assoc_class).to receive(:prev_page).and_return 1
|
28
|
+
expect(applications_assoc_class).to receive(:count).and_return 3
|
29
|
+
expect(applications_assoc_class).to receive(:as_json).and_return(applications_result)
|
30
|
+
end
|
31
|
+
it 'returns a populated array of applications' do
|
32
|
+
get '/v1/users/1/applications'
|
33
|
+
expect(last_response.status).to eq(200)
|
34
|
+
expect(JSON.parse(last_response.body)).to eq('applications' => applications_result, 'total' => 3)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
describe 'POST /users/1/applications' do
|
38
|
+
let(:create_attributes) { { username: 'user1', password: 'password', name: 'application1', record_requests: true } }
|
39
|
+
let(:to_be_created_attributes) { create_attributes.merge(user_id: current_user.id, record_requests: 'true').stringify_keys }
|
40
|
+
let(:created_attributes) { to_be_created_attributes }
|
41
|
+
let(:mock_application) { double('AgileProxy::Application', create_attributes) }
|
42
|
+
before :each do
|
43
|
+
expect(current_user).to receive(:applications).and_return applications_assoc_class
|
44
|
+
expect(applications_assoc_class).to receive(:create!).with(to_be_created_attributes).and_return(mock_application)
|
45
|
+
expect(mock_application).to receive(:as_json).and_return(to_be_created_attributes)
|
46
|
+
end
|
47
|
+
it 'Creates a new application and returns it' do
|
48
|
+
post '/v1/users/1/applications', create_attributes, 'Content-Type' => 'application/json'
|
49
|
+
expect(last_response.status).to eq(201)
|
50
|
+
expect(JSON.parse(last_response.body)).to eql(created_attributes)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
describe 'DELETE /users/1/applications' do
|
54
|
+
before :each do
|
55
|
+
expect(current_user).to receive(:applications).and_return(applications_assoc_class)
|
56
|
+
expect(applications_assoc_class).to receive(:destroy_all)
|
57
|
+
end
|
58
|
+
it 'Should destroy all applications for the user' do
|
59
|
+
delete '/v1/users/1/applications'
|
60
|
+
expect(last_response.status).to eq(200)
|
61
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(applications: [], total: 0)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
describe '/users/1/applications/10' do
|
65
|
+
let(:persisted_attributes) { { username: 'user1', password: 'password', name: 'application10', record_requests: true, id: 10 } }
|
66
|
+
let(:mock_application) { double('AgileProxy::Application', persisted_attributes) }
|
67
|
+
before :each do
|
68
|
+
expect(current_user).to receive(:applications).and_return(applications_assoc_class)
|
69
|
+
expect(applications_assoc_class).to receive(:where).with(id: '10').and_return applications_assoc_class
|
70
|
+
expect(applications_assoc_class).to receive(:first).and_return mock_application
|
71
|
+
expect(mock_application).to receive(:as_json).with({}).and_return persisted_attributes
|
72
|
+
end
|
73
|
+
context 'GET' do
|
74
|
+
it 'Should retrieve the application from persistence store' do
|
75
|
+
get '/v1/users/1/applications/10'
|
76
|
+
expect(last_response.status).to eq(200)
|
77
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(persisted_attributes)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
context 'DELETE' do
|
81
|
+
it 'Should call destroy on the application found' do
|
82
|
+
expect(mock_application).to receive(:destroy)
|
83
|
+
delete '/v1/users/1/applications/10'
|
84
|
+
expect(last_response.status).to eq(200)
|
85
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(persisted_attributes)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
context 'PUT' do
|
89
|
+
let(:to_be_updated_attributes) { { username: 'user1', password: 'password', name: 'application10 new name', record_requests: 'true' }.stringify_keys }
|
90
|
+
let(:updated_attributes) { to_be_updated_attributes.merge(record_requests: true).stringify_keys }
|
91
|
+
it 'Should call update_attributes on the application found' do
|
92
|
+
expect(mock_application).to receive(:update_attributes).with(to_be_updated_attributes)
|
93
|
+
persisted_attributes.merge! updated_attributes
|
94
|
+
persisted_attributes.delete(:id) # We dont allow modification of the id
|
95
|
+
put '/v1/users/1/applications/10', to_be_updated_attributes
|
96
|
+
expect(last_response.status).to eq(200)
|
97
|
+
expect(JSON.parse(last_response.body)).to eql(updated_attributes)
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module AgileProxy
|
2
|
+
module Test
|
3
|
+
module Api
|
4
|
+
# A common helper for all API unit tests
|
5
|
+
module Common
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
before :each do
|
9
|
+
setup_active_record_environment!
|
10
|
+
def app
|
11
|
+
AgileProxy::Api::Root
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_user
|
18
|
+
@__current_user ||= double('AgileProxy::User', id: 1, name: 'Test User')
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_application
|
22
|
+
@__current_application ||= double('AgileProxy::Application', name: 'Default Application', id: 1)
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup_active_record_environment!
|
26
|
+
allow(AgileProxy::User).to receive(:first).and_return current_user
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative 'common_helper'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe AgileProxy::Api::Recordings, api_test: true do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
include AgileProxy::Test::Api::Common
|
8
|
+
let(:applications_assoc_class) do
|
9
|
+
Class.new do
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let(:recordings_assoc_class) do
|
13
|
+
Class.new do
|
14
|
+
def self.destroy_all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
let(:application_instance) { applications_assoc_class.new }
|
19
|
+
|
20
|
+
before :each do
|
21
|
+
expect(current_user).to receive(:applications).and_return(applications_assoc_class)
|
22
|
+
expect(applications_assoc_class).to receive(:where).with(id: '1').and_return applications_assoc_class
|
23
|
+
expect(applications_assoc_class).to receive(:first).and_return application_instance
|
24
|
+
expect(application_instance).to receive(:recordings).and_return recordings_assoc_class
|
25
|
+
|
26
|
+
end
|
27
|
+
describe 'GET /users/1/applications/1/recordings' do
|
28
|
+
let(:recordings_result) do
|
29
|
+
[
|
30
|
+
{
|
31
|
+
application_id: 1,
|
32
|
+
request_headers: '{}',
|
33
|
+
request_body: '',
|
34
|
+
request_url: 'http://www.test.com/1',
|
35
|
+
request_method: 'GET',
|
36
|
+
response_headers: '{}',
|
37
|
+
response_body: '{}',
|
38
|
+
response_status: '200'
|
39
|
+
}.stringify_keys,
|
40
|
+
{
|
41
|
+
application_id: 1,
|
42
|
+
request_headers: '{}',
|
43
|
+
request_body: '',
|
44
|
+
request_url: 'http://www.test.com/2',
|
45
|
+
request_method: 'GET',
|
46
|
+
response_headers: '{}',
|
47
|
+
response_body: '{}',
|
48
|
+
response_status: '200'
|
49
|
+
}.stringify_keys,
|
50
|
+
{
|
51
|
+
application_id: 1,
|
52
|
+
request_headers: '{}',
|
53
|
+
request_body: '',
|
54
|
+
request_url: 'http://www.test.com/3',
|
55
|
+
request_method: 'GET',
|
56
|
+
response_headers: '{}',
|
57
|
+
response_body: '{}',
|
58
|
+
response_status: '200'
|
59
|
+
}.stringify_keys
|
60
|
+
]
|
61
|
+
end
|
62
|
+
before :each do
|
63
|
+
expect(recordings_assoc_class).to receive(:page).and_return recordings_assoc_class
|
64
|
+
expect(recordings_assoc_class).to receive(:per).and_return recordings_assoc_class
|
65
|
+
expect(recordings_assoc_class).to receive(:padding).and_return recordings_assoc_class
|
66
|
+
expect(recordings_assoc_class).to receive(:total_count).and_return 3
|
67
|
+
expect(recordings_assoc_class).to receive(:num_pages).and_return 1
|
68
|
+
expect(recordings_assoc_class).to receive(:current_page).and_return 1
|
69
|
+
expect(recordings_assoc_class).to receive(:next_page).and_return 1
|
70
|
+
expect(recordings_assoc_class).to receive(:prev_page).and_return 1
|
71
|
+
expect(recordings_assoc_class).to receive(:count).and_return 3
|
72
|
+
expect(recordings_assoc_class).to receive(:as_json).with({}).and_return recordings_result
|
73
|
+
|
74
|
+
end
|
75
|
+
it 'returns a populated array of recordings' do
|
76
|
+
get '/v1/users/1/applications/1/recordings'
|
77
|
+
expect(last_response.status).to eq(200)
|
78
|
+
expect(JSON.parse(last_response.body)).to eq('recordings' => recordings_result, 'total' => 3)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
describe 'DELETE /users/1/applications/1/recordings' do
|
82
|
+
it 'Should destroy all applications for the user' do
|
83
|
+
expect(recordings_assoc_class).to receive(:destroy_all)
|
84
|
+
delete '/v1/users/1/applications/1/recordings'
|
85
|
+
expect(last_response.status).to eq(200)
|
86
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(recordings: [], total: 0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
describe '/users/1/applications/1/recordings/10' do
|
90
|
+
let(:recording_instance) { recordings_assoc_class.new }
|
91
|
+
let(:persisted_attributes) { { request_headers: '', response_headers: {} } }
|
92
|
+
before :each do
|
93
|
+
expect(recordings_assoc_class).to receive(:where).with(id: '10').and_return recordings_assoc_class
|
94
|
+
expect(recordings_assoc_class).to receive(:first).and_return recording_instance
|
95
|
+
expect(recording_instance).to receive(:as_json).with({}).and_return persisted_attributes
|
96
|
+
end
|
97
|
+
context 'GET' do
|
98
|
+
it 'Should fetch an individual recording' do
|
99
|
+
get '/v1/users/1/applications/1/recordings/10'
|
100
|
+
expect(last_response.status).to eq(200)
|
101
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(persisted_attributes)
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
context 'DELETE' do
|
106
|
+
it 'Should delete an individual recording' do
|
107
|
+
expect(recording_instance).to receive(:destroy)
|
108
|
+
delete '/v1/users/1/applications/1/recordings/10'
|
109
|
+
expect(last_response.status).to eq(200)
|
110
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eql(persisted_attributes)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative 'common_helper'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
describe AgileProxy::Api::RequestSpecs, api_test: true do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
include AgileProxy::Test::Api::Common
|
8
|
+
let(:applications_assoc_class) do
|
9
|
+
Class.new do
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let(:request_spec_assoc_class) do
|
13
|
+
Class.new do
|
14
|
+
def self.destroy_all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
let(:application_instance) { applications_assoc_class.new }
|
19
|
+
before :each do
|
20
|
+
expect(current_user).to receive(:applications).at_least(:once).and_return(applications_assoc_class)
|
21
|
+
expect(applications_assoc_class).to receive(:where).with(id: '1').at_least(:once).and_return applications_assoc_class
|
22
|
+
expect(applications_assoc_class).to receive(:first).at_least(:once).and_return application_instance
|
23
|
+
expect(application_instance).to receive(:request_specs).and_return request_spec_assoc_class
|
24
|
+
end
|
25
|
+
let(:default_json_spec) { { include: { response: { except: [:created_at, :updated_at] } } } }
|
26
|
+
|
27
|
+
# def mock_collection_data
|
28
|
+
# @__all_request_specs ||= [double('HttpFlexiblePrAgileProxy', :id => 1),double('AgileProxy::ReAgileProxy=> 2),double('AgileProxy::RequestSpAgileProxyeach do |d|
|
29
|
+
# allow(d).to receive(:as_json).with(default_json_spec).and_return({:spec => "Spec #{d.id}"}.as_json)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# def mock_collection_association
|
33
|
+
# return @__mock_collection_association if @__mock_collection_association.present?
|
34
|
+
# @__mock_collection_association = double('Mock Association')
|
35
|
+
# @__mock_collection_association.tap do |o|
|
36
|
+
# allow(o).to receive(:total_count).and_return 3
|
37
|
+
# allow(o).to receive(:num_pages).and_return 1
|
38
|
+
# allow(o).to receive(:current_page).and_return 1
|
39
|
+
# allow(o).to receive(:next_page).and_return nil
|
40
|
+
# allow(o).to receive(:prev_page).and_return nil
|
41
|
+
# allow(o).to receive(:page).and_return o
|
42
|
+
# allow(o).to receive(:per).and_return o
|
43
|
+
# allow(o).to receive(:padding).and_return o
|
44
|
+
# end
|
45
|
+
# allow(@__mock_collection_association).to receive(:as_json).with(default_json_spec).and_return(mock_collection_data.as_json(default_json_spec))
|
46
|
+
# allow(@__mock_collection_association).to receive(:count).and_return 3
|
47
|
+
# allow(@__mock_collection_association).to receive(:where) do |options|
|
48
|
+
# if options.key?(:id)
|
49
|
+
# mock_collection_data.select{|r| r.id.to_s == options[:id]}
|
50
|
+
# else
|
51
|
+
# throw "mock_collection_association called with an unknown where clause of #{where.to_json}"
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
# @__mock_collection_association
|
55
|
+
# end
|
56
|
+
# def created_member(attrs)
|
57
|
+
# double("AgileProxy::RequestSpec", attrs.merge({:as_json => {"spec" => attrs[:spec]}}))
|
58
|
+
# end
|
59
|
+
describe 'GET /users/1/applications/1/request_specs' do
|
60
|
+
let(:request_specs_result) do
|
61
|
+
[{ 'spec' => 'Spec 1' }, { 'spec' => 'Spec 2' }, { 'spec' => 'Spec 3' }]
|
62
|
+
end
|
63
|
+
before :each do
|
64
|
+
expect(request_spec_assoc_class).to receive(:page).and_return request_spec_assoc_class
|
65
|
+
expect(request_spec_assoc_class).to receive(:per).and_return request_spec_assoc_class
|
66
|
+
expect(request_spec_assoc_class).to receive(:padding).and_return request_spec_assoc_class
|
67
|
+
expect(request_spec_assoc_class).to receive(:total_count).and_return 3
|
68
|
+
expect(request_spec_assoc_class).to receive(:num_pages).and_return 1
|
69
|
+
expect(request_spec_assoc_class).to receive(:current_page).and_return 1
|
70
|
+
expect(request_spec_assoc_class).to receive(:next_page).and_return 1
|
71
|
+
expect(request_spec_assoc_class).to receive(:prev_page).and_return 1
|
72
|
+
expect(request_spec_assoc_class).to receive(:count).and_return 3
|
73
|
+
expect(request_spec_assoc_class).to receive(:as_json).with(default_json_spec).and_return request_specs_result
|
74
|
+
end
|
75
|
+
it 'returns a populated array of request specs' do
|
76
|
+
get '/v1/users/1/applications/1/request_specs'
|
77
|
+
expect(last_response.status).to eq(200)
|
78
|
+
expect(JSON.parse(last_response.body)).to eq('request_specs' => [{ 'spec' => 'Spec 1' }, { 'spec' => 'Spec 2' }, { 'spec' => 'Spec 3' }], 'total' => 3)
|
79
|
+
end
|
80
|
+
it 'Should not list items from a different application'
|
81
|
+
it 'Should not list items that belong to a different user'
|
82
|
+
end
|
83
|
+
describe '/users/1/applications/1/request_specs/2' do
|
84
|
+
let(:request_spec_instance) { request_spec_assoc_class.new }
|
85
|
+
let(:persisted_attributes) { { user_id: 1, application_id: 1, url: 'http://www.test.com', http_method: 'GET' } }
|
86
|
+
before :each do
|
87
|
+
expect(request_spec_assoc_class).to receive(:where).with(id: '2').and_return request_spec_assoc_class
|
88
|
+
expect(request_spec_assoc_class).to receive(:first).and_return request_spec_instance
|
89
|
+
expect(request_spec_instance).to receive(:as_json).with(default_json_spec).and_return persisted_attributes
|
90
|
+
end
|
91
|
+
describe 'GET' do
|
92
|
+
it 'returns a single item in json format' do
|
93
|
+
get '/v1/users/1/applications/1/request_specs/2'
|
94
|
+
expect(last_response.status).to eq(200)
|
95
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(persisted_attributes)
|
96
|
+
end
|
97
|
+
it 'Should not find a request spec which does not belong to the application specified'
|
98
|
+
it 'Should not find a request spec which does not belong to the user specified'
|
99
|
+
end
|
100
|
+
describe 'PUT' do
|
101
|
+
it 'Should update an existing item with the attributes given' do
|
102
|
+
expect(current_user).to receive(:id).and_return(1)
|
103
|
+
expect(application_instance).to receive(:id).and_return(1)
|
104
|
+
expect(request_spec_instance).to receive(:update_attributes).with(spec: 'Renamed Spec 2', user_id: 1, application_id: 1).and_return true
|
105
|
+
put '/v1/users/1/applications/1/request_specs/2', { spec: 'Renamed Spec 2' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
106
|
+
expect(last_response.status).to eq 200
|
107
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(persisted_attributes) # Note that the mocked update_attributes doesnt actually update so the original json is expected
|
108
|
+
end
|
109
|
+
end
|
110
|
+
describe 'DELETE' do
|
111
|
+
it 'Should delete the existing item and return it in json form' do
|
112
|
+
expect(request_spec_instance).to receive(:destroy)
|
113
|
+
delete '/v1/users/1/applications/1/request_specs/2'
|
114
|
+
expect(last_response.status).to eq 200
|
115
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(persisted_attributes)
|
116
|
+
end
|
117
|
+
it 'Should not allow deleting of other peoples request specs'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
describe 'POST /users/1/applications/1/request_specs' do
|
121
|
+
let(:request_spec_instance) { request_spec_assoc_class.new }
|
122
|
+
let(:persisted_attributes) { { user_id: 1, application_id: 1, url: 'http://www.test.com', http_method: 'GET' } }
|
123
|
+
before :each do
|
124
|
+
expect(request_spec_instance).to receive(:as_json).with(default_json_spec).and_return(persisted_attributes)
|
125
|
+
expect(current_user).to receive(:id).and_return(1)
|
126
|
+
expect(application_instance).to receive(:id).and_return(1)
|
127
|
+
end
|
128
|
+
it 'Should create a new item with the correct attributes set' do
|
129
|
+
expect(request_spec_assoc_class).to receive(:create).with(spec: 'Spec 4', user_id: 1, application_id: 1).and_return request_spec_instance
|
130
|
+
post '/v1/users/1/applications/1/request_specs', { spec: 'Spec 4' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
131
|
+
expect([200, 201]).to include(last_response.status)
|
132
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(persisted_attributes)
|
133
|
+
end
|
134
|
+
it 'Should allow creating of a response object also' do
|
135
|
+
response_attributes = { name: 'Test Response', content: '<h1>Hello World</h1>', content_type: 'text/html', status_code: 200, headers: '{}', is_template: false }
|
136
|
+
expect(request_spec_assoc_class).to receive(:create).with(spec: 'Spec 4', user_id: 1, application_id: 1, response_attributes: Hashie::Mash.new(response_attributes)).and_return request_spec_instance
|
137
|
+
post '/v1/users/1/applications/1/request_specs', { spec: 'Spec 4', response: response_attributes }.to_json, 'CONTENT_TYPE' => 'application/json'
|
138
|
+
expect([200, 201]).to include(last_response.status)
|
139
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(persisted_attributes)
|
140
|
+
end
|
141
|
+
it 'Should inform the router of the new entry'
|
142
|
+
it 'Should not allow the user to specify the user_id to prevent creating for a different user'
|
143
|
+
it 'Should not allow setting of an application_id which doesnt belong to the current user'
|
144
|
+
end
|
145
|
+
describe 'DELETE /users/1/applications/1/request_specs' do
|
146
|
+
before :each do
|
147
|
+
expect(request_spec_assoc_class).to receive(:delete_all)
|
148
|
+
end
|
149
|
+
it 'Should delete all request specs for the users application' do
|
150
|
+
delete '/v1/users/1/applications/1/request_specs'
|
151
|
+
expect(JSON.parse(last_response.body).symbolize_keys).to eq(request_specs: [], total: 0)
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
it 'Should not find other peoples request specs to update'
|
156
|
+
it 'Should not allow updates of the user_id to prevent changing ownership'
|
157
|
+
it 'Should not allow updates of the application_id to prevent changing ownership via the application'
|
158
|
+
it 'Should inform the router of the update if the spec or response has changed'
|
159
|
+
end
|