blix-rest 0.1.30

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.
@@ -0,0 +1,8 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'cucumber'
4
+ require 'blix/rest'
5
+ require 'blix/rest/cucumber/world'
6
+ require 'blix/rest/cucumber/hooks'
7
+ require 'blix/rest/cucumber/request_steps'
8
+ require 'blix/rest/cucumber/resource_steps'
@@ -0,0 +1,5 @@
1
+ Before do
2
+ #@_app = Blix::Rest::Server.new
3
+ #@_srv = Rack::MockRequest.new(@_app)
4
+ Blix::Rest::RequestMapper.set_path_root(nil)
5
+ end
@@ -0,0 +1,207 @@
1
+ #========== requests with tokens
2
+
3
+ Given(/^(.*?) requests token for service "(.*?)"$/) do |user,service|
4
+ path = "/myservices/" + service + "/token"
5
+ send_request('POST',user,path,nil)
6
+ @_token = valid_response.data["token"]
7
+ end
8
+
9
+ Given(/^(.*?) validates the token for service "(.*?)"$/) do |user,service|
10
+ path = "/services/" + service + "/validate/" + @_token
11
+ send_request('GET',user,path,nil)
12
+ end
13
+
14
+
15
+ # Given(/^guest gets "(.*?)"( .*)?$/) do |path,condition|
16
+ # path = add_token_to_path(path,@_token) if condition == " with token"
17
+ # send_request('GET',"guest",path,nil)
18
+ # end
19
+
20
+ # general requests
21
+
22
+ Given(/^(.*?) gets ["'](.*?)["']( with token)?$/) do |user, path, condition|
23
+ path = add_token_to_path(path,@_token) if condition == " with token"
24
+ send_request('GET',user,path,nil)
25
+ end
26
+
27
+ Given(/^(.*?) options ["'](.*?)["']( with token)?$/) do |user, path, condition|
28
+ path = add_token_to_path(path,@_token) if condition == " with token"
29
+ send_request('OPTIONS',user,path,nil)
30
+ end
31
+
32
+ Given(/^(.*?) posts ["'](.*?)["'] with (.*?)$/) do |user, path, json|
33
+ send_request('POST',user,path,json)
34
+ end
35
+
36
+ # doc string version
37
+ Given(/^(.*?) posts ["'](.*?)["'] with$/) do |user, path, json|
38
+ send_request('POST',user,path,json)
39
+ end
40
+
41
+ Given(/^(.*?) deletes ["'](.*?)["']$/) do |user, path|
42
+ send_request('DELETE',user,path,nil)
43
+ end
44
+
45
+ Given(/^(.*?) puts ["'](.*?)["'] with (.*?)$/) do |user, path, json|
46
+ send_request('PUT',user,path,json)
47
+ end
48
+
49
+ # doc string version
50
+ Given(/^(.*?) puts ["'](.*?)["'] with$/) do |user, path, json|
51
+ send_request('PUT',user,path,json)
52
+ end
53
+
54
+ # alternative format
55
+
56
+ Given(/^I am (.*?)$/) do | string |
57
+ @_current_user = string.split(' ')[-1]
58
+ end
59
+
60
+ Given(/^I get ["'](.*?)["']$/) do |path|
61
+ send_request('GET',@_current_user,path,nil)
62
+ end
63
+
64
+ Given(/^I post ["'](.*?)["'] with (.*?)$/) do |path, json|
65
+ send_request('POST',@_current_user,path,json)
66
+ end
67
+
68
+ Given(/^I delete ["'](.*?)["']$/) do | path|
69
+ send_request('DELETE',@_current_user,path,nil)
70
+ end
71
+
72
+ Given(/^I put ["'](.*?)["'] with (.*?)$/) do |path, json|
73
+ send_request('PUT',@_current_user,path,json)
74
+ end
75
+
76
+ # response steps ==============================
77
+
78
+ Then(/^the status should be (\d+)$/) do |code|
79
+ expect(valid_response.status).to eq code.to_i
80
+ end
81
+
82
+ Then(/^there should be an error$/) do
83
+ expect(valid_response.status.to_s[0,1]).not_to eq '2'
84
+ expect(valid_response.error).not_to be_nil
85
+ end
86
+
87
+ Then(/^the error message should include ["'](.*?)["']$/) do |field|
88
+ expect(valid_response.error && (valid_response.error =~ %r/#{field}/)).to_not be nil
89
+ end
90
+
91
+ Given(/^explain$/) do
92
+ explain
93
+ end
94
+
95
+ Then(/^the data type should be ["'](.*?)["']$/) do |type|
96
+ if valid_response.data.kind_of? Array
97
+ expect(valid_response.data[0]["_type"]).to eq type
98
+ else
99
+ expect(valid_response.data["_type"]).to eq type
100
+ end
101
+ end
102
+
103
+
104
+ Then(/^the data length should be (\d+)$/) do |len|
105
+ if valid_response.data.kind_of? Array
106
+ expect(valid_response.data.length).to eq len.to_i
107
+ else
108
+ 1
109
+ end
110
+ end
111
+
112
+ Then(/^the data length should equal (\d+)$/) do |len|
113
+ if valid_response.data.kind_of? Array
114
+ expect(valid_response.data.length).to eq len.to_i
115
+ else
116
+ 1
117
+ end
118
+ end
119
+
120
+ Then(/^the data "(.*?)" should == (.*?)$/) do |field,val|
121
+ if valid_data.kind_of? Array
122
+ data = valid_data[0]
123
+ else
124
+ data = valid_data
125
+ end
126
+ v = data[field].to_s
127
+
128
+ if val =~ %r{^@([^@]*)$}
129
+ expect(v).to eq store[$1].to_s
130
+ elsif val =~ %r{^(::)?[A-Z][A-z_a-z:]*$}
131
+ expect(v).to eq Module.const_get(val).to_s
132
+ elsif val =~ %r{^['"](.*)['"]$}
133
+ expect(v).to eq $1
134
+ end
135
+
136
+ end
137
+
138
+ Then(/^the data "(.*?)" should equal ["'](.*?)["']$/) do |field,val|
139
+ if valid_response.data.kind_of? Array
140
+ data = valid_response.data[0]
141
+ else
142
+ data = valid_response.data
143
+ end
144
+ expect(data[field].to_s).to eq val
145
+ end
146
+
147
+ Then(/^the data ["'](.*?)["'] should == nil$/) do |field|
148
+ if valid_response.data.kind_of? Array
149
+ data = valid_response.data[0]
150
+ else
151
+ data = valid_response.data
152
+ end
153
+ expect(data[field]).to be nil
154
+ end
155
+
156
+ Then(/^the data ["'](.*?)["'] should equal nil$/) do |field|
157
+ if valid_response.data.kind_of? Array
158
+ data = valid_response.data[0]
159
+ else
160
+ data =valid_response.data
161
+ end
162
+ expect(data[field]).to be nil
163
+ end
164
+
165
+ Then(/^the body should eq ["'](.*?)["']$/) do |val|
166
+ val.gsub!("\\n","\n")
167
+ expect(valid_response.body).to eq val
168
+ end
169
+
170
+
171
+
172
+ Then(/^the data should( not)? include ["'](.*?)["']$/) do |state, field|
173
+ if valid_response.data.kind_of? Array
174
+ data = valid_response.data[0]
175
+ else
176
+ data = valid_response.data
177
+ end
178
+ if state == " not"
179
+ expect(data.key?(field)).to eq false
180
+ else
181
+ expect(data.key?(field)).to eq true
182
+ end
183
+ end
184
+
185
+
186
+
187
+ Then(/^store the ["'](.*?)["'] as ["'](.*?)["']$/) do |name,key|
188
+ if valid_response.data.kind_of?(Array)
189
+ data = valid_response.data[0]
190
+ else
191
+ data = valid_response.data
192
+ end
193
+ if data.kind_of?(Hash) && data.key?(name)
194
+ store[key] = data[name]
195
+ end
196
+ end
197
+
198
+ Given(/^save the "([^"]*)"$/) do |name|
199
+ if valid_response.data.kind_of?(Array)
200
+ data = valid_response.data[0]
201
+ else
202
+ data = valid_response.data
203
+ end
204
+ if data.kind_of?(Hash) && data.key?(name)
205
+ store[name] = data[name]
206
+ end
207
+ end
@@ -0,0 +1,28 @@
1
+ class UserHash < Hash
2
+ def set(k,v)
3
+ self[k.to_s] = v
4
+ end
5
+
6
+ def get(k)
7
+ self[k.to_s]
8
+ end
9
+ end
10
+
11
+ Given(/^the following users exist:$/) do |table|
12
+ table.hashes.each do |h|
13
+
14
+ name = h["name"] || h["login"]
15
+
16
+ next if name=="guest"
17
+
18
+ u = UserHash.new.merge!(h)
19
+
20
+
21
+
22
+ u.set(:pw,h["secret"] || h["password"] || name+"@12345678")
23
+
24
+ before_user_create(u,h)
25
+ users[name] = u
26
+ after_user_create(u,h)
27
+ end
28
+ end
@@ -0,0 +1,273 @@
1
+ # the step definitions are executed in an instance of world so
2
+ # we can add helper methods for use in the step definitions.
3
+
4
+ class RestWorld
5
+ # the entry point to the rack application to be tested
6
+ def self.app
7
+ @_app ||= Rack::Builder.parse_file('config.ru').first
8
+ end
9
+
10
+ # a dummy request to sent to the server
11
+ def self.request
12
+ @_req ||= Rack::MockRequest.new(app)
13
+ end
14
+
15
+ # a class to represent a response from the server
16
+ class Response
17
+ def initialize(resp)
18
+ @resp = resp
19
+ if @resp.header['Content-Type'] == 'application/json'
20
+ begin
21
+ @h = MultiJson.load(@resp.body) || {}
22
+ rescue Exception => e
23
+ puts 'INVALID RESPONSE BODY=>' + @resp.body
24
+ raise
25
+ end
26
+ else
27
+ @h = { 'html' => @resp.body }
28
+ end
29
+
30
+ # get_ids_from_hash
31
+ end
32
+
33
+ def [](k)
34
+ @h[k]
35
+ end
36
+
37
+ def body
38
+ @resp.body
39
+ end
40
+
41
+ def data
42
+ @h['data']
43
+ end
44
+
45
+ def error
46
+ @h['error']
47
+ end
48
+
49
+ def status
50
+ @resp.status.to_i
51
+ end
52
+
53
+ def header
54
+ @resp.header || {}
55
+ end
56
+
57
+ def content_type
58
+ header['Content-Type']
59
+ end
60
+
61
+ def inspect
62
+ @resp.inspect
63
+ end
64
+ end
65
+
66
+ # store cookies for each user here
67
+ def cookies
68
+ @_cookies ||= {}
69
+ @_cookies[@_current_user] ||= []
70
+ end
71
+
72
+ # store current user information here
73
+ def users
74
+ @_users ||= {}
75
+ end
76
+
77
+ # store current user tokens here
78
+ def tokens
79
+ @_tokens ||= {}
80
+ end
81
+
82
+ # store general information here
83
+ def store
84
+ @_store ||= {}
85
+ end
86
+
87
+ def valid_response
88
+ @_response || raise('no valid response from service')
89
+ end
90
+
91
+ def valid_data
92
+ @_response && @_response.data || raise("no valid data returned from service:#{@_response.error}")
93
+ end
94
+
95
+ def explain
96
+ puts "request ==> #{@_verb} #{@_request}"
97
+ puts "cookies ==> #{cookies.join('; ')}" if cookies.length > 0
98
+ puts "body ==> #{@_body}" if @_body
99
+ puts "response ==> #{@_response.inspect}"
100
+ end
101
+
102
+ def before_parse_path(path); end
103
+
104
+ def before_parse_body(json); end
105
+
106
+ def parse_path(path)
107
+ path = path.dup
108
+
109
+ before_parse_path(path)
110
+
111
+ path = path.gsub /\/(@[a-z0-9_]+)/ do |str|
112
+ str = str[2..-1]
113
+ id = store[str]
114
+ raise ":#{str} has not been stored" unless id
115
+ if id[0] == '/'
116
+ "#{id}"
117
+ else
118
+ "/#{id}"
119
+ end
120
+ end
121
+ # and the query part
122
+ path.gsub /\=(@[a-z0-9_]+)/ do |str|
123
+ str = str[2..-1]
124
+ id = store[str]
125
+ raise ":#{str} has not been stored" unless id
126
+
127
+ "=#{id}"
128
+ end
129
+ end
130
+
131
+ def parse_json(json)
132
+ # replace original format
133
+ json = json.gsub /:@([a-z0-9_]+)/ do |str|
134
+ str = str[2..-1]
135
+ id = store[str]
136
+ raise ":#{str} has not been stored" unless id
137
+
138
+ if id.is_a?(String)
139
+ ":\"#{id}\""
140
+ else
141
+ ":#{id}"
142
+ end
143
+ end
144
+
145
+ # replace alternative format
146
+ json = json.gsub /#\{([a-z0-9_]+)\}/ do |str|
147
+ str = str[2..-2]
148
+ id = store[str]
149
+ raise ":#{str} has not been stored" unless id
150
+
151
+ if id.is_a?(String)
152
+ "\"#{id}\""
153
+ else
154
+ "#{id}"
155
+ end
156
+ end
157
+ end
158
+
159
+ def parse_body(json)
160
+ json = json.dup
161
+ before_parse_body(json)
162
+ parse_json(json)
163
+ end
164
+
165
+ def add_token_to_request
166
+ return if @_request.include?('token=')
167
+ if @_user
168
+ token = @_user.get(:token) || "token12345678-#{@_user.get(:login)}"
169
+ @_request = if @_request.include?('?')
170
+ @_request + "&token=#{token}"
171
+ else
172
+ @_request + "?token=#{token}"
173
+ end
174
+ end
175
+ end
176
+
177
+ def add_token_to_path(path,token)
178
+ return unless token
179
+ if path.include?('?')
180
+ path + "&token=" + token
181
+ else
182
+ path + "?token=" + token
183
+ end
184
+ end
185
+
186
+ def rack_request_headers
187
+ env = {}
188
+ env['REMOTE_ADDR'] = '10.0.0.1'
189
+ env['HTTP_COOKIE'] = cookies.join('; ')
190
+ env["HTTP_AUTHORIZATION"] = @_auth if @_auth
191
+ env["HTTP_HOST"] = @_host if @_host
192
+ env
193
+ end
194
+
195
+ def request
196
+ RestWorld.request
197
+ end
198
+
199
+ def set_host(name)
200
+ @_host = name
201
+ end
202
+
203
+ def set_auth_headers(user)
204
+ raise "invalid user name:#{user}" unless u = users[user]
205
+ pw = u.get(:pw)
206
+ raise "iuser name:#{user} has no password!" unless pw
207
+ str = user + ":" + pw
208
+ str = Base64.encode64(str)
209
+ str = "Basic " + str
210
+ #Rack::MockRequest::DEFAULT_ENV["HTTP_AUTHORIZATION"] = str
211
+ @_auth = str
212
+ end
213
+
214
+ # save the response for furthur enquiries and store any cookies.
215
+ def handle_response(raw_response)
216
+ @_auth = nil
217
+ @_response = Response.new(raw_response)
218
+ # add cookies to the cookie jar.
219
+ #unless @_current_user=="guest"
220
+ if cookie = @_response.header["Set-Cookie"]
221
+ parts = cookie.split(';')
222
+ cookies << parts[0].strip
223
+ end
224
+ #end
225
+ end
226
+
227
+ def parse_user(user)
228
+ user.split(' ')[-1]
229
+ end
230
+
231
+ def send_request(verb, username, path, json)
232
+ username = parse_user(username)
233
+ @_verb = verb
234
+ @_body = json && parse_body(json)
235
+ @_request = parse_path(path)
236
+ @_current_user = username
237
+
238
+ if username == 'guest'
239
+ @_user = nil
240
+ else
241
+ @_user = users[username]
242
+ raise "user :#{username} has not been initialized" unless @_user
243
+
244
+ pw = @_user.get(:pw)
245
+ add_token_to_request
246
+ set_auth_headers(username)
247
+ end
248
+ case verb
249
+ when 'GET'
250
+ handle_response(request.get(@_request, rack_request_headers))
251
+ when 'OPTIONS'
252
+ handle_response(request.options(@_request, rack_request_headers))
253
+ when 'POST'
254
+ handle_response(request.post(@_request, rack_request_headers.merge(input: @_body)))
255
+ when 'PUT'
256
+ handle_response(request.put(@_request, rack_request_headers.merge(input: @_body)))
257
+ when 'DELETE'
258
+ handle_response(request.delete(@_request, rack_request_headers.merge(input: @_body)))
259
+ end
260
+ end
261
+
262
+ # a hook that is called before creating a user
263
+ def before_user_create(user, hash); end
264
+
265
+ # a hook that is called before creating a user
266
+ def after_user_create(user, hash); end
267
+ end
268
+
269
+
270
+
271
+ World do
272
+ RestWorld.new
273
+ end