weichat_rails 0.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/weichat_rails.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "weichat_rails/api"
2
2
  require "weichat_rails/auto_generate_secret_key"
3
+ require 'dalli'
3
4
 
4
5
  module WeichatRails
5
6
 
@@ -16,12 +17,20 @@ module WeichatRails
16
17
  end
17
18
  end
18
19
 
20
+ Config = Struct.new(:cache,:cache_namespace,:appid,:secret,:timeout,:skip_verify_ssl)
19
21
 
20
22
  class << self
23
+
21
24
  def config
22
- @config || OpenStruct.new({wechat_secret_string: nil,wechat_token_string: nil})
25
+ @config ||= Config.new(nil,'weichat_rails',nil,nil,20,true)
26
+ end
27
+
28
+ def api
29
+ @weichat_api ||= WeichatRails::Api.new(config.appid,config.secret,config.timeout,config.skip_verify_ssl)
23
30
  end
24
31
 
32
+
33
+
25
34
  #can configure the wechat_secret_string,wechat_token_string in weichat_rails_config.rb file
26
35
  def configure
27
36
  yield config if block_given?
@@ -29,13 +38,14 @@ module WeichatRails
29
38
 
30
39
  end
31
40
 
32
- #DEFAULT_TOKEN_COLUMN_NAME = "wechat_token".freeze
33
- #DEFAULT_WECHAT_SECRET_KEY = "wechat_secret_key".freeze
34
-
41
+ #config.cache_namespace = 'weichat_rails'
35
42
 
36
- #def self.api
37
- # # @api ||= WechatRails::Api.new(self.config.appid, self.config.secret, self.config.access_token)
38
- #end
43
+ #if use rails with dalli,you can set config.cache = Rails.cache
44
+ self.config.cache ||= if defined?(::Rails)
45
+ Rails.cache
46
+ else
47
+ Dalli::Client.new('localhost:11211',namespace: config.cache_namespace,conpress: true)
48
+ end
39
49
  end
40
50
 
41
51
  if defined? ActionController::Base
