flexmls_api 0.4.5 → 0.6.4
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/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
|
+
|