rhaiker 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.1.2 2009-05-30
2
+
3
+ * 画像ファイル投稿に対応
4
+ * バグを修正
5
+ * 実行テスト(rhaiker_run_spec_.rb)の追加
6
+
1
7
  == 0.1.1 2009-5-25
2
8
 
3
9
  * エラー処理、定数名など修正を行う
@@ -1,3 +1,10 @@
1
+ == 0.1.2 2009-05-30
2
+
3
+ * 1 minor enhancement:
4
+ * upload image file support.
5
+ * [bug][fix]some tiny bugs.
6
+ * add rhaiker_run_spec_.rb.
7
+
1
8
  == 0.1.1 2009-05-26
2
9
 
3
10
  * 1 minor enhancement:
@@ -0,0 +1,8 @@
1
+
2
+ Known bugs in rhaiker version 0.1.2
3
+
4
+ 1. 2009-05-30: Methods for keyword can't support keyword title which includes whitespace.
5
+
6
+ STATUS: Now ask Hatena Inc to tell us how to work around this problem.
7
+ workarounds are to do URI.escape(keyword) when call method for keyword.
8
+
File without changes
@@ -1,5 +1,6 @@
1
1
  History.ja.txt
2
2
  History.txt
3
+ KNOWNBUG.txt
3
4
  License.txt
4
5
  Manifest.txt
5
6
  README.ja.txt
@@ -12,6 +13,7 @@ example/get_following_all_words.rb
12
13
  example/get_hot_keywords.rb
13
14
  example/haiku_update.rb
14
15
  lib/rhaiker.rb
16
+ lib/rhaiker/multipart_builder.rb
15
17
  lib/rhaiker/utils.rb
16
18
  lib/rhaiker/version.rb
17
19
  lib/rhaiker/xml_parser.rb
@@ -20,9 +22,14 @@ script/destroy
20
22
  script/generate
21
23
  script/txt2html
22
24
  setup.rb
25
+ spec/config.yaml
26
+ spec/rhaiker_matchers.rb
27
+ spec/rhaiker_run_spec_.rb
23
28
  spec/rhaiker_spec.rb
24
29
  spec/spec.opts
25
30
  spec/spec_helper.rb
31
+ spec/test.gif
32
+ spec/utils.rb
26
33
  tasks/deployment.rake
27
34
  tasks/environment.rake
28
35
  tasks/rspec.rake
File without changes
data/README.txt CHANGED
File without changes
data/Rakefile CHANGED
File without changes
@@ -1,6 +1,6 @@
1
1
  require 'rhaiker/version'
2
2
 
3
- AUTHOR = 'saronpasu' # can also be an array of Authors
3
+ AUTHOR = ['saronpasu', 'yukky2001'] # can also be an array of Authors
4
4
  EMAIL = "jamneco@gmail.com"
5
5
  DESCRIPTION = "Hatena::Haiku::API ruby binding"
6
6
  GEM_NAME = 'rhaiker' # what ppl will type to install your gem
@@ -52,7 +52,9 @@ end
52
52
  # Generate all the Rake tasks
53
53
  # Run 'rake -T' to see list of generated tasks (from gem root directory)
54
54
  $hoe = Hoe.new(GEM_NAME, VERS) do |p|
55
- p.developer(AUTHOR, EMAIL)
55
+ #p.developer(AUTHOR, EMAIL)
56
+ p.author = AUTHOR
57
+ p.email = EMAIL
56
58
  p.description = DESCRIPTION
57
59
  p.summary = DESCRIPTION
58
60
  p.url = HOMEPATH
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -3,14 +3,16 @@
3
3
  $:.unshift(File.dirname(__FILE__)) unless
4
4
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
5
 
6
+ require 'rhaiker/version'
6
7
  require 'rhaiker/utils'
7
8
  require 'rhaiker/xml_parser'
9
+ require 'rhaiker/multipart_builder'
8
10
 
9
11
  =begin rdoc
10
12
  Rhaiker is Hatena::Haiku::API ruby binding.
11
13
  Use only Pure Ruby library.
12
14
 
