Helipad 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README +101 -0
  2. data/lib/helipad.rb +457 -0
  3. data/test/test_helipad.rb +122 -0
  4. metadata +61 -0
data/README ADDED
@@ -0,0 +1,101 @@
1
+ # Ruby interface to the excellent Helipad[http://pad.helicoid.net/home.html]
2
+ # online note pad.
3
+ #
4
+ # Author: Lonnon Foster (lonnon.foster@gmail.com)
5
+ #
6
+ # == Overview
7
+ #
8
+ # This package provides three classes for working with
9
+ # Helipad[http://pad.helicoid.net/home.html]: Helipad, Helipad::Document, and
10
+ # Helipad::Response.
11
+ #
12
+ # The Helipad class does all the heavy lifting. Creating an instance of
13
+ # Helipad requires your login credentials.
14
+ #
15
+ # hp = Helipad.new("lonnon@example.com", "password")
16
+ #
17
+ # Armed with an instance of Helipad, you can call its methods to interact
18
+ # with Helipad[http://pad.helicoid.net/home.html] documents.
19
+ #
20
+ # The Helipad::Document class holds the data contained in a
21
+ # Helipad[http://pad.helicoid.net/home.html] document. The get method
22
+ # returns a Helipad::Document instance. The find, get_all, and get_titles
23
+ # methods return an Array of Helipad::Document instances.
24
+ #
25
+ # The Helipad::Response class holds return data sent by
26
+ # Helipad[http://pad.helicoid.net/home.html] that describes the success or
27
+ # failure of various actions. The create, destroy, and update methods
28
+ # return a Helipad::Response instance.
29
+ #
30
+ # == Examples of Use
31
+ #
32
+ # All of these examples assume that a Helipad object called +hp+ exists.
33
+ #
34
+ # hp = Helipad.new("lonnon@example.com", "password")
35
+ #
36
+ # === Get an Existing Document
37
+ #
38
+ # document = hp.get(3)
39
+ # puts document.source
40
+ #
41
+ # === Get a Document Formatted as HTML
42
+ #
43
+ # puts hp.get_html(3)
44
+ #
45
+ # === Find Documents
46
+ #
47
+ # def how_many(search_term)
48
+ # documents = hp.find(search_term)
49
+ # documents.size
50
+ # end
51
+ #
52
+ # find_this = "wombats"
53
+ # puts "#{how_many(find_this)} document(s) were found containing '#{find_this}'."
54
+ #
55
+ # === Find Documents by Tags
56
+ #
57
+ # documents = hp.find(:tag, "work")
58
+ # titles = documents.collect { |doc| doc.title }
59
+ # puts "Documents tagged with 'work':\n #{titles.join("\n ")}"
60
+ #
61
+ # === Create a Document
62
+ #
63
+ # source = File.read("cake_recipe.txt")
64
+ # response = hp.create(:title => "Delicious Chocolate Cake",
65
+ # :tags => "recipe dessert",
66
+ # :source => source)
67
+ # puts "Recipe saved" if response.saved?
68
+ #
69
+ # === Delete Documents
70
+ #
71
+ # doc_ids = hp.find(:tag, "incriminating").collect { |doc| doc.doc_id }
72
+ # doc_ids.each do |id|
73
+ # hp.destroy(id)
74
+ # end
75
+ #
76
+ # == Legal
77
+ #
78
+ # Copyright (c) 2008 Lonnon Foster. All rights reserved.
79
+ #
80
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
81
+ # of this software and associated documentation files (the "Software"), to deal
82
+ # in the Software without restriction, including without limitation the rights
83
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
84
+ # copies of the Software, and to permit persons to whom the Software is
85
+ # furnished to do so, subject to the following conditions:
86
+ #
87
+ # The above copyright notice and this permission notice shall be included in
88
+ # all copies or substantial portions of the Software.
89
+ #
90
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
93
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
95
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
96
+ # THE SOFTWARE.
97
+ #
98
+ # == Thanks
99
+ #
100
+ # Special thanks to {Alex Young}[http://alexyoung.org/] at Helicoid[http://helicoid.net]
101
+ # for creating Helipad[http://pad.helicoid.net/home.html].
@@ -0,0 +1,457 @@
1
+ #--
2
+ # Copyright (c) 2008 Lonnon Foster. All rights reserved.
3
+ # See README for permissions.
4
+ #++
5
+
6
+ require 'net/http'
7
+ require 'uri'
8
+ require 'rexml/document'
9
+ require 'date'
10
+
11
+ # Class Helipad provides a wrapper for the {Helipad XML
12
+ # API}[http://pad.helicoid.net/document/public/6313d317].
13
+ #
14
+ # See the documentation in the file README for an overview.
15
+ class Helipad
16
+ # Create a new Helipad object.
17
+ #
18
+ # ==== Parameters
19
+ # +email+ and +password+ are the same credentials you use to log on to your Helipad account.
20
+ def initialize(email, password)
21
+ @email = email
22
+ @password = password
23
+ raise(ArgumentError, "Email address not specified", caller) if @email.nil?
24
+ raise(ArgumentError, "Password not specified", caller) if @password.nil?
25
+ end
26
+
27
+ # Create a new Helipad[http://pad.helicoid.net/home.html] document.
28
+ #
29
+ # ==== Parameters
30
+ # +args+ is a Hash containing properties for the created document.
31
+ #
32
+ # * <tt>:title</tt> - Title for the new document. This parameter is
33
+ # required.
34
+ # * <tt>:tags</tt> - Space-separated list of tags for the new document
35
+ # * <tt>:source</tt> - Body of the new document.
36
+ # Helipad[http://pad.helicoid.net/home.html] understands {Textile markup}[http://pad.helicoid.net/formatting],
37
+ # which you can use to format the document's text.
38
+ #
39
+ # ==== Returns
40
+ # This method returns a Helipad::Response object, which has the following methods:
41
+ # * <tt>saved?</tt> - +true+ if the document was created successfully
42
+ # * +doc_id+ - ID of the newly created document
43
+ #
44
+ # ==== Example
45
+ # hp = Helipad.new("lonnon@example.com", "password")
46
+ # response = hp.create(:title => "Marsupial Inventory",
47
+ # :tags => "marsupial australia animals",
48
+ # :source => "|koala|2|\n|kangaroo|8|\n|platypus|1|")
49
+ # puts "Inventory saved as document #{response.doc_id}" if response.saved?
50
+ def create(*args)
51
+ options = args.extract_options!
52
+ validate_options(options, :create)
53
+ raise(ArgumentError, "No document options specified", caller) if options.empty?
54
+ raise(ArgumentError, "Document must have a title", caller) if options[:title].nil?
55
+ url = URI.parse("http://pad.helicoid.net/document/create")
56
+ Response.new(send_request(url, build_request(options)))
57
+ end
58
+
59
+ # Delete a Helipad[http://pad.helicoid.net/home.html] document.
60
+ #
61
+ # ==== Parameter
62
+ # * +id+ - ID of the document to delete
63
+ #
64
+ # ==== Returns
65
+ # This method returns a Helipad::Response object, which has the following method:
66
+ # * <tt>deleted?</tt> - +true+ if the document was deleted successfully
67
+ #
68
+ # ==== Example
69
+ # hp = Helipad.new("lonnon@example.com", "password")
70
+ # response = hp.destroy(81)
71
+ # puts "Document deleted" if response.deleted?
72
+ def destroy(id)
73
+ url = URI.parse("http://pad.helicoid.net/document/#{id}/destroy")
74
+ Response.new(send_request(url, build_request))
75
+ end
76
+
77
+ # Search for Helipad[http://pad.helicoid.net/home.html] documents by text content or by tags.
78
+ #
79
+ # ==== Parameters
80
+ # The find method searches differently depending on its arguments:
81
+ # * <tt>find(String)</tt> - Search for the string in the titles and bodies of documents.
82
+ # * <tt>find(:tag, String)</tt> - Search for documents tagged with the string.
83
+ #
84
+ # ==== Returns
85
+ # This method returns an Array of Helipad::Document objects, or +nil+ if nothing
86
+ # could be found matching the given search string. See Helipad::Document for more details
87
+ # about the Document object.
88
+ #
89
+ # ==== Examples
90
+ # hp = Helipad.new("lonnon@example.com", "password")
91
+ # docs = hp.find("wibble")
92
+ # puts "#{docs.size} documents contain 'wibble'"
93
+ #
94
+ # docs = hp.find(:tag, "diary")
95
+ # puts "First diary entry is titled '#{docs.first.title}'"
96
+ def find(*args)
97
+ raise(ArgumentError, "No find arguments supplied", caller) if args.size == 0
98
+ term = args.extract_search_term!
99
+ case args.first
100
+ when :tag then find_by_tag(term)
101
+ when nil then search(term)
102
+ else raise(ArgumentError, "Unknown find option '#{args.first}' supplied", caller)
103
+ end
104
+ end
105
+
106
+ # Retrieve a Helipad[http://pad.helicoid.net/home.html] document.
107
+ #
108
+ # ==== Parameter
109
+ # * +id+ - ID of the document to retrieve
110
+ #
111
+ # ==== Returns
112
+ # This method returns a Helipad::Document object, which holds the contents and
113
+ # properties of the document. See Helipad::Document for more details about the
114
+ # Document object.
115
+ #
116
+ # ==== Example
117
+ # hp = Helipad.new("lonnon@example.com", "password")
118
+ # document = hp.get(29)
119
+ # puts "#{document.title} contains #{document.source.length} characters."
120
+ def get(id)
121
+ url = URI.parse("http://pad.helicoid.net/document/#{id}/get")
122
+ Document.new(send_request(url, build_request))
123
+ end
124
+
125
+ # Retrieve all documents on a Helipad[http://pad.helicoid.net/home.html]
126
+ # account.
127
+ #
128
+ # ==== Returns
129
+ # This method returns an Array of Helipad::Document objects. See
130
+ # Helipad::Document for more details about the document object.
131
+ #
132
+ # ==== Example
133
+ # hp = Helipad.new("lonnon@example.com", "password")
134
+ # docs = hp.get_all
135
+ # case docs.size
136
+ # when > 1000 then puts "Slow down there, Shakespeare!"
137
+ # when > 100 then puts "That's a respectable amount of writing."
138
+ # when > 10 then puts "Keep at it!"
139
+ # else puts "Do you even use your Helipad account?"
140
+ # end
141
+ def get_all
142
+ url = URI.parse("http://pad.helicoid.net/")
143
+ response = REXML::Document.new(send_request(url, build_request))
144
+ documents = Array.new
145
+ REXML::XPath.match(response, "//document").each do |doc|
146
+ documents.push Document.new(doc)
147
+ end
148
+ documents
149
+ end
150
+
151
+ # Retrieve an HTML-formatted version of a Helipad[http://pad.helicoid.net/home.html] document.
152
+ #
153
+ # ==== Parameter
154
+ # * +id+ - ID of the document to retrieve
155
+ #
156
+ # ==== Returns
157
+ # This method returns a String containing the HTML-formatted document.
158
+ #
159
+ # ==== Example
160
+ # hp = Helipad.new("lonnon@example.com", "password")
161
+ # puts hp.get_html(94)
162
+ def get_html(id)
163
+ url = URI.parse("http://pad.helicoid.net/document/#{id}/format/html")
164
+ doc = REXML::Document.new(send_request(url, build_request))
165
+ REXML::XPath.match(doc, "html/child::text()").join.strip
166
+ end
167
+
168
+ # Retrieve a list of all the document titles in a Helipad[http://pad.helicoid.net/home.html] account.
169
+ #
170
+ # ==== Returns
171
+ # This method returns an Array of Helipad::Document objects that contain titles, but
172
+ # no document source. See Helipad::Document for more details about the Document object.
173
+ #
174
+ # ==== Example
175
+ # hp = Helipad.new("lonnon@example.com", "password")
176
+ # puts "Table of Contents"
177
+ # hp.get_titles.each do |doc|
178
+ # puts doc.title
179
+ # end
180
+ def get_titles
181
+ url = URI.parse("http://pad.helicoid.net/documents/titles")
182
+ response = REXML::Document.new(send_request(url, build_request))
183
+ documents = Array.new
184
+ REXML::XPath.match(response, "//document").each do |doc|
185
+ documents.push Document.new(doc)
186
+ end
187
+ documents
188
+ end
189
+
190
+ # Update an existing Helipad[http://pad.helicoid.net/home.html] document.
191
+ #
192
+ # ==== Parameters
193
+ # +id+ is the ID of the document to be updated.
194
+ #
195
+ # +args+ is a Hash containing properties to update in the document. All of the properties
196
+ # are optional.
197
+ #
198
+ # * <tt>:title</tt> - Updated title for the document
199
+ # * <tt>:tags</tt> - Space-separated list of tags for the document
200
+ # * <tt>:source</tt> - Updated body of the document.
201
+ # Helipad[http://pad.helicoid.net/home.html] understands {Textile markup}[http://pad.helicoid.net/formatting],
202
+ # which you can use to format the document's text.
203
+ #
204
+ # ==== Returns
205
+ # This method returns a Helipad::Response object, which has the following method:
206
+ # * <tt>saved?</tt> - +true+ if the document was created successfully
207
+ #
208
+ # ==== Example
209
+ # hp = Helipad.new("lonnon@example.com", "password")
210
+ # response = hp.update(:title => "Marsupial Inventory (amended)",
211
+ # :source => "|koala|2|\n|kangaroo|2|\n|platypus|19|")
212
+ # puts "Inventory updated" if response.saved?
213
+ def update(id, *args)
214
+ url = URI.parse("http://pad.helicoid.net/document/#{id}/update")
215
+ options = args.extract_options!
216
+ validate_options(options, :update)
217
+ raise(ArgumentError, "No options specified", caller) if options.empty?
218
+ Response.new(send_request(url, build_request(options)))
219
+ end
220
+
221
+
222
+ # Contains the properties and data that make up a Helipad[http://pad.helicoid.net/home.html] document.
223
+ #
224
+ # Various Helipad methods create and return Helipad::Document objects; there is
225
+ # probably little reason to make an instance of Helipad::Document in your own code.
226
+ #
227
+ # The class contains a number of read-only methods for retrieving a document's properties. Depending
228
+ # on which Helipad method created the Helipad::Document object, some of these methods may
229
+ # not be present. For example, the Helipad.get_titles method leaves out the +source+
230
+ # attribute.
231
+ # * +doc_id+ - ID of the document
232
+ # * +title+ - Title of the document
233
+ # * +source+ - Body of the document. Helipad[http://pad.helicoid.net/home.html] understands
234
+ # {Textile markup}[http://pad.helicoid.net/formatting],
235
+ # which you can use to format the document's text.
236
+ # * +tags+ - An Array containing the document's tags, each of which is a String
237
+ # * +created_on+ - A DateTime object containing the creation time of the document
238
+ # * +updated_on+ - A DateTime object containing the document's last modification time
239
+ # * +share+ - The URL where the document is shared, or +nil+ if the document is not shared
240
+ # * <tt>approved?</tt> - +true+ if the document contains a plugin approved by
241
+ # Helipad[http://pad.helicoid.net/home.html] staff; +false+ otherwise.
242
+ # * <tt>dangerous?</tt> - I don't know what this means, but it's +true+ if the document's "dangerous"
243
+ # property is true, and +false+ otherwise.
244
+ # * +raw_response+ - The raw XML response returned by Helipad[http://pad.helicoid.net/home.html].
245
+ # This could be useful if, for some reason, you want to parse the results yourself. See the
246
+ # {Helipad API documentation}[http://pad.helicoid.net/document/public/6313d317] for more
247
+ # information.
248
+ class Document
249
+ def initialize(source) #:nodoc:
250
+ if source.kind_of? REXML::Element
251
+ doc = REXML::Document.new(source.to_s)
252
+ else
253
+ doc = REXML::Document.new(source)
254
+ end
255
+ REXML::XPath.match(doc, "document/*").each do |tag|
256
+ suffix = ""
257
+ case tag.name
258
+ when "approved"
259
+ name = "approved"
260
+ suffix = "?"
261
+ value = tag.text == "true" ? true : false
262
+ when "created-on"
263
+ name = "created_on"
264
+ value = DateTime.parse tag.text
265
+ when "dangerous"
266
+ name = "dangerous"
267
+ suffix = "?"
268
+ value = tag.text == "true" ? true : false
269
+ when "share"
270
+ name = "share"
271
+ if tag.attributes["nil"] == "true"
272
+ value = nil
273
+ else
274
+ value = "http://pad.helicoid.net/document/public/#{tag.text}"
275
+ end
276
+ when "source"
277
+ name = "source"
278
+ value = tag.text
279
+ when "title"
280
+ name = "title"
281
+ value = tag.text
282
+ when "updated-on"
283
+ name = "updated_on"
284
+ value = DateTime.parse tag.text
285
+ when "id"
286
+ name = "doc_id"
287
+ value = Integer(tag.text)
288
+ when "tags"
289
+ name = "tags"
290
+ value = Array.new
291
+ REXML::XPath.match(tag, "tag/name/child::text()").each do |this_tag|
292
+ value.push this_tag.to_s
293
+ end
294
+ else
295
+ name = tag.name
296
+ value = tag.text
297
+ end
298
+ self.instance_eval %{
299
+ def self.#{name}#{suffix}
300
+ @#{name}
301
+ end
302
+ @#{name} = value
303
+ }, __FILE__, __LINE__
304
+ end
305
+ self.instance_eval %{
306
+ def self.raw_response
307
+ @raw_response
308
+ end
309
+ @raw_response = %{#{source}}
310
+ }, __FILE__, __LINE__
311
+ end
312
+ end
313
+
314
+
315
+ # Contains the data returned by Helipad[http://pad.helicoid.net/home.html] in response to certain
316
+ # API calls.
317
+ #
318
+ # Various Helipad methods create and return Helipad::Response objects; there is
319
+ # probably little reason to make an instance of Helipad::Response in your own code.
320
+ #
321
+ # The class contains a number of read-only methods for retrieving a response's properties. Depending
322
+ # on which Helipad method created the Helipad::Response object, some of these methods may
323
+ # not be present. For example, the Helipad.update method leaves out the +doc_id+
324
+ # attribute, and Helipad.destroy doesn't use the <tt>saved?</tt> method.
325
+ # * +doc_id+ - ID of the document associated with the response. Helipad.create returns this
326
+ # to let you know the ID of the document it just created.
327
+ # * <tt>saved?</tt> - +true+ if the document was saved succesfully, otherwise +false+
328
+ # * <tt>deleted?</tt> - +true+ if the document was deleted successfully, otherwise +false+
329
+ # * +raw_response+ - The raw XML response returned by Helipad[http://pad.helicoid.net/home.html].
330
+ # This could be useful if, for some reason, you want to parse the results yourself. See the
331
+ # {Helipad API documentation}[http://pad.helicoid.net/document/public/6313d317] for more
332
+ # information.
333
+ class Response
334
+ def initialize(raw_response) #:nodoc:
335
+ doc = REXML::Document.new raw_response
336
+ REXML::XPath.match(doc, "//*").each do |tag|
337
+ suffix = ""
338
+ case tag.name
339
+ when "saved"
340
+ name = "saved"
341
+ suffix = "?"
342
+ value = tag.text == "true" ? true : false
343
+ when "deleted"
344
+ name = "deleted"
345
+ suffix = "?"
346
+ value = tag.text == "true" ? true : false
347
+ when "id"
348
+ name = "doc_id"
349
+ value = Integer(tag.text)
350
+ else
351
+ name = tag.name
352
+ value = tag.text
353
+ end
354
+ self.instance_eval %{
355
+ def self.#{name}#{suffix}
356
+ @#{name}
357
+ end
358
+ @#{name} = value
359
+ }, __FILE__, __LINE__ unless tag.name == "response"
360
+ end
361
+ self.instance_eval %{
362
+ def self.raw_response
363
+ @raw_response
364
+ end
365
+ @raw_response = %{#{raw_response}}
366
+ }, __FILE__, __LINE__
367
+ end
368
+ end
369
+
370
+ private
371
+
372
+ def authentication_block
373
+ block = %{
374
+ <authentication>
375
+ <email>#{@email}</email>
376
+ <password>#{@password}</password>
377
+ </authentication>
378
+ }
379
+ end
380
+
381
+ def build_request(*args)
382
+ options = args.extract_options!
383
+ request = "<request>#{authentication_block}"
384
+ unless options.empty?
385
+ request << "<document>"
386
+ options.each_pair do |key, value|
387
+ request << "<#{key}>#{value}</#{key}>"
388
+ end
389
+ request << "</document>"
390
+ end
391
+ request << "</request>"
392
+ end
393
+
394
+ def find_by_tag(tag)
395
+ raise(ArgumentError, "No tag supplied", caller) if tag.nil?
396
+ url = URI.parse("http://pad.helicoid.net/document/tag/#{URI.escape(tag)}")
397
+ request = "<request>#{authentication_block}</request>"
398
+ response = REXML::Document.new(send_request(url, request))
399
+ documents = Array.new
400
+ REXML::XPath.match(response, "//document").each do |doc|
401
+ documents.push Document.new(doc)
402
+ end
403
+ documents.size > 0 ? documents : nil
404
+ end
405
+
406
+ def search(term)
407
+ url = URI.parse("http://pad.helicoid.net/document/search")
408
+ request = "<request>#{authentication_block}<search>#{term}</search></request>"
409
+ response = REXML::Document.new(send_request(url, request))
410
+ documents = Array.new
411
+ REXML::XPath.match(response, "//document").each do |doc|
412
+ documents.push Document.new(doc)
413
+ end
414
+ documents.size > 0 ? documents : nil
415
+ end
416
+
417
+ def send_request(url, request)
418
+ response = Net::HTTP.start(url.host, url.port) do |http|
419
+ http.post(url.path, request,
420
+ {'Accept' => 'application/xml', 'Content-Type' => 'application/xml'})
421
+ end
422
+ case response
423
+ when Net::HTTPSuccess, Net::HTTPRedirection
424
+ response.body
425
+ else
426
+ response.error!
427
+ end
428
+ end
429
+
430
+ VALID_CREATE_OPTIONS = [:title, :source, :tags] #:nodoc:
431
+ VALID_UPDATE_OPTIONS = [:title, :source, :tags] #:nodoc:
432
+
433
+ def validate_options(options, action)
434
+ case action
435
+ when :create then constant = VALID_CREATE_OPTIONS
436
+ when :update then constant = VALID_UPDATE_OPTIONS
437
+ end
438
+ options.assert_valid_keys(constant)
439
+ end
440
+ end
441
+
442
+ class Array #:nodoc: all
443
+ def extract_options!
444
+ last.is_a?(::Hash) ? pop : {}
445
+ end
446
+
447
+ def extract_search_term!
448
+ last.is_a?(::String) ? pop : nil
449
+ end
450
+ end
451
+
452
+ class Hash #:nodoc: all
453
+ def assert_valid_keys(*valid_keys)
454
+ unknown_keys = keys - [valid_keys].flatten
455
+ raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
456
+ end
457
+ end
@@ -0,0 +1,122 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'helipad'
3
+ require 'test/unit'
4
+ require 'optparse'
5
+
6
+ class TestHelipad < Test::Unit::TestCase
7
+ def setup
8
+ raise(ArgumentError, "Usage: #{$0} -- email password", caller) if ARGV.length != 2
9
+ @email = ARGV[0]
10
+ @password = ARGV[1]
11
+ @hp = Helipad.new(@email, @password)
12
+ @test_string = [Array.new(6){rand(256).chr}.join].pack("m").chomp
13
+ response = @hp.create(:title => "test #{@test_string}",
14
+ :tags => "test #{@test_string}",
15
+ :source => "test #{@test_string}")
16
+ @test_id = response.doc_id
17
+ end
18
+
19
+ def teardown
20
+ @hp.destroy(@test_id)
21
+ end
22
+
23
+ def test_create
24
+ response = nil
25
+ assert_nothing_raised do
26
+ response = @hp.create(:title => "New document", :tags => "test",
27
+ :source => "Just a test document")
28
+ end
29
+ assert_equal(true, response.saved?, "Document not created.")
30
+ @hp.destroy(response.doc_id) if response.saved?
31
+ end
32
+
33
+ def test_destroy
34
+ create_response = @hp.create(:title => "Document for deletion", :tags => "test",
35
+ :source => "Should be deleted by test case")
36
+ response = nil
37
+ assert_nothing_raised do
38
+ response = @hp.destroy(create_response.doc_id)
39
+ end
40
+ assert_equal(true, response.deleted?, "Document not deleted.")
41
+ end
42
+
43
+ def test_find
44
+ documents = nil
45
+ assert_nothing_raised do
46
+ documents = @hp.find(@test_string)
47
+ end
48
+ assert_equal("test #{@test_string}", documents[0].title,
49
+ "By search term: First document title is wrong.")
50
+
51
+ documents = @hp.find("32908p9832tn9p85h92gng825g82ngp88p9834p98v348anvs8")
52
+ assert_nil(documents, "Bogus string should not be found.")
53
+
54
+ assert_nothing_raised do
55
+ documents = @hp.find(:tag, @test_string)
56
+ end
57
+ assert_equal("test #{@test_string}", documents[0].title,
58
+ "By tag: First document title is wrong.")
59
+
60
+ documents = @hp.find(:tag, "02vhn45g70h4cgh0872h54gmv072hm45g70hmv0hmv2g20457gh")
61
+ assert_nil(documents, "Bogus tag should not be found.")
62
+
63
+ assert_raise(ArgumentError) {@hp.find}
64
+ assert_raise(ArgumentError) {@hp.find(:wibble)}
65
+ assert_raise(ArgumentError) {@hp.find(:tag)}
66
+ end
67
+
68
+ def test_get
69
+ doc = nil
70
+ assert_nothing_raised do
71
+ doc = @hp.get(@test_id)
72
+ end
73
+ assert_equal("test #{@test_string}", doc.title, "Title is wrong.")
74
+ assert_equal("test #{@test_string}", doc.source, "Source is wrong.")
75
+ assert_equal(["test", @test_string], doc.tags, "Tags are wrong.")
76
+ end
77
+
78
+ def test_get_all
79
+ documents = nil
80
+ assert_nothing_raised do
81
+ documents = @hp.get_all
82
+ end
83
+ end
84
+
85
+ def test_get_html
86
+ html = nil
87
+ assert_nothing_raised do
88
+ html = @hp.get_html(@test_id)
89
+ end
90
+ exemplar = %{<h1>test #{@test_string}</h1>
91
+ <p>test #{@test_string}</p>}
92
+ assert_equal(exemplar, html, "HTML contents are wrong.")
93
+ end
94
+
95
+ def test_get_titles
96
+ documents = nil
97
+ assert_nothing_raised do
98
+ documents = @hp.get_titles
99
+ end
100
+ end
101
+
102
+ def test_update
103
+ response = nil
104
+ assert_raise(ArgumentError) {@hp.update(@test_id)}
105
+ assert_raise(ArgumentError) {@hp.update(@test_id, :wibble => "freem")}
106
+
107
+ response = @hp.update(@test_id, :title => "Modified the title")
108
+ assert_equal(true, response.saved?, "Document title wasn't updated.")
109
+ doc = @hp.get(@test_id)
110
+ assert_equal("Modified the title", doc.title, "Title is wrong.")
111
+
112
+ response = @hp.update(@test_id, :source => "Modified, darlin'")
113
+ assert_equal(true, response.saved?, "Document source wasn't updated.")
114
+ doc = @hp.get(@test_id)
115
+ assert_equal("Modified, darlin'", doc.source, "Source is wrong.")
116
+
117
+ response = @hp.update(@test_id, :tags => "test stuff")
118
+ assert_equal(true, response.saved?, "Document tags weren't updated.")
119
+ doc = @hp.get(@test_id)
120
+ assert_equal(["test", "stuff"], doc.tags, "Tags are wrong.")
121
+ end
122
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Helipad
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lonnon Foster
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-07 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: lonnon.foster@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - lib/helipad.rb
26
+ - README
27
+ has_rdoc: true
28
+ homepage: http://nyerm.com/helipad
29
+ licenses: []
30
+
31
+ post_install_message:
32
+ rdoc_options:
33
+ - --charset=UTF-8
34
+ - --title
35
+ - Helipad Documentation
36
+ - --main
37
+ - README
38
+ - --inline-source
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project: helipad
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Ruby interface to the excellent Helipad online notepad
60
+ test_files:
61
+ - test/test_helipad.rb