Helipad 0.0.1

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