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.
Files changed (93) hide show
  1. data/Gemfile +2 -17
  2. data/Gemfile.lock +35 -27
  3. data/README.md +23 -1
  4. data/Rakefile +18 -5
  5. data/VERSION +1 -1
  6. data/bin/flexmls_api +8 -0
  7. data/lib/flexmls_api.rb +2 -0
  8. data/lib/flexmls_api/authentication.rb +5 -6
  9. data/lib/flexmls_api/authentication/api_auth.rb +4 -2
  10. data/lib/flexmls_api/authentication/oauth2.rb +51 -99
  11. data/lib/flexmls_api/authentication/oauth2_impl/grant_type_base.rb +85 -0
  12. data/lib/flexmls_api/authentication/oauth2_impl/grant_type_code.rb +48 -0
  13. data/lib/flexmls_api/authentication/oauth2_impl/grant_type_password.rb +45 -0
  14. data/lib/flexmls_api/authentication/oauth2_impl/grant_type_refresh.rb +36 -0
  15. data/lib/flexmls_api/authentication/oauth2_impl/middleware.rb +39 -0
  16. data/lib/flexmls_api/cli.rb +132 -0
  17. data/lib/flexmls_api/cli/api_auth.rb +8 -0
  18. data/lib/flexmls_api/cli/oauth2.rb +43 -0
  19. data/lib/flexmls_api/cli/setup.rb +44 -0
  20. data/lib/flexmls_api/configuration.rb +6 -6
  21. data/lib/flexmls_api/faraday.rb +11 -21
  22. data/lib/flexmls_api/models.rb +3 -0
  23. data/lib/flexmls_api/models/account.rb +48 -5
  24. data/lib/flexmls_api/models/base.rb +27 -2
  25. data/lib/flexmls_api/models/contact.rb +28 -9
  26. data/lib/flexmls_api/models/listing_cart.rb +72 -0
  27. data/lib/flexmls_api/models/note.rb +0 -2
  28. data/lib/flexmls_api/models/saved_search.rb +16 -0
  29. data/lib/flexmls_api/models/shared_listing.rb +35 -0
  30. data/lib/flexmls_api/multi_client.rb +37 -0
  31. data/lib/flexmls_api/paginate.rb +5 -0
  32. data/lib/flexmls_api/request.rb +7 -3
  33. data/script/console +6 -0
  34. data/script/example.rb +27 -0
  35. data/spec/fixtures/accounts/all.json +160 -0
  36. data/spec/fixtures/accounts/my.json +74 -0
  37. data/spec/fixtures/accounts/my_portal.json +20 -0
  38. data/spec/fixtures/accounts/my_put.json +5 -0
  39. data/spec/fixtures/accounts/my_save.json +5 -0
  40. data/spec/fixtures/accounts/office.json +142 -0
  41. data/spec/fixtures/base.json +13 -0
  42. data/spec/fixtures/contact_my.json +19 -0
  43. data/spec/fixtures/contact_new.json +11 -0
  44. data/spec/fixtures/contact_new_empty.json +8 -0
  45. data/spec/fixtures/contact_new_notify.json +11 -0
  46. data/spec/fixtures/contact_tags.json +11 -0
  47. data/spec/fixtures/contacts.json +6 -3
  48. data/spec/fixtures/contacts_post.json +10 -0
  49. data/spec/fixtures/empty.json +3 -0
  50. data/spec/fixtures/errors/failure.json +5 -0
  51. data/spec/fixtures/listing_cart.json +19 -0
  52. data/spec/fixtures/listing_cart_add_listing.json +13 -0
  53. data/spec/fixtures/listing_cart_add_listing_post.json +5 -0
  54. data/spec/fixtures/listing_cart_empty.json +5 -0
  55. data/spec/fixtures/listing_cart_new.json +12 -0
  56. data/spec/fixtures/listing_cart_post.json +10 -0
  57. data/spec/fixtures/listing_cart_remove_listing.json +13 -0
  58. data/spec/fixtures/note_new.json +5 -0
  59. data/spec/fixtures/{oauth2_access.json → oauth2/access.json} +0 -0
  60. data/spec/fixtures/oauth2/access_with_old_refresh.json +5 -0
  61. data/spec/fixtures/oauth2/access_with_refresh.json +5 -0
  62. data/spec/fixtures/oauth2/authorization_code_body.json +7 -0
  63. data/spec/fixtures/oauth2/error.json +3 -0
  64. data/spec/fixtures/oauth2/password_body.json +7 -0
  65. data/spec/fixtures/oauth2/refresh_body.json +7 -0
  66. data/spec/fixtures/saved_search.json +17 -0
  67. data/spec/fixtures/shared_listing_new.json +9 -0
  68. data/spec/fixtures/shared_listing_post.json +10 -0
  69. data/spec/mock_helper.rb +123 -0
  70. data/spec/oauth2_helper.rb +69 -0
  71. data/spec/spec_helper.rb +1 -57
  72. data/spec/unit/flexmls_api/authentication/api_auth_spec.rb +1 -0
  73. data/spec/unit/flexmls_api/authentication/oauth2_impl/grant_type_base_spec.rb +10 -0
  74. data/spec/unit/flexmls_api/authentication/oauth2_spec.rb +74 -79
  75. data/spec/unit/flexmls_api/configuration_spec.rb +25 -4
  76. data/spec/unit/flexmls_api/models/account_spec.rb +152 -85
  77. data/spec/unit/flexmls_api/models/base_spec.rb +69 -25
  78. data/spec/unit/flexmls_api/models/contact_spec.rb +48 -34
  79. data/spec/unit/flexmls_api/models/document_spec.rb +1 -7
  80. data/spec/unit/flexmls_api/models/listing_cart_spec.rb +114 -0
  81. data/spec/unit/flexmls_api/models/listing_spec.rb +8 -56
  82. data/spec/unit/flexmls_api/models/note_spec.rb +8 -38
  83. data/spec/unit/flexmls_api/models/photo_spec.rb +1 -11
  84. data/spec/unit/flexmls_api/models/saved_search_spec.rb +34 -0
  85. data/spec/unit/flexmls_api/models/shared_listing_spec.rb +30 -0
  86. data/spec/unit/flexmls_api/models/standard_fields_spec.rb +50 -30
  87. data/spec/unit/flexmls_api/models/tour_of_home_spec.rb +1 -7
  88. data/spec/unit/flexmls_api/models/video_spec.rb +1 -10
  89. data/spec/unit/flexmls_api/models/virtual_tour_spec.rb +1 -7
  90. data/spec/unit/flexmls_api/multi_client_spec.rb +48 -0
  91. data/spec/unit/flexmls_api/request_spec.rb +42 -5
  92. metadata +239 -93
  93. data/spec/unit/flexmls_api/standard_fields_spec.rb +0 -86
