screenbeacon 0.1.0
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 +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +29 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.rdoc +44 -0
- data/Rakefile +7 -0
- data/VERSION +1 -0
- data/bin/screenbeacon-console +7 -0
- data/gemfiles/default-with-activesupport.gemfile +10 -0
- data/gemfiles/json.gemfile +12 -0
- data/gemfiles/yajl.gemfile +12 -0
- data/lib/data/ca-certificates.crt +5165 -0
- data/lib/screenbeacon/alert.rb +32 -0
- data/lib/screenbeacon/api_operations/create.rb +16 -0
- data/lib/screenbeacon/api_operations/delete.rb +11 -0
- data/lib/screenbeacon/api_operations/list.rb +17 -0
- data/lib/screenbeacon/api_operations/request.rb +42 -0
- data/lib/screenbeacon/api_operations/update.rb +17 -0
- data/lib/screenbeacon/api_resource.rb +35 -0
- data/lib/screenbeacon/errors/api_connection_error.rb +4 -0
- data/lib/screenbeacon/errors/api_error.rb +4 -0
- data/lib/screenbeacon/errors/authentication_error.rb +4 -0
- data/lib/screenbeacon/errors/invalid_request_error.rb +10 -0
- data/lib/screenbeacon/errors/screenbeacon_error.rb +20 -0
- data/lib/screenbeacon/project.rb +13 -0
- data/lib/screenbeacon/screenbeacon_object.rb +263 -0
- data/lib/screenbeacon/test.rb +8 -0
- data/lib/screenbeacon/util.rb +130 -0
- data/lib/screenbeacon/version.rb +3 -0
- data/lib/screenbeacon.rb +305 -0
- data/screenbeacon.gemspec +27 -0
- data/test/screenbeacon/alert_test.rb +14 -0
- data/test/screenbeacon/api_resource_test.rb +82 -0
- data/test/screenbeacon/project_test.rb +36 -0
- data/test/screenbeacon/screenbeacon_object_test.rb +28 -0
- data/test/screenbeacon/test_test.rb +36 -0
- data/test/screenbeacon/util_test.rb +34 -0
- data/test/test_data.rb +147 -0
- data/test/test_helper.rb +43 -0
- metadata +176 -0
data/lib/screenbeacon.rb
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
# Screenbeacon Ruby bindings
|
2
|
+
# API spec at https://screenbeacon.readme.io
|
3
|
+
require 'cgi'
|
4
|
+
require 'openssl'
|
5
|
+
require 'rbconfig'
|
6
|
+
require 'set'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
require 'rest-client'
|
10
|
+
require 'json'
|
11
|
+
|
12
|
+
# Version
|
13
|
+
require 'screenbeacon/version'
|
14
|
+
|
15
|
+
# API operations
|
16
|
+
require 'screenbeacon/api_operations/create'
|
17
|
+
require 'screenbeacon/api_operations/update'
|
18
|
+
require 'screenbeacon/api_operations/delete'
|
19
|
+
require 'screenbeacon/api_operations/list'
|
20
|
+
require 'screenbeacon/api_operations/request'
|
21
|
+
|
22
|
+
# Resources
|
23
|
+
require 'screenbeacon/util'
|
24
|
+
require 'screenbeacon/screenbeacon_object'
|
25
|
+
require 'screenbeacon/api_resource'
|
26
|
+
require 'screenbeacon/project'
|
27
|
+
require 'screenbeacon/test'
|
28
|
+
require 'screenbeacon/alert'
|
29
|
+
|
30
|
+
# Errors
|
31
|
+
require 'screenbeacon/errors/screenbeacon_error'
|
32
|
+
require 'screenbeacon/errors/api_error'
|
33
|
+
require 'screenbeacon/errors/api_connection_error'
|
34
|
+
require 'screenbeacon/errors/invalid_request_error'
|
35
|
+
require 'screenbeacon/errors/authentication_error'
|
36
|
+
|
37
|
+
module Screenbeacon
|
38
|
+
DEFAULT_CA_BUNDLE_PATH = File.dirname(__FILE__) + '/data/ca-certificates.crt'
|
39
|
+
@api_base = 'https://api.screenbeacon.com'
|
40
|
+
|
41
|
+
@ssl_bundle_path = DEFAULT_CA_BUNDLE_PATH
|
42
|
+
@verify_ssl_certs = true
|
43
|
+
|
44
|
+
|
45
|
+
class << self
|
46
|
+
attr_accessor :api_id, :api_token, :api_base, :verify_ssl_certs, :api_version #, :connect_base, :uploads_base
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.api_url(url='', api_base_url=nil)
|
50
|
+
(api_base_url || @api_base) + url
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.request(method, url, api_id, api_token, params={}, headers={}, api_base_url=nil)
|
54
|
+
api_base_url = api_base_url || @api_base
|
55
|
+
|
56
|
+
unless api_id ||= @api_id
|
57
|
+
raise AuthenticationError.new('No API ID provided. ' \
|
58
|
+
'Set your API ID using "Screenbeacon.api_id = <API-ID>". ' \
|
59
|
+
'You can generate API ID from the Screenbeacon web interface. ' \
|
60
|
+
'See https://screenbeacon.com/dashboard/settings for details, or email support@screenbeacon.com ' \
|
61
|
+
'if you have any questions.')
|
62
|
+
end
|
63
|
+
|
64
|
+
unless api_token ||= @api_token
|
65
|
+
raise AuthenticationError.new('No API token provided. ' \
|
66
|
+
'Set your API token using "Screenbeacon.api_token = <API-TOKEN>". ' \
|
67
|
+
'You can generate API token from the Screenbeacon web interface. ' \
|
68
|
+
'See https://screenbeacon.com/dashboard/settings for details, or email support@screenbeacon.com ' \
|
69
|
+
'if you have any questions.')
|
70
|
+
end
|
71
|
+
|
72
|
+
if api_id =~ /\s/
|
73
|
+
raise AuthenticationError.new('Your API key is invalid, as it contains ' \
|
74
|
+
'whitespace. (HINT: You can double-check your API key from the ' \
|
75
|
+
'Screenbeacon web interface. See https://screenbeacon.com/dashboard/settings for details, or ' \
|
76
|
+
'email support@screenbeacon.com if you have any questions.)')
|
77
|
+
end
|
78
|
+
|
79
|
+
if api_token =~ /\s/
|
80
|
+
raise AuthenticationError.new('Your API token is invalid, as it contains ' \
|
81
|
+
'whitespace. (HINT: You can double-check your API token from the ' \
|
82
|
+
'Screenbeacon web interface. See https://screenbeacon.com/dashboard/settings for details, or ' \
|
83
|
+
'email support@screenbeacon.com if you have any questions.)')
|
84
|
+
end
|
85
|
+
|
86
|
+
if verify_ssl_certs
|
87
|
+
request_opts = {:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
88
|
+
:ssl_ca_file => @ssl_bundle_path}
|
89
|
+
else
|
90
|
+
request_opts = {:verify_ssl => false}
|
91
|
+
unless @verify_ssl_warned
|
92
|
+
@verify_ssl_warned = true
|
93
|
+
$stderr.puts("WARNING: Running without SSL cert verification. " \
|
94
|
+
"You should never do this in production. " \
|
95
|
+
"Execute 'Screenbeacon.verify_ssl_certs = true' to enable verification.")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
params = Util.objects_to_ids(params)
|
100
|
+
url = api_url(url, api_base_url)
|
101
|
+
|
102
|
+
case method.to_s.downcase.to_sym
|
103
|
+
when :get, :head, :delete
|
104
|
+
# Make params into GET parameters
|
105
|
+
url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
|
106
|
+
payload = nil
|
107
|
+
else
|
108
|
+
if headers[:content_type] && headers[:content_type] == "multipart/form-data"
|
109
|
+
payload = params
|
110
|
+
else
|
111
|
+
payload = uri_encode(params)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
request_opts.update(:headers => request_headers(api_id, api_token).update(headers),
|
116
|
+
:method => method, :open_timeout => 30,
|
117
|
+
:payload => payload, :url => url, :timeout => 80)
|
118
|
+
|
119
|
+
begin
|
120
|
+
response = execute_request(request_opts)
|
121
|
+
rescue SocketError => e
|
122
|
+
handle_restclient_error(e, api_base_url)
|
123
|
+
rescue NoMethodError => e
|
124
|
+
# Work around RestClient bug
|
125
|
+
if e.message =~ /\WRequestFailed\W/
|
126
|
+
e = APIConnectionError.new('Unexpected HTTP response code')
|
127
|
+
handle_restclient_error(e, api_base_url)
|
128
|
+
else
|
129
|
+
raise
|
130
|
+
end
|
131
|
+
rescue RestClient::ExceptionWithResponse => e
|
132
|
+
if rcode = e.http_code and rbody = e.http_body
|
133
|
+
handle_api_error(rcode, rbody)
|
134
|
+
else
|
135
|
+
handle_restclient_error(e, api_base_url)
|
136
|
+
end
|
137
|
+
rescue RestClient::Exception, Errno::ECONNREFUSED => e
|
138
|
+
handle_restclient_error(e, api_base_url)
|
139
|
+
end
|
140
|
+
|
141
|
+
[parse(response), api_id, api_token]
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def self.user_agent
|
147
|
+
@uname ||= get_uname
|
148
|
+
lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
149
|
+
|
150
|
+
{
|
151
|
+
:bindings_version => Screenbeacon::VERSION,
|
152
|
+
:lang => 'ruby',
|
153
|
+
:lang_version => lang_version,
|
154
|
+
:platform => RUBY_PLATFORM,
|
155
|
+
:engine => defined?(RUBY_ENGINE) ? RUBY_ENGINE : '',
|
156
|
+
:publisher => 'screenbeacon',
|
157
|
+
:uname => @uname,
|
158
|
+
:hostname => Socket.gethostname,
|
159
|
+
}
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.get_uname
|
164
|
+
if File.exist?('/proc/version')
|
165
|
+
File.read('/proc/version').strip
|
166
|
+
else
|
167
|
+
case RbConfig::CONFIG['host_os']
|
168
|
+
when /linux|darwin|bsd|sunos|solaris|cygwin/i
|
169
|
+
_uname_uname
|
170
|
+
when /mswin|mingw/i
|
171
|
+
_uname_ver
|
172
|
+
else
|
173
|
+
"unknown platform"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self._uname_uname
|
179
|
+
(`uname -a 2>/dev/null` || '').strip
|
180
|
+
rescue Errno::ENOMEM # couldn't create subprocess
|
181
|
+
"uname lookup failed"
|
182
|
+
end
|
183
|
+
|
184
|
+
def self._uname_ver
|
185
|
+
(`ver` || '').strip
|
186
|
+
rescue Errno::ENOMEM # couldn't create subprocess
|
187
|
+
"uname lookup failed"
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
def self.uri_encode(params)
|
192
|
+
Util.flatten_params(params).
|
193
|
+
map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.request_headers(api_id, api_token)
|
197
|
+
headers = {
|
198
|
+
:user_agent => "Screenbeacon/v1 RubyBindings/#{Screenbeacon::VERSION}",
|
199
|
+
# :authorization => "Bearer #{api_id}",
|
200
|
+
:content_type => 'application/x-www-form-urlencoded'
|
201
|
+
}
|
202
|
+
|
203
|
+
headers['Screenbeacon-Version'] = api_version if api_version
|
204
|
+
headers['X-API-ID'] = api_id
|
205
|
+
headers['X-API-TOKEN'] = api_token
|
206
|
+
|
207
|
+
begin
|
208
|
+
headers.update(:x_screenbeacon_client_user_agent => JSON.generate(user_agent))
|
209
|
+
rescue => e
|
210
|
+
headers.update(:x_screenbeacon_client_raw_user_agent => user_agent.inspect,
|
211
|
+
:error => "#{e} (#{e.class})")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.execute_request(opts)
|
216
|
+
RestClient::Request.execute(opts)
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.parse(response)
|
220
|
+
begin
|
221
|
+
# Would use :symbolize_names => true, but apparently there is
|
222
|
+
# some library out there that makes symbolize_names not work.
|
223
|
+
response = JSON.parse(response.body)
|
224
|
+
rescue JSON::ParserError
|
225
|
+
raise general_api_error(response.code, response.body)
|
226
|
+
end
|
227
|
+
|
228
|
+
Util.symbolize_names(response)
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.general_api_error(rcode, rbody)
|
232
|
+
APIError.new("Invalid response object from API: #{rbody.inspect} " +
|
233
|
+
"(HTTP response code was #{rcode})", rcode, rbody)
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.handle_api_error(rcode, rbody)
|
237
|
+
begin
|
238
|
+
error_obj = JSON.parse(rbody)
|
239
|
+
error_obj = Util.symbolize_names(error_obj)
|
240
|
+
error = error_obj[:error] or raise ScreenbeaconError.new # escape from parsing
|
241
|
+
|
242
|
+
rescue JSON::ParserError, ScreenbeaconError
|
243
|
+
raise general_api_error(rcode, rbody)
|
244
|
+
end
|
245
|
+
|
246
|
+
case rcode
|
247
|
+
when 400, 404
|
248
|
+
raise invalid_request_error error, rcode, rbody, error_obj
|
249
|
+
when 401
|
250
|
+
raise authentication_error error, rcode, rbody, error_obj
|
251
|
+
when 402
|
252
|
+
raise card_error error, rcode, rbody, error_obj
|
253
|
+
else
|
254
|
+
raise api_error error, rcode, rbody, error_obj
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.invalid_request_error(error, rcode, rbody, error_obj)
|
260
|
+
# We're not returning a params as part of the error for now, so set it to nil.
|
261
|
+
InvalidRequestError.new(error, nil, rcode, rbody, error_obj)
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.authentication_error(error, rcode, rbody, error_obj)
|
265
|
+
AuthenticationError.new(error, rcode, rbody, error_obj)
|
266
|
+
end
|
267
|
+
|
268
|
+
def self.api_error(error, rcode, rbody, error_obj)
|
269
|
+
APIError.new(error, rcode, rbody, error_obj)
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.handle_restclient_error(e, api_base_url=nil)
|
273
|
+
api_base_url = @api_base unless api_base_url
|
274
|
+
connection_message = "Please check your internet connection and try again. " \
|
275
|
+
"If this problem persists, you should check Screenbeacon's service status at " \
|
276
|
+
"https://twitter.com/screenbeacon, or let us know at support@screenbeacon.com."
|
277
|
+
|
278
|
+
case e
|
279
|
+
when RestClient::RequestTimeout
|
280
|
+
message = "Could not connect to Screenbeacon (#{api_base_url}). #{connection_message}"
|
281
|
+
|
282
|
+
when RestClient::ServerBrokeConnection
|
283
|
+
message = "The connection to the server (#{api_base_url}) broke before the " \
|
284
|
+
"request completed. #{connection_message}"
|
285
|
+
|
286
|
+
when RestClient::SSLCertificateNotVerified
|
287
|
+
message = "Could not verify Screenbeacon's SSL certificate. " \
|
288
|
+
"Please make sure that your network is not intercepting certificates. " \
|
289
|
+
"(Try going to https://api.screenbeacon.com in your browser.) " \
|
290
|
+
"If this problem persists, let us know at support@screenbeacon.com."
|
291
|
+
|
292
|
+
when SocketError
|
293
|
+
message = "Unexpected error communicating when trying to connect to Screenbeacon. " \
|
294
|
+
"You may be seeing this message because your DNS is not working. " \
|
295
|
+
"To check, try running 'host screenbeacon.com' from the command line."
|
296
|
+
|
297
|
+
else
|
298
|
+
message = "Unexpected error communicating with Screenbeacon. " \
|
299
|
+
"If this problem persists, let us know at support@screenbeacon.com."
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
|
304
|
+
end
|
305
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
|
+
|
3
|
+
require 'screenbeacon/version'
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = 'screenbeacon'
|
7
|
+
s.version = Screenbeacon::VERSION
|
8
|
+
s.summary = 'Ruby bindings for the Screenbeacon API'
|
9
|
+
s.description = 'Screenbeacon is a visual design testing service.'
|
10
|
+
s.authors = ['Jordan Humphreys']
|
11
|
+
s.email = ['jordan@screenbeacon.com']
|
12
|
+
s.homepage = 'https://screenbeacon.readme.io'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.add_dependency('rest-client', '~> 1.4')
|
16
|
+
s.add_dependency('json', '~> 1.8.1')
|
17
|
+
|
18
|
+
s.add_development_dependency('mocha', '~> 0.13.2')
|
19
|
+
s.add_development_dependency('shoulda', '~> 3.4.0')
|
20
|
+
s.add_development_dependency('test-unit')
|
21
|
+
s.add_development_dependency('rake')
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ['lib']
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Screenbeacon
|
4
|
+
class AlertTest < ::Test::Unit::TestCase
|
5
|
+
should "alerts should be listable" do
|
6
|
+
@mock.expects(:get).once.returns(test_response(test_alert_array))
|
7
|
+
c = Screenbeacon::Alert.all
|
8
|
+
assert c.kind_of? Array
|
9
|
+
# TODO: Should be a Screenbeacon::Alert
|
10
|
+
assert c[0].kind_of? Screenbeacon::ScreenbeaconObject
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require File.expand_path('../../test_helper', __FILE__)
|
3
|
+
|
4
|
+
module Screenbeacon
|
5
|
+
class ApiResourceTest < ::Test::Unit::TestCase
|
6
|
+
should "creating a new APIResource should not fetch over the network" do
|
7
|
+
@mock.expects(:get).never
|
8
|
+
Screenbeacon::Project.new("someid")
|
9
|
+
end
|
10
|
+
|
11
|
+
should "creating a new APIResource from a hash should not fetch over the network" do
|
12
|
+
@mock.expects(:get).never
|
13
|
+
Screenbeacon::Project.construct_from({
|
14
|
+
:id => "somecustomer",
|
15
|
+
:object => "customer"
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
should "setting an attribute should not cause a network request" do
|
20
|
+
@mock.expects(:get).never
|
21
|
+
@mock.expects(:post).never
|
22
|
+
c = Screenbeacon::Project.new("test_project");
|
23
|
+
c.card = {:id => "somecard", :object => "card"}
|
24
|
+
end
|
25
|
+
|
26
|
+
should "accessing id should not issue a fetch" do
|
27
|
+
@mock.expects(:get).never
|
28
|
+
c = Screenbeacon::Project.new("test_project")
|
29
|
+
c.id
|
30
|
+
end
|
31
|
+
|
32
|
+
should "not specifying api credentials should raise an exception" do
|
33
|
+
Screenbeacon.api_id = nil
|
34
|
+
Screenbeacon.api_token = nil
|
35
|
+
assert_raises Screenbeacon::AuthenticationError do
|
36
|
+
Screenbeacon::Project.new("test_project").refresh
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "using a nil api key should raise an exception" do
|
41
|
+
assert_raises TypeError do
|
42
|
+
Screenbeacon::Project.all({}, nil)
|
43
|
+
end
|
44
|
+
assert_raises TypeError do
|
45
|
+
Screenbeacon::Project.all({}, { :api_id => nil, :api_token => nil })
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
should "specifying api credentials containing whitespace should raise an exception" do
|
50
|
+
Screenbeacon.api_id = "id "
|
51
|
+
Screenbeacon.api_token = " token"
|
52
|
+
assert_raises Screenbeacon::AuthenticationError do
|
53
|
+
Screenbeacon::Project.new("test_project").refresh
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
should "specifying invalid api credentials should raise an exception" do
|
58
|
+
Screenbeacon.api_id = "invalid"
|
59
|
+
Screenbeacon.api_token = "token"
|
60
|
+
response = test_response(test_invalid_api_id_error, 401)
|
61
|
+
assert_raises Screenbeacon::AuthenticationError do
|
62
|
+
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
|
63
|
+
Screenbeacon::Project.retrieve("failing_project")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
should "AuthenticationErrors should have an http status, http body, and JSON body" do
|
68
|
+
Screenbeacon.api_id = "invalid"
|
69
|
+
Screenbeacon.api_token = "token"
|
70
|
+
response = test_response(test_invalid_api_id_error, 401)
|
71
|
+
begin
|
72
|
+
@mock.expects(:get).once.raises(RestClient::ExceptionWithResponse.new(response, 401))
|
73
|
+
Screenbeacon::Project.retrieve("failing_project")
|
74
|
+
rescue Screenbeacon::AuthenticationError => e
|
75
|
+
assert_equal(401, e.http_status)
|
76
|
+
assert_equal(true, !!e.http_body)
|
77
|
+
assert_equal(true, !!e.json_body[:error])
|
78
|
+
assert_equal(test_invalid_api_id_error[:error], e.json_body[:error])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Screenbeacon
|
4
|
+
class ProjectTest < ::Test::Unit::TestCase
|
5
|
+
should "projects should be listable" do
|
6
|
+
@mock.expects(:get).once.returns(test_response(test_project_array))
|
7
|
+
c = Screenbeacon::Project.all
|
8
|
+
assert c.kind_of? Array
|
9
|
+
assert c[0].kind_of? Screenbeacon::ScreenbeaconObject
|
10
|
+
end
|
11
|
+
|
12
|
+
should "project should be deletable" do
|
13
|
+
@mock.expects(:delete).once.returns(test_response(test_project({:deleted => true})))
|
14
|
+
c = Screenbeacon::Project.new("test_project")
|
15
|
+
c.delete
|
16
|
+
assert c.deleted
|
17
|
+
end
|
18
|
+
|
19
|
+
# should "projects should be updateable" do
|
20
|
+
# @mock.expects(:get).once.returns(test_response(test_project({:name => "fubu"})))
|
21
|
+
# @mock.expects(:post).once.returns(test_response(test_project({:name => "barbu"})))
|
22
|
+
# c = Screenbeacon::Project.new(test_project({:name => "fubu"})).refresh
|
23
|
+
# assert_equal "fubu", c.name
|
24
|
+
# c.name = "barbu"
|
25
|
+
# c.save
|
26
|
+
# assert_equal "barbu", c.name
|
27
|
+
# end
|
28
|
+
|
29
|
+
should "create should return a new project" do
|
30
|
+
@mock.expects(:post).once.returns(test_response(test_project))
|
31
|
+
c = Screenbeacon::Project.create
|
32
|
+
assert_equal "Screenbeacon", c.name
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Screenbeacon
|
4
|
+
class ScreenbeaconObjectTest < ::Test::Unit::TestCase
|
5
|
+
should "implement #respond_to correctly" do
|
6
|
+
obj = Screenbeacon::ScreenbeaconObject.construct_from({ :id => 1, :foo => 'bar' })
|
7
|
+
assert obj.respond_to?(:id)
|
8
|
+
assert obj.respond_to?(:foo)
|
9
|
+
assert !obj.respond_to?(:baz)
|
10
|
+
end
|
11
|
+
|
12
|
+
should "marshal a screenbeacon object correctly" do
|
13
|
+
obj = Screenbeacon::ScreenbeaconObject.construct_from({ :id => 1, :name => 'Screenbeacon' }, {:api_id => 'apiid', :api_token => 'apitoken'})
|
14
|
+
m = Marshal.load(Marshal.dump(obj))
|
15
|
+
assert_equal 1, m.id
|
16
|
+
assert_equal 'Screenbeacon', m.name
|
17
|
+
expected_hash = {:api_id => 'apiid', :api_token => 'apitoken'}
|
18
|
+
assert_equal expected_hash, m.instance_variable_get('@opts')
|
19
|
+
end
|
20
|
+
|
21
|
+
should "recursively call to_hash on its values" do
|
22
|
+
nested = Screenbeacon::ScreenbeaconObject.construct_from({ :id => 7, :foo => 'bar' })
|
23
|
+
obj = Screenbeacon::ScreenbeaconObject.construct_from({ :id => 1, :nested => nested })
|
24
|
+
expected_hash = { :id => 1, :nested => { :id => 7, :foo => 'bar' } }
|
25
|
+
assert_equal expected_hash, obj.to_hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Screenbeacon
|
4
|
+
class TestTest < ::Test::Unit::TestCase
|
5
|
+
should "tests should be listable" do
|
6
|
+
@mock.expects(:get).once.returns(test_response(test_test_array))
|
7
|
+
c = Screenbeacon::Test.all
|
8
|
+
assert c.kind_of? Array
|
9
|
+
assert c[0].kind_of? Screenbeacon::ScreenbeaconObject
|
10
|
+
end
|
11
|
+
|
12
|
+
should "test should be deletable" do
|
13
|
+
@mock.expects(:delete).once.returns(test_response(test_test({:deleted => true})))
|
14
|
+
c = Screenbeacon::Test.new("test_test")
|
15
|
+
c.delete
|
16
|
+
assert c.deleted
|
17
|
+
end
|
18
|
+
|
19
|
+
# should "tests should be updateable" do
|
20
|
+
# @mock.expects(:get).once.returns(test_response(test_test({:name => "fubu"})))
|
21
|
+
# @mock.expects(:post).once.returns(test_response(test_test({:name => "barbu"})))
|
22
|
+
# c = Screenbeacon::Test.new("test_test").refresh
|
23
|
+
# assert_equal "fubu", c.name
|
24
|
+
# c.name = "barbu"
|
25
|
+
# c.save
|
26
|
+
# assert_equal "barbu", c.name
|
27
|
+
# end
|
28
|
+
|
29
|
+
should "create should return a new test" do
|
30
|
+
@mock.expects(:post).once.returns(test_response(test_test({:name => "Screenbeacon"})))
|
31
|
+
c = Screenbeacon::Test.create
|
32
|
+
assert_equal "Screenbeacon", c.name
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Screenbeacon
|
4
|
+
class UtilTest < ::Test::Unit::TestCase
|
5
|
+
should "symbolize_names should convert names to symbols" do
|
6
|
+
start = {
|
7
|
+
'foo' => 'bar',
|
8
|
+
'array' => [{ 'foo' => 'bar' }],
|
9
|
+
'nested' => {
|
10
|
+
1 => 2,
|
11
|
+
:symbol => 9,
|
12
|
+
'string' => nil
|
13
|
+
}
|
14
|
+
}
|
15
|
+
finish = {
|
16
|
+
:foo => 'bar',
|
17
|
+
:array => [{ :foo => 'bar' }],
|
18
|
+
:nested => {
|
19
|
+
1 => 2,
|
20
|
+
:symbol => 9,
|
21
|
+
:string => nil
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
symbolized = Screenbeacon::Util.symbolize_names(start)
|
26
|
+
assert_equal(finish, symbolized)
|
27
|
+
end
|
28
|
+
|
29
|
+
should "normalize_opts should reject nil keys" do
|
30
|
+
assert_raise { Screenbeacon::Util.normalize_opts(nil) }
|
31
|
+
assert_raise { Screenbeacon::Util.normalize_opts(:api_id => nil, :api_token => nil) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|