13
- see exsample/*.rb
15
+ see example/*.rb
14
16
 
15
17
  please show Hatena::Haiku::API::Guide[http://h.hatena.ne.jp/api]
16
18
 
@@ -34,7 +36,7 @@ class Rhaiker
34
36
  include XML_Parser
35
37
 
36
38
  def initialize #:nodoc:
37
- @user_agent = 'rhaiker'
39
+ @user_agent = 'rhaiker/' + VERSION::STRING
38
40
  @source = 'rhaiker'
39
41
  end
40
42
 
@@ -173,7 +175,7 @@ RelatedMethods::
173
175
  uri_base += keyword ? "/#{keyword}.xml" : '.xml'
174
176
  uri = create_uri(uri_base)
175
177
  request = create_request(:get, uri)
176
- http_access(uri, request)
178
+ document = http_access(uri, request)
177
179
  return parse_timeline(document)
178
180
  end
179
181
 
@@ -212,6 +214,7 @@ Description::
212
214
 
213
215
  Params::
214
216
  user_id (target user_id)
217
+ options => {:page => pagenum}
215
218
 
216
219
  Return::
217
220
  users ([{:name => 'hoge', ...}, ...])
@@ -222,9 +225,10 @@ RelatedMethods::
222
225
  Utils#http_access,
223
226
  XML_Parser#parse_users
224
227
  =end
225
- def get_friends(user_id = nil)
228
+ def get_friends(user_id = nil, options = nil)
226
229
  uri_base = BASE_ADDRESS + 'statuses/friends'
227
230
  uri_base += user_id ? "/#{user_id}.xml" : '.xml'
231
+ uri_base += parse_options(options) if options
228
232
  uri = create_uri(uri_base)
229
233
  request = create_request(:get, uri, user_id.nil?)
230
234
  document = http_access(uri, request)
@@ -351,7 +355,7 @@ RelatedMethods::
351
355
  XML_Parser#parse_keywords
352
356
  =end
353
357
  def get_keywords(user_id = nil)
354
- uri_base = BASE_ADDRESS + 'statuses/keywrods'
358
+ uri_base = BASE_ADDRESS + 'statuses/keywords'
355
359
  uri_base += user_id ? "/#{user_id}.xml" : '.xml'
356
360
  uri = create_uri(uri_base)
357
361
  request = create_request(:get, uri, user_id.nil?)
@@ -380,7 +384,7 @@ RelatedMethods::
380
384
  uri = create_uri(
381
385
  BASE_ADDRESS +
382
386
  'keywords/show/' +
383
- keyword + 'xml'
387
+ keyword + '.xml'
384
388
  )
385
389
  request = create_request(:get, uri)
386
390
  document = http_access(uri, request)
@@ -406,7 +410,7 @@ RelatedMethods::
406
410
  XML_Parser#parse_status
407
411
 
408
412
  Notes::
409
- Still does not support of 'Upload Image File'
413
+ To upload Image File, set File object (or object has 'read' and 'path' methods) to options[:file].
410
414
  =end
411
415
  def status_update(options)
412
416
  uri_base = BASE_ADDRESS + 'statuses/update.xml'
@@ -414,7 +418,19 @@ Notes::
414
418
  uri_base += '&source=' + @source
415
419
  uri = create_uri(uri_base)
416
420
  request = create_request(:post, uri, true)
417
- document = http_access(uri, request)
421
+ document = nil
422
+ if options[:file]
423
+ # Upload Image File
424
+ builder = MultipartBuilder.new
425
+ builder.update(options)
426
+ builder.store_file(:file, options[:file])
427
+ body = builder.build
428
+ request['Content-Length'] = body.length.to_s
429
+ request['Content-Type'] = "multipart/form-data; boundary=#{builder.boundary}"
430
+ document = http_access(uri, request, body)
431
+ else
432
+ document = http_access(uri, request)
433
+ end
418
434
  return parse_status(document.root)
419
435
  end
420
436
 
@@ -438,7 +454,7 @@ RelationMethods::
438
454
  def status_destroy(status_id)
439
455
  uri = create_uri(
440
456
  BASE_ADDRESS +
441
- 'statuses/status/destroy/' +
457
+ 'statuses/destroy/' +
442
458
  status_id.to_s + '.xml'
443
459
  )
444
460
  request = create_request(:post, uri, true)
@@ -0,0 +1,103 @@
1
+ #!ruby -Ku
2
+ # -*- encoding: UTF-8 -*-
3
+ require 'forwardable'
4
+
5
+ =begin
6
+ Builder of multipart/form-data.
7
+
8
+ =end
9
+ class Rhaiker
10
+ class MultipartBuilder
11
+ extend Forwardable
12
+
13
+ EOL = "\r\n"
14
+
15
+ def_delegators :@data, :clear, :empty?, :has_key?, :key?, :length, :size
16
+ attr_accessor :boundary
17
+
18
+ def initialize(boundary = 'MultipartBuilder_boundary')
19
+ @boundary = boundary
20
+ @data = {}
21
+ end
22
+
23
+ def build
24
+ return '' if @data.empty?
25
+ body = ''
26
+ @data.each do |name, value|
27
+ body << '--' << @boundary << EOL
28
+ body << value.to_s
29
+ end
30
+ body << '--' << @boundary << '--' << EOL
31
+ return body
32
+ end
33
+
34
+ def each
35
+ @data.each do |name, value|
36
+ yield(name, value.value)
37
+ end
38
+ end
39
+
40
+ def fetch(name)
41
+ @data.fetch(name).value
42
+ end
43
+
44
+ def store(name, value)
45
+ @data.store(name, MultipartData.new(value, name))
46
+ end
47
+
48
+ def store_file(name, fileobj)
49
+ @data.store(name, MultipartFileData.new(fileobj, name))
50
+ end
51
+
52
+ def update(other)
53
+ other.each do |name, value|
54
+ store(name, value)
55
+ end
56
+ end
57
+
58
+ alias :to_s :build
59
+
60
+ class MultipartData
61
+ EOL = "\r\n"
62
+
63
+ attr_accessor :value, :field_name
64
+
65
+ def initialize(value, field_name)
66
+ @value = value
67
+ @field_name = field_name
68
+ end
69
+
70
+ def to_s
71
+ body = ''
72
+ body << "Content-Disposition: form-data; name=\"#{@field_name.to_s}\"" << EOL
73
+ body << EOL
74
+ body << @value.to_s << EOL
75
+ return body
76
+ end
77
+ end
78
+
79
+ class MultipartFileData < MultipartData
80
+ def initialize(value, field_name)
81
+ super(value, field_name)
82
+ end
83
+
84
+ def to_s
85
+ body = ''
86
+ body << "Content-Disposition: form-data; name=\"#{@field_name.to_s}\"; filename=\"#{File.basename(@value.path)}\"" << EOL
87
+ body << EOL
88
+ body << @value.read << EOL
89
+ return body
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ # simple test
96
+ if __FILE__ == $0
97
+ File::open($0, 'rb'){|f|
98
+ builder = Rhaiker::MultipartBuilder.new
99
+ builder.store('field1', 'this is field1.')
100
+ builder.store_file('field2', f)
101
+ puts builder.build
102
+ }
103
+ end
@@ -77,9 +77,9 @@ RelatedMethods::
77
77
  create_uri,
78
78
  create_request
79
79
  =end
80
- def http_access(uri, request)
80
+ def http_access(uri, request, body = nil)
81
81
  Net::HTTP.start(uri.host, uri.port){|http|
82
- response = http.request(request)
82
+ response = http.request(request, body)
83
83
  if RUBY_VERSION.match(/^1\.9\./)
84
84
  response.body.force_encoding('UTF-8')
85
85
  end
@@ -2,7 +2,7 @@ class Rhaiker
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 1
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -52,6 +52,8 @@ RelatedMethods::
52
52
  status.elements['id'].text.to_i,
53
53
  :text =>
54
54
  status.elements['text'].text,
55
+ :keyword =>
56
+ status.elements['keyword'].text,
55
57
  :link =>
56
58
  URI.parse(status.elements['link'].text),
57
59
  :created_at =>
@@ -204,7 +206,7 @@ RelatedMethods::
204
206
  :link =>
205
207
  URI.parse(keyword.elements['link'].text),
206
208
  :related_keywords =>
207
- keyword.elements.to_a('related_keywords')
209
+ keyword.elements.to_a('related_keywords').collect{|elem| elem.text }
208
210
  }
209
211
  end
210
212
  end
data/setup.rb CHANGED
File without changes
@@ -0,0 +1,26 @@
1
+ #
2
+ # UnitTest Configration
3
+ #
4
+ # NOTICE: you must modify this file before running test.
5
+
6
+ # if you want to run test, enable this variable.
7
+ # execute_run_test: true
8
+
9
+ # your hatena id
10
+ user_id: "your hatena_id"
11
+
12
+ # your haiku password
13
+ api_key: "your password"
14
+
15
+ # status text for test_status_and_favorite()
16
+ test_status: "Test Update."
17
+
18
+ # keyword title for test_keyword_and_relation()
19
+ test_keyword: "RhaikerTest"
20
+
21
+ # user_id for test_friendship()
22
+ # *CAUTION* you should set your subaccount id here.
23
+ test_friend_user_id: ""
24
+
25
+ # image filename for test_upload_file()
26
+ test_image_filename: "test.gif"
@@ -0,0 +1,143 @@
1
+ # -*- encoding: UTF-8 -*-
2
+ require File.dirname(__FILE__) + '/spec_helper.rb'
3
+
4
+ =begin rdoc
5
+ Custom Rhaiker Matchers for RSpec.
6
+
7
+ =end
8
+
9
+ module CustomRhaikerMatchers
10
+ class BasicMatcher < Spec::Matchers::SimpleMatcher
11
+ include Spec::Matchers
12
+ end
13
+
14
+ class BeAnArrayOf < BasicMatcher
15
+ def initialize(description, matcher)
16
+ super description
17
+ @matcher = matcher
18
+ end
19
+
20
+ def matches?(actual)
21
+ @actual = actual
22
+ @actual.should be_a_kind_of(Array)
23
+ @actual.each do |item|
24
+ item.should @matcher
25
+ end
26
+ end
27
+ end
28
+
29
+ class BeHash < BasicMatcher
30
+ attr_accessor :klasses
31
+
32
+ def initialize(description = nil, klasses = nil)
33
+ super description
34
+ @klasses = klasses
35
+ end
36
+
37
+ def matches?(actual)
38
+ @actual = actual
39
+ @actual.should be_a_kind_of(Hash)
40
+ @klasses.each do |key, klass|
41
+ @actual.should have_key(key)
42
+ @actual[key].should be_a_kind_of(klass)
43
+ end
44
+ end
45
+ end
46
+
47
+ class BeStatus < BeHash
48
+ STATUS_KLASSES = {
49
+ :id => Integer,
50
+ :text => String,
51
+ :keyword => String,
52
+ :link => URI,
53
+ :created_at => DateTime,
54
+ :favorited => Integer,
55
+ :user => Hash
56
+ }
57
+
58
+ def initialize
59
+ super 'Status', STATUS_KLASSES
60
+ end
61
+
62
+ def matches?(actual)
63
+ super actual
64
+ if actual.has_key?(:in_reply_to)
65
+ actual[:in_reply_to][:status_id].should be_a_kind_of(Integer)
66
+ actual[:in_reply_to][:user_id].should be_a_kind_of(String)
67
+ end
68
+ if actual.has_key?(:replies)
69
+ actual[:replies].should BeAnArrayOf.new('Replies', BeReply.new)
70
+ end
71
+ if actual.has_key?(:source)
72
+ actual[:source].should be_a_kind_of(String)
73
+ end
74
+ actual[:user].should BeUser.new
75
+ end
76
+ end
77
+
78
+ class BeReply < BeHash
79
+ REPLY_KLASSES = {
80
+ :id => Integer,
81
+ :text => String,
82
+ :created_at => DateTime,
83
+ :favorited => Integer,
84
+ :source => String,
85
+ :user => Hash
86
+ }
87
+
88
+ def initialize
89
+ super 'Reply', REPLY_KLASSES
90
+ end
91
+
92
+ def matches?(actual)
93
+ super actual
94
+ actual[:user].should BeUser.new
95
+ end
96
+ end
97
+
98
+ class BeUser < BeHash
99
+ USER_KLASSES = {
100
+ :id => String,
101
+ :name => String,
102
+ :screen_name => String,
103
+ :followers_count => Integer,
104
+ :url => URI,
105
+ :profile_image_url => URI,
106
+ }
107
+
108
+ def initialize
109
+ super 'User', USER_KLASSES
110
+ end
111
+ end
112
+
113
+ class BeKeyword < BeHash
114
+ KEYWORD_KLASSES = {
115
+ :title => String,
116
+ :entry_count => Integer,
117
+ :followers_count => Integer,
118
+ :link => URI,
119
+ :related_keywords => Array
120
+ }
121
+
122
+ def initialize
123
+ super 'Keyword', KEYWORD_KLASSES
124
+ end
125
+
126
+ def matches?(actual)
127
+ super actual
128
+ actual[:related_keywords].each do |keyword_title|
129
+ keyword_title.should be_a_kind_of(String)
130
+ end
131
+ end
132
+ end
133
+
134
+ def be_status; BeStatus.new; end
135
+ def be_reply; BeReply.new; end
136
+ def be_user; BeUser.new; end
137
+ def be_keyword; BeKeyword.new; end
138
+ def be_an_array_of_status; BeAnArrayOf.new('Statuses', BeStatus.new); end
139
+ def be_an_array_of_reply; BeAnArrayOf.new('Replies', BeReply.new ); end
140
+ def be_an_array_of_user; BeAnArrayOf.new('Users', BeUser.new); end
141
+ def be_an_array_of_keyword; BeAnArrayOf.new('Keywords', BeKeyword.new); end
142
+ alias :be_timeline :be_an_array_of_status
143
+ end
@@ -0,0 +1,176 @@
1
+ # -*- encoding: UTF-8 -*-
2
+ require File.dirname(__FILE__) + '/spec_helper.rb'
3
+ require 'yaml'
4
+ require 'rhaiker_matchers'
5
+ require 'utils'
6
+
7
+ =begin rdoc
8
+ Test for Rhaiker API.
9
+
10
+ NOTICE::
11
+ * you must modify config.yaml before running test.
12
+ * this test create and delete dummy status, favorite(star), keyword, keyword relation. then you should pay attention to execute this test.
13
+ =end
14
+
15
+ CONFIG_FILE = 'config.yaml'
16
+
17
+ describe Rhaiker, ' when use' do
18
+ include CustomRhaikerMatchers
19
+ include Rhaiker::Test::Utils
20
+
21
+ before :all do
22
+ @config = intern_hash_keys(YAML.load_file(CONFIG_FILE))
23
+ @accessor = Rhaiker.new
24
+ @accessor.user_id = @config[:user_id] if @config[:user_id]
25
+ @accessor.api_key = @config[:api_key] if @config[:api_key]
26
+ @keyword = "id:#{@config[:user_id]}"
27
+ end
28
+
29
+ before :each do
30
+ pending 'ignore run test' unless @config[:execute_run_test]
31
+ end
32
+
33
+ it 'get_public_timeline and return an Array of Status' do
34
+ wait_api{ @accessor.get_public_timeline }.should be_an_array_of_status
35
+ end
36
+
37
+ it 'get_friends_timeline and return an Array of Status' do
38
+ wait_api{ @accessor.get_friends_timeline }.should be_an_array_of_status
39
+ end
40
+
41
+ it 'get_user_timeline and return an Array of Status' do
42
+ statuses = wait_api{ @accessor.get_user_timeline }
43
+ statuses.should be_an_array_of_status
44
+ statuses.first[:user][:id].should be_eql @config[:user_id]
45
+ end
46
+
47
+ it 'get_keyword_timeline and return an Array of Status' do
48
+ statuses = wait_api{ @accessor.get_keyword_timeline(@keyword) }
49
+ statuses.should be_an_array_of_status
50
+ statuses.first[:keyword].should be_eql @keyword
51
+ end
52
+
53
+ it 'get_album and return an Array of Status' do
54
+ wait_api{ @accessor.get_album }.should be_an_array_of_status
55
+ end
56
+
57
+ it 'get_status and return Status' do
58
+ wait_api{ @accessor.get_status(get_dummy(:id)) }.should be_status
59
+ end
60
+
61
+ it 'get_friends and return an Array of User' do
62
+ wait_api{ @accessor.get_friends }.should be_an_array_of_user
63
+ end
64
+
65
+ it 'get_followers and return an Array of User' do
66
+ wait_api{ @accessor.get_followers }.should be_an_array_of_user
67
+ end
68
+
69
+ it 'get_friend and return User' do
70
+ wait_api{ @accessor.get_friend(@config[:user_id]) }.should be_user
71
+ end
72
+
73
+ it 'get_hot_keywords and return an Array of Keyword' do
74
+ wait_api{ @accessor.get_hot_keywords }.should be_an_array_of_keyword
75
+ end
76
+
77
+ it 'get_keyword_list and return an Array of Keyword' do
78
+ wait_api{ @accessor.get_keyword_list }.should be_an_array_of_keyword
79
+ end
80
+
81
+ it 'get_keywords and return an Array of Keyword' do
82
+ wait_api{ @accessor.get_keywords }.should be_an_array_of_keyword
83
+ end
84
+
85
+ it 'get_keyword and return Keyword' do
86
+ keyword = wait_api{ @accessor.get_keyword(@keyword) }
87
+ keyword.should be_keyword
88
+ keyword[:title].should be_eql @keyword
89
+ end
90
+
91
+ # Test for Create, Update, Delete API
92
+ it 'create and destroy a status, and increase and decrease a star' do
93
+ begin
94
+ status_before = wait_api do
95
+ @accessor.status_update({
96
+ :status => @config[:test_status],
97
+ :keyword => @keyword
98
+ })
99
+ end
100
+ status_before.should be_status
101
+
102
+ # increase star
103
+ status_now = wait_api{ @accessor.favorites_create(status_before[:id]) }
104
+ status_now.should be_status
105
+ (status_now[:favorited] - status_before[:favorited]).should be_eql 1
106
+ status_before = status_now
107
+
108
+ # decrease star
109
+ status_now = wait_api{ @accessor.favorites_destroy(status_before[:id]) }
110
+ status_now.should be_status
111
+ (status_now[:favorited] - status_before[:favorited]).should be_eql 0
112
+ ensure
113
+ status_now = wait_api{ @accessor.status_destroy(status_before[:id]) }
114
+ status_now.should be_status
115
+ end
116
+ end
117
+
118
+ it 'follow and unfollow a keyword' do
119
+ pending 'need to set test_keyword' unless @config[:test_keyword].size > 0
120
+ begin
121
+ wait_api{ @accessor.keyword_create(@config[:test_keyword]) }.should be_keyword
122
+ ensure
123
+ wait_api{ @accessor.keyword_destroy(@config[:test_keyword]) }.should be_keyword
124
+ end
125
+ end
126
+
127
+ it 'create and destroy a keyword relation' do
128
+ pending 'need to set test_keyword' unless @config[:test_keyword].size > 0
129
+ begin
130
+ keyword = wait_api{ @accessor.keyword_relation_create(@config[:test_keyword], @keyword) }
131
+ keyword.should be_keyword
132
+ keyword[:related_keywords].should include @keyword
133
+ ensure
134
+ keyword = wait_api{ @accessor.keyword_relation_destroy(@config[:test_keyword], @keyword) }
135
+ keyword.should be_keyword
136
+
137
+ # NOTICE: you can't destroy a keyword relation other user created.
138
+ #keyword[:related_keywords].should_not include @keyword
139
+ end
140
+ end
141
+
142
+ it 'create and destroy friendship' do
143
+ pending 'need to set test_friend_user_id' unless @config[:test_friend_user_id].size > 0
144
+ begin
145
+ user = wait_api{ @accessor.friendship_create(@config[:test_friend_user_id]) }
146
+ user.should be_user
147
+ ensure
148
+ user = wait_api{ @accessor.friendship_destroy(@config[:test_friend_user_id]) }
149
+ user.should be_user
150
+ end
151
+ end
152
+
153
+ it 'upload image file' do
154
+ pending 'need to set test_image_filename' unless @config[:test_image_filename].size > 0
155
+
156
+ status = nil
157
+ begin
158
+ File::open(@config[:test_image_filename], 'rb'){|f|
159
+ wait_api do
160
+ status = @accessor.status_update({
161
+ :status => @config[:test_status],
162
+ :keyword => @keyword,
163
+ :file => f
164
+ })
165
+ end
166
+ status.should be_status
167
+ }
168
+ ensure
169
+ wait_api{ @accessor.status_destroy(status[:id]) }.should be_status
170
+ end
171
+ end
172
+
173
+ after :all do
174
+ @accessor = nil
175
+ end
176
+ end
@@ -8,7 +8,7 @@ describe Rhaiker, ' when first created' do
8
8
  end
9
9
 
10
10
  it 'should be have a user_agent "rhaiker"' do
11
- @accessor.user_agent.should be_eql("rhaiker")
11
+ @accessor.user_agent.should be_eql("rhaiker/0.1.2")
12
12
  end
13
13
 
14
14
  it 'should be have a source "rhaiker"' do
@@ -32,8 +32,8 @@ end
32
32
  describe Rhaiker::Utils, " when use" do
33
33
  before do
34
34
  @accessor = Rhaiker.new
35
- @accessor.user_id = 'saronpasu'
36
- @accessor.api_key = 'ar3hge2f'
35
+ @accessor.user_id = 'dummy'
36
+ @accessor.api_key = 'dummy'
37
37
  end
38
38
 
39
39
  it 'create_uri should be URI instance' do
@@ -61,7 +61,7 @@ describe Rhaiker::Utils, " when use" do
61
61
  @accessor.create_request(
62
62
  :get, uri, true
63
63
  )['Authorization'].should be_eql(
64
- "Basic c2Fyb25wYXN1OmFyM2hnZTJm"
64
+ "Basic ZHVtbXk6ZHVtbXk="
65
65
  )
66
66
  end
67
67
 
@@ -134,7 +134,7 @@ describe Rhaiker::XML_Parser, 'when use' do
134
134
  <in_reply_to_user_id/>
135
135
  <favorited>0</favorited>
136
136
  <link>http://h.hatena.ne.jp/saronpasu/1234567890</link>
137
- <source>web</source>
137
+ <source/>
138
138
  <user>
139
139
  <id>saronpasu</id>
140
140
  <name>saronpasu</name>
@@ -201,27 +201,99 @@ describe Rhaiker::XML_Parser, 'when use' do
201
201
 
202
202
  it 'have status id' do
203
203
  @result.first.should have_key(:id)
204
+ @result.first[:id].should be_a_kind_of(Integer)
204
205
  end
205
206
  it 'have status text' do
206
207
  @result.first.should have_key(:text)
208
+ @result.first[:text].should be_a_kind_of(String)
207
209
  end
208
210
  it 'have status source' do
209
211
  @result.first.should have_key(:source)
212
+ @result.first[:source].should be_a_kind_of(String)
210
213
  end
211
214
  it 'have status favorited' do
212
215
  @result.first.should have_key(:favorited)
216
+ @result.first[:favorited].should be_a_kind_of(Integer)
217
+ end
218
+ it 'have status created_at' do
219
+ @result.first.should have_key(:created_at)
220
+ @result.first[:created_at].should be_a_kind_of(DateTime)
221
+ end
222
+ it 'have status keyword' do
223
+ @result.first.should have_key(:keyword)
224
+ @result.first[:keyword].should be_a_kind_of(String)
213
225
  end
214
226
  it 'have status link' do
215
227
  @result.first.should have_key(:link)
228
+ @result.first[:link].should be_a_kind_of(URI)
216
229
  end
217
230
  it 'have user' do
218
231
  @result.first.should have_key(:user)
232
+ @result.first[:user].should be_a_kind_of(Hash)
233
+ end
234
+
235
+ describe 'status user' do
236
+ it 'have id' do
237
+ @result.first[:user].should have_key(:id)
238
+ @result.first[:user][:id].should be_a_kind_of(String)
239
+ end
240
+ it 'have name' do
241
+ @result.first[:user].should have_key(:name)
242
+ @result.first[:user][:name].should be_a_kind_of(String)
243
+ end
244
+ it 'have screen_name' do
245
+ @result.first[:user].should have_key(:screen_name)
246
+ @result.first[:user][:screen_name].should be_a_kind_of(String)
247
+ end
248
+ it 'have followers_count' do
249
+ @result.first[:user].should have_key(:followers_count)
250
+ @result.first[:user][:followers_count].should be_a_kind_of(Integer)
251
+ end
252
+ it 'have url' do
253
+ @result.first[:user].should have_key(:url)
254
+ @result.first[:user][:url].should be_a_kind_of(URI)
255
+ end
256
+ it 'have profile_image_url' do
257
+ @result.first[:user].should have_key(:profile_image_url)
258
+ @result.first[:user][:profile_image_url].should be_a_kind_of(URI)
259
+ end
219
260
  end
261
+
220
262
  it 'have replies' do
221
263
  @result.first.should have_key(:replies)
264
+ @result.first[:replies].should be_a_kind_of(Array)
222
265
  end
266
+
267
+ describe 'a reply' do
268
+ it 'have id' do
269
+ @result.first[:replies].first.should have_key(:id)
270
+ @result.first[:replies].first[:id].should be_a_kind_of(Integer)
271
+ end
272
+ it 'have created_at' do
273
+ @result.first[:replies].first.should have_key(:created_at)
274
+ @result.first[:replies].first[:created_at].should be_a_kind_of(DateTime)
275
+ end
276
+ it 'have favorited' do
277
+ @result.first[:replies].first.should have_key(:favorited)
278
+ @result.first[:replies].first[:favorited].should be_a_kind_of(Integer)
279
+ end
280
+ it 'have source' do
281
+ @result.first[:replies].first.should have_key(:source)
282
+ @result.first[:replies].first[:source].should be_a_kind_of(String)
283
+ end
284
+ it 'have text' do
285
+ @result.first[:replies].first.should have_key(:text)
286
+ @result.first[:replies].first[:text].should be_a_kind_of(String)
287
+ end
288
+ it 'have user' do
289
+ @result.first[:replies].first.should have_key(:user)
290
+ @result.first[:replies].first[:user].should be_a_kind_of(Hash)
291
+ end
292
+ end
293
+
223
294
  it 'have in_reply_to' do
224
295
  @result.first.should have_key(:in_reply_to)
296
+ @result.first[:in_reply_to].should be_a_kind_of(Hash)
225
297
  end
226
298
 
227
299
  after do
@@ -233,6 +305,48 @@ describe Rhaiker::XML_Parser, 'when use' do
233
305
  @accessor.parse_status(@status).should be_a_kind_of(Hash)
234
306
  end
235
307
 
308
+ describe 'parse_status result' do
309
+ before do
310
+ @result = @accessor.parse_status(@status)
311
+ end
312
+
313
+ it 'should be a kind of Hash' do
314
+ @accessor.parse_status(@status).should be_a_kind_of(Hash)
315
+ end
316
+
317
+ it 'have id' do
318
+ @result.should have_key(:id)
319
+ @result[:id].should be_a_kind_of(Integer)
320
+ end
321
+
322
+ it 'have text' do
323
+ @result.should have_key(:text)
324
+ @result[:text].should be_a_kind_of(String)
325
+ end
326
+
327
+ it 'have source and not set source' do
328
+ @result.should have_key(:source)
329
+ @result[:source].should be_nil
330
+ end
331
+
332
+ it 'have keyword' do
333
+ @result.should have_key(:keyword)
334
+ @result[:keyword].should be_a_kind_of(String)
335
+ end
336
+
337
+ it 'have not reply_to' do
338
+ @result.should_not have_key(:reply_to)
339
+ end
340
+
341
+ it 'have not replies' do
342
+ @result.should_not have_key(:replies)
343
+ end
344
+
345
+ after do
346
+ @result = nil
347
+ end
348
+ end
349
+
236
350
  it 'parse_users and return Hash in Array Data' do
237
351
  @accessor.parse_users(@users).should be_a_kind_of(Array)
238
352
  @accessor.parse_users(@users).first.should be_a_kind_of(Hash)
@@ -317,3 +431,59 @@ describe Rhaiker::XML_Parser, 'when use' do
317
431
  end
318
432
  end
319
433
 
434
+ describe Rhaiker::MultipartBuilder, 'when first created' do
435
+ before do
436
+ @builder = Rhaiker::MultipartBuilder.new
437
+ end
438
+
439
+ it 'should be empty' do
440
+ @builder.should be_empty
441
+ end
442
+
443
+ it 'should have a boundary' do
444
+ boundary = @builder.boundary
445
+ boundary.should be_a_kind_of(String)
446
+ boundary.should_not be_empty
447
+ end
448
+
449
+ it 'build and return empty string' do
450
+ body = @builder.build
451
+ body.should be_a_kind_of(String)
452
+ body.should be_empty
453
+ end
454
+ end
455
+
456
+ describe Rhaiker::MultipartBuilder, 'when use' do
457
+ def store_a_data_and_a_fileobj
458
+ @stub_fileobj = Object.new
459
+ @stub_fileobj.stub!(:read).and_return("this is dummy file body.\n\nend of file\n")
460
+ @stub_fileobj.stub!(:path).and_return('dummyfile.txt')
461
+ @builder.store_file('field1', @stub_fileobj)
462
+ @builder.store('field2', 'here is field2')
463
+ end
464
+
465
+ before do
466
+ @builder = Rhaiker::MultipartBuilder.new
467
+ end
468
+
469
+ it 'store a data and a fileobj, then have two items' do
470
+ store_a_data_and_a_fileobj
471
+ @builder.should have(2).items
472
+ @builder.should have_key('field1')
473
+ @builder.should have_key('field2')
474
+ @builder.should_not have_key('field3')
475
+ end
476
+
477
+ it 'store a data and a fileobj, then build and return body string' do
478
+ store_a_data_and_a_fileobj
479
+ body = @builder.build
480
+ body.should be_a_kind_of(String)
481
+ body.should_not be_empty
482
+ end
483
+
484
+ it 'store a data and a fileobj, then clear and should be empty' do
485
+ store_a_data_and_a_fileobj
486
+ @builder.clear
487
+ @builder.should be_empty
488
+ end
489
+ end
File without changes
File without changes
Binary file
@@ -0,0 +1,44 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ =begin
4
+ Utils for Test.
5
+
6
+ =end
7
+
8
+ class Rhaiker
9
+ module Test
10
+ module Utils
11
+ protected
12
+ def wait_api(sec = 1, &block)
13
+ if block_given?
14
+ ret = yield
15
+ sleep sec
16
+ return ret
17
+ else
18
+ sleep sec
19
+ end
20
+ end
21
+
22
+ # set dummy data automatically if dummy isn't set
23
+ def get_dummy(key)
24
+ unless (@dummy and @dummy.has_key?(key))
25
+ status = wait_api{ @accessor.get_public_timeline }.first
26
+ @dummy = (@dummy ? status.merge(@dummy) : status)
27
+ end
28
+ return @dummy.fetch(key)
29
+ end
30
+
31
+ def intern_hash_keys(hash)
32
+ ret = {}
33
+ hash.each do |key, value|
34
+ if value.kind_of?(Hash)
35
+ ret[key.intern] = intern_hash_keys(value)
36
+ else
37
+ ret[key.intern] = value
38
+ end
39
+ end
40
+ return ret
41
+ end
42
+ end
43
+ end
44
+ end
File without changes
File without changes
@@ -14,8 +14,22 @@ EOS
14
14
  exit(0)
15
15
  end
16
16
 
17
- desc "Run the specs under spec/models"
17
+ desc "Run the all specs"
18
18
  Spec::Rake::SpecTask.new do |t|
19
19
  t.spec_opts = ['--options', "spec/spec.opts"]
20
20
  t.spec_files = FileList['spec/**/*_spec.rb']