@@ -0,0 +1,13 @@
1
+ {"D": {
2
+ "Success": true,
3
+ "Results": [{
4
+ "Id": 1,
5
+ "Name": "My Example",
6
+ "Test": true
7
+ },
8
+ {
9
+ "Id": 2,
10
+ "Name": "My Example2",
11
+ "Test": false
12
+ }]}
13
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "D": {
3
+ "Results": [
4
+ {
5
+ "HomeStreetAddress": "23541235",
6
+ "ResourceUri": "/v1/my/contact",
7
+ "DisplayName": "BH FOO",
8
+ "Id": "20090928182824338901000000",
9
+ "Tags": [
10
+ "IDX Lead"
11
+ ],
12
+ "PrimaryEmail": "bhfoo@fbsdata.com",
13
+ "FamilyName": "foo",
14
+ "GivenName": "bh"
15
+ }
16
+ ],
17
+ "Success": true
18
+ }
19
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "D": {
3
+ "Notify": false,
4
+ "Contacts": [
5
+ {
6
+ "DisplayName": "Contact Four",
7
+ "PrimaryEmail": "contact4@fbsdata.com"
8
+ }
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "D": {
3
+ "Notify": false,
4
+ "Contacts": [
5
+ { }
6
+ ]
7
+ }
8
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "D": {
3
+ "Contacts": [
4
+ {
5
+ "DisplayName": "Contact Four",
6
+ "PrimaryEmail": "contact4@fbsdata.com"
7
+ }
8
+ ],
9
+ "Notify": true
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {"ResourceUri": "/v1/contacts/tags/Current Buyers", "Tag": "Current Buyers"},
6
+ {"ResourceUri": "/v1/contacts/tags/Past Buyers", "Tag": "Past Buyers"},
7
+ {"ResourceUri": "/v1/contacts/tags/Current Sellers", "Tag": "Current Sellers"},
8
+ {"ResourceUri": "/v1/contacts/tags/TEST", "Tag": "TEST"}
9
+ ]
10
+ }
11
+ }
@@ -6,19 +6,22 @@
6
6
  "ResourceUri":"/v1/contacts/20101230223226074201000000",
7
7
  "DisplayName":"Contact One",
8
8
  "Id":"20101230223226074201000000",
9
- "PrimaryEmail":"contact1@fbsdata.com"
9
+ "PrimaryEmail":"contact1@fbsdata.com",
10
+ "Tags": ["IDX Lead"]
10
11
  },
