scenario_server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,283 @@
1
+ #!/usr/env ruby
2
+ require 'fileutils'
3
+ require 'sequel'
4
+ require 'sequel/extensions/pretty_table'
5
+
6
+ class ScenarioDB
7
+
8
+ attr_accessor :db, :db_file, :scenarios, :routes, :testdata
9
+
10
+ def initialize(options={})
11
+ if options[:db_file]
12
+ self.db_file = options[:db_file]
13
+ else
14
+ self.db_file = File.dirname(File.expand_path(__FILE__)) + '/data/scenario_db.sqlite3'
15
+ end
16
+
17
+ handle_cli_options(options)
18
+ end
19
+
20
+ def handle_cli_options(options)
21
+ if options[:setup]
22
+
23
+ configure_database
24
+ puts 'database setup complete.'
25
+ end
26
+
27
+ if !options[:add_scenario].nil? && options[:add_scenario].length == 1
28
+ configure_database
29
+
30
+ add_scenario(options[:add_scenario][0])
31
+ if self.scenarios.count > 0
32
+ Sequel::PrettyTable.print(self.scenarios)
33
+ else
34
+ puts 'No records to display.'
35
+ end
36
+ end
37
+
38
+ if !options[:delete_scenario].nil?
39
+ configure_database
40
+
41
+ delete_scenario(options[:delete_scenario])
42
+ if self.db[:scenarios].count > 0
43
+ Sequel::PrettyTable.print(self.db[:scenarios])
44
+ else
45
+ puts 'No records to display.'
46
+ end
47
+ end
48
+
49
+ if !options[:add_route].nil? && options[:add_route].length == 4
50
+ configure_database
51
+
52
+ add_route_for_scenario(options[:add_route][0], options[:add_route][1], options[:add_route][2], options[:add_route][3])
53
+ if self.routes.count > 0
54
+ Sequel::PrettyTable.print(self.routes)
55
+ else
56
+ puts 'No records to display.'
57
+ end
58
+ end
59
+
60
+ if !options[:delete_route].nil?
61
+ configure_database
62
+
63
+ delete_route(options[:delete_route])
64
+ if self.db[:routes].count > 0
65
+ Sequel::PrettyTable.print(self.routes)
66
+ else
67
+ puts 'No records to display.'
68
+ end
69
+ end
70
+
71
+ if !options[:add_testdata].nil? && options[:add_testdata].length == 3
72
+ configure_database
73
+
74
+ add_testdata_for_scenario(options[:add_testdata][0], options[:add_testdata][1], options[:add_testdata][2])
75
+ if self.testdata.count > 0
76
+ Sequel::PrettyTable.print(self.testdata)
77
+ else
78
+ puts 'No records to display.'
79
+ end
80
+ end
81
+
82
+ if !options[:delete_testdata].nil?
83
+ configure_database
84
+
85
+ delete_route(options[:delete_testdata])
86
+ if self.testdata.count > 0
87
+ Sequel::PrettyTable.print(self.testdata)
88
+ else
89
+ puts 'No records to display.'
90
+ end
91
+ end
92
+
93
+ if options[:scenarios]
94
+ configure_database
95
+
96
+ if self.scenarios.count > 0
97
+ Sequel::PrettyTable.print(self.scenarios)
98
+ else
99
+ puts 'No records to display.'
100
+ end
101
+ end
102
+
103
+ if options[:routes]
104
+ configure_database
105
+
106
+ if self.routes.count > 0
107
+ Sequel::PrettyTable.print(self.routes)
108
+ else
109
+ puts 'No records to display.'
110
+ end
111
+ end
112
+
113
+ if options[:testdata]
114
+ configure_database
115
+
116
+ if self.testdata.count > 0
117
+ Sequel::PrettyTable.print(self.testdata)
118
+ else
119
+ puts 'No records to display.'
120
+ end
121
+ end
122
+ end
123
+
124
+ def configure_database
125
+ setup_database
126
+ open_database
127
+ create_scenarios_table
128
+ create_routes_table
129
+ create_testdata_table
130
+ end
131
+
132
+ def setup_database
133
+ # Create an empty database file
134
+ if !File.exists?(self.db_file)
135
+ puts self.db_file
136
+ File.open(self.db_file, 'w'){}
137
+ end
138
+ end
139
+
140
+ def open_database
141
+ # Open the database
142
+ self.db ||= Sequel.sqlite(self.db_file)
143
+ self.scenarios ||= self.db[:scenarios]
144
+ self.routes ||= self.db[:routes]
145
+ self.testdata ||= self.db[:testdata]
146
+ end
147
+
148
+ #scenarios
149
+
150
+ def create_scenarios_table
151
+ # Create Scenarios table
152
+ if !self.db.table_exists?(:scenarios)
153
+ # puts "Creating the scenarios table"
154
+ self.db.create_table :scenarios do
155
+ primary_key :id
156
+ String :name
157
+ DateTime :created_at
158
+ DateTime :updated_at
159
+ end
160
+ end
161
+ end
162
+
163
+ def add_scenario(name)
164
+ if self.scenarios.where(:name => name).to_a.count == 0
165
+ now = DateTime.now
166
+ self.scenarios.insert(:name => name, :created_at => now, :updated_at => now)
167
+ end
168
+ end
169
+
170
+ def delete_scenario(scenario_id)
171
+ self.scenarios.filter(:id => scenario_id).delete
172
+ end
173
+
174
+ def reset_scenarios
175
+ self.scenarios.delete
176
+ create_scenarios_table
177
+ end
178
+
179
+ def get_ordered_scenarios
180
+ return self.scenarios.order(:name).select(:id, :name).to_a
181
+ end
182
+
183
+ def get_scenario_names
184
+ return self.scenarios.map(:name)
185
+ end
186
+
187
+ def delete_scenario_for_id(scenario_id)
188
+ self.scenarios.filter(:id => scenario_id).delete
189
+ end
190
+
191
+ def get_scenario_for_id(scenario_id)
192
+ return self.scenarios.where(:id => scenario_id).first
193
+ end
194
+
195
+ def get_last_scenario_id
196
+ return self.scenarios.reverse_order(:id).first[:id]
197
+ end
198
+
199
+ #routes
200
+
201
+ def create_routes_table
202
+ # Create the routes table
203
+ if !self.db.table_exists?(:routes)
204
+ # puts "Creating the routes table"
205
+ self.db.create_table :routes do
206
+ primary_key :id
207
+ foreign_key :scenario_id, :scenarios, :on_delete => :cascade, :on_update => :cascade
208
+ String :route_type
209
+ String :path
210
+ String :fixture
211
+ DateTime :created_at
212
+ DateTime :updated_at
213
+ end
214
+ end
215
+ end
216
+
217
+ def add_route_for_scenario(route_type, path, fixture, scenario_id)
218
+ now = DateTime.now
219
+ if self.routes.where(:scenario_id => scenario_id, route_type=> route_type, path=> path).to_a.count == 0
220
+ self.routes.insert(:scenario_id => scenario_id, :route_type=>route_type, :path => path, :fixture => fixture, :created_at => now, :updated_at => now)
221
+ end
222
+ # puts "<scenario_id: #{scenario_id} #{}route_type} #Path: #{path} fixture: #{fixture}>"
223
+ end
224
+
225
+ def delete_route(route_id)
226
+ self.routes.filter(:id => route_id).delete
227
+ end
228
+
229
+ def get_routes_for_scenario(scenario_id)
230
+ return self.routes.filter(:scenario_id=>scenario_id).select(:id, :scenario_id,:route_type,:path,:fixture).to_a
231
+ end
232
+
233
+ def get_fixture_from_routes(route_type, path, scenario_name)
234
+
235
+ self.routes.left_outer_join(:scenarios, :id=>:scenario_id).where(:route_type=>route_type,
236
+ :path=>path,
237
+ :name=>scenario_name).map(:fixture).first
238
+
239
+
240
+ #TODO instead of returning first fixture, add checks to avoid duplicate insertions
241
+ end
242
+
243
+ def get_route(route_id)
244
+ return self.routes.where(:id => route_id).first
245
+ end
246
+
247
+ def get_last_routes_id
248
+ return self.routes.reverse_order(:id).first[:id]
249
+ end
250
+
251
+
252
+ #testdata
253
+
254
+ def create_testdata_table
255
+ # Create the testdata table
256
+ if !self.db.table_exists?(:testdata)
257
+ # puts 'Creating the testdata table'
258
+ self.db.create_table :testdata do
259
+ primary_key :id
260
+ foreign_key :scenario_id, :scenarios, :on_delete => :cascade, :on_update => :cascade
261
+ String :name
262
+ String :value
263
+ DateTime :created_at
264
+ DateTime :updated_at
265
+ end
266
+ end
267
+ end
268
+
269
+ def add_testdata_for_scenario(name, value, scenario_id)
270
+ now = DateTime.now
271
+ self.testdata.insert(:name=>name, :value=>value, :scenario_id => scenario_id, :created_at => now, :updated_at => now)
272
+ # puts "<#Name: #{name} value: #{value} scenario_id: #{scenario_id}>"
273
+ end
274
+
275
+ def delete_testdata_for_scenario(testdata_id)
276
+ self.testdata.filter(:id=>testdata_id).delete
277
+ end
278
+
279
+ def get_last_testdata_id
280
+ return self.testdata.reverse_order(:id).first[:id]
281
+ end
282
+
283
+ end
@@ -0,0 +1,3 @@
1
+ module Scenarios
2
+ VERSION = "0.0.1"
3
+ end
data/lib/scenarios.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "scenarios/version"
2
+
3
+ module Scenarios
4
+ # Your code goes here...
5
+ end
data/scenarios.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'scenarios/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "scenario_server"
8
+ spec.version = Scenarios::VERSION
9
+ spec.authors = ["Vaibhav Bhatia"]
10
+ spec.email = ["vaikings@gmail.com"]
11
+ spec.summary = %q{Scenarios is a sinatra server which returns mock json fixtures for routes in the current scenario}
12
+ spec.description = %q{This gem is useful for development where a mock rest api server is required and with frank UI test automation.}
13
+ spec.homepage = 'https://bitbucket.org/vaikings/scenarios'
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "sinatra", "~> 1.4"
22
+ spec.add_runtime_dependency "sinatra-contrib", "~> 1.4"
23
+ spec.add_runtime_dependency "sequel", "4.7"
24
+
25
+ spec.add_development_dependency "sqlite3" , "~> 1.3"
26
+ spec.add_development_dependency "bundler", "~> 1.5"
27
+ spec.add_development_dependency "rake", "~> 10.1"
28
+ spec.add_development_dependency "rack-test", "~> 0.6"
29
+ spec.add_development_dependency "rspec", "~> 2.0"
30
+ spec.add_development_dependency "json_spec", "~> 1.1"
31
+
32
+ end
data/spec/app_spec.rb ADDED
@@ -0,0 +1,149 @@
1
+ require './spec/spec_helper'
2
+ require './lib/scenarios/application/app'
3
+ require './lib/scenarios/scenario_db'
4
+
5
+
6
+ describe "scenario api" do
7
+
8
+ attr_accessor :scenario_db
9
+
10
+ before(:all) do
11
+ options = {:db_file=>File.dirname(File.expand_path(__FILE__)) + '/../lib/scenarios/data/scenario_testdb.sqlite3'}
12
+ self.scenario_db = ScenarioDB.new(options)
13
+ self.scenario_db.configure_database()
14
+
15
+ end
16
+
17
+ def app
18
+ ScenarioServer
19
+ end
20
+
21
+ before(:each) do
22
+ reset_scenario
23
+ end
24
+
25
+ it "GET /scenario" do
26
+ get '/scenario'
27
+
28
+ expect(last_response.status).to eq(200)
29
+ expect(last_response.body).to eq("default")
30
+ end
31
+
32
+ it "PUT /scenario/:name" do
33
+ put '/scenario/test'
34
+
35
+ expect(last_response.status).to eq(400)
36
+ expect(scenario).to eq("default")
37
+ end
38
+
39
+ it "PUT /scenario/:name" do
40
+ self.scenario_db.add_scenario('test')
41
+
42
+ put '/scenario/test'
43
+
44
+ expect(last_response.status).to eq(200)
45
+ expect(scenario).to eq("test")
46
+ end
47
+
48
+ it "DELETE /scenario" do
49
+ delete "/scenario"
50
+
51
+ expect(last_response.status).to eq(200)
52
+ expect(scenario).to eq("default")
53
+ end
54
+
55
+ end
56
+
57
+ describe "scenarios and routes REST api" do
58
+
59
+ def app
60
+ ScenarioServer
61
+ end
62
+
63
+ attr_accessor :scenario_db
64
+
65
+ before(:all) do
66
+ options = {:db_file=>File.dirname(File.expand_path(__FILE__)) + '/../lib/scenarios/data/scenario_testdb.sqlite3'}
67
+ self.scenario_db = ScenarioDB.new(options)
68
+ self.scenario_db.configure_database()
69
+
70
+ end
71
+
72
+ before(:each) do
73
+ self.scenario_db.reset_scenarios
74
+ scenario_id = self.scenario_db.add_scenario("default")
75
+ route_id = self.scenario_db.add_route_for_scenario('GET', '/hello', {"hello"=>"world"}.to_json, scenario_id)
76
+ end
77
+
78
+ #specs
79
+
80
+ it 'GET /scenarios' do
81
+ get '/scenarios'
82
+ expect(last_response.status).to eq(200)
83
+ file_data = parse_json(load_json('all_scenarios.json'))
84
+
85
+ last_response.body.should be_json_eql(load_json('all_scenarios.json')).excluding("id")
86
+ end
87
+
88
+ it 'GET /scenarios/{scenario_id}' do
89
+ last_scenario_id = self.scenario_db.get_last_scenario_id
90
+
91
+ get '/scenarios/'+last_scenario_id.to_s
92
+
93
+ expect(last_response.status).to eq(200)
94
+ last_response.body.should be_json_eql(load_json("default_scenario.json")).excluding("id")
95
+ end
96
+
97
+ it "POST /scenarios/new" do
98
+ post '/scenarios/new',"default",{}
99
+
100
+ expect(last_response.status).to eq(200)
101
+ last_response.body.should have_json_path("url")
102
+
103
+ end
104
+
105
+ it 'DELETE /scenarios/:scenario_id' do
106
+ last_scenario_id = self.scenario_db.get_last_scenario_id
107
+
108
+ delete '/scenarios/'+last_scenario_id.to_s
109
+ expect(last_response.status).to eq(200)
110
+ end
111
+
112
+ it 'POST /scenarios/:scenario_id/routes/new' do
113
+ last_scenario_id = self.scenario_db.get_last_scenario_id
114
+
115
+ content = '{"path":"/v1/mystyle","fixture":"{\"json\":\"body\"}","route_type":"GET" }'
116
+ path = '/scenarios/'+last_scenario_id.to_s + '/routes/new'
117
+ post path, content, {}
118
+
119
+ expect(last_response.status).to eq(200)
120
+ last_response.body.should have_json_path('url')
121
+ end
122
+
123
+ it 'GET /scenarios/:scenario_id/routes' do
124
+ last_scenario_id = self.scenario_db.get_last_scenario_id
125
+
126
+ get '/scenarios/'+last_scenario_id.to_s+'/routes'
127
+
128
+ expect(last_response.status).to eq(200)
129
+ last_response.body.should have_json_path('routes')
130
+ end
131
+
132
+ it 'DELETE /scenarios/:scenario_id/routes/:route_id' do
133
+ last_scenario_id = self.scenario_db.get_last_scenario_id
134
+ last_route_id = self.scenario_db.get_last_routes_id
135
+
136
+ delete '/scenarios/'+last_scenario_id.to_s+'/routes/'+last_route_id.to_s
137
+ expect(last_response.status).to eq(200)
138
+
139
+ end
140
+
141
+ it 'GET /scenarios/:scenario_id/routes/:route_id' do
142
+ last_scenario_id = self.scenario_db.get_last_scenario_id
143
+ last_route_id = self.scenario_db.get_last_routes_id
144
+
145
+ get '/scenarios/'+last_scenario_id.to_s+'/routes/'+last_route_id.to_s
146
+ expect(last_response.status).to eq(200)
147
+ end
148
+
149
+ end
@@ -0,0 +1,48 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ ENV["RACK_ENV"] = "test"
8
+
9
+ require 'rspec'
10
+ require 'rspec/expectations'
11
+ require 'rack/test'
12
+ require 'json_spec'
13
+
14
+ JsonSpec.directory ="./fixtures/"
15
+
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+ config.run_all_when_everything_filtered = true
19
+ config.filter_run :focus
20
+
21
+ # Run specs in random order to surface order dependencies. If you find an
22
+ # order dependency and want to debug it, you can fix the order by providing
23
+ # the seed, which is printed after each run.
24
+ # --seed 1234
25
+ config.order = 'random'
26
+
27
+ #include Rack::Test::Methods by default
28
+ config.include Rack::Test::Methods
29
+ config.include JsonSpec::Helpers
30
+ end
31
+
32
+
33
+ # helper methods
34
+
35
+ def scenario
36
+ get '/scenario'
37
+ last_response.body
38
+ end
39
+
40
+ def reset_scenario
41
+ delete "/scenario"
42
+ expect(last_response.status).to eq(200)
43
+ end
44
+
45
+ def set_scenario(name)
46
+ put "/scenario/#{name}"
47
+ expect(last_response.status).to eq(200)
48
+ end