21
21
  end
22
+
23
+ desc "Run specs only use mock"
24
+ Spec::Rake::SpecTask.new(:"spec:mock") do |t|
25
+ t.spec_opts = ['--options', "spec/spec.opts"]
26
+ t.spec_files = FileList['spec/rhaiker_spec.rb']
27
+ end
28
+
29
+ desc "Run specs use access to Hatena::Haiku::API"
30
+ Spec::Rake::SpecTask.new(:"spec:api") do |t|
31
+ t.spec_opts = ['--options', "spec/spec.opts"]
32
+ t.ruby_opts = ['-Ispec']
33
+ t.spec_files = ['spec/rhaiker_run_spec_.rb']
34
+ end
35
+
File without changes
@@ -33,7 +33,7 @@
33
33
  <h1>rhaiker</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/rhaiker"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/rhaiker" class="numbers">0.1.1</a>
36
+ <a href="http://rubyforge.org/projects/rhaiker" class="numbers">0.0.1</a>
37
37
  </div>
38
38
  <h2>What</h2>
39
39
  <p>Rhaiker is Hatena::Haiku::<span class="caps">API</span> ruby binding.<br />
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhaiker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - saronpasu
8
+ - yukky2001
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-05-25 00:00:00 +09:00
13
+ date: 2009-06-01 00:00:00 +09:00
13
14
  default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