11
12
  {
12
13
  "ResourceUri":"/v1/contacts/20101230223226074202000000",
13
14
  "DisplayName":"Contact Two",
14
15
  "Id":"20101230223226074202000000",
15
- "PrimaryEmail":"contact2fbsdata.com"
16
+ "PrimaryEmail":"contact2fbsdata.com",
17
+ "Tags": ["IDX Lead"]
16
18
  },
17
19
  {
18
20
  "ResourceUri":"/v1/contacts/20101230223226074203000000",
19
21
  "DisplayName":"Contact Three",
20
22
  "Id":"20101230223226074203000000",
21
- "PrimaryEmail":"contact3@fbsdata.com"
23
+ "PrimaryEmail":"contact3@fbsdata.com",
24
+ "Tags": ["IDX Lead"]
22
25
  }
23
26
  ]
24
27
  }
@@ -0,0 +1,10 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri":"/v1/contacts/20101230223226074204000000"
7
+ }
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "D": { }
3
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "Success": false
4
+ }
5
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/listingcarts/20100912153422758914000000",
7
+ "Id": "20100912153422758914000000",
8
+ "Name": "My Listing Cart",
9
+ "ListingCount": 10
10
+ },
11
+ {
12
+ "ResourceUri": "/v1/listingcarts/20110112133422752751000000",
13
+ "Id": "20110112133422752751000000",
14
+ "Name": "My Other Listing Cart",
15
+ "ListingCount": 15
16
+ }
17
+ ]
18
+ }
19
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/listingcarts/20100912153422758914000000",
7
+ "Id": "20100912153422758914000000",
8
+ "Name": "My Listing Cart",
9
+ "ListingCount": 11
10
+ }
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "ListingIds": [ "20110621133454434543000000" ]
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "ListingCarts": [{}]
4
+ }
5
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "D": {
3
+ "ListingCarts": [{
4
+ "Name": "My Cart's Name",
5
+ "ListingIds": [
6
+ "20110112234857732941000000",
7
+ "20110302120238448431000000",
8
+ "20110510011212354751000000"
9
+ ]
10
+ }]
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri":"/v1/listingcarts/20100912153422758914000000"
7
+ }
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/listingcarts/20100912153422758914000000",
7
+ "Id": "20100912153422758914000000",
8
+ "Name": "My Listing Cart",
9
+ "ListingCount": 9
10
+ }
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "D": {
3
+ "Note": "lorem ipsum dolor"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "expires_in":0,
3
+ "refresh_token":"0ld-r3fr35h-70k3n",
4
+ "access_token": "0ld-04u7h-4cc355-70k3n"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "expires_in":86384,
3
+ "refresh_token":"r3fr35h-70k3n",
4
+ "access_token": "04u7h-4cc355-70k3n"
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "code":"my_code",
3
+ "client_secret":"example-password",
4
+ "client_id":"example-id",
5
+ "redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback",
6
+ "grant_type":"authorization_code"
7
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "error": "invalid_request"
3
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "client_secret":"example-password",
3
+ "client_id":"example-id",
4
+ "grant_type":"password",
5
+ "username":"angry_dev",
6
+ "password":"nerds"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "client_id":"example-id",
3
+ "client_secret":"example-password",
4
+ "refresh_token":"example-token",
5
+ "grant_type":"refresh_token",
6
+ "redirect_uri":"https://exampleapp.fbsdata.com/oauth-callback",
7
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "/v1/savedsearches/20100815220615294367000000",
7
+ "Id": "20100815220615294367000000",
8
+ "Name": "Search name here"
9
+ },
10
+ {
11
+ "ResourceUri": "/v1/savedsearches/20100615220615292711000000",
12
+ "Id": "20100615220615292711000000",
13
+ "Name": "Second search name here"
14
+ }
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "D": {
3
+ "ListingIds": [
4
+ "20110224152431857619000000",
5
+ "20110125122333785431000000"
6
+ ],
7
+ "ViewId": "20080125122333787615000000"
8
+ }
9
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "D": {
3
+ "Success": true,
4
+ "Results": [
5
+ {
6
+ "ResourceUri": "http://www.flexmls.com/share/15Ar/3544-N-Olsen-Avenue-Tucson-AZ-85719"
7
+ }
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,123 @@
1
+
2
+ Rspec.configure do |config|
3
+ config.include WebMock::API
4
+ end
5
+
6
+ $test_client = FlexmlsApi::Client.new({:api_key=>"", :api_secret=>""})
7
+ def stub_api_get(service_path, stub_fixture="success.json", opts={})
8
+ params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
9
+ sig = $test_client.authenticator.sign_token("/#{FlexmlsApi.version}#{service_path}", params)
10
+ s=stub_request(:get, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}#{service_path}").
11
+ with(:query => {
12
+ :ApiSig => sig
13
+ }.merge(params))
14
+ if(block_given?)
15
+ yield s
16
+ else
17
+ s.to_return(:body => fixture(stub_fixture))
18
+ end
19
+ log_stub(s)
20
+ end
21
+ def stub_api_delete(service_path, stub_fixture="success.json", opts={})
22
+ params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
23
+ sig = $test_client.authenticator.sign_token("/#{FlexmlsApi.version}#{service_path}", params)
24
+ s=stub_request(:delete, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}#{service_path}").
25
+ with(:query => {
26
+ :ApiSig => sig
27
+ }.merge(params))
28
+ if(block_given?)
29
+ yield s
30
+ else
31
+ s.to_return(:body => fixture(stub_fixture))
32
+ end
33
+ log_stub(s)
34
+ end
35
+ def stub_api_post(service_path, body, stub_fixture="success.json", opts={})
36
+ body_str = JSON.parse(fixture(body).read).to_json
37
+ params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
38
+ sig = $test_client.authenticator.sign_token("/#{FlexmlsApi.version}#{service_path}", params, body_str)
39
+ s=stub_request(:post, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}#{service_path}").
40
+ with(:query => {
41
+ :ApiSig => sig
42
+ }.merge(params),
43
+ :body => body_str
44
+ )
45
+ if(block_given?)
46
+ yield s
47
+ else
48
+ s.to_return(:body => fixture(stub_fixture))
49
+ end
50
+ log_stub(s)
51
+ end
52
+ def stub_api_put(service_path, body, stub_fixture="success.json", opts={})
53
+ body_str = JSON.parse(fixture(body).read).to_json
54
+ params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
55
+ sig = $test_client.authenticator.sign_token("/#{FlexmlsApi.version}#{service_path}", params, body_str)
56
+ s=stub_request(:put, "#{FlexmlsApi.endpoint}/#{FlexmlsApi.version}#{service_path}").
57
+ with(:query => {
58
+ :ApiSig => sig
59
+ }.merge(params),
60
+ :body => body_str
61
+ )
62
+ if(block_given?)
63
+ yield s
64
+ else
65
+ s.to_return(:body => fixture(stub_fixture))
66
+ end
67
+ log_stub(s)
68
+ end
69
+
70
+ def log_stub(s)
71
+ FlexmlsApi.logger.debug("Stubbed Request: #{s.inspect}")
72
+ end
73
+
74
+ def mock_session()
75
+ FlexmlsApi::Authentication::Session.new("AuthToken" => "1234", "Expires" => (Time.now + 3600).to_s, "Roles" => "['idx']")
76
+ end
77
+
78
+ def mock_oauth_session()
79
+ FlexmlsApi::Authentication::OAuthSession.new("access_token" => "1234", "expires_in" => 3600, "scope" => nil, "refresh_token"=> "1000refresh")
80
+ end
81
+
82
+ class MockClient < FlexmlsApi::Client
83
+ attr_accessor :connection
84
+ def connection(ssl = false)
85
+ @connection
86
+ end
87
+ end
88
+
89
+ class MockApiAuthenticator < FlexmlsApi::Authentication::ApiAuth
90
+ # Sign a request
91
+ def sign(sig)
92
+ "SignedToken"
93
+ end
94
+ end
95
+
96
+ def mock_client(stubs)
97
+ c = MockClient.new
98
+ c.session = mock_session()
99
+ c.connection = test_connection(stubs)
100
+ c
101
+ end
102
+
103
+ def mock_expired_session()
104
+ FlexmlsApi::Authentication::Session.new("AuthToken" => "1234", "Expires" => (Time.now - 60).to_s, "Roles" => "['idx']")
105
+ end
106
+
107
+ def test_connection(stubs)
108
+ Faraday::Connection.new(nil, {:headers => FlexmlsApi::Client.new.headers}) do |builder|
109
+ builder.adapter :test, stubs
110
+ builder.use FlexmlsApi::FaradayExt::FlexmlsMiddleware
111
+ end
112
+ end
113
+
114
+ def stub_auth_request()
115
+ stub_request(:post, "https://api.flexmls.com/#{FlexmlsApi.version}/session").
116
+ with(:query => {:ApiKey => "", :ApiSig => "806737984ab19be2fd08ba36030549ac"}).
117
+ to_return(:body => fixture("session.json"))
118
+ end
119
+
120
+ def fixture(file)
121
+ File.new(File.expand_path("../fixtures", __FILE__) + '/' + file)
122
+ end
123
+