plangrade-ruby 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,109 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Copyright (c) Microsoft Corporation
4
+ # All rights reserved.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
+ # ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
14
+ # IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR
15
+ # PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
16
+ #
17
+ # See the Apache Version 2.0 License for specific language governing
18
+ # permissions and limitations under the License.
19
+
20
+ require File.expand_path('../spec_helper', __FILE__)
21
+
22
+ describe Plangrade::OAuth2Client do
23
+
24
+ subject do
25
+ Plangrade::OAuth2Client.new('PRbTcg9qjgKsp4jjpm1pw', 'a2nQpcUm2Dgq1chWdAvbXGTk', {
26
+ :connection_options => {
27
+ :headers => {
28
+ 'User-Agent' => "Plangrade OAuth2 Client #{Plangrade::Ruby::VERSION}",
29
+ "Accept" => "application/json"
30
+ }
31
+ }
32
+ })
33
+ end
34
+
35
+ describe "#webserver_authorization_url" do
36
+ it "returns the authorization url" do
37
+ params = {
38
+ "client_id" => "PRbTcg9qjgKsp4jjpm1pw",
39
+ "redirect_uri" => "https://localhost:3000/callback",
40
+ "response_type" =>"code",
41
+ "state" => "12345"
42
+ }
43
+
44
+ auth_url = subject.webserver_authorization_url(
45
+ :client_id => 'PRbTcg9qjgKsp4jjpm1pw',
46
+ :state => '12345',
47
+ :redirect_uri => 'https://localhost:3000/callback'
48
+ )
49
+
50
+ parsed_url = Addressable::URI.parse(auth_url)
51
+ expect(parsed_url.path).to eq '/oauth/authorize'
52
+ expect(parsed_url.query_values).to eq params
53
+ expect(parsed_url.scheme).to eq 'https'
54
+ expect(parsed_url.host).to eq 'plangrade.com'
55
+ end
56
+ end
57
+
58
+ describe "#exchange_auth_code_for_token" do
59
+ it "makes a POST request to exchange authorization code for access token" do
60
+
61
+ stub_request(:post, "https://plangrade.com/oauth/token").with(
62
+ :body => {
63
+ :grant_type => 'authorization_code',
64
+ :code => 'MmOGL795LbIZuJJVnL49Cc',
65
+ :redirect_uri => 'http://localhost:3000/callback',
66
+ :client_id => 'PRbTcg9qjgKsp4jjpm1pw',
67
+ :client_secret => 'a2nQpcUm2Dgq1chWdAvbXGTk'
68
+ },
69
+ :headers => {
70
+ 'Accept' =>'application/json',
71
+ 'Content-Type' =>'application/x-www-form-urlencoded',
72
+ 'User-Agent' =>"Plangrade OAuth2 Client #{Plangrade::Ruby::VERSION}"
73
+ })
74
+
75
+ subject.exchange_auth_code_for_token(
76
+ :params => {
77
+ :code => 'MmOGL795LbIZuJJVnL49Cc',
78
+ :redirect_uri => 'http://localhost:3000/callback'
79
+ }
80
+ )
81
+ end
82
+ end
83
+
84
+ describe "#refresh_access_token" do
85
+ it "makes a POST request to exchange a refresh token for access token" do
86
+
87
+ stub_request(:post, "https://plangrade.com/oauth/token").with(
88
+ :body => {
89
+ :grant_type => 'refresh_token',
90
+ :refresh_token => 'MmOGL795LbIZuJJVnL49Cc',
91
+ :redirect_uri => 'http://localhost:3000/callback',
92
+ :client_id => 'PRbTcg9qjgKsp4jjpm1pw',
93
+ :client_secret => 'a2nQpcUm2Dgq1chWdAvbXGTk'
94
+ },
95
+ :headers => {
96
+ 'Accept' =>'application/json',
97
+ 'Content-Type' =>'application/x-www-form-urlencoded',
98
+ 'User-Agent' =>"Plangrade OAuth2 Client #{Plangrade::Ruby::VERSION}"
99
+ })
100
+
101
+ subject.refresh_access_token(
102
+ :params => {
103
+ :refresh_token => 'MmOGL795LbIZuJJVnL49Cc',
104
+ :redirect_uri => 'http://localhost:3000/callback'
105
+ }
106
+ )
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,190 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Copyright (c) Microsoft Corporation
4
+ # All rights reserved.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
+ # ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
14
+ # IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR
15
+ # PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
16
+ #
17
+ # See the Apache Version 2.0 License for specific language governing
18
+ # permissions and limitations under the License.
19
+
20
+ require File.expand_path('../../spec_helper', __FILE__)
21
+
22
+ describe Plangrade::Resources::Base do
23
+
24
+ class DummyModel < Plangrade::Resources::Base
25
+ attr_accessor_deffered :name, :email
26
+ end
27
+
28
+ class Plangrade::Client
29
+ def update_dummy_model(id, opts={})
30
+ put("/api/v1/dummy_models/#{id}", opts)
31
+ end
32
+ end
33
+
34
+ before :all do
35
+ Plangrade.configure do |conf|
36
+ conf.access_token = 'TolNOFka9Uls2DxahNi78A'
37
+ end
38
+ end
39
+
40
+ after :all do
41
+ Plangrade.reset!
42
+ end
43
+
44
+ context 'new user object with id' do
45
+
46
+ subject { DummyModel.new(:id => 42) }
47
+
48
+ describe "#id" do
49
+ it 'should be 42' do
50
+ expect(subject.id).to eq 42
51
+ end
52
+ end
53
+
54
+ describe "#id=" do
55
+ it 'sets id' do
56
+ subject.send(:"id=", 2)
57
+ expect(subject.id).to eq 2
58
+ end
59
+ end
60
+
61
+ describe "#new_record?" do
62
+ it 'returns false' do
63
+ expect(subject.new_record?).to eq false
64
+ end
65
+ end
66
+
67
+ describe "#modified?" do
68
+
69
+ context 'new model and no changes' do
70
+ it 'returns false' do
71
+ model = DummyModel.new(:name => 'jim', :email => 'compliance@plangrade.com')
72
+ expect(model.modified?).to eq false
73
+ end
74
+ end
75
+
76
+ context 'new model and no changes' do
77
+ it 'returns false' do
78
+ model = DummyModel.new(:name => 'mary', :email => 'support@plangrade.com')
79
+ model.name = 'jim'
80
+ model.email = 'compliance@plangrade.com'
81
+ expect(model.modified?).to eq false
82
+ end
83
+ end
84
+
85
+ context 'persisted model and no changes' do
86
+ it 'returns true' do
87
+ model = DummyModel.new(:id => 12, :name => 'jim', :email => 'compliance@plangrade.com')
88
+ expect(model.modified?).to eq false
89
+ end
90
+ end
91
+
92
+ context 'persisted model and changes' do
93
+ it 'returns true' do
94
+ model = DummyModel.new(:id => 42, :name => 'jim', :email => 'compliance@plangrade.com')
95
+ model.name = 'smithy'
96
+ expect(model.modified?).to eq true
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "#changes" do
102
+ it 'returns empty hash' do
103
+ expect(subject.changes).to eq({})
104
+ end
105
+ end
106
+
107
+ describe "#save" do
108
+ it 'returns true' do
109
+ stub_request(:put, "https://plangrade.com/api/v1/dummy_models/42").with(
110
+ :body => {"name"=>"smithy"},
111
+ :headers => {
112
+ 'Accept' =>'application/json',
113
+ 'Authorization'=>'Bearer TolNOFka9Uls2DxahNi78A',
114
+ 'Content-Type' =>'application/x-www-form-urlencoded',
115
+ 'User-Agent' =>"Plangrade Ruby Gem #{Plangrade::Ruby::VERSION}"})
116
+ model = DummyModel.new(:id => 42, :name => 'jim', :email => 'compliance@plangrade.com')
117
+ model.name = 'smithy'
118
+ model.save
119
+ end
120
+ end
121
+
122
+ describe "#base_name" do
123
+ it 'returns true' do
124
+ expect(subject.base_name).to eq 'dummy_model'
125
+ end
126
+ end
127
+
128
+ describe "setters" do
129
+ it 'should update modified attributes hash' do
130
+ subject
131
+ end
132
+ end
133
+
134
+ describe "#save" do
135
+
136
+ context 'unmodified model' do
137
+ it 'does nothing' do
138
+ expect(subject.save).to eq subject
139
+ end
140
+ end
141
+
142
+ context 'modified model' do
143
+ subject { DummyModel.new(:id => 42, :name => 'john', :email => 'compliance@plangrade.com') }
144
+
145
+ it 'should update model' do
146
+ api_handler = double("ApiHandler")
147
+ api_handler.should_receive(:update_dummy_model).with(42, hash_including(
148
+ :name =>'john',
149
+ :email => 'support@plangrade.com')
150
+ ).and_return(double('Response', :success? => true, :created? => true, :body => {:id => 2}))
151
+
152
+ subject.stub(:api_handler).and_return(api_handler)
153
+ subject.name = 'john'
154
+ subject.email = 'support@plangrade.com'
155
+ subject.save
156
+ end
157
+ end
158
+
159
+ context 'unmodified new model' do
160
+ subject { DummyModel.new(:name => 'jim', :email => 'compliance@plangrade.com') }
161
+
162
+ it 'should do nothing' do
163
+ api_handler = double("ApiHandler")
164
+ api_handler.should_receive(:create_dummy_model).with(
165
+ hash_including(:name =>'jim', :email => 'compliance@plangrade.com')
166
+ ).and_return(double('Response', :success? => true, :created? => true, :body => {:id => '2'}))
167
+
168
+ subject.stub(:api_handler).and_return(api_handler)
169
+ subject.save
170
+ end
171
+ end
172
+
173
+ context 'modified new model' do
174
+ subject { DummyModel.new(:name => 'jim', :email => 'compliance@plangrade.com') }
175
+
176
+ it 'should create model' do
177
+ api_handler = double("ApiHandler")
178
+ api_handler.should_receive(:create_dummy_model).with({
179
+ :name =>'john',
180
+ :email => 'compliance@plangrade.com'
181
+ }).and_return(double('Response', :success? => true, :created? => true, :body => {:id => 2}))
182
+
183
+ subject.stub(:api_handler).and_return(api_handler)
184
+ subject.name = 'john'
185
+ subject.save
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,135 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Copyright (c) Microsoft Corporation
4
+ # All rights reserved.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
+ # ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
14
+ # IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR
15
+ # PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
16
+ #
17
+ # See the Apache Version 2.0 License for specific language governing
18
+ # permissions and limitations under the License.
19
+
20
+ require File.expand_path('../../spec_helper', __FILE__)
21
+
22
+ describe Plangrade::Resources::Company do
23
+
24
+ before :all do
25
+ Plangrade.configure do |conf|
26
+ conf.access_token = 'TolNOFka9Uls2DxahNi78A'
27
+ end
28
+ end
29
+
30
+ after :all do
31
+ Plangrade.reset!
32
+ end
33
+
34
+ context 'class methods' do
35
+
36
+ subject { Plangrade::Resources::Company }
37
+
38
+ describe '#create' do
39
+ it 'creates a new company' do
40
+ stub_request(:post, "https://plangrade.com/api/v1/companies").with(
41
+ :body => { :name => "plangrade, llc", :ein => '123456789' },
42
+ :headers => {
43
+ 'Accept' => 'application/json',
44
+ 'Authorization' => "Bearer #{Plangrade.access_token}",
45
+ 'Content-Type' => 'application/x-www-form-urlencoded',
46
+ 'User-Agent' => "Plangrade Ruby Gem #{Plangrade::Ruby::VERSION}"
47
+ }
48
+ ).to_return(
49
+ :status => 201,
50
+ :body => '',
51
+ :headers => { 'Location' => 'https://plangrade.com/api/v1/companies/4'}
52
+ )
53
+ subject.create("123456789", "plangrade, llc")
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'new company object with id' do
59
+
60
+ before :each do
61
+ Plangrade::Resources::Company.identity_map.purge!
62
+ end
63
+
64
+ subject { Plangrade::Resources::Company.new(:id => 1) }
65
+
66
+ describe "#id" do
67
+ it 'returns id' do
68
+ expect(subject.id).to eq 1
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'hydrated user object' do
74
+ subject { Plangrade::Resources::Company.new(MultiJson.load(fixture('company.json'), :symbolize_keys => true)) }
75
+
76
+ describe "#id" do
77
+ it 'returns id' do
78
+ expect(subject.id).to eq 4
79
+ end
80
+ end
81
+
82
+ describe "#ein" do
83
+ it 'returns ein' do
84
+ stub_request(:get, "https://plangrade.com/api/v1/companies/4").
85
+ with(:headers => {
86
+ 'Accept'=>'application/json',
87
+ 'Authorization'=>"Bearer #{Plangrade.access_token}",
88
+ 'User-Agent'=>"Plangrade Ruby Gem #{Plangrade::Ruby::VERSION}"
89
+ }).to_return(
90
+ :status => 200,
91
+ :body => fixture('company.json'),
92
+ :headers => {}
93
+ )
94
+ expect(subject.ein).to eq '123456789'
95
+ end
96
+ end
97
+
98
+ describe "#delete" do
99
+ it 'deletes company' do
100
+ stub_request(:delete, "https://plangrade.com/api/v1/companies/4").
101
+ with(:headers => {
102
+ 'Accept'=>'application/json',
103
+ 'Authorization'=>"Bearer #{Plangrade.access_token}",
104
+ 'User-Agent'=>"Plangrade Ruby Gem #{Plangrade::Ruby::VERSION}"
105
+ }).to_return(
106
+ :status => 200,
107
+ :body => '',
108
+ :headers => {}
109
+ )
110
+ subject.delete!
111
+ end
112
+ end
113
+
114
+ describe '#update' do
115
+ context 'with id as an integer' do
116
+ it 'updates company' do
117
+ stub_request(:put, "https://plangrade.com/api/v1/companies/4").with(
118
+ :body => { :name => 'plangrade, llc' },
119
+ :headers => {
120
+ 'Accept' => 'application/json',
121
+ 'Authorization' => "Bearer #{Plangrade.access_token}",
122
+ 'Content-Type' => 'application/x-www-form-urlencoded',
123
+ 'User-Agent' => "Plangrade Ruby Gem #{Plangrade::Ruby::VERSION}"
124
+ }
125
+ ).to_return(
126
+ :status => 200,
127
+ :body => '',
128
+ :headers => { 'Location' => 'https://plangrade.com/api/v1/companies/4'}
129
+ )
130
+ subject.update!(:name => 'plangrade, llc')
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,127 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # Copyright (c) Microsoft Corporation
4
+ # All rights reserved.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
+ # ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
14
+ # IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR
15
+ # PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
16
+ #
17
+ # See the Apache Version 2.0 License for specific language governing
18
+ # permissions and limitations under the License.
19
+
20
+ require File.expand_path('../../spec_helper', __FILE__)
21
+ require 'plangrade/resources/identity_map'
22
+
23
+ describe Plangrade::Resources::IdentityMap do
24
+
25
+ subject { Plangrade::Resources::IdentityMap.new }
26
+
27
+ after :each do
28
+ subject.purge!
29
+ end
30
+
31
+ context 'after initialization' do
32
+ describe '#size' do
33
+ it 'should be zero' do
34
+ expect(subject.size).to eq 0
35
+ end
36
+ end
37
+
38
+ describe '#get' do
39
+ context 'with string parameter' do
40
+ it 'should return nil' do
41
+ expect(subject.get(:key)).to eq nil
42
+ end
43
+ end
44
+
45
+ context 'with symbol parameter' do
46
+ it 'should return nil' do
47
+ expect(subject.get('key')).to eq nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ context 'with data' do
54
+ describe '#put' do
55
+ context 'with nil key' do
56
+ it 'should throw exception' do
57
+ expect { subject.put(nil, 'value') }.to raise_error(Plangrade::Resources::IdentityMap::InvalidKeyError)
58
+ end
59
+ end
60
+
61
+ context 'with empty string' do
62
+ it 'should throw exception' do
63
+ expect { subject.put('', 'value') }.to raise_error(Plangrade::Resources::IdentityMap::InvalidKeyError)
64
+ end
65
+ end
66
+
67
+ it 'should store new value' do
68
+ subject.put('user_1', 'smith')
69
+ expect(subject.size).to eq 1
70
+ expect(subject.get('user_1')).to eq 'smith'
71
+ end
72
+
73
+ it 'should overwrite existing value' do
74
+ subject.put('user_1', 'smith')
75
+ subject.put('user_1', 'john')
76
+ expect(subject.size).to eq 1
77
+ expect(subject.get('user_1')).to eq 'john'
78
+ end
79
+ end
80
+
81
+ describe '#get' do
82
+ context 'with nil key' do
83
+ it 'should throw exception' do
84
+ expect(subject.get(nil)).to eq nil
85
+ end
86
+ end
87
+
88
+ context 'with empty string' do
89
+ it 'should throw exception' do
90
+ expect(subject.get('')).to eq nil
91
+ end
92
+ end
93
+
94
+ context 'with valid key' do
95
+ it 'should return a value' do
96
+ subject.put('user_1', 'smith')
97
+ end
98
+ end
99
+
100
+ context 'with valid key and default value' do
101
+ it 'should return default' do
102
+ subject.put('user_1', 'smith')
103
+ expect(subject.get('user_1', 'test')).to eq 'smith'
104
+ end
105
+ end
106
+
107
+ context 'with invalid key and default value' do
108
+ it 'should return default' do
109
+ expect(subject.get('user_1', 'test')).to eq 'test'
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#purge!' do
116
+ before do
117
+ subject.put('user_1', 'smith')
118
+ subject.put('user_2', 'john')
119
+ end
120
+
121
+ it 'empties the map' do
122
+ expect(subject.size).to eq 2
123
+ subject.purge!
124
+ expect(subject.size).to eq 0
125
+ end
126
+ end
127
+ end