flexmls_api 0.3.6 → 0.4.5
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 +6 -6
- data/Gemfile.lock +6 -6
- data/README.md +5 -3
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/flexmls_api/authentication.rb +25 -54
- data/lib/flexmls_api/authentication/api_auth.rb +100 -0
- data/lib/flexmls_api/authentication/base_auth.rb +47 -0
- data/lib/flexmls_api/authentication/oauth2.rb +219 -0
- data/lib/flexmls_api/client.rb +7 -1
- data/lib/flexmls_api/configuration.rb +5 -2
- data/lib/flexmls_api/faraday.rb +6 -2
- data/lib/flexmls_api/models.rb +2 -0
- data/lib/flexmls_api/models/base.rb +5 -1
- data/lib/flexmls_api/models/contact.rb +1 -0
- data/lib/flexmls_api/models/custom_fields.rb +2 -2
- data/lib/flexmls_api/models/finders.rb +2 -2
- data/lib/flexmls_api/models/idx_link.rb +1 -1
- data/lib/flexmls_api/models/listing.rb +31 -5
- data/lib/flexmls_api/models/market_statistics.rb +1 -1
- data/lib/flexmls_api/models/note.rb +43 -0
- data/lib/flexmls_api/models/standard_fields.rb +43 -0
- data/lib/flexmls_api/models/subresource.rb +5 -2
- data/lib/flexmls_api/models/system_info.rb +7 -0
- data/lib/flexmls_api/models/tour_of_home.rb +24 -0
- data/lib/flexmls_api/request.rb +13 -28
- data/spec/fixtures/add_note.json +11 -0
- data/spec/fixtures/agent_shared_note.json +11 -0
- data/spec/fixtures/agent_shared_note_empty.json +7 -0
- data/spec/fixtures/authentication_failure.json +7 -0
- data/spec/fixtures/count.json +10 -0
- data/spec/fixtures/errors/expired.json +7 -0
- data/spec/fixtures/generic_delete.json +1 -0
- data/spec/fixtures/generic_failure.json +5 -0
- data/spec/fixtures/oauth2_access.json +3 -0
- data/spec/fixtures/oauth2_error.json +3 -0
- data/spec/fixtures/session.json +1 -1
- data/spec/fixtures/standardfields.json +188 -0
- data/spec/fixtures/standardfields_city.json +1031 -0
- data/spec/fixtures/standardfields_nearby.json +53 -0
- data/spec/fixtures/standardfields_stateorprovince.json +36 -0
- data/spec/fixtures/tour_of_homes.json +23 -0
- data/spec/spec_helper.rb +22 -5
- data/spec/unit/flexmls_api/authentication/api_auth_spec.rb +159 -0
- data/spec/unit/flexmls_api/authentication/oauth2_spec.rb +183 -0
- data/spec/unit/flexmls_api/authentication_spec.rb +10 -2
- data/spec/unit/flexmls_api/configuration_spec.rb +2 -2
- data/spec/unit/flexmls_api/faraday_spec.rb +3 -7
- data/spec/unit/flexmls_api/models/base_spec.rb +1 -1
- data/spec/unit/flexmls_api/models/contact_spec.rb +8 -4
- data/spec/unit/flexmls_api/models/document_spec.rb +2 -5
- data/spec/unit/flexmls_api/models/listing_spec.rb +46 -9
- data/spec/unit/flexmls_api/models/note_spec.rb +90 -0
- data/spec/unit/flexmls_api/models/photo_spec.rb +2 -2
- data/spec/unit/flexmls_api/models/system_info_spec.rb +37 -3
- data/spec/unit/flexmls_api/models/tour_of_home_spec.rb +43 -0
- data/spec/unit/flexmls_api/models/video_spec.rb +2 -4
- data/spec/unit/flexmls_api/models/virtual_tour_spec.rb +2 -2
- data/spec/unit/flexmls_api/paginate_spec.rb +11 -8
- data/spec/unit/flexmls_api/request_spec.rb +31 -16
- data/spec/unit/flexmls_api/standard_fields_spec.rb +86 -0
- data/spec/unit/flexmls_api_spec.rb +6 -27
- metadata +119 -76
@@ -0,0 +1,53 @@
|
|
1
|
+
{
|
2
|
+
"D": {
|
3
|
+
"Success": true,
|
4
|
+
"Results": [{
|
5
|
+
"City": {
|
6
|
+
"ResourceUri": "/v1/standardfields/nearby/A/City",
|
7
|
+
"HasList": true,
|
8
|
+
"FieldList": [{
|
9
|
+
"Name": "Fargo",
|
10
|
+
"Value": "'Fargo'"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"Name": "Moorhead",
|
14
|
+
"Value": "'Moorhead'"
|
15
|
+
}],
|
16
|
+
"Searchable": true,
|
17
|
+
"Type": "Character"
|
18
|
+
},
|
19
|
+
"PostalCode": {
|
20
|
+
"ResourceUri": "/v1/standardfields/nearby/A/PostalCode",
|
21
|
+
"HasList": true,
|
22
|
+
"FieldList": [{
|
23
|
+
"Name": "56560",
|
24
|
+
"Value": "'56560'"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"Name": "58102",
|
28
|
+
"Value": "'58102'"
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"Name": "58103",
|
32
|
+
"Value": "'58103'"
|
33
|
+
}],
|
34
|
+
"Searchable": true,
|
35
|
+
"Type": "Character"
|
36
|
+
},
|
37
|
+
"StateOrProvince": {
|
38
|
+
"ResourceUri": "/v1/standardfields/nearby/A/StateOrProvince",
|
39
|
+
"HasList": true,
|
40
|
+
"FieldList": [{
|
41
|
+
"Name": "MN",
|
42
|
+
"Value": "'MN'"
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"Name": "ND",
|
46
|
+
"Value": "'ND'"
|
47
|
+
}],
|
48
|
+
"Searchable": true,
|
49
|
+
"Type": "Character"
|
50
|
+
}
|
51
|
+
}]
|
52
|
+
}
|
53
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"D": {
|
3
|
+
"Success": true,
|
4
|
+
"Results": [{
|
5
|
+
"StateOrProvince": {
|
6
|
+
"ResourceUri": "/v1/standardfields/StateOrProvince",
|
7
|
+
"FieldList": [{
|
8
|
+
"Name": "IA",
|
9
|
+
"Applies To": ["A", "B", "G", "I", "J", "K", "M"],
|
10
|
+
"Value": "IA"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"Name": "MN",
|
14
|
+
"Value": "MN"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"Name": "ND",
|
18
|
+
"Value": "ND"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"Name": "SD",
|
22
|
+
"Applies To": ["A", "B", "G", "I", "J", "K", "M"],
|
23
|
+
"Value": "SD"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"Name": "WI",
|
27
|
+
"Applies To": ["A", "B", "G", "I", "J", "K", "M"],
|
28
|
+
"Value": "WI"
|
29
|
+
}],
|
30
|
+
"HasList": true,
|
31
|
+
"Searchable": true,
|
32
|
+
"Type": "Character"
|
33
|
+
}
|
34
|
+
}]
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"D": {
|
3
|
+
"Results": [
|
4
|
+
{"ResourceUri":"/listings/20060725224713296297000000/tourofhomes/20101127153422574618000000",
|
5
|
+
"Id": "20101127153422574618000000",
|
6
|
+
"Date": "10/01/2010",
|
7
|
+
"StartTime": "09:00 AM",
|
8
|
+
"EndTime": "12:00 PM",
|
9
|
+
"Comments": "Wonderful home; must see!",
|
10
|
+
"AdditionalInfo": [{"Hosted By": "Joe Smith"}, {"Host Phone": "123-456-7890"}, {"Tour Area": "North-Central"}]
|
11
|
+
},
|
12
|
+
{"ResourceUri":"/listings/20060725224713296297000000/tourofhomes/20101127153422174618000000",
|
13
|
+
"Id": "20101127153422174618000000",
|
14
|
+
"Date": "10/08/2010",
|
15
|
+
"StartTime": "09:00 AM",
|
16
|
+
"EndTime": "12:00 PM",
|
17
|
+
"Comments": "Wonderful home; must see!",
|
18
|
+
"AdditionalInfo": [{"Hosted By": "Joe Smith"}, {"Host Phone": "123-456-7890"}, {"Tour Area": "North-Central"}]
|
19
|
+
}
|
20
|
+
],
|
21
|
+
"Success": true
|
22
|
+
}
|
23
|
+
}
|
data/spec/spec_helper.rb
CHANGED
@@ -36,9 +36,23 @@ def mock_session()
|
|
36
36
|
FlexmlsApi::Authentication::Session.new("AuthToken" => "1234", "Expires" => (Time.now + 3600).to_s, "Roles" => "['idx']")
|
37
37
|
end
|
38
38
|
|
39
|
+
def mock_oauth_session()
|
40
|
+
FlexmlsApi::Authentication::OAuthSession.new("access_token" => "1234", "expires_in" => 3600, "scope" => nil, "refresh_token"=> "1000refresh")
|
41
|
+
end
|
39
42
|
|
40
43
|
class MockClient < FlexmlsApi::Client
|
41
|
-
attr_accessor :connection
|
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
|
42
56
|
end
|
43
57
|
|
44
58
|
def mock_client(stubs)
|
@@ -60,19 +74,22 @@ def test_connection(stubs)
|
|
60
74
|
end
|
61
75
|
end
|
62
76
|
|
63
|
-
|
64
77
|
def stub_auth_request()
|
65
78
|
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
66
79
|
with(:query => {:ApiKey => "", :ApiSig => "806737984ab19be2fd08ba36030549ac"}).
|
67
80
|
to_return(:body => fixture("session.json"))
|
68
81
|
end
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
83
|
def fixture(file)
|
74
84
|
File.new(File.expand_path("../fixtures", __FILE__) + '/' + file)
|
75
85
|
end
|
76
86
|
|
87
|
+
def reset_config()
|
88
|
+
FlexmlsApi.reset
|
89
|
+
FlexmlsApi.configure do |config|
|
90
|
+
config.api_user = "foobar"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
reset_config
|
77
94
|
|
78
95
|
include FlexmlsApi::Models
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe FlexmlsApi::Authentication::ApiAuth do
|
4
|
+
subject {FlexmlsApi::Authentication::ApiAuth.new(nil) }
|
5
|
+
describe "build_param_hash" do
|
6
|
+
it "should return a blank string when passed nil" do
|
7
|
+
subject.build_param_string(nil).should be_empty
|
8
|
+
end
|
9
|
+
it "should return a correct param string for one item" do
|
10
|
+
subject.build_param_string({:foo => "bar"}).should match("foobar")
|
11
|
+
end
|
12
|
+
it "should alphabatize the param names by key first, then by value" do
|
13
|
+
subject.build_param_string({:zoo => "zar", :ooo => "car"}).should match("ooocarzoozar")
|
14
|
+
subject.build_param_string({:Akey => "aValue", :aNotherkey => "AnotherValue"}).should
|
15
|
+
match "AkeyaValueaNotherkeyAnotherValue"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "authenticate" do
|
20
|
+
let(:client) { FlexmlsApi::Client.new({:api_key => "my_key", :api_secret => "my_secret"}) }
|
21
|
+
subject do
|
22
|
+
s = FlexmlsApi::Authentication::ApiAuth.new(client)
|
23
|
+
client.authenticator = s
|
24
|
+
s
|
25
|
+
end
|
26
|
+
it "should authenticate the api credentials" do
|
27
|
+
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
28
|
+
with(:query => {:ApiKey => "my_key", :ApiSig => "c731cf2455fbc7a4ef937b2301108d7a"}).
|
29
|
+
to_return(:body => fixture("session.json"))
|
30
|
+
subject.authenticate()
|
31
|
+
end
|
32
|
+
it "should raise an error when api credentials are invalid" do
|
33
|
+
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
34
|
+
with(:query => {:ApiKey => "my_key", :ApiSig => "c731cf2455fbc7a4ef937b2301108d7a"}).
|
35
|
+
to_return(:body => fixture("authentication_failure.json"), :status=>401)
|
36
|
+
expect {subject.authenticate()}.to raise_error(FlexmlsApi::ClientError){ |e| e.status.should == 401 }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "authenticated?" do
|
41
|
+
let(:session) { Object.new }
|
42
|
+
it "should return true when session is active" do
|
43
|
+
subject.session = session
|
44
|
+
session.stub(:expired?) { false }
|
45
|
+
subject.authenticated?.should eq(true)
|
46
|
+
end
|
47
|
+
it "should return false when session is expired" do
|
48
|
+
subject.session = session
|
49
|
+
session.stub(:expired?) { true }
|
50
|
+
subject.authenticated?.should eq(false)
|
51
|
+
end
|
52
|
+
it "should return false when session is uninitialized" do
|
53
|
+
subject.authenticated?.should eq(false)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "logout" do
|
58
|
+
let(:session) { mock_session }
|
59
|
+
let(:client) { Object.new }
|
60
|
+
subject {FlexmlsApi::Authentication::ApiAuth.new(client) }
|
61
|
+
it "should logout when there is an active session" do
|
62
|
+
logged_out = false
|
63
|
+
subject.session = session
|
64
|
+
client.stub(:delete).with("/session/1234") { logged_out = true }
|
65
|
+
subject.logout
|
66
|
+
subject.session.should eq(nil)
|
67
|
+
logged_out.should eq(true)
|
68
|
+
end
|
69
|
+
it "should skip logging out when there is no active session information" do
|
70
|
+
client.stub(:delete) { raise "Should not be called" }
|
71
|
+
subject.logout.should eq(nil)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Since the request method is overly complex, the following tests just go through the whole stack
|
76
|
+
# with some semi realistic requests. Performing this type of test here should allow us to safely
|
77
|
+
# mock out authentication for the rest of our unit tests and still have some decent coverage.
|
78
|
+
describe "request" do
|
79
|
+
let(:client) { FlexmlsApi::Client.new({:api_key => "my_key", :api_secret => "my_secret"}) }
|
80
|
+
let(:session) { mock_session }
|
81
|
+
subject do
|
82
|
+
s = FlexmlsApi::Authentication::ApiAuth.new(client)
|
83
|
+
client.authenticator = s
|
84
|
+
s.session = session
|
85
|
+
s
|
86
|
+
end
|
87
|
+
it "should handle a get request" do
|
88
|
+
stub_auth_request
|
89
|
+
args = {
|
90
|
+
:ApiUser => "foobar",
|
91
|
+
:_limit => '10',
|
92
|
+
:_page => '1',
|
93
|
+
:_pagination => '1'
|
94
|
+
}
|
95
|
+
stub_request(:get, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}/listings").
|
96
|
+
with(:query => {
|
97
|
+
:ApiSig => "1cb789831f8f4c6925dc708c93762a2c",
|
98
|
+
:AuthToken => "1234"}.merge(args)).
|
99
|
+
to_return(:body => fixture("listing_no_subresources.json"))
|
100
|
+
subject.session = session
|
101
|
+
subject.request(:get, "/#{FlexmlsApi.version}/listings", nil, args).status.should eq(200)
|
102
|
+
end
|
103
|
+
it "should handle a post request" do
|
104
|
+
stub_auth_request
|
105
|
+
args = {:ApiUser => "foobar"}
|
106
|
+
contact = '{"D":{"Contacts":[{"DisplayName":"Contact Four","PrimaryEmail":"contact4@fbsdata.com"}]}}'
|
107
|
+
stub_request(:post, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}/contacts").
|
108
|
+
with(:query => {
|
109
|
+
:ApiSig => "82898ef88d22e1b31bd2e2ea6bb8efe7",
|
110
|
+
:AuthToken => "1234"}.merge(args),
|
111
|
+
:body => contact
|
112
|
+
).
|
113
|
+
to_return(:body => '{"D": {
|
114
|
+
"Success": true,
|
115
|
+
"Results": [
|
116
|
+
{
|
117
|
+
"ResourceUri":"/v1/contacts/20101230223226074204000000"
|
118
|
+
}]}
|
119
|
+
}',
|
120
|
+
:status=>201)
|
121
|
+
subject.request(:post, "/#{FlexmlsApi.version}/contacts", contact, args).status.should eq(201)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "sign" do
|
126
|
+
it "should sign the auth parameters correctly" do
|
127
|
+
sign_token = "my_secretApiKeymy_key"
|
128
|
+
subject.sign(sign_token).should eq("c731cf2455fbc7a4ef937b2301108d7a")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when the server says the session is expired (even if we disagree)" do
|
133
|
+
it "should reset the session and reauthenticate" do
|
134
|
+
count = 0
|
135
|
+
# Make sure the auth request goes out twice.
|
136
|
+
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
|
137
|
+
with(:query => {:ApiKey => "", :ApiSig => "806737984ab19be2fd08ba36030549ac"}).
|
138
|
+
to_return do |r|
|
139
|
+
count += 1
|
140
|
+
{:body => fixture("session.json")}
|
141
|
+
end
|
142
|
+
# Fail the first time, but then return the correct value after reauthentication
|
143
|
+
stub_request(:get, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}/listings/1234").
|
144
|
+
with(:query => {
|
145
|
+
:ApiSig => "554b6e2a3efec8719b782647c19d238d",
|
146
|
+
:AuthToken => "c401736bf3d3f754f07c04e460e09573",
|
147
|
+
:ApiUser => "foobar",
|
148
|
+
:_expand => "Documents"
|
149
|
+
}).
|
150
|
+
to_return(:body => fixture('errors/expired.json'), :status => 401).times(1).then.
|
151
|
+
to_return(:body => fixture('listing_with_documents.json'))
|
152
|
+
l = Listing.find('1234', :_expand => "Documents")
|
153
|
+
|
154
|
+
count.should eq(2)
|
155
|
+
FlexmlsApi.client.session.expired?.should eq(false)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
@@ -0,0 +1,183 @@
|
|
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
|
32
|
+
|
33
|
+
describe FlexmlsApi::Authentication::OAuth2 do
|
34
|
+
let(:provider) { TestOAuth2Provider.new() }
|
35
|
+
let(:client) { FlexmlsApi::Client.new({:authentication_mode => FlexmlsApi::Authentication::OAuth2,:oauth2_provider => provider}) }
|
36
|
+
subject {client.authenticator }
|
37
|
+
# Make sure the client boostraps the right plugin based on configuration.
|
38
|
+
describe "plugin" do
|
39
|
+
it "should load the oauth2 authenticator" do
|
40
|
+
client.authenticator.class.should eq(FlexmlsApi::Authentication::OAuth2)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
describe "authenticate" do
|
44
|
+
it "should authenticate the api credentials" do
|
45
|
+
stub_request(:post, provider.access_uri).
|
46
|
+
with(:query => {
|
47
|
+
:client_id => provider.client_id,
|
48
|
+
:client_secret => provider.client_secret,
|
49
|
+
:grant_type => "authorization_code",
|
50
|
+
:redirect_uri => provider.redirect_uri,
|
51
|
+
:code => "my_code"
|
52
|
+
}
|
53
|
+
).
|
54
|
+
to_return(:body => fixture("oauth2_access.json"), :status=>200)
|
55
|
+
subject.authenticate.access_token.should eq("04u7h-4cc355-70k3n")
|
56
|
+
subject.authenticate.expires_in.should eq(7200)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should raise an error when api credentials are invalid" do
|
60
|
+
stub_request(:post, provider.access_uri).
|
61
|
+
with(:query => {
|
62
|
+
:client_id => provider.client_id,
|
63
|
+
:client_secret => provider.client_secret,
|
64
|
+
:grant_type => "authorization_code",
|
65
|
+
:redirect_uri => provider.redirect_uri,
|
66
|
+
:code => "my_code"
|
67
|
+
}
|
68
|
+
).
|
69
|
+
to_return(:body => fixture("oauth2_error.json"), :status=>400)
|
70
|
+
expect {subject.authenticate()}.to raise_error(FlexmlsApi::ClientError){ |e| e.status.should == 400 }
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "authenticated?" do
|
76
|
+
let(:session) { Object.new }
|
77
|
+
it "should return true when session is active" do
|
78
|
+
subject.session = session
|
79
|
+
session.stub(:expired?) { false }
|
80
|
+
subject.authenticated?.should eq(true)
|
81
|
+
end
|
82
|
+
it "should return false when session is expired" do
|
83
|
+
subject.session = session
|
84
|
+
session.stub(:expired?) { true }
|
85
|
+
subject.authenticated?.should eq(false)
|
86
|
+
end
|
87
|
+
it "should return false when session is uninitialized" do
|
88
|
+
subject.authenticated?.should eq(false)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "logout" do
|
93
|
+
let(:session) { mock_oauth_session }
|
94
|
+
it "should logout when there is an active session" do
|
95
|
+
subject.session = session
|
96
|
+
subject.logout
|
97
|
+
subject.session.should eq(nil)
|
98
|
+
end
|
99
|
+
it "should skip logging out when there is no active session information" do
|
100
|
+
client.stub(:delete) { raise "Should not be called" }
|
101
|
+
subject.logout.should eq(nil)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "request" do
|
106
|
+
let(:session) { mock_oauth_session }
|
107
|
+
it "should handle a get request" do
|
108
|
+
subject.session = session
|
109
|
+
args = {
|
110
|
+
:_limit => '10',
|
111
|
+
:_page => '1',
|
112
|
+
:_pagination => '1'
|
113
|
+
}
|
114
|
+
c = stub_request(:get, "https://api.flexmls.com/#{FlexmlsApi.version}/listings").
|
115
|
+
with(:query => {:access_token => "1234"}.merge(args)).
|
116
|
+
to_return(:body => fixture("listing_no_subresources.json"))
|
117
|
+
subject.session = session
|
118
|
+
subject.request(:get, "/#{FlexmlsApi.version}/listings", nil, args).status.should eq(200)
|
119
|
+
end
|
120
|
+
it "should handle a post request" do
|
121
|
+
subject.session = session
|
122
|
+
args = {}
|
123
|
+
contact = '{"D":{"Contacts":[{"DisplayName":"Contact Four","PrimaryEmail":"contact4@fbsdata.com"}]}}'
|
124
|
+
stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/contacts").
|
125
|
+
with(:query => {:access_token => "1234"}.merge(args),
|
126
|
+
:body => contact
|
127
|
+
).
|
128
|
+
to_return(:body => '{"D": {
|
129
|
+
"Success": true,
|
130
|
+
"Results": [
|
131
|
+
{
|
132
|
+
"ResourceUri":"/v1/contacts/20101230223226074204000000"
|
133
|
+
}]}
|
134
|
+
}',
|
135
|
+
:status=>201)
|
136
|
+
subject.request(:post, "/#{FlexmlsApi.version}/contacts", contact, args).status.should eq(201)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when the server says the session is expired (even if we disagree)" do
|
141
|
+
it "should reset the session and reauthenticate" do
|
142
|
+
count = 0
|
143
|
+
stub_request(:post, provider.access_uri).
|
144
|
+
with(:query => {
|
145
|
+
:client_id => provider.client_id,
|
146
|
+
:client_secret => provider.client_secret,
|
147
|
+
:grant_type => "authorization_code",
|
148
|
+
:redirect_uri => provider.redirect_uri,
|
149
|
+
:code => "my_code"
|
150
|
+
}
|
151
|
+
).
|
152
|
+
to_return do
|
153
|
+
count += 1
|
154
|
+
{:body => fixture("oauth2_access.json"), :status=>200}
|
155
|
+
end
|
156
|
+
# Make sure the auth request goes out twice.
|
157
|
+
# Fail the first time, but then return the correct value after reauthentication
|
158
|
+
stub_request(:get, "https://api.flexmls.com/#{FlexmlsApi.version}/listings/1234").
|
159
|
+
with(:query => {:access_token => "04u7h-4cc355-70k3n"}).
|
160
|
+
to_return(:body => fixture('errors/expired.json'), :status => 401).times(1).then.
|
161
|
+
to_return(:body => fixture('listing_with_documents.json'))
|
162
|
+
|
163
|
+
client.get("/listings/1234")
|
164
|
+
count.should eq(2)
|
165
|
+
client.session.expired?.should eq(false)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
describe FlexmlsApi::Authentication::BaseOAuth2Provider do
|
172
|
+
context "session_timeout" do
|
173
|
+
it "should provide a default" do
|
174
|
+
subject.session_timeout.should eq(3600)
|
175
|
+
end
|
176
|
+
describe TestOAuth2Provider do
|
177
|
+
subject { TestOAuth2Provider.new }
|
178
|
+
it "should be able to override the session timeout" do
|
179
|
+
subject.session_timeout.should eq(7200)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|