plangrade-ruby 0.2.0 → 0.3.0

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.
@@ -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