flexmls_api 0.4.5 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -17
- data/Gemfile.lock +35 -27
- data/README.md +23 -1
- data/Rakefile +18 -5
- data/VERSION +1 -1
- data/bin/flexmls_api +8 -0
- data/lib/flexmls_api.rb +2 -0
- data/lib/flexmls_api/authentication.rb +5 -6
- data/lib/flexmls_api/authentication/api_auth.rb +4 -2
- data/lib/flexmls_api/authentication/oauth2.rb +51 -99
- data/lib/flexmls_api/authentication/oauth2_impl/grant_type_base.rb +85 -0
- data/lib/flexmls_api/authentication/oauth2_impl/grant_type_code.rb +48 -0
- data/lib/flexmls_api/authentication/oauth2_impl/grant_type_password.rb +45 -0
- data/lib/flexmls_api/authentication/oauth2_impl/grant_type_refresh.rb +36 -0
- data/lib/flexmls_api/authentication/oauth2_impl/middleware.rb +39 -0
- data/lib/flexmls_api/cli.rb +132 -0
- data/lib/flexmls_api/cli/api_auth.rb +8 -0
- data/lib/flexmls_api/cli/oauth2.rb +43 -0
- data/lib/flexmls_api/cli/setup.rb +44 -0
- data/lib/flexmls_api/configuration.rb +6 -6
- data/lib/flexmls_api/faraday.rb +11 -21
- data/lib/flexmls_api/models.rb +3 -0
- data/lib/flexmls_api/models/account.rb +48 -5
- data/lib/flexmls_api/models/base.rb +27 -2
- data/lib/flexmls_api/models/contact.rb +28 -9
- data/lib/flexmls_api/models/listing_cart.rb +72 -0
- data/lib/flexmls_api/models/note.rb +0 -2
- data/lib/flexmls_api/models/saved_search.rb +16 -0
- data/lib/flexmls_api/models/shared_listing.rb +35 -0
- data/lib/flexmls_api/multi_client.rb +37 -0
- data/lib/flexmls_api/paginate.rb +5 -0
- data/lib/flexmls_api/request.rb +7 -3
- data/script/console +6 -0
- data/script/example.rb +27 -0
- data/spec/fixtures/accounts/all.json +160 -0
- data/spec/fixtures/accounts/my.json +74 -0
- data/spec/fixtures/accounts/my_portal.json +20 -0
- data/spec/fixtures/accounts/my_put.json +5 -0
- data/spec/fixtures/accounts/my_save.json +5 -0
- data/spec/fixtures/accounts/office.json +142 -0
- data/spec/fixtures/base.json +13 -0
- data/spec/fixtures/contact_my.json +19 -0
- data/spec/fixtures/contact_new.json +11 -0
- data/spec/fixtures/contact_new_empty.json +8 -0
- data/spec/fixtures/contact_new_notify.json +11 -0
- data/spec/fixtures/contact_tags.json +11 -0
- data/spec/fixtures/contacts.json +6 -3
- data/spec/fixtures/contacts_post.json +10 -0
- data/spec/fixtures/empty.json +3 -0
- data/spec/fixtures/errors/failure.json +5 -0
- data/spec/fixtures/listing_cart.json +19 -0
- data/spec/fixtures/listing_cart_add_listing.json +13 -0
- data/spec/fixtures/listing_cart_add_listing_post.json +5 -0
- data/spec/fixtures/listing_cart_empty.json +5 -0
- data/spec/fixtures/listing_cart_new.json +12 -0
- data/spec/fixtures/listing_cart_post.json +10 -0
- data/spec/fixtures/listing_cart_remove_listing.json +13 -0
- data/spec/fixtures/note_new.json +5 -0
- data/spec/fixtures/{oauth2_access.json → oauth2/access.json} +0 -0
- data/spec/fixtures/oauth2/access_with_old_refresh.json +5 -0
- data/spec/fixtures/oauth2/access_with_refresh.json +5 -0
- data/spec/fixtures/oauth2/authorization_code_body.json +7 -0
- data/spec/fixtures/oauth2/error.json +3 -0
- data/spec/fixtures/oauth2/password_body.json +7 -0
- data/spec/fixtures/oauth2/refresh_body.json +7 -0
- data/spec/fixtures/saved_search.json +17 -0
- data/spec/fixtures/shared_listing_new.json +9 -0
- data/spec/fixtures/shared_listing_post.json +10 -0
- data/spec/mock_helper.rb +123 -0
- data/spec/oauth2_helper.rb +69 -0
- data/spec/spec_helper.rb +1 -57
- data/spec/unit/flexmls_api/authentication/api_auth_spec.rb +1 -0
- data/spec/unit/flexmls_api/authentication/oauth2_impl/grant_type_base_spec.rb +10 -0
- data/spec/unit/flexmls_api/authentication/oauth2_spec.rb +74 -79
- data/spec/unit/flexmls_api/configuration_spec.rb +25 -4
- data/spec/unit/flexmls_api/models/account_spec.rb +152 -85
- data/spec/unit/flexmls_api/models/base_spec.rb +69 -25
- data/spec/unit/flexmls_api/models/contact_spec.rb +48 -34
- data/spec/unit/flexmls_api/models/document_spec.rb +1 -7
- data/spec/unit/flexmls_api/models/listing_cart_spec.rb +114 -0
- data/spec/unit/flexmls_api/models/listing_spec.rb +8 -56
- data/spec/unit/flexmls_api/models/note_spec.rb +8 -38
- data/spec/unit/flexmls_api/models/photo_spec.rb +1 -11
- data/spec/unit/flexmls_api/models/saved_search_spec.rb +34 -0
- data/spec/unit/flexmls_api/models/shared_listing_spec.rb +30 -0
- data/spec/unit/flexmls_api/models/standard_fields_spec.rb +50 -30
- data/spec/unit/flexmls_api/models/tour_of_home_spec.rb +1 -7
- data/spec/unit/flexmls_api/models/video_spec.rb +1 -10
- data/spec/unit/flexmls_api/models/virtual_tour_spec.rb +1 -7
- data/spec/unit/flexmls_api/multi_client_spec.rb +48 -0
- data/spec/unit/flexmls_api/request_spec.rb +42 -5
- metadata +239 -93
- data/spec/unit/flexmls_api/standard_fields_spec.rb +0 -86
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
# Lightweight example of an oauth2 provider used by the ruby client.
|
3
|
+
class TestOAuth2Provider < FlexmlsApi::Authentication::BaseOAuth2Provider
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@authorization_uri = "https://test.fbsdata.com/r/oauth2"
|
7
|
+
@access_uri = "https://api.test.fbsdata.com/v1/oauth2/grant"
|
8
|
+
@redirect_uri = "https://exampleapp.fbsdata.com/oauth-callback"
|
9
|
+
@client_id="example-id"
|
10
|
+
@client_secret="example-password"
|
11
|
+
@session_cache = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def redirect(url)
|
15
|
+
# User redirected to url, signs in, and gets code sent to callback
|
16
|
+
self.code="my_code"
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_session()
|
20
|
+
@session_cache["test_user_session"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_session(session)
|
24
|
+
@session_cache["test_user_session"] = session
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def session_timeout; 7200; end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
class TestCLIOAuth2Provider < FlexmlsApi::Authentication::BaseOAuth2Provider
|
34
|
+
def initialize
|
35
|
+
@authorization_uri = "https://test.fbsdata.com/r/oauth2"
|
36
|
+
@access_uri = "https://api.test.fbsdata.com/v1/oauth2/grant"
|
37
|
+
@client_id="example-id"
|
38
|
+
@client_secret="example-secret"
|
39
|
+
@username="example-user"
|
40
|
+
@password="example-password"
|
41
|
+
@session_cache = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def grant_type
|
45
|
+
:password
|
46
|
+
end
|
47
|
+
|
48
|
+
def redirect(url)
|
49
|
+
raise "Unsupported in oauth grant_type=password mode"
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_session()
|
53
|
+
@session_cache["test_user_session"]
|
54
|
+
end
|
55
|
+
def save_session(session)
|
56
|
+
@session_cache["test_user_session"] = session
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
def session_timeout; 60; end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
class InvalidAuth2Provider < FlexmlsApi::Authentication::BaseOAuth2Provider
|
64
|
+
|
65
|
+
def grant_type
|
66
|
+
:not_a_real_type
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,17 +3,13 @@ require "json"
|
|
3
3
|
require "rspec"
|
4
4
|
require 'webmock/rspec'
|
5
5
|
|
6
|
-
|
7
|
-
Rspec.configure do |config|
|
8
|
-
config.include WebMock::API
|
9
|
-
end
|
10
|
-
|
11
6
|
begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
|
12
7
|
path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
13
8
|
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
14
9
|
require path + '/flexmls_api'
|
15
10
|
|
16
11
|
require 'flexmls_api'
|
12
|
+
require File.expand_path('../mock_helper', __FILE__)
|
17
13
|
require File.expand_path('../json_helper', __FILE__)
|
18
14
|
|
19
15
|
|
@@ -32,58 +28,6 @@ end
|
|
32
28
|
|
33
29
|
FlexmlsApi.logger.info("Setup gem for rspec testing")
|
34
30
|
|
35
|
-
def mock_session()
|
36
|
-
FlexmlsApi::Authentication::Session.new("AuthToken" => "1234", "Expires" => (Time.now + 3600).to_s, "Roles" => "['idx']")
|
37
|
-
end
|
38
|
-
|
39
|
-
def mock_oauth_session()
|
40
|
-
FlexmlsApi::Authentication::OAuthSession.new("access_token" => "1234", "expires_in" => 3600, "scope" => nil, "refresh_token"=> "1000refresh")
|
41
|
-
end
|
42
|
-
|
43
|
-
class MockClient < FlexmlsApi::Client
|
44
|
-
attr_accessor :connection
|
45
|
-
|
46
|
-
def connection(ssl = false)
|
47
|
-
@connection
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class MockApiAuthenticator < FlexmlsApi::Authentication::ApiAuth
|
52
|
-
# Sign a request
|
53
|
-
def sign(sig)
|
54
|
-
"SignedToken"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def mock_client(stubs)
|
59
|
-
c = MockClient.new
|
60
|
-
c.session = mock_session()
|
61
|
-
c.connection = test_connection(stubs)
|
62
|
-
c
|
63
|
-
end
|
64
|
-
|
65
|
-
def mock_expired_session()
|
66
|
-
FlexmlsApi::Authentication::Session.new("AuthToken" => "1234", "Expires" => (Time.now - 60).to_s, "Roles" => "['idx']")
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_connection(stubs)
|
70
|
-
Faraday::Connection.new(nil, {:headers => FlexmlsApi::Client.new.headers}) do |builder|
|
71
|
-
builder.adapter :test, stubs
|
72
|
-
builder.use Faraday::Response::ParseJson
|
73
|
-
builder.use FlexmlsApi::FaradayExt::FlexmlsMiddleware
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def stub_auth_request()
|
78
|
-
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
79
|
-
with(:query => {:ApiKey => "", :ApiSig => "806737984ab19be2fd08ba36030549ac"}).
|
80
|
-
to_return(:body => fixture("session.json"))
|
81
|
-
end
|
82
|
-
|
83
|
-
def fixture(file)
|
84
|
-
File.new(File.expand_path("../fixtures", __FILE__) + '/' + file)
|
85
|
-
end
|
86
|
-
|
87
31
|
def reset_config()
|
88
32
|
FlexmlsApi.reset
|
89
33
|
FlexmlsApi.configure do |config|
|
@@ -131,6 +131,7 @@ describe FlexmlsApi::Authentication::ApiAuth do
|
|
131
131
|
|
132
132
|
context "when the server says the session is expired (even if we disagree)" do
|
133
133
|
it "should reset the session and reauthenticate" do
|
134
|
+
reset_config
|
134
135
|
count = 0
|
135
136
|
# Make sure the auth request goes out twice.
|
136
137
|
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require './spec/oauth2_helper'
|
3
|
+
|
4
|
+
describe FlexmlsApi::Authentication::OAuth2Impl::GrantTypeBase do
|
5
|
+
subject { FlexmlsApi::Authentication::OAuth2Impl::GrantTypeBase }
|
6
|
+
# Make sure the client boostraps the right plugin based on configuration.
|
7
|
+
it "create should " do
|
8
|
+
expect {subject.create(nil, InvalidAuth2Provider.new())}.to raise_error(FlexmlsApi::ClientError){ |e| e.message.should == "Unsupported grant type [not_a_real_type]" }
|
9
|
+
end
|
10
|
+
end
|
@@ -1,34 +1,5 @@
|
|
1
1
|
require './spec/spec_helper'
|
2
|
-
|
3
|
-
# Lightweight example of an oauth2 provider used by the ruby client.
|
4
|
-
class TestOAuth2Provider < FlexmlsApi::Authentication::BaseOAuth2Provider
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@authorization_uri = "https://test.fbsdata.com/r/oauth2"
|
8
|
-
@access_uri = "https://api.test.fbsdata.com/v1/oauth2/grant"
|
9
|
-
@redirect_uri = "https://exampleapp.fbsdata.com/oauth-callback"
|
10
|
-
@client_id="example-id"
|
11
|
-
@client_secret="example-password"
|
12
|
-
@session_cache = {}
|
13
|
-
end
|
14
|
-
|
15
|
-
def redirect(url)
|
16
|
-
# User redirected to url, signs in, and gets code sent to callback
|
17
|
-
self.code="my_code"
|
18
|
-
end
|
19
|
-
|
20
|
-
def load_session()
|
21
|
-
@session_cache["test_user_session"]
|
22
|
-
end
|
23
|
-
|
24
|
-
def save_session(session)
|
25
|
-
@session_cache["test_user_session"] = session
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
|
-
def session_timeout; 7200; end
|
30
|
-
|
31
|
-
end
|
2
|
+
require './spec/oauth2_helper'
|
32
3
|
|
33
4
|
describe FlexmlsApi::Authentication::OAuth2 do
|
34
5
|
let(:provider) { TestOAuth2Provider.new() }
|
@@ -43,30 +14,20 @@ describe FlexmlsApi::Authentication::OAuth2 do
|
|
43
14
|
describe "authenticate" do
|
44
15
|
it "should authenticate the api credentials" do
|
45
16
|
stub_request(:post, provider.access_uri).
|
46
|
-
with(:
|
47
|
-
:client_id
|
48
|
-
:client_secret => provider.client_secret,
|
49
|
-
:grant_type => "authorization_code",
|
50
|
-
:redirect_uri => provider.redirect_uri,
|
51
|
-
:code => "my_code"
|
52
|
-
}
|
17
|
+
with(:body =>
|
18
|
+
'{"code":"my_code","client_secret":"example-password","client_id":"example-id","redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback","grant_type":"authorization_code"}'
|
53
19
|
).
|
54
|
-
to_return(:body => fixture("
|
20
|
+
to_return(:body => fixture("oauth2/access.json"), :status=>200)
|
55
21
|
subject.authenticate.access_token.should eq("04u7h-4cc355-70k3n")
|
56
22
|
subject.authenticate.expires_in.should eq(7200)
|
57
23
|
end
|
58
24
|
|
59
25
|
it "should raise an error when api credentials are invalid" do
|
60
|
-
stub_request(:post, provider.access_uri).
|
61
|
-
with(:
|
62
|
-
|
63
|
-
:client_secret => provider.client_secret,
|
64
|
-
:grant_type => "authorization_code",
|
65
|
-
:redirect_uri => provider.redirect_uri,
|
66
|
-
:code => "my_code"
|
67
|
-
}
|
26
|
+
s=stub_request(:post, provider.access_uri).
|
27
|
+
with(:body =>
|
28
|
+
'{"code":"my_code","client_secret":"example-password","client_id":"example-id","redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback","grant_type":"authorization_code"}'
|
68
29
|
).
|
69
|
-
to_return(:body => fixture("
|
30
|
+
to_return(:body => fixture("oauth2/error.json"), :status=>400)
|
70
31
|
expect {subject.authenticate()}.to raise_error(FlexmlsApi::ClientError){ |e| e.status.should == 400 }
|
71
32
|
end
|
72
33
|
|
@@ -89,6 +50,7 @@ describe FlexmlsApi::Authentication::OAuth2 do
|
|
89
50
|
end
|
90
51
|
end
|
91
52
|
|
53
|
+
|
92
54
|
describe "logout" do
|
93
55
|
let(:session) { mock_oauth_session }
|
94
56
|
it "should logout when there is an active session" do
|
@@ -112,7 +74,7 @@ describe FlexmlsApi::Authentication::OAuth2 do
|
|
112
74
|
:_pagination => '1'
|
113
75
|
}
|
114
76
|
c = stub_request(:get, "https://api.flexmls.com/#{FlexmlsApi.version}/listings").
|
115
|
-
with(:query =>
|
77
|
+
with(:query => args).
|
116
78
|
to_return(:body => fixture("listing_no_subresources.json"))
|
117
79
|
subject.session = session
|
118
80
|
subject.request(:get, "/#{FlexmlsApi.version}/listings", nil, args).status.should eq(200)
|
@@ -122,9 +84,7 @@ describe FlexmlsApi::Authentication::OAuth2 do
|
|
122
84
|
args = {}
|
123
85
|
contact = '{"D":{"Contacts":[{"DisplayName":"Contact Four","PrimaryEmail":"contact4@fbsdata.com"}]}}'
|
124
86
|
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/contacts").
|
125
|
-
with(:
|
126
|
-
:body => contact
|
127
|
-
).
|
87
|
+
with(:body => contact).
|
128
88
|
to_return(:body => '{"D": {
|
129
89
|
"Success": true,
|
130
90
|
"Results": [
|
@@ -137,41 +97,61 @@ describe FlexmlsApi::Authentication::OAuth2 do
|
|
137
97
|
end
|
138
98
|
end
|
139
99
|
|
140
|
-
context "
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
:
|
150
|
-
|
151
|
-
).
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
100
|
+
context "with an expired session" do
|
101
|
+
context "and a valid refresh token" do
|
102
|
+
it "should reset the session and reauthenticate" do
|
103
|
+
count = 0
|
104
|
+
refresh_count = 0
|
105
|
+
stub_request(:post, provider.access_uri).
|
106
|
+
with(:body => '{"code":"my_code","client_secret":"example-password","client_id":"example-id","redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback","grant_type":"authorization_code"}').
|
107
|
+
to_return do
|
108
|
+
count += 1
|
109
|
+
{:body => fixture("oauth2/access_with_old_refresh.json"), :status=>200}
|
110
|
+
end
|
111
|
+
stub_request(:post, provider.access_uri).
|
112
|
+
with(:body => '{"client_id":"example-id","client_secret":"example-password","grant_type":"refresh_token","redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback","refresh_token":"0ld-r3fr35h-70k3n"}').
|
113
|
+
to_return do
|
114
|
+
refresh_count += 1
|
115
|
+
{:body => fixture("oauth2/access_with_refresh.json"), :status=>200}
|
116
|
+
end
|
117
|
+
# Make sure the auth request goes out twice.
|
118
|
+
# Fail the first time, but then return the correct value after reauthentication
|
119
|
+
stub_request(:get, "https://api.flexmls.com/#{FlexmlsApi.version}/listings/1234").
|
120
|
+
to_return(:body => fixture('errors/expired.json'), :status => 401).times(1).then.
|
121
|
+
to_return(:body => fixture('listing_with_documents.json'))
|
122
|
+
client.get("/listings/1234")
|
123
|
+
count.should eq(1)
|
124
|
+
refresh_count.should eq(1)
|
125
|
+
client.session.expired?.should eq(false)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
context "and an invalid refresh token" do
|
129
|
+
it "should reset the session and reauthenticate" do
|
130
|
+
count = 0
|
131
|
+
stub_request(:post, provider.access_uri).
|
132
|
+
with(:body => '{"code":"my_code","client_secret":"example-password","client_id":"example-id","redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback","grant_type":"authorization_code"}').
|
133
|
+
to_return do
|
134
|
+
count += 1
|
135
|
+
{:body => fixture("oauth2/access.json"), :status=>200}
|
136
|
+
end
|
137
|
+
# Make sure the auth request goes out twice.
|
138
|
+
# Fail the first time, but then return the correct value after reauthentication
|
139
|
+
stub_request(:get, "https://api.flexmls.com/#{FlexmlsApi.version}/listings/1234").
|
140
|
+
to_return(:body => fixture('errors/expired.json'), :status => 401).times(1).then.
|
141
|
+
to_return(:body => fixture('listing_with_documents.json'))
|
142
|
+
|
143
|
+
client.get("/listings/1234")
|
144
|
+
count.should eq(2)
|
145
|
+
client.session.expired?.should eq(false)
|
146
|
+
end
|
166
147
|
end
|
167
148
|
end
|
168
|
-
|
169
149
|
end
|
170
150
|
|
171
151
|
describe FlexmlsApi::Authentication::BaseOAuth2Provider do
|
172
152
|
context "session_timeout" do
|
173
153
|
it "should provide a default" do
|
174
|
-
subject.session_timeout.should eq(
|
154
|
+
subject.session_timeout.should eq(86400)
|
175
155
|
end
|
176
156
|
describe TestOAuth2Provider do
|
177
157
|
subject { TestOAuth2Provider.new }
|
@@ -181,3 +161,18 @@ describe FlexmlsApi::Authentication::BaseOAuth2Provider do
|
|
181
161
|
end
|
182
162
|
end
|
183
163
|
end
|
164
|
+
|
165
|
+
describe "password authentication" do
|
166
|
+
let(:provider) { TestCLIOAuth2Provider.new() }
|
167
|
+
let(:client) { FlexmlsApi::Client.new({:authentication_mode => FlexmlsApi::Authentication::OAuth2,:oauth2_provider => provider}) }
|
168
|
+
subject {client.authenticator }
|
169
|
+
it "should authenticate the api credentials with username and password" do
|
170
|
+
stub_request(:post, provider.access_uri).
|
171
|
+
with(:body =>
|
172
|
+
'{"username":"example-user","client_secret":"example-secret","client_id":"example-id","password":"example-password","grant_type":"password"}'
|
173
|
+
).
|
174
|
+
to_return(:body => fixture("oauth2/access.json"), :status=>200)
|
175
|
+
subject.authenticate.access_token.should eq("04u7h-4cc355-70k3n")
|
176
|
+
subject.authenticate.expires_in.should eq(60)
|
177
|
+
end
|
178
|
+
end
|
@@ -11,7 +11,7 @@ describe FlexmlsApi::Client, "Client config" do
|
|
11
11
|
FlexmlsApi.api_secret.should be_nil
|
12
12
|
FlexmlsApi.version.should match("v1")
|
13
13
|
FlexmlsApi.endpoint.should match("api.flexmls.com")
|
14
|
-
|
14
|
+
FlexmlsApi.user_agent.should match(/flexmls API Ruby Gem .*/)
|
15
15
|
FlexmlsApi.api_key = "my_api_key"
|
16
16
|
FlexmlsApi.api_key.should match("my_api_key")
|
17
17
|
end
|
@@ -79,7 +79,6 @@ describe FlexmlsApi::Client, "Client config" do
|
|
79
79
|
to_return(:body => '{"D":{"Success": true,"Results": [{"SSL":false}]}}')
|
80
80
|
|
81
81
|
FlexmlsApi.client.get('/connections')[0]["SSL"].should eq(false)
|
82
|
-
|
83
82
|
end
|
84
83
|
|
85
84
|
it "should use https when ssl is enabled" do
|
@@ -90,11 +89,33 @@ describe FlexmlsApi::Client, "Client config" do
|
|
90
89
|
:AuthToken => "c401736bf3d3f754f07c04e460e09573"
|
91
90
|
}).
|
92
91
|
to_return(:body => '{"D":{"Success": true,"Results": [{"SSL":true}]}}')
|
93
|
-
|
94
|
-
|
92
|
+
|
93
|
+
c = FlexmlsApi::Client.new(:endpoint => "https://api.flexmls.com", :ssl => true)
|
95
94
|
c.get('/connections')[0]["SSL"].should eq(true)
|
96
95
|
end
|
97
96
|
|
97
|
+
it "should have correct headers based on configuration" do
|
98
|
+
stub_auth_request
|
99
|
+
stub_request(:get, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}/headers").
|
100
|
+
with(:query => {
|
101
|
+
:ApiSig => "6f0cfef263e0bfe7a9ae1f60063a8ad9",
|
102
|
+
:AuthToken => "c401736bf3d3f754f07c04e460e09573"
|
103
|
+
}).
|
104
|
+
to_return(:body => '{"D":{"Success": true,"Results": []}}')
|
105
|
+
FlexmlsApi.reset
|
106
|
+
FlexmlsApi.configure do |config|
|
107
|
+
config.user_agent = "my useragent"
|
108
|
+
end
|
109
|
+
FlexmlsApi.client.get '/headers'
|
110
|
+
WebMock.should have_requested(:get, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}/headers?ApiSig=6f0cfef263e0bfe7a9ae1f60063a8ad9&AuthToken=c401736bf3d3f754f07c04e460e09573").
|
111
|
+
with(:headers => {
|
112
|
+
'User-Agent' => FlexmlsApi::Configuration::DEFAULT_USER_AGENT,
|
113
|
+
FlexmlsApi::Configuration::X_FLEXMLS_API_USER_AGENT => "my useragent",
|
114
|
+
'Accept'=>'application/json',
|
115
|
+
'Content-Type'=>'application/json'
|
116
|
+
})
|
117
|
+
end
|
118
|
+
|
98
119
|
end
|
99
120
|
|
100
121
|
end
|
@@ -1,96 +1,163 @@
|
|
1
1
|
require './spec/spec_helper'
|
2
2
|
|
3
3
|
describe Account do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
4
|
+
describe "units" do
|
5
|
+
before(:each) do
|
6
|
+
@account = Account.new({
|
7
|
+
"Name"=>"Sample User",
|
8
|
+
"Id"=>"20000426173054342350000000",
|
9
|
+
"Office"=>"Sample Office",
|
10
|
+
"Mls"=>"Sample MLS",
|
11
|
+
"MlsId"=>"20000426143505724628000000",
|
12
|
+
"Emails"=>[
|
13
|
+
{
|
14
|
+
"Type"=>"Work",
|
15
|
+
"Name"=>"My Work E-mail",
|
16
|
+
"Address"=>"work@test.com",
|
17
|
+
"Primary"=>true
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"Type"=>"Home",
|
21
|
+
"Name"=>"My Home E-mail",
|
22
|
+
"Address"=>"home@test.com"
|
23
|
+
}
|
24
|
+
],
|
25
|
+
"Phones"=>[
|
26
|
+
{
|
27
|
+
"Type"=>"Work",
|
28
|
+
"Name"=>"My Work Phone",
|
29
|
+
"Number"=>"701-555-1212",
|
30
|
+
"Primary"=>true
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"Type"=>"Home",
|
34
|
+
"Name"=>"My Home Phone",
|
35
|
+
"Number"=>"702-555-1313"
|
36
|
+
}
|
37
|
+
],
|
38
|
+
"Websites"=>[
|
39
|
+
{
|
40
|
+
"Type"=>"Work",
|
41
|
+
"Name"=>"My Work Website",
|
42
|
+
"Uri"=>"http://iamthebestagent.com",
|
43
|
+
"Primary"=>true
|
44
|
+
},
|
45
|
+
{
|
46
|
+
"Type"=>"Home",
|
47
|
+
"Name"=>"My Home Website",
|
48
|
+
"Uri"=>"http://myspace.com/lolcats"
|
49
|
+
}
|
50
|
+
],
|
51
|
+
"Addresses"=>[
|
52
|
+
{
|
53
|
+
"Type"=>"Work",
|
54
|
+
"Name"=>"My Work Address",
|
55
|
+
"Address"=>"101 Main Ave, Phoenix, AZ 12345",
|
56
|
+
"Primary"=>true
|
57
|
+
},
|
58
|
+
{
|
59
|
+
"Type"=>"Home",
|
60
|
+
"Name"=>"My Home Address",
|
61
|
+
"Address"=>"102 Main Ave, Gilbert, AZ 54321"
|
62
|
+
}
|
63
|
+
],
|
64
|
+
"Images"=>[
|
65
|
+
{
|
66
|
+
"Type"=>"Photo",
|
67
|
+
"Name"=>"My Photo 1",
|
68
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
69
|
+
},
|
70
|
+
{
|
71
|
+
"Type"=>"Photo",
|
72
|
+
"Name"=>"My Photo two",
|
73
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
74
|
+
},
|
75
|
+
{
|
76
|
+
"Type"=>"Logo",
|
77
|
+
"Name"=>"1 My Logo",
|
78
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"Type"=>"Logo",
|
82
|
+
"Name"=>"My Other Logo",
|
83
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"Type"=>"Logo",
|
87
|
+
"Name"=>"My Logo",
|
88
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
89
|
+
}
|
90
|
+
]
|
91
|
+
})
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should respond to attributes" do
|
95
|
+
['Name','Id','Mls','MlsId','Office'].each do |k|
|
96
|
+
(@account.send k.to_sym).should be_a(String)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should have primary subresources" do
|
101
|
+
@account.emails.primary.Address.should eq("work@test.com")
|
102
|
+
@account.phones.primary.Number.should eq("701-555-1212")
|
103
|
+
@account.addresses.primary.Address.should eq("101 Main Ave, Phoenix, AZ 12345")
|
104
|
+
@account.websites.primary.Uri.should eq("http://iamthebestagent.com")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should be able to provide a primary image" do
|
108
|
+
@account.primary_img("Photo").Name.should == 'My Photo 1'
|
109
|
+
@account.primary_img("Logo").Name.should == '1 My Logo'
|
110
|
+
end
|
111
|
+
|
112
|
+
after(:each) do
|
113
|
+
@acount = nil
|
114
|
+
end
|
76
115
|
end
|
77
116
|
|
78
|
-
|
79
|
-
|
80
|
-
|
117
|
+
describe "functionals" do
|
118
|
+
before(:each) do
|
119
|
+
stub_auth_request
|
81
120
|
end
|
82
|
-
end
|
83
121
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
122
|
+
it "should get my account" do
|
123
|
+
stub_api_get("/my/account", 'accounts/my.json')
|
124
|
+
account = Account.my
|
125
|
+
account.Id.should eq("20000426173054342350000000")
|
126
|
+
account.websites.first.Name.should == 'My Work Website'
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should get all accounts" do
|
130
|
+
stub_api_get("/accounts", 'accounts/all.json')
|
131
|
+
accounts = Account.get
|
132
|
+
accounts.should be_an(Array)
|
133
|
+
accounts.length.should eq(3)
|
134
|
+
accounts.first.Id.should eq("20000426173054342350000000")
|
135
|
+
accounts.last.Id.should eq("20110126173054382350000000")
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should all office accounts" do
|
139
|
+
stub_api_get("/accounts/by/office/20030426173014239760000000", 'accounts/office.json')
|
140
|
+
accounts = Account.by_office("20030426173014239760000000")
|
141
|
+
accounts.should be_an(Array)
|
142
|
+
accounts.length.should eq(2)
|
143
|
+
accounts.each do |account|
|
144
|
+
accounts.first.OfficeId.should eq("20030426173014239760000000")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should save my portal account" do
|
149
|
+
stub_api_get("/my/account", 'accounts/my_portal.json')
|
150
|
+
stub_api_put("/my/account", 'accounts/my_save.json', 'accounts/my_put.json')
|
151
|
+
account = Account.my
|
152
|
+
account.Id.should eq("20110426173054342350000000")
|
153
|
+
account.GetEmailUpdates.should eq(false)
|
154
|
+
account.GetEmailUpdates = true
|
155
|
+
account.save!
|
156
|
+
account.GetEmailUpdates.should eq(true)
|
157
|
+
end
|
91
158
|
|
92
|
-
|
93
|
-
@acount = nil
|
159
|
+
|
94
160
|
end
|
95
161
|
|
96
162
|
end
|
163
|
+
|