rhaiker 0.1.1 → 0.1.2

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