@@ -23,8 +24,7 @@ dependencies:
23
24
  version: 1.8.0
24
25
  version:
25
26
  description: Hatena::Haiku::API ruby binding
26
- email:
27
- - jamneco@gmail.com
27
+ email: jamneco@gmail.com
28
28
  executables: []
29
29
 
30
30
  extensions: []
@@ -32,6 +32,7 @@ extensions: []
32
32
  extra_rdoc_files:
33
33
  - History.ja.txt
34
34
  - History.txt
35
+ - KNOWNBUG.txt
35
36
  - License.txt
36
37
  - Manifest.txt
37
38
  - README.ja.txt
@@ -40,6 +41,7 @@ extra_rdoc_files:
40
41
  files:
41
42
  - History.ja.txt
42
43
  - History.txt
44
+ - KNOWNBUG.txt
43
45
  - License.txt
44
46
  - Manifest.txt
45
47
  - README.ja.txt
@@ -52,6 +54,7 @@ files:
52
54
  - example/get_hot_keywords.rb
53
55
  - example/haiku_update.rb
54
56
  - lib/rhaiker.rb
57
+ - lib/rhaiker/multipart_builder.rb
55
58
  - lib/rhaiker/utils.rb
56
59
  - lib/rhaiker/version.rb
57
60
  - lib/rhaiker/xml_parser.rb