data/spec/examples.txt ADDED
@@ -0,0 +1,74 @@
1
+ example_id | status | run_time |
2
+ ---------------------------------------------------- | ------ | --------------- |
3
+ ./spec/lib/weichat_rails/access_token_spec.rb[1:1:1] | passed | 0.00105 seconds |
4
+ ./spec/lib/weichat_rails/access_token_spec.rb[1:1:2] | passed | 0.00137 seconds |
5
+ ./spec/lib/weichat_rails/access_token_spec.rb[1:1:3] | passed | 0.00112 seconds |
6
+ ./spec/lib/weichat_rails/access_token_spec.rb[1:2:1] | passed | 0.01163 seconds |
7
+ ./spec/lib/weichat_rails/api_spec.rb[1:1:1] | passed | 0.00069 seconds |
8
+ ./spec/lib/weichat_rails/api_spec.rb[1:2:1] | passed | 0.00113 seconds |
9
+ ./spec/lib/weichat_rails/api_spec.rb[1:3:1] | passed | 0.00109 seconds |
10
+ ./spec/lib/weichat_rails/api_spec.rb[1:4:1] | passed | 0.00108 seconds |
11
+ ./spec/lib/weichat_rails/api_spec.rb[1:4:2] | passed | 0.00112 seconds |
12
+ ./spec/lib/weichat_rails/api_spec.rb[1:5:1] | passed | 0.00148 seconds |
13
+ ./spec/lib/weichat_rails/api_spec.rb[1:6:1] | passed | 0.00118 seconds |
14
+ ./spec/lib/weichat_rails/api_spec.rb[1:6:2] | passed | 0.00124 seconds |
15
+ ./spec/lib/weichat_rails/api_spec.rb[1:7:1] | passed | 0.00115 seconds |
16
+ ./spec/lib/weichat_rails/api_spec.rb[1:8:1] | passed | 0.00113 seconds |
17
+ ./spec/lib/weichat_rails/api_spec.rb[1:8:2] | passed | 0.00118 seconds |
18
+ ./spec/lib/weichat_rails/api_spec.rb[1:9:1] | passed | 0.00109 seconds |
19
+ ./spec/lib/weichat_rails/api_spec.rb[1:10:1] | passed | 0.00115 seconds |
20
+ ./spec/lib/weichat_rails/api_spec.rb[1:11:1] | passed | 0.00115 seconds |
21
+ ./spec/lib/weichat_rails/api_spec.rb[1:12:1] | passed | 0.00117 seconds |
22
+ ./spec/lib/weichat_rails/api_spec.rb[1:13:1] | passed | 0.00119 seconds |
23
+ ./spec/lib/weichat_rails/api_spec.rb[1:14:1] | passed | 0.00115 seconds |
24
+ ./spec/lib/weichat_rails/api_spec.rb[1:14:2] | passed | 0.00116 seconds |
25
+ ./spec/lib/weichat_rails/api_spec.rb[1:15:1] | passed | 0.00114 seconds |
26
+ ./spec/lib/weichat_rails/api_spec.rb[1:16:1] | passed | 0.00116 seconds |
27
+ ./spec/lib/weichat_rails/api_spec.rb[1:17:1] | passed | 0.0024 seconds |
28
+ ./spec/lib/weichat_rails/api_spec.rb[1:18:1] | passed | 0.00128 seconds |
29
+ ./spec/lib/weichat_rails/api_spec.rb[1:19:1] | passed | 0.00118 seconds |
30
+ ./spec/lib/weichat_rails/api_spec.rb[1:20:1] | passed | 0.00116 seconds |
31
+ ./spec/lib/weichat_rails/api_spec.rb[1:21:1] | passed | 0.00108 seconds |
32
+ ./spec/lib/weichat_rails/api_spec.rb[1:22:1] | passed | 0.00113 seconds |
33
+ ./spec/lib/weichat_rails/api_spec.rb[1:23:1] | passed | 0.00116 seconds |
34
+ ./spec/lib/weichat_rails/api_spec.rb[1:24:1] | passed | 0.00117 seconds |
35
+ ./spec/lib/weichat_rails/api_spec.rb[1:25:1] | passed | 0.00139 seconds |
36
+ ./spec/lib/weichat_rails/api_spec.rb[1:26:1] | passed | 0.00134 seconds |
37
+ ./spec/lib/weichat_rails/client_spec.rb[1:1:1] | passed | 0.00136 seconds |
38
+ ./spec/lib/weichat_rails/client_spec.rb[1:2:1] | passed | 0.0043 seconds |
39
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:1] | passed | 0.00085 seconds |
40
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:2] | passed | 0.00238 seconds |
41
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:3] | passed | 0.00357 seconds |
42
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:4] | passed | 0.0042 seconds |
43
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:5:1] | passed | 0.00078 seconds |
44
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:5:2] | passed | 0.00092 seconds |
45
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:5:3] | passed | 0.00184 seconds |
46
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:6:1] | passed | 0.01241 seconds |
47
+ ./spec/lib/weichat_rails/client_spec.rb[1:3:6:2] | passed | 0.0011 seconds |
48
+ ./spec/lib/weichat_rails/message_spec.rb[1:1:1] | passed | 0.00021 seconds |
49
+ ./spec/lib/weichat_rails/message_spec.rb[1:2:1] | passed | 0.00026 seconds |
50
+ ./spec/lib/weichat_rails/message_spec.rb[1:3:1] | passed | 0.00244 seconds |
51
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:1] | passed | 0.00033 seconds |
52
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:2] | passed | 0.00023 seconds |
53
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:3] | passed | 0.0005 seconds |
54
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:4] | passed | 0.00078 seconds |
55
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:5] | passed | 0.00115 seconds |
56
+ ./spec/lib/weichat_rails/message_spec.rb[1:4:6] | passed | 0.00076 seconds |
57
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:1:1] | passed | 0.00023 seconds |
58
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:2:1] | passed | 0.0002 seconds |
59
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:3:1] | passed | 0.00024 seconds |
60
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:4:1] | passed | 0.00023 seconds |
61
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:5:1] | passed | 0.00021 seconds |
62
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:6:1] | passed | 0.00037 seconds |
63
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:7:1] | passed | 0.00045 seconds |
64
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:8:1] | passed | 0.00056 seconds |
65
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:8:2] | passed | 0.00048 seconds |
66
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:9:1] | passed | 0.20899 seconds |
67
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:9:2] | passed | 0.00724 seconds |
68
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:1] | passed | 0.00029 seconds |
69
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:2] | passed | 0.00026 seconds |
70
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:3] | passed | 0.00028 seconds |
71
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:4] | passed | 0.0004 seconds |
72
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:5] | passed | 0.00051 seconds |
73
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:10:6] | passed | 0.00059 seconds |
74
+ ./spec/lib/weichat_rails/message_spec.rb[1:5:11:1] | passed | 0.0011 seconds |
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe WeichatRails::AccessToken do
4
+ let(:token) { '12345' }
5
+ let(:client) { double(:client) }
6
+
7
+ subject { WeichatRails::AccessToken.new(client,'appid','secret') }
8
+
9
+ before :each do
10
+ allow(client).to receive(:get).with('token', params: {grant_type: 'client_credential', appid: 'appid', secret: 'secret'})
11
+ .and_return("access_token" => '12345', "expires_in" => 7200)
12
+ end
13
+
14
+ after :each do
15
+ WeichatRails.config.cache.delete(subject.appid)
16
+ end
17
+
18
+ describe '#token' do
19
+ it 'read from mamcache if access_token is not initialized' do
20
+ WeichatRails.config.cache.set(subject.appid,'12345',7200)
21
+ expect(subject.token).to eq('12345')
22
+ end
23
+
24
+ it "refresh access_token if token file did'n exist" do
25
+ expect(WeichatRails.config.cache.get(subject.appid)).to be nil
26
+ expect(subject.token).to eq('12345')
27
+ expect(WeichatRails.config.cache.get(subject.appid)).to eq('12345')
28
+ end
29
+
30
+ it 'raise exception if token failed' do
31
+ allow(client).to receive(:get).and_raise('error')
32
+ expect{subject.token}.to raise_error('error')
33
+ end
34
+ end
35
+
36
+ describe '#refresh' do
37
+ it 'will delete access_token' do
38
+ expect(subject.refresh).to eq(WeichatRails.config.cache.get(subject.appid))
39
+ expect(subject.token).to eq('12345')
40
+ end
41
+
42
+ end
43
+
44
+
45
+
46
+
47
+
48
+ end
@@ -0,0 +1,276 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe WeichatRails::Api do
4
+
5
+ subject do
6
+ WeichatRails::Api.new('appid','secret',20,false)
7
+ end
8
+
9
+ before :each do
10
+ allow(subject.access_token).to receive(:token).and_return('access_token')
11
+ end
12
+
13
+ describe '#client.base' do
14
+ it 'with get correct API_BASE' do
15
+ expect(subject.client.base).to eq WeichatRails::Api::API_BASE
16
+ end
17
+ end
18
+
19
+ describe '#callbackip' do
20
+ it 'will get callbackip with access_token' do
21
+ server_ip_result = 'server_ip_result'
22
+ expect(subject.client).to receive(:get).with('getcallbackip', params: { access_token: 'access_token'}).and_return(server_ip_result)
23
+ expect(subject.callbackip).to eq server_ip_result
24
+
25
+ end
26
+ end
27
+
28
+ describe '#qcode' do
29
+ it 'will get showqrcode with ticket at file based api endpoint as file' do
30
+ ticket_result = 'ticket_result'
31
+
32
+ expect(subject.client).to receive(:get).with('showqrcode', params: {ticket: 'ticket'}, base: WeichatRails::Api::MP_BASE, as: :file).and_return(ticket_result)
33
+
34
+ expect(subject.qrcode('ticket')).to eq(ticket_result)
35
+ end
36
+ end
37
+
38
+ describe '#groups' do
39
+ before :each do
40
+ @groups_result = 'groups_result'
41
+ expect(subject.client).to receive(:get).with('groups/get', params: {access_token: 'access_token'}).and_return(@groups_result)
42
+ end
43
+
44
+ it 'will get groups with access_token' do
45
+ expect(subject.groups).to eq(@groups_result)
46
+ end
47
+
48
+ it 'will get groups with access_token by groups alias' do
49
+ expect(subject.group_get).to eq(@groups_result)
50
+ end
51
+ end
52
+
53
+ describe '#group_create' do
54
+ it 'will post groups/create with access_token and new group json_data' do
55
+ new_group = { group: {name: 'new_group_name'}}
56
+ expect(subject.client).to receive(:post).with('groups/create', new_group.to_json, params: {access_token: 'access_token'} ).and_return(true)
57
+ expect(subject.group_create('new_group_name')).to be_truthy
58
+ end
59
+ end
60
+
61
+ describe '#group_update' do
62
+ before :each do
63
+ update_group = { group: {id: 108, name: 'test2_modify'}}
64
+ expect(subject.client).to receive(:post).with('groups/update', update_group.to_json, params: {access_token: 'access_token'}).and_return(true)
65
+ end
66
+
67
+ it 'will post groups/update with access_token and json_data' do
68
+ expect(subject.group_update(108,'test2_modify')).to be_truthy
69
+ end
70
+
71
+ it 'will post group/update with access_token and json_data by alias method group_name_update' do
72
+ expect(subject.group_name_update(108, 'test2_modify')).to be_truthy
73
+ end
74
+ end
75
+
76
+
77
+ describe '#group_delete' do
78
+ it 'will post groups/delete with access_token' do
79
+ delete_group = {group: {id: 108}}
80
+ expect(subject.client).to receive(:post).with('groups/delete', delete_group.to_json, params: {access_token: 'access_token'}).and_return(true)
81
+ expect(subject.group_delete(108)).to be_truthy
82
+ end
83
+ end
84
+
85
+
86
+ describe '#users' do
87
+ it 'will get user/get with access_token' do
88
+ users_result = "users_result"
89
+ expect(subject.client).to receive(:get).with('user/get', params: {access_token: 'access_token'}).and_return(users_result)
90
+ expect(subject.users).to eq(users_result)
91
+ end
92
+
93
+ it 'will get user/get with access_token and next_openid' do
94
+ users_result = 'users_result'
95
+ expect(subject.client).to receive(:get).with('user/get', params: {access_token: 'access_token', next_openid: 'next_openid'}).and_return(users_result)
96
+ expect(subject.users('next_openid')).to eq(users_result)
97
+
98
+ end
99
+ end
100
+
101
+
102
+ describe '#user' do
103
+ it 'will get user/info with access_token and openid' do
104
+ user_result = 'user_result'
105
+ expect(subject.client).to receive(:get).with('user/info', params: {access_token: 'access_token', openid: 'openid'}).and_return(user_result)
106
+ expect(subject.user('openid')).to eq(user_result)
107
+ end
108
+ end
109
+
110
+ describe '#user_group' do
111
+ it 'will post groups/getid with access_token and openid to get user groups info' do
112
+ user_request = {openid: 'openid'}
113
+ user_response = {gruopid: 102}
114
+ expect(subject.client).to receive(:post).with('groups/getid', user_request.to_json, params: {access_token: 'access_token'}).and_return(user_response)
115
+ expect(subject.user_group('openid')).to eq(user_response)
116
+ end
117
+ end
118
+
119
+ describe '#user_change_group' do
120
+ it 'will post groups/members/update with access_token and openid to get user groups info' do
121
+ user_request = {openid: 'openid', to_groupid: 108}
122
+ expect(subject.client).to receive(:post).with('groups/members/update', user_request.to_json, params: {access_token: 'access_token'}).and_return(true)
123
+ expect(subject.user_change_group('openid',108)).to be_truthy
124
+ end
125
+ end
126
+
127
+ describe '#user_update_remark' do
128
+ it 'will post groups/info/updatermark with access_token and openid to set user remark' do
129
+ user_update_remark_request = {openid: 'openid', remark: 'remark'}
130
+ user_update_remark_result = {errorcode: 0, errmsg: 'ok'}
131
+ expect(subject.client).to receive(:post).with('user/info/updateremark', user_update_remark_request.to_json, params: {access_token: 'access_token'}).and_return(user_update_remark_result)
132
+ expect(subject.user_update_remark('openid','remark')).to eq(user_update_remark_result)
133
+ end
134
+ end
135
+
136
+ describe '#qrcode_create_scene' do
137
+ it 'will post qrcode/create with access_token, scene_id and expire_seconds' do
138
+ scene_id = 101
139
+ qrcode_scene_res = {expire_seconds: 60, action_name: 'QR_SCENE', action_info: {scene: {scene_id: scene_id}}}
140
+ qrcode_scene_result = {ticket: 'qr_code_ticket', expire_seconds: 60, url: 'qr_code_ticket_pic_url'}
141
+ expect(subject.client).to receive(:post).with('qrcode/create', qrcode_scene_res.to_json, params: {access_token: 'access_token'}).and_return(qrcode_scene_result)
142
+ expect(subject.qrcode_create_scene(scene_id, 60)).to eq(qrcode_scene_result)
143
+ end
144
+ end
145
+
146
+
147
+ describe '#qrcode_create_limit_scene' do
148
+ qrcode_limit_scene_result = {ticket: 'qr_code_ticket', url: 'qr_code_ticket_pic_url'}
149
+
150
+ it 'will post qrcode/create with access_token and scene_id' do
151
+ scene_id = 101
152
+ qrcode_limit_scene_req = {action_name: 'QR_LIMIT_SCENE', action_info: {scene: {scene_id: scene_id}}}
153
+ expect(subject.client).to receive(:post).with('qrcode/create', qrcode_limit_scene_req.to_json, params: {access_token: 'access_token'}).and_return(qrcode_limit_scene_result)
154
+ expect(subject.qrcode_create_limit_scene(scene_id)).to eq(qrcode_limit_scene_result)
155
+ end
156
+
157
+ it 'will post qrcode/create with access_token and scene_str' do
158
+ scene_str = 'scene_str'
159
+ qrcode_limit_str_scene_req = {action_name: 'QR_LIMIT_STR_SCENE', action_info: {scene: {scene_str: scene_str}}}
160
+ expect(subject.client).to receive(:post).with('qrcode/create', qrcode_limit_str_scene_req.to_json, params: {access_token: 'access_token'}).and_return(qrcode_limit_scene_result)
161
+ expect(subject.qrcode_create_limit_scene(scene_str)).to eq(qrcode_limit_scene_result)
162
+ end
163
+ end
164
+
165
+ describe '#menu' do
166
+ it 'will get menu/get with access_token' do
167
+ menu_result = 'menu_result'
168
+ expect(subject.client).to receive(:get).with('menu/get', params: {access_token: 'access_token'}).and_return(menu_result)
169
+ expect(subject.menu).to eq(menu_result)
170
+ end
171
+ end
172
+
173
+ describe '#menu_create' do
174
+ it 'will post menu/create with access_token and json_data' do
175
+ menu = {buttons: ['a_button']}
176
+ expect(subject.client).to receive(:post).with('menu/create', menu.to_json, params: {access_token: 'access_token'}).and_return(true)
177
+ expect(subject.menu_create(menu)).to be true
178
+ end
179
+ end
180
+
181
+ describe '#menu_delete' do
182
+ it 'will get menu/delete with access_token' do
183
+ expect(subject.client).to receive(:get).with('menu/delete', params: {access_token: 'access_token'}).and_return(true)
184
+ expect(subject.menu_delete).to be true
185
+ end
186
+ end
187
+
188
+ describe '#media' do
189
+ it 'will get media/get with access_token and media_id at file based api endpoint as file' do
190
+ media_result = 'media_result'
191
+ expect(subject.client).to receive(:get).with('media/get', params: {access_token: 'access_token', media_id: 'media_id'}, as: :file).and_return(media_result)
192
+ expect(subject.media('media_id')).to eq(media_result)
193
+
194
+ end
195
+ end
196
+
197
+ describe '#media_create' do
198
+ it 'will post media/upload with access_token,type and media payload at file based api endpoint' do
199
+ file = "README.md"
200
+ expect(subject.client).to receive(:post_file).with('media/upload',file, params: {type: 'image', access_token: 'access_token'}).and_return(true)
201
+ expect(subject.media_create('image',file)).to be true
202
+ end
203
+ end
204
+
205
+ describe '#material' do
206
+ it 'will get material/get with access_token and media_id at file based api endpoint as file' do
207
+ material_result = 'material_result'
208
+ expect(subject.client).to receive(:get).with('material/get', params: {access_token: 'access_token', media_id: 'media_id'}, as: :file).and_return(material_result)
209
+ expect(subject.material('media_id')).to eq(material_result)
210
+ end
211
+ end
212
+
213
+ describe '#material_count' do
214
+ it 'will get material_count with access_token' do
215
+ material_count_result = {voice_count: 1, video_count: 2, image_count: 3, news_count: 4}
216
+ expect(subject.client).to receive(:get).with('material/get_materialcount', params: { access_token: 'access_token'}).and_return(material_count_result)
217
+ expect(subject.material_count).to eq(material_count_result)
218
+
219
+ end
220
+ end
221
+
222
+ describe '#material_list' do
223
+ it 'will get material list with access_token' do
224
+ material_list_request = {type: 'image', offset: 0, count: 20}
225
+ material_list_result = {total_count: 1, item_count: 1, item: [{media_id: 'media_id', name: 'name', update_time: 12345, url: 'url'}]}
226
+ expect(subject.client).to receive(:post).with('material/batchget_material', material_list_request.to_json, params: { access_token: 'access_token'}).and_return(material_list_result)
227
+ expect(subject.material_list('image', 0, 20)).to eq(material_list_result)
228
+ end
229
+ end
230
+
231
+ describe '#material_add' do
232
+ it 'will post material/add_material with access_token, type and media payload at file based api endpoint' do
233
+ file = "README.md"
234
+ expect(subject.client).to receive(:post_file).with('material/add_material', file, params: {type: 'image', access_token: 'access_token'}).and_return(true)
235
+ expect(subject.material_add('image',file)).to be true
236
+ end
237
+ end
238
+
239
+ describe '#material_delete' do
240
+ it 'will post material/del_material with access_token and media_id in payload' do
241
+ media_id = 'media_id'
242
+ material_delete_result = {errcode: 0, errmsg: 'deleted'}
243
+ expect(subject.client).to receive(:post).with('material/del_material', {media_id: media_id}, params: {access_token: 'access_token'}).and_return(material_delete_result)
244
+ expect(subject.material_delete(media_id)).to eq(material_delete_result)
245
+ end
246
+ end
247
+
248
+ describe '#custom_message_send' do
249
+ it 'will post message/custom/send with access_token, and json payload' do
250
+ payload = {touser: 'openid', msgtype: 'text', text: {content: 'message content'}}
251
+ expect(subject.client).to receive(:post).with('message/custom/send', payload.to_json, params: { access_token: 'access_token'}, content_type: :json).and_return(true)
252
+ expect(subject.custom_message_send(WeichatRails::Message.to('openid').text('message content'))).to be true
253
+ end
254
+ end
255
+
256
+ describe '#template_message_send' do
257
+ it 'will post message/template/send with access_token, and json payload' do
258
+ payload = { touser: 'OPENID',
259
+ template_id: 'ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY',
260
+ url: 'http://weixin.qq.com/download',
261
+ topcolor: '#FF0000',
262
+ data: { first: { value: '恭喜你购买成功!', color: '#173177' },
263
+ keynote1: { value: '巧克力', color: '#173177' },
264
+ keynote2: { value: '39.8元', color: '#173177' },
265
+ keynote3: { value: '2014年9月16日', color: '#173177' },
266
+ remark: { value: '欢迎再次购买!', color: '#173177' } } }
267
+ response_result = { errcode: 0, errmsg: 'ok', msgid: 332 }
268
+
269
+ expect(subject.client).to receive(:post).with('message/template/send', payload.to_json, params: {access_token: 'access_token'},content_type: :json).and_return(response_result)
270
+ expect(subject.template_message_send(payload)).to eq(response_result)
271
+ end
272
+ end
273
+
274
+
275
+
276
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe WeichatRails::Client do
4
+ subject { WeichatRails::Client.new('http://host/',20,false) }
5
+
6
+ let(:response_params) do
7
+ {
8
+ headers: {content_type: 'text/plain'},
9
+ status: 200
10
+ }
11
+ end
12
+
13
+ let(:response_404) { double '404', response_params.merge(status: 404) }
14
+ let(:response_text) { double 'text', response_params.merge(body: 'some text') }
15
+ let(:response_json) { double 'json', response_params.merge(body: {result: 'success'}.to_json, headers: {content_type: 'application/json'}) }
16
+ let(:response_image) { double 'image', response_params.merge(body: 'image data', headers: {content_type: 'image/gif'}) }
17
+
18
+ describe '#get' do
19
+ it 'will use http get method to request data' do
20
+ allow(HTTP).to receive_message_chain('headers.get') {response_json}
21
+ subject.get('token')
22
+ end
23
+ end
24
+
25
+ describe '#post' do
26
+ it 'Will use http post method to request data' do
27
+ allow(HTTP).to receive_message_chain('headers.post') {response_json}
28
+ subject.post('token','some_data')
29
+ end
30
+ end
31
+
32
+ describe '#request' do
33
+ it 'will add accept => :json for request' do
34
+ block = lambda do |url, headers|
35
+ expect(url).to eq('http://host/token')
36
+ expect(headers).to eq(params: { access_token: '1234'}, 'Accept' => 'application/json')
37
+ response_json
38
+ end
39
+
40
+ subject.send(:request, 'token', params: {access_token: '1234'}, &block )
41
+ end
42
+
43
+ it 'will use base option to construct url' do
44
+ block = lambda do |url,_headers|
45
+ expect(url).to eq('http://override/token')
46
+ response_json
47
+ end
48
+ subject.send(:request, 'token', base: 'http://override/', &block)
49
+
50
+ end
51
+
52
+ it 'will not pass as option for request' do
53
+ block = lambda do |_url,headers|
54
+ expect(headers[:as]).to be_nil
55
+ response_json
56
+ end
57
+ subject.send(:request, 'token', as: :text, &block)
58
+
59
+ end
60
+
61
+ it 'will raise error if response code is not 200' do
62
+ expect { subject.send(:request, 'token'){ response_404} }.to raise_error(/Request not OK/)
63
+ end
64
+
65
+
66
+ context 'parse response body' do
67
+ it 'will return response body for text response' do
68
+ expect(subject.send(:request, 'text', as: :text){ response_text }).to eq(response_text.body)
69
+ end
70
+
71
+ it 'will return response body as file for image' do
72
+ expect(subject.send(:request, 'image'){ response_image }).to be_a(Tempfile)
73
+ end
74
+
75
+ it 'will return response body as file for unknown content_type' do
76
+ response_stream = double 'image', response_params.merge(body: 'stream', headers: {content_type: 'stream'})
77
+ expect(subject.send(:request, 'image', as: :file){response_stream}).to be_a(Tempfile)
78
+ end
79
+
80
+ end
81
+
82
+ context 'json error' do
83
+ it 'raise ResponseError given response has error json' do
84
+ allow(response_json).to receive(:body).and_return({ errcode: 1106, errmsg: 'error message'}.to_json)
85
+ expect { subject.send(:request, 'image', as: :file){response_json} }.to raise_error(WeichatRails::ResponseError)
86
+ end
87
+
88
+ it 'raise AccessTokenExpiredError given response has error json with errorcode 40014' do
89
+ allow(response_json).to receive(:body).and_return( {errcode: 40014, errmsg: 'error_message'}.to_json )
90
+ expect { subject.send(:request, 'image', as: :file) {response_json} }.to raise_error(WeichatRails::AccessTokenExpiredError)
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ end