slayer-rpx_now 0.6.24
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.
- data/.gitignore +6 -0
- data/CHANGELOG +38 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +28 -0
- data/MIGRATION +9 -0
- data/Rakefile +22 -0
- data/Readme.md +165 -0
- data/VERSION +1 -0
- data/certs/ssl_cert.pem +3154 -0
- data/init.rb +2 -0
- data/lib/rpx_now/api.rb +75 -0
- data/lib/rpx_now/contacts_collection.rb +20 -0
- data/lib/rpx_now/user_integration.rb +9 -0
- data/lib/rpx_now/user_proxy.rb +19 -0
- data/lib/rpx_now.rb +201 -0
- data/rpx_now.gemspec +63 -0
- data/spec/fixtures/get_contacts_response.json +58 -0
- data/spec/integration/mapping_spec.rb +40 -0
- data/spec/rpx_now/api_spec.rb +50 -0
- data/spec/rpx_now/contacts_collection_spec.rb +32 -0
- data/spec/rpx_now/user_proxy_spec.rb +33 -0
- data/spec/rpx_now_spec.rb +414 -0
- data/spec/spec_helper.rb +16 -0
- metadata +107 -0
data/init.rb
ADDED
data/lib/rpx_now/api.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module RPXNow
|
6
|
+
# low-level interaction with rpxnow.com api
|
7
|
+
# - send requests
|
8
|
+
# - parse response
|
9
|
+
# - handle server errors
|
10
|
+
class Api
|
11
|
+
SSL_CERT = File.join(File.dirname(__FILE__), '..', '..', 'certs', 'ssl_cert.pem')
|
12
|
+
|
13
|
+
def self.call(method, data)
|
14
|
+
data = data.dup
|
15
|
+
version = RPXNow.extract_version(data)
|
16
|
+
data.delete(:api_version)
|
17
|
+
|
18
|
+
path = "/api/v#{version}/#{method}"
|
19
|
+
response = request(path, {:apiKey => RPXNow.api_key}.merge(data))
|
20
|
+
parse_response(response)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.host(subdomain=nil)
|
24
|
+
if subdomain
|
25
|
+
"https://#{subdomain}.#{RPXNow.domain}"
|
26
|
+
else
|
27
|
+
"https://#{RPXNow.domain}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def self.request(path, data)
|
34
|
+
client.request(request_object(path, data))
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.request_object(path, data)
|
38
|
+
request = Net::HTTP::Post.new(path)
|
39
|
+
request.form_data = stringify_keys(data)
|
40
|
+
request
|
41
|
+
end
|
42
|
+
|
43
|
+
# symbol keys -> string keys
|
44
|
+
# because of ruby 1.9.x bug in Net::HTTP
|
45
|
+
# http://redmine.ruby-lang.org/issues/show/1351
|
46
|
+
def self.stringify_keys(hash)
|
47
|
+
hash.map{|k,v| [k.to_s,v]}
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.client
|
51
|
+
client = Net::HTTP.new(RPXNow.domain, 443)
|
52
|
+
client.use_ssl = true
|
53
|
+
client.ca_file = SSL_CERT
|
54
|
+
client.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
55
|
+
client.verify_depth = 5
|
56
|
+
client
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parse_response(response)
|
60
|
+
if response.code.to_i >= 400
|
61
|
+
raise ServiceUnavailableError, "The RPX service is temporarily unavailable. (4XX)"
|
62
|
+
else
|
63
|
+
result = JSON.parse(response.body)
|
64
|
+
return result unless result['err']
|
65
|
+
|
66
|
+
code = result['err']['code']
|
67
|
+
if code == -1
|
68
|
+
raise ServiceUnavailableError, "The RPX service is temporarily unavailable."
|
69
|
+
else
|
70
|
+
raise ApiError, "Got error: #{result['err']['msg']} (code: #{code}), HTTP status: #{response.code}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RPXNow
|
2
|
+
# Makes returned contacts feel like a array
|
3
|
+
class ContactsCollection < Array
|
4
|
+
def initialize(list)
|
5
|
+
@raw = list
|
6
|
+
@additional_info = list.reject{|k,v|k=='entry'}
|
7
|
+
list['entry'].each{|item| self << parse_data(item)}
|
8
|
+
end
|
9
|
+
|
10
|
+
def additional_info;@additional_info;end
|
11
|
+
def raw;@raw;end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def parse_data(entry)
|
16
|
+
entry['emails'] = (entry['emails'] ? entry['emails'].map{|email| email['value']} : [])
|
17
|
+
entry
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RPXNow
|
2
|
+
class UserProxy
|
3
|
+
def initialize(id)
|
4
|
+
@id = id
|
5
|
+
end
|
6
|
+
|
7
|
+
def identifiers
|
8
|
+
RPXNow.mappings(@id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def map(identifier)
|
12
|
+
RPXNow.map(identifier, @id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def unmap(identifier)
|
16
|
+
RPXNow.unmap(identifier, @id)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/rpx_now.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'rpx_now/api'
|
2
|
+
require 'rpx_now/contacts_collection'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module RPXNow
|
6
|
+
extend self
|
7
|
+
|
8
|
+
attr_accessor :api_key
|
9
|
+
attr_accessor :api_version
|
10
|
+
attr_accessor :domain
|
11
|
+
|
12
|
+
self.api_version = 2
|
13
|
+
self.domain = 'rpxnow.com'
|
14
|
+
|
15
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
16
|
+
|
17
|
+
# retrieve the users data
|
18
|
+
# - cleaned Hash
|
19
|
+
# - complete/unclean response when block was given user_data{|response| ...; return hash }
|
20
|
+
# - nil when token was invalid / data was not found
|
21
|
+
def user_data(token, options={})
|
22
|
+
options = options.dup
|
23
|
+
return_raw = options.delete(:raw_response)
|
24
|
+
|
25
|
+
data = begin
|
26
|
+
auth_info(token, options)
|
27
|
+
rescue ServerError
|
28
|
+
return nil if $!.to_s=~/Data not found/
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
|
32
|
+
result = (block_given? ? yield(data) : (return_raw ? data : parse_user_data(data, options)))
|
33
|
+
with_indifferent_access(result)
|
34
|
+
end
|
35
|
+
|
36
|
+
# same data as user_data, but without any kind of post-processing
|
37
|
+
def auth_info(token, options={})
|
38
|
+
data = Api.call("auth_info", options.merge(:token => token))
|
39
|
+
with_indifferent_access(data)
|
40
|
+
end
|
41
|
+
|
42
|
+
# same as for auth_info if Offline Profile Access is enabled,
|
43
|
+
# but can be called at any time and does not need a token / does not expire
|
44
|
+
def get_user_data(identifier, options={})
|
45
|
+
data = Api.call("get_user_data", options.merge(:identifier => identifier))
|
46
|
+
with_indifferent_access(data)
|
47
|
+
end
|
48
|
+
|
49
|
+
# set the users status
|
50
|
+
def set_status(identifier, status, options={})
|
51
|
+
options = options.merge(:identifier => identifier, :status => status)
|
52
|
+
Api.call("set_status", options)
|
53
|
+
rescue ServerError
|
54
|
+
return nil if $!.to_s=~/Data not found/
|
55
|
+
raise
|
56
|
+
end
|
57
|
+
|
58
|
+
# Post an activity update to the user's activity stream.
|
59
|
+
# See more: https://rpxnow.com/docs#api_activity
|
60
|
+
def activity(identifier, activity_options, options={})
|
61
|
+
options = options.merge(:identifier => identifier, :activity => activity_options.to_json)
|
62
|
+
Api.call("activity", options)
|
63
|
+
end
|
64
|
+
|
65
|
+
# maps an identifier to an primary-key (e.g. user.id)
|
66
|
+
def map(identifier, primary_key, options={})
|
67
|
+
Api.call("map", options.merge(:identifier => identifier, :primaryKey => primary_key))
|
68
|
+
end
|
69
|
+
|
70
|
+
# un-maps an identifier to an primary-key (e.g. user.id)
|
71
|
+
def unmap(identifier, primary_key, options={})
|
72
|
+
Api.call("unmap", options.merge(:identifier => identifier, :primaryKey => primary_key))
|
73
|
+
end
|
74
|
+
|
75
|
+
# returns an array of identifiers which are mapped to one of your primary-keys (e.g. user.id)
|
76
|
+
def mappings(primary_key, options={})
|
77
|
+
Api.call("mappings", options.merge(:primaryKey => primary_key))['identifiers']
|
78
|
+
end
|
79
|
+
|
80
|
+
def all_mappings(options={})
|
81
|
+
Api.call("all_mappings", options)['mappings']
|
82
|
+
end
|
83
|
+
|
84
|
+
def contacts(identifier, options={})
|
85
|
+
data = Api.call("get_contacts", options.merge(:identifier => identifier))
|
86
|
+
RPXNow::ContactsCollection.new(data['response'])
|
87
|
+
end
|
88
|
+
alias get_contacts contacts
|
89
|
+
|
90
|
+
# embedded rpx login (via iframe)
|
91
|
+
# options: :width, :height, :language, :flags, :api_version, :default_provider
|
92
|
+
def embed_code(subdomain, url, options={})
|
93
|
+
options = {:width => '400', :height => '240'}.merge(options)
|
94
|
+
<<-EOF
|
95
|
+
<iframe src="#{Api.host(subdomain)}/openid/embed?#{embed_params(url, options)}"
|
96
|
+
scrolling="no" frameBorder="no" style="width:#{options[:width]}px;height:#{options[:height]}px;" id="rpx_now_embed" allowtransparency="allowtransparency">
|
97
|
+
</iframe>
|
98
|
+
EOF
|
99
|
+
end
|
100
|
+
|
101
|
+
# popup window for rpx login
|
102
|
+
# options: :language, :flags, :unobtrusive, :api_version, :default_provider, :html
|
103
|
+
def popup_code(text, subdomain, url, options = {})
|
104
|
+
if options[:unobtrusive]
|
105
|
+
unobtrusive_popup_code(text, subdomain, url, options)
|
106
|
+
else
|
107
|
+
obtrusive_popup_code(text, subdomain, url, options)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# javascript for popup
|
112
|
+
# only needed in combination with popup_code(x,y,z, :unobtrusive => true)
|
113
|
+
def popup_source(subdomain, url, options={})
|
114
|
+
<<-EOF
|
115
|
+
<script src="#{Api.host}/openid/v#{extract_version(options)}/widget" type="text/javascript"></script>
|
116
|
+
<script type="text/javascript">
|
117
|
+
//<![CDATA[
|
118
|
+
$(function () {
|
119
|
+
RPXNOW.token_url = '#{url}';
|
120
|
+
RPXNOW.realm = '#{subdomain}';
|
121
|
+
RPXNOW.overlay = true;
|
122
|
+
#{ "RPXNOW.language_preference = '#{options[:language]}';" if options[:language] }
|
123
|
+
#{ "RPXNOW.default_provider = '#{options[:default_provider]}';" if options[:default_provider] }
|
124
|
+
#{ "RPXNOW.flags = '#{options[:flags]}';" if options[:flags] }
|
125
|
+
});
|
126
|
+
//]]>
|
127
|
+
</script>
|
128
|
+
EOF
|
129
|
+
end
|
130
|
+
|
131
|
+
# url for unobtrusive popup window
|
132
|
+
# options: :language, :flags, :api_version, :default_provider
|
133
|
+
def popup_url(subdomain, url, options={})
|
134
|
+
"#{Api.host(subdomain)}/openid/v#{extract_version(options)}/signin?#{embed_params(url, options)}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def extract_version(options)
|
138
|
+
options[:api_version] || api_version
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def self.embed_params(url, options)
|
144
|
+
{
|
145
|
+
:token_url => CGI::escape( url ),
|
146
|
+
:language_preference => options[:language],
|
147
|
+
:flags => options[:flags],
|
148
|
+
:default_provider => options[:default_provider]
|
149
|
+
}.map{|k,v| "#{k}=#{v}" if v}.compact.join('&')
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.parse_user_data(response, options)
|
153
|
+
user_data = response['profile']
|
154
|
+
data = {}
|
155
|
+
data[:identifier] = user_data['identifier']
|
156
|
+
data[:email] = user_data['verifiedEmail'] || user_data['email']
|
157
|
+
data[:username] = user_data['preferredUsername'] || data[:email].to_s.sub(/@.*/,'')
|
158
|
+
data[:name] = user_data['displayName'] || data[:username]
|
159
|
+
data[:id] = user_data['primaryKey'] unless user_data['primaryKey'].to_s.empty?
|
160
|
+
|
161
|
+
additional = (options[:additional] || [])
|
162
|
+
additional << :extended if options[:extended]
|
163
|
+
additional.each do |key|
|
164
|
+
data[key] = case key
|
165
|
+
when :raw
|
166
|
+
warn "RPXNow :raw is deprecated, please use :raw_response + e.g. data['raw_response']['profile']['verifiedEmail']"
|
167
|
+
user_data
|
168
|
+
when :raw_response
|
169
|
+
response
|
170
|
+
when :extended
|
171
|
+
response.reject{|k,v| ['profile','stat'].include?(k) }
|
172
|
+
else
|
173
|
+
user_data[key.to_s]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
data
|
177
|
+
end
|
178
|
+
|
179
|
+
def unobtrusive_popup_code(text, subdomain, url, options={})
|
180
|
+
options = options.dup
|
181
|
+
html_options = options.delete(:html) || {}
|
182
|
+
html_options[:class] = "rpxnow #{html_options[:class]}".strip
|
183
|
+
html_options[:href] ||= popup_url(subdomain, url, options)
|
184
|
+
html_options = html_options.sort_by{|k,v|k.to_s}.map{|k,v| %{#{k}="#{v}"}}
|
185
|
+
|
186
|
+
%{<a #{html_options.join(' ')}>#{text}</a>}
|
187
|
+
end
|
188
|
+
|
189
|
+
def obtrusive_popup_code(text, subdomain, url, options = {})
|
190
|
+
unobtrusive_popup_code(text, subdomain, url, options) +
|
191
|
+
popup_source(subdomain, url, options)
|
192
|
+
end
|
193
|
+
|
194
|
+
def with_indifferent_access(hash)
|
195
|
+
hash.respond_to?(:with_indifferent_access) ? hash.with_indifferent_access : hash
|
196
|
+
end
|
197
|
+
|
198
|
+
class ServerError < RuntimeError; end #backwards compatibility / catch all
|
199
|
+
class ApiError < ServerError; end
|
200
|
+
class ServiceUnavailableError < ServerError; end
|
201
|
+
end
|
data/rpx_now.gemspec
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rpx_now}
|
8
|
+
s.version = "0.6.24"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2011-02-21}
|
13
|
+
s.email = %q{grosser.michael@gmail.com}
|
14
|
+
s.files = [
|
15
|
+
"CHANGELOG",
|
16
|
+
"Gemfile",
|
17
|
+
"Gemfile.lock",
|
18
|
+
"MIGRATION",
|
19
|
+
"Rakefile",
|
20
|
+
"Readme.md",
|
21
|
+
"VERSION",
|
22
|
+
"certs/ssl_cert.pem",
|
23
|
+
"init.rb",
|
24
|
+
"lib/rpx_now.rb",
|
25
|
+
"lib/rpx_now/api.rb",
|
26
|
+
"lib/rpx_now/contacts_collection.rb",
|
27
|
+
"lib/rpx_now/user_integration.rb",
|
28
|
+
"lib/rpx_now/user_proxy.rb",
|
29
|
+
"rpx_now.gemspec",
|
30
|
+
"spec/fixtures/get_contacts_response.json",
|
31
|
+
"spec/integration/mapping_spec.rb",
|
32
|
+
"spec/rpx_now/api_spec.rb",
|
33
|
+
"spec/rpx_now/contacts_collection_spec.rb",
|
34
|
+
"spec/rpx_now/user_proxy_spec.rb",
|
35
|
+
"spec/rpx_now_spec.rb",
|
36
|
+
"spec/spec_helper.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/grosser/rpx_now}
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.4.2}
|
41
|
+
s.summary = %q{Helper to simplify RPX Now user login/creation}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/integration/mapping_spec.rb",
|
44
|
+
"spec/rpx_now/api_spec.rb",
|
45
|
+
"spec/rpx_now/contacts_collection_spec.rb",
|
46
|
+
"spec/rpx_now/user_proxy_spec.rb",
|
47
|
+
"spec/rpx_now_spec.rb",
|
48
|
+
"spec/spec_helper.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<json_pure>, [">= 0"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<json_pure>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<json_pure>, [">= 0"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"response": {
|
3
|
+
"itemsPerPage": 5,
|
4
|
+
"totalResults": 5,
|
5
|
+
"entry": [
|
6
|
+
{
|
7
|
+
"displayName": "Bob Johnson",
|
8
|
+
"emails": [
|
9
|
+
{
|
10
|
+
"type": "other",
|
11
|
+
"value": "bob@example.com"
|
12
|
+
}
|
13
|
+
]
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"displayName": "Cindy Smith",
|
17
|
+
"emails": [
|
18
|
+
{
|
19
|
+
"type": "other",
|
20
|
+
"value": "cindy.smith@example.com"
|
21
|
+
}
|
22
|
+
]
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"displayName": "Fred Williams",
|
26
|
+
"emails": [
|
27
|
+
{
|
28
|
+
"type": "other",
|
29
|
+
"value": "fred.williams@example.com"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"type": "other",
|
33
|
+
"value": "fred@example.com"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"emails": [
|
39
|
+
{
|
40
|
+
"type": "other",
|
41
|
+
"value": "j.lewis@example.com"
|
42
|
+
}
|
43
|
+
]
|
44
|
+
},
|
45
|
+
{
|
46
|
+
"displayName": "Mary Jones",
|
47
|
+
"emails": [
|
48
|
+
{
|
49
|
+
"type": "other",
|
50
|
+
"value": "mary.jones@example.com"
|
51
|
+
}
|
52
|
+
]
|
53
|
+
}
|
54
|
+
],
|
55
|
+
"startIndex": 1
|
56
|
+
},
|
57
|
+
"stat": "ok"
|
58
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe RPXNow do
|
4
|
+
describe :mapping_integration do
|
5
|
+
before do
|
6
|
+
@k1 = 'http://test.myopenid.com'
|
7
|
+
RPXNow.unmap(@k1, 1)
|
8
|
+
@k2 = 'http://test-2.myopenid.com'
|
9
|
+
RPXNow.unmap(@k2, 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has no mappings when nothing was mapped" do
|
13
|
+
RPXNow.mappings(1).should == []
|
14
|
+
end
|
15
|
+
|
16
|
+
it "unmaps mapped keys" do
|
17
|
+
RPXNow.map(@k2, 1)
|
18
|
+
RPXNow.unmap(@k2, 1)
|
19
|
+
RPXNow.mappings(1).should == []
|
20
|
+
end
|
21
|
+
|
22
|
+
it "maps keys to a primary key and then retrieves them" do
|
23
|
+
RPXNow.map(@k1, 1)
|
24
|
+
RPXNow.map(@k2, 1)
|
25
|
+
RPXNow.mappings(1).sort.should == [@k2,@k1]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "does not add duplicate mappings" do
|
29
|
+
RPXNow.map(@k1, 1)
|
30
|
+
RPXNow.map(@k1, 1)
|
31
|
+
RPXNow.mappings(1).should == [@k1]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "finds all mappings" do
|
35
|
+
RPXNow.map(@k1, 1)
|
36
|
+
RPXNow.map(@k2, 2)
|
37
|
+
RPXNow.all_mappings.sort.should == [["1", ["http://test.myopenid.com"]], ["2", ["http://test-2.myopenid.com"]]]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe RPXNow::Api do
|
4
|
+
describe 'ssl cert' do
|
5
|
+
it "has an absolute path" do
|
6
|
+
RPXNow::Api::SSL_CERT[0..0].should == File.expand_path( RPXNow::Api::SSL_CERT )[0..0] # start with '/' on *nix, drive letter on win
|
7
|
+
end
|
8
|
+
|
9
|
+
it "exists" do
|
10
|
+
File.read(RPXNow::Api::SSL_CERT).to_s.should_not be_empty
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe :parse_response do
|
15
|
+
it "parses json when status is ok" do
|
16
|
+
response = mock(:code=>'200', :body=>%Q({"stat":"ok","data":"xx"}))
|
17
|
+
RPXNow::Api.send(:parse_response, response)['data'].should == "xx"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises when there is a communication error" do
|
21
|
+
response = stub(:code=>'200', :body=>%Q({"err":"wtf","stat":"ok"}))
|
22
|
+
lambda{
|
23
|
+
RPXNow::Api.send(:parse_response,response)
|
24
|
+
}.should raise_error(RPXNow::ApiError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "raises when service has downtime" do
|
28
|
+
response = stub(:code=>'200', :body=>%Q({"err":{"code":-1},"stat":"ok"}))
|
29
|
+
lambda{
|
30
|
+
RPXNow::Api.send(:parse_response,response)
|
31
|
+
}.should raise_error(RPXNow::ServiceUnavailableError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises when service is down" do
|
35
|
+
response = stub(:code=>'400',:body=>%Q({"stat":"err"}))
|
36
|
+
lambda{
|
37
|
+
RPXNow::Api.send(:parse_response,response)
|
38
|
+
}.should raise_error(RPXNow::ServiceUnavailableError)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe :request_object do
|
43
|
+
it "converts symbols to string keys" do
|
44
|
+
mock = ''
|
45
|
+
mock.should_receive(:form_data=).with([['symbol', 'value']])
|
46
|
+
Net::HTTP::Post.should_receive(:new).and_return(mock)
|
47
|
+
RPXNow::Api.send(:request_object, 'something', :symbol=>'value')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe RPXNow::ContactsCollection do
|
4
|
+
before do
|
5
|
+
data = JSON.parse(File.read('spec/fixtures/get_contacts_response.json'))['response']
|
6
|
+
@collection = RPXNow::ContactsCollection.new(data)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "behaves like an array" do
|
10
|
+
@collection.size.should == 5
|
11
|
+
@collection[0] = "1"
|
12
|
+
@collection[0].should == "1"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses entry to items" do
|
16
|
+
@collection[0]['displayName'].should == "Bob Johnson"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "parses emails to list" do
|
20
|
+
@collection[0]['emails'].should == ["bob@example.com"]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "parses emails to list with multiple emails" do
|
24
|
+
@collection[2]['emails'].should == ["fred.williams@example.com","fred@example.com"]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "holds additional_info" do
|
28
|
+
@collection.additional_info['startIndex'].should == 1
|
29
|
+
@collection.additional_info['itemsPerPage'].should == 5
|
30
|
+
@collection.additional_info['totalResults'].should == 5
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
require 'rpx_now/user_integration'
|
3
|
+
|
4
|
+
class User
|
5
|
+
include RPXNow::UserIntegration
|
6
|
+
|
7
|
+
def id
|
8
|
+
5
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe RPXNow::UserProxy do
|
13
|
+
before { @user = User.new }
|
14
|
+
|
15
|
+
it "has a proxy" do
|
16
|
+
@user.rpx.class.should == RPXNow::UserProxy
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has identifiers" do
|
20
|
+
RPXNow.should_receive(:mappings).with(@user.id).and_return(['identifiers'])
|
21
|
+
@user.rpx.identifiers.should == ['identifiers']
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can map" do
|
25
|
+
RPXNow.should_receive(:map).with('identifier', @user.id)
|
26
|
+
@user.rpx.map('identifier')
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can unmap" do
|
30
|
+
RPXNow.should_receive(:unmap).with('identifier', @user.id)
|
31
|
+
@user.rpx.unmap('identifier')
|
32
|
+
end
|
33
|
+
end
|