@@ -60,9 +63,14 @@ files:
60
63
  - script/generate
61
64
  - script/txt2html
62
65
  - setup.rb
66
+ - spec/config.yaml
67
+ - spec/rhaiker_matchers.rb
68
+ - spec/rhaiker_run_spec_.rb
63
69
  - spec/rhaiker_spec.rb
64
70
  - spec/spec.opts
65
71
  - spec/spec_helper.rb
72
+ - spec/test.gif
73
+ - spec/utils.rb
66
74
  - tasks/deployment.rake
67
75
  - tasks/environment.rake
68
76
  - tasks/rspec.rake
@@ -74,6 +82,8 @@ files:
74
82
  - website/template.html.erb
75
83
  has_rdoc: true
76
84
  homepage: http://rhaiker.rubyforge.org
85
+ licenses: []
86
+
77
87
  post_install_message: ""
78
88
  rdoc_options:
79
89
  - --main
@@ -95,9 +105,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
105
  requirements: []
96
106
 
97
107
  rubyforge_project: rhaiker
98
- rubygems_version: 1.3.1
108
+ rubygems_version: 1.3.3
99
109
  signing_key:
100
- specification_version: 2
110
+ specification_version: 3
101
111
  summary: Hatena::Haiku::API ruby binding
102
112
  test_files: []
103
113