wufoo_party 0.1.1 → 1.0.0
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.
- data/README.rdoc +68 -20
- data/lib/wufoo_party.rb +314 -56
- data/test/wufoo_party_test.rb +87 -28
- metadata +59 -10
data/README.rdoc
CHANGED
@@ -1,44 +1,92 @@
|
|
1
1
|
= WufooParty
|
2
2
|
|
3
|
-
|
3
|
+
WufooParty is a fairly lightweight wrapper for Wufoo's REST API[http://wufoo.com/docs/api/v3]
|
4
|
+
using HTTParty[http://httparty.rubyforge.org].
|
4
5
|
|
5
|
-
==
|
6
|
+
== API Support
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
Wufoo's REST API supports viewing and submitting entries, filtering entries,
|
9
|
+
viewing reports, and viewing users.
|
9
10
|
|
10
|
-
This
|
11
|
+
This library supports all methods of Wufoo's API version 3.0.
|
12
|
+
|
13
|
+
There is an older version of this library (version 0.1.x) that only supports version 2 of Wufoo's API.
|
14
|
+
Make sure you have latest version installed (1.0.0 or higher).
|
15
|
+
|
16
|
+
== Source & Download
|
17
|
+
|
18
|
+
* {Homepage & Demo}[http://wufooparty.71m.us]
|
19
|
+
* {Source Code}[http://github.com/seven1m/wufoo_party]
|
20
|
+
* {RDoc Documentation}[http://seven1m.github.com/wufoo_party]
|
11
21
|
|
12
22
|
== Installation
|
13
23
|
|
14
|
-
|
24
|
+
gem install wufoo_party
|
15
25
|
|
16
26
|
== Usage
|
17
27
|
|
18
28
|
require 'wufoo_party'
|
19
|
-
|
29
|
+
|
20
30
|
ACCOUNT = 'accountname'
|
21
31
|
API_KEY = 'AAAA-BBBB-CCCC-DDDD'
|
22
32
|
FORM_ID = 'my-form-id'
|
23
|
-
|
33
|
+
|
24
34
|
wufoo = WufooParty.new(ACCOUNT, API_KEY)
|
25
|
-
|
26
|
-
wufoo.
|
27
|
-
|
28
|
-
|
35
|
+
|
36
|
+
wufoo.forms # list all accessible forms and details
|
37
|
+
form = wufoo.form(FORM_ID) # or details for a specific form
|
38
|
+
|
39
|
+
# query all entries
|
40
|
+
form.entries
|
41
|
+
|
42
|
+
# ...or filter entries (see http://wufoo.com/docs/api/v3/entries/get/#filter)
|
43
|
+
form.entries([['Field1', 'Is_equal_to', 'Tim']])
|
44
|
+
|
45
|
+
# To submit, use field numbers shown on the 'API Information' page in Wufoo
|
46
|
+
result = wufoo.submit(
|
47
|
+
'Field1' => 'Tim',
|
48
|
+
'Field2' => 'Morgan'
|
29
49
|
})
|
30
|
-
result
|
31
|
-
|
32
|
-
|
33
|
-
# "Name"=>"Tim"}
|
50
|
+
if result['Success'] == 0
|
51
|
+
puts result['ErrorText']
|
52
|
+
end
|
34
53
|
|
35
54
|
== Feedback
|
36
55
|
|
37
|
-
I’d love to hear from you if you have suggestions for improvement, bug fixes, or whatever.
|
56
|
+
I’d love to hear from you if you have suggestions for improvement, bug fixes, or whatever.
|
57
|
+
Email me at mailto:tim@timmorgan.org or fork the project[http://github.com/seven1m/wufoo_party] and send a pull request.
|
58
|
+
|
59
|
+
http://timmorgan.org
|
38
60
|
|
39
|
-
|
61
|
+
== Tests
|
62
|
+
|
63
|
+
To run the tests, you must create a form called "Test Form" and pass in its id via the
|
64
|
+
ENV variable WUFOO_FORM_ID. Give the form a standard name and address field.
|
65
|
+
Make the name field required. Then run:
|
40
66
|
|
41
67
|
WUFOO_ACCOUNT=accountname \
|
42
68
|
WUFOO_API_KEY=AAAA-BBBB-CCCC-DDDD \
|
43
|
-
WUFOO_FORM_ID=
|
44
|
-
ruby -rrubygems test/wufoo_party_test.rb
|
69
|
+
WUFOO_FORM_ID=test-form \
|
70
|
+
ruby -rrubygems test/wufoo_party_test.rb
|
71
|
+
|
72
|
+
== License
|
73
|
+
|
74
|
+
Copyright (c) 2010 Tim Morgan
|
75
|
+
|
76
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
77
|
+
of this software and associated documentation files (the "Software"), to deal
|
78
|
+
in the Software without restriction, including without limitation the rights
|
79
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
80
|
+
copies of the Software, and to permit persons to whom the Software is
|
81
|
+
furnished to do so, subject to the following conditions:
|
82
|
+
|
83
|
+
The above copyright notice and this permission notice shall be included in
|
84
|
+
all copies or substantial portions of the Software.
|
85
|
+
|
86
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
87
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
88
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
89
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
90
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
91
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
92
|
+
THE SOFTWARE.
|
data/lib/wufoo_party.rb
CHANGED
@@ -1,79 +1,337 @@
|
|
1
1
|
require 'httparty'
|
2
|
+
gem 'multipart-post'
|
3
|
+
require 'net/http/post/multipart'
|
4
|
+
gem 'mime-types'
|
5
|
+
require 'mime/types'
|
6
|
+
|
7
|
+
# multipart POST support from David Balater's fork of HTTParty:
|
8
|
+
# http://github.com/dbalatero/httparty
|
9
|
+
# :stopdoc:
|
10
|
+
module HTTParty
|
11
|
+
module ClassMethods
|
12
|
+
def post(path, options={})
|
13
|
+
klass = options[:multipart] ? Net::HTTP::Post::Multipart : Net::HTTP::Post
|
14
|
+
perform_request klass, path, options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class Request
|
18
|
+
SupportedHTTPMethods << Net::HTTP::Post::Multipart
|
19
|
+
private
|
20
|
+
def setup_raw_request
|
21
|
+
if multipart?
|
22
|
+
@file_handles = []
|
23
|
+
io_objects = {}
|
24
|
+
|
25
|
+
options[:multipart].each do |field_name, info|
|
26
|
+
fp = File.open(info[:path])
|
27
|
+
@file_handles << fp
|
28
|
+
|
29
|
+
io_objects[field_name] = UploadIO.new(fp,
|
30
|
+
info[:type],
|
31
|
+
info[:path])
|
32
|
+
end
|
33
|
+
|
34
|
+
options[:body].each do |field_name, value|
|
35
|
+
io_objects[field_name] = value
|
36
|
+
end
|
37
|
+
|
38
|
+
@raw_request = http_method.new(uri.request_uri,
|
39
|
+
io_objects)
|
40
|
+
|
41
|
+
# We have to duplicate and merge the headers set by the
|
42
|
+
# multipart object to make sure that Net::HTTP
|
43
|
+
# doesn't override them down the line when it calls
|
44
|
+
# initialize_http_header.
|
45
|
+
#
|
46
|
+
# Otherwise important headers like Content-Length,
|
47
|
+
# Accept, and Content-Type will be deleted.
|
48
|
+
original_headers = {}
|
49
|
+
@raw_request.each do |key, value|
|
50
|
+
original_headers[key] = value
|
51
|
+
end
|
52
|
+
|
53
|
+
options[:headers] ||= {}
|
54
|
+
original_headers.merge!(options[:headers])
|
55
|
+
options[:headers] = original_headers
|
56
|
+
else
|
57
|
+
@raw_request = http_method.new(uri.request_uri)
|
58
|
+
@raw_request.body = body if body
|
59
|
+
end
|
60
|
+
|
61
|
+
@raw_request.initialize_http_header options[:headers]
|
62
|
+
@raw_request.basic_auth(username, password) if options[:basic_auth]
|
63
|
+
end
|
64
|
+
def multipart?
|
65
|
+
Net::HTTP::Post::Multipart == http_method
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
# :startdoc:
|
2
70
|
|
3
71
|
class WufooParty
|
4
72
|
include HTTParty
|
5
73
|
format :json
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
74
|
+
|
75
|
+
VERSION = '1.0.0'
|
76
|
+
|
77
|
+
# Represents a general error connecting to the Wufoo service
|
78
|
+
class ConnectionError < RuntimeError; end
|
79
|
+
|
80
|
+
# Represents a specific error returned from Wufoo.
|
81
|
+
class HTTPError < RuntimeError
|
82
|
+
def initialize(code, message) # :nodoc:
|
83
|
+
@code = code
|
84
|
+
super(message)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Error code
|
88
|
+
attr_reader :code
|
89
|
+
end
|
90
|
+
|
91
|
+
ENDPOINT = 'https://%s.wufoo.com/api/v3'
|
92
|
+
API_VERSION = '3.0'
|
93
|
+
|
11
94
|
# Create a new WufooParty object
|
12
95
|
def initialize(account, api_key)
|
13
96
|
@account = account
|
14
97
|
@api_key = api_key
|
15
98
|
@field_numbers = {}
|
16
99
|
end
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'w_version' => API_VERSION,
|
24
|
-
'w_form' => form_id
|
25
|
-
}
|
26
|
-
result = self.class.post(QUERY_ENDPOINT % @account, :body => args)
|
27
|
-
add_title_to_fields!(result)
|
28
|
-
result
|
100
|
+
|
101
|
+
# Returns list of forms and details accessible by the user account.
|
102
|
+
def forms
|
103
|
+
get(:forms)['Forms'].map do |details|
|
104
|
+
Form.new(details['Url'], :party => self, :details => details)
|
105
|
+
end
|
29
106
|
end
|
30
|
-
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
'w_form' => form_id
|
37
|
-
}.merge(data)
|
38
|
-
self.class.post(SUBMIT_ENDPOINT % @account, :body => args)
|
107
|
+
|
108
|
+
# Returns list of reports and details accessible by the user account.
|
109
|
+
def reports
|
110
|
+
get(:reports)['Reports'].map do |details|
|
111
|
+
Report.new(details['Url'], :party => self, :details => details)
|
112
|
+
end
|
39
113
|
end
|
40
|
-
|
41
|
-
#
|
42
|
-
def
|
43
|
-
|
114
|
+
|
115
|
+
# Returns list of users and details.
|
116
|
+
def users
|
117
|
+
get(:users)['Users'].map do |details|
|
118
|
+
User.new(details['Url'], :party => self, :details => details)
|
119
|
+
end
|
44
120
|
end
|
45
|
-
|
46
|
-
#
|
47
|
-
def
|
48
|
-
|
121
|
+
|
122
|
+
# Returns details about the specified form.
|
123
|
+
def form(form_id)
|
124
|
+
if f = get("forms/#{form_id}")['Forms']
|
125
|
+
Form.new(f.first['Url'], :party => self, :details => f.first)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns details about the specified report.
|
130
|
+
def report(report_id)
|
131
|
+
if r = get("reports/#{report_id}")['Reports']
|
132
|
+
Form.new(r.first['Url'], :party => self, :details => r.first)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def get(method, options={}) # :nodoc:
|
137
|
+
options.merge!(:basic_auth => {:username => @api_key})
|
138
|
+
url = "#{base_url}/#{method}.json"
|
139
|
+
result = self.class.get(url, options)
|
140
|
+
if result.is_a?(String)
|
141
|
+
raise ConnectionError, result
|
142
|
+
elsif result['HTTPCode']
|
143
|
+
raise HTTPError.new(result['HTTPCode'], result['Text'])
|
144
|
+
else
|
145
|
+
result
|
146
|
+
end
|
49
147
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
148
|
+
|
149
|
+
def post(method, options={}) # :nodoc:
|
150
|
+
options.merge!(:basic_auth => {:username => @api_key})
|
151
|
+
url = "#{base_url}/#{method}.json"
|
152
|
+
result = self.class.post(url, options)
|
153
|
+
if result.is_a?(String)
|
154
|
+
raise ConnectionError, result
|
155
|
+
elsif result['HTTPCode']
|
156
|
+
raise HTTPError.new(result['HTTPCode'], result['Text'])
|
157
|
+
else
|
158
|
+
result
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def base_url
|
165
|
+
ENDPOINT % @account
|
166
|
+
end
|
167
|
+
|
168
|
+
public
|
169
|
+
|
170
|
+
# ----------
|
171
|
+
|
172
|
+
class Entity # :nodoc:
|
173
|
+
include HTTParty
|
174
|
+
format :json
|
175
|
+
|
176
|
+
def initialize(id, options)
|
177
|
+
@id = id
|
178
|
+
if options[:party]
|
179
|
+
@party = options[:party]
|
180
|
+
elsif options[:account] and options[:api_key]
|
181
|
+
@party = WufooParty.new(options[:account], options[:api_key])
|
182
|
+
else
|
183
|
+
raise WufooParty::InitializationException, "You must either specify a :party object or pass the :account and :api_key options. Please see the README."
|
59
184
|
end
|
60
|
-
|
185
|
+
@details = options[:details]
|
61
186
|
end
|
187
|
+
|
188
|
+
attr_accessor :details
|
62
189
|
end
|
63
|
-
|
64
|
-
#
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
190
|
+
|
191
|
+
# Wraps an individual Wufoo Form.
|
192
|
+
# == Instantiation
|
193
|
+
# There are two ways to instantiate a Form object:
|
194
|
+
# 1. Via the parent WufooParty object that represents the account.
|
195
|
+
# 2. Via the WufooParty::Form class directly.
|
196
|
+
# wufoo = WufooParty.new(ACCOUNT, API_KEY)
|
197
|
+
# form = wufoo.form(FORM_ID)
|
198
|
+
# # or...
|
199
|
+
# form = WufooParty::Form.new(FORM_ID, :account => ACCOUNT, :api_key => API_KEY)
|
200
|
+
# The first technique makes a call to the Wufoo API to get the form details,
|
201
|
+
# while the second technique lazily loads the form details, once something is accessed via [].
|
202
|
+
# == \Form Details
|
203
|
+
# Access form details like it is a Hash, e.g.:
|
204
|
+
# form['Name']
|
205
|
+
# form['RedirectMessage']
|
206
|
+
class Form < Entity
|
207
|
+
# Returns field details for the form.
|
208
|
+
def fields
|
209
|
+
@party.get("forms/#{@id}/fields")['Fields']
|
210
|
+
end
|
211
|
+
|
212
|
+
# Access form details.
|
213
|
+
def [](id)
|
214
|
+
@details ||= @party.form(@id)
|
215
|
+
@details[id]
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns fields and subfields, as a flattened array, e.g.
|
219
|
+
# [{'ID' => 'Field1', 'Title' => 'Name - First', 'Type' => 'shortname', 'Required' => true }, # (subfield)
|
220
|
+
# {'ID' => 'Field2', 'Title' => 'Name - Last', 'Type' => 'shortname', 'Required' => true }, # (subfield)
|
221
|
+
# {'ID' => 'Field3', 'Title' => 'Birthday', 'Type' => 'date', 'Required' => flase}] # (field)
|
222
|
+
# By default, only fields that can be submitted are returned. Pass *true* as the first arg to return all fields.
|
223
|
+
def flattened_fields(all=false)
|
224
|
+
flattened = []
|
225
|
+
fields.each do |field|
|
226
|
+
next unless all or field['ID'] =~ /^Field/
|
227
|
+
if field['SubFields']
|
228
|
+
field['SubFields'].each do |sub_field|
|
229
|
+
flattened << {'ID' => sub_field['ID'], 'Title' => field['Title'] + ' - ' + sub_field['Label'], 'Type' => field['Type'], 'Required' => field['IsRequired'] == '1'}
|
74
230
|
end
|
231
|
+
else
|
232
|
+
flattened << {'ID' => field['ID'], 'Title' => field['Title'], 'Type' => field['Type'], 'Required' => field['IsRequired'] == '1'}
|
233
|
+
end
|
234
|
+
end
|
235
|
+
flattened
|
236
|
+
end
|
237
|
+
|
238
|
+
# Return entries already submitted to the form.
|
239
|
+
#
|
240
|
+
# If you need to filter entries, pass an array as the first argument:
|
241
|
+
# entries([[field_id, operator, value], ...])
|
242
|
+
# e.g.:
|
243
|
+
# entries([['EntryId', 'Is_after', 12], ['EntryId', 'Is_before', 17]])
|
244
|
+
# entries([['Field1', 'Is_equal', 'Tim']])
|
245
|
+
# The second arg is the match parameter (AND/OR) and defaults to 'AND', e.g.
|
246
|
+
# entries([['Field2', 'Is_equal', 'Morgan'], ['Field2', 'Is_equal', 'Smith']], 'OR')
|
247
|
+
# See http://wufoo.com/docs/api/v3/entries/get/#filter for details
|
248
|
+
def entries(filters=[], filter_match='AND')
|
249
|
+
if filters.any?
|
250
|
+
options = {'match' => filter_match}
|
251
|
+
filters.each_with_index do |filter, index|
|
252
|
+
options["Filter#{index+1}"] = filter.join(' ')
|
253
|
+
end
|
254
|
+
options = {:query => options}
|
255
|
+
else
|
256
|
+
options = {}
|
257
|
+
end
|
258
|
+
@party.get("forms/#{@id}/entries", options)['Entries']
|
259
|
+
end
|
260
|
+
|
261
|
+
# Submit form data to the form.
|
262
|
+
# Pass data as a hash, with field ids as the hash keys, e.g.
|
263
|
+
# submit('Field1' => 'Tim', 'Field2' => 'Morgan')
|
264
|
+
# Return value is a Hash that includes the following keys:
|
265
|
+
# * Status
|
266
|
+
# * ErrorText
|
267
|
+
# * FieldErrors
|
268
|
+
# You must submit values for required fields (including all sub fields),
|
269
|
+
# and dates must be formatted as <tt>YYYYMMDD</tt>.
|
270
|
+
def submit(data)
|
271
|
+
options = {}
|
272
|
+
data.each do |key, value|
|
273
|
+
if value.is_a?(Hash)
|
274
|
+
type = MIME::Types.of(value[:path]).first.content_type rescue 'application/octet-stream'
|
275
|
+
options[:multipart] ||= {}
|
276
|
+
options[:multipart][key] = {:type => type, :path => value[:path]}
|
277
|
+
else
|
278
|
+
options[:body] ||= {}
|
279
|
+
options[:body][key] = value
|
75
280
|
end
|
76
281
|
end
|
282
|
+
@party.post("forms/#{@id}/entries", options)
|
283
|
+
end
|
284
|
+
|
285
|
+
# Returns comment details for the form.
|
286
|
+
# See Wufoo API documentation for possible options,
|
287
|
+
# e.g. to filter comments for a specific form entry:
|
288
|
+
# form.comments('entryId' => 123)
|
289
|
+
def comments(options={})
|
290
|
+
options = {:query => options} if options.any?
|
291
|
+
@party.get("forms/#{@id}/comments", options)['Comments']
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# Wraps an individual Wufoo Report.
|
296
|
+
# == Instantiation
|
297
|
+
# There are two ways to instantiate a Report object:
|
298
|
+
# 1. Via the parent WufooParty object that represents the account.
|
299
|
+
# 2. Via the WufooParty::Report class directly.
|
300
|
+
# wufoo = WufooParty.new(ACCOUNT, API_KEY)
|
301
|
+
# report = wufoo.report(REPORT_ID)
|
302
|
+
# # or...
|
303
|
+
# report = WufooParty::Report.new(REPORT_ID, :account => ACCOUNT, :api_key => API_KEY)
|
304
|
+
# The first technique makes a call to the Wufoo API to get the report details,
|
305
|
+
# while the second technique lazily loads the report details, once something is accessed via [].
|
306
|
+
# == \Report Details
|
307
|
+
# Access report details like it is a Hash, e.g.:
|
308
|
+
# report['Name']
|
309
|
+
class Report < Entity
|
310
|
+
# Access report details.
|
311
|
+
def [](id)
|
312
|
+
@details ||= @party.report(@id)
|
313
|
+
@details[id]
|
77
314
|
end
|
315
|
+
|
316
|
+
# Returns field details for the report
|
317
|
+
def fields
|
318
|
+
@party.get("reports/#{@id}/fields")['Fields']
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns widget details for the report
|
322
|
+
def widgets
|
323
|
+
@party.get("reports/#{@id}/widgets")['Widgets']
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Wraps an individual Wufoo User.
|
328
|
+
class User < Entity
|
329
|
+
|
330
|
+
# Access user details.
|
331
|
+
def [](id)
|
332
|
+
@details ||= @party.report(@id)
|
333
|
+
@details[id]
|
334
|
+
end
|
335
|
+
|
78
336
|
end
|
79
|
-
end
|
337
|
+
end
|
data/test/wufoo_party_test.rb
CHANGED
@@ -2,7 +2,12 @@ require File.dirname(__FILE__) + '/../lib/wufoo_party'
|
|
2
2
|
require 'test/unit'
|
3
3
|
|
4
4
|
class WufooPartyTest < Test::Unit::TestCase
|
5
|
-
|
5
|
+
|
6
|
+
# Must create a form called "Test Form" and pass in its id
|
7
|
+
# via the ENV variable WUFOO_FORM_ID.
|
8
|
+
# Give the form standard name and address fields.
|
9
|
+
# Make the name field required.
|
10
|
+
|
6
11
|
def setup
|
7
12
|
if ENV['WUFOO_ACCOUNT'] and ENV['WUFOO_API_KEY'] and ENV['WUFOO_FORM_ID']
|
8
13
|
@wufoo = WufooParty.new(ENV['WUFOO_ACCOUNT'], ENV['WUFOO_API_KEY'])
|
@@ -12,30 +17,84 @@ class WufooPartyTest < Test::Unit::TestCase
|
|
12
17
|
exit(1)
|
13
18
|
end
|
14
19
|
end
|
15
|
-
|
16
|
-
def
|
17
|
-
assert @wufoo.
|
18
|
-
end
|
19
|
-
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
assert_equal '
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
20
|
+
|
21
|
+
def test_forms
|
22
|
+
assert @wufoo.forms
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_form
|
26
|
+
form = @wufoo.form(@form_id)
|
27
|
+
assert form
|
28
|
+
assert_equal 'Test Form', form['Name']
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_form_by_hash
|
32
|
+
hash = @wufoo.form(@form_id)['Hash']
|
33
|
+
assert @wufoo.form(hash)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_form_directly
|
37
|
+
form = WufooParty::Form.new(@form_id, :account => ENV['WUFOO_ACCOUNT'], :api_key => ENV['WUFOO_API_KEY'])
|
38
|
+
assert_equal 'Test Form', form['Name']
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_non_existent_form
|
42
|
+
assert_raise WufooParty::HTTPError do
|
43
|
+
@wufoo.form('does-not-exist')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_reports
|
48
|
+
assert @wufoo.reports
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_users
|
52
|
+
assert @wufoo.users
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_form_fields
|
56
|
+
form = @wufoo.form(@form_id)
|
57
|
+
field_names = form.fields.map { |f| f['Title'] }
|
58
|
+
assert field_names.include?('Name')
|
59
|
+
assert field_names.include?('Address')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_form_submit
|
63
|
+
form = @wufoo.form(@form_id)
|
64
|
+
result = form.submit('Field1' => 'Tim', 'Field2' => 'Morgan', 'Field3' => '4010 W. New Orleans', 'Field5' => 'Broken Arrow', 'Field6' => 'OK', 'Field7' => '74011')
|
65
|
+
assert_equal 1, result['Success']
|
66
|
+
assert result['EntryId']
|
67
|
+
assert result['EntryLink']
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_form_submit_error
|
71
|
+
form = @wufoo.form(@form_id)
|
72
|
+
# test a form error -- non-existent field
|
73
|
+
result = form.submit('Field1' => 'Tim', 'Field2' => 'Morgan', 'Field100' => 'Foobar')
|
74
|
+
assert_equal 0, result['Success']
|
75
|
+
assert result['ErrorText']
|
76
|
+
assert_equal [], result['FieldErrors']
|
77
|
+
# test a field error -- nothing in a required field
|
78
|
+
result = form.submit('Field2' => 'Morgan')
|
79
|
+
assert_equal 0, result['Success']
|
80
|
+
assert_equal 1, result['FieldErrors'].length
|
81
|
+
error = result['FieldErrors'].first
|
82
|
+
assert_equal 'Field1', error['ID']
|
83
|
+
assert_match /required/i, error['ErrorText']
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_entries
|
87
|
+
form = @wufoo.form(@form_id)
|
88
|
+
form.submit('Field1' => 'Tim', 'Field2' => 'Morgan')
|
89
|
+
assert form.entries.last['Field1'].any?
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_filtering_entries
|
93
|
+
form = @wufoo.form(@form_id)
|
94
|
+
form.submit('Field1' => 'Tim', 'Field2' => 'Morgan')
|
95
|
+
id = form.submit('Field1' => 'Jane', 'Field2' => 'Smith')['EntryId']
|
96
|
+
assert form.entries([['Field2', 'Is_equal_to', 'Morgan']]).any?
|
97
|
+
assert_equal 1, form.entries([['EntryId', 'Is_equal_to', id]]).length
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wufoo_party
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Tim Morgan
|
@@ -9,19 +15,56 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-08-29 00:00:00 -05:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: httparty
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 5
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 6
|
33
|
+
- 1
|
34
|
+
version: 0.6.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: multipart-post
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 21
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 0
|
49
|
+
- 1
|
50
|
+
version: 1.0.1
|
17
51
|
type: :runtime
|
18
|
-
|
19
|
-
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: mime-types
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
20
58
|
requirements:
|
21
59
|
- - ">="
|
22
60
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
61
|
+
hash: 47
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 16
|
65
|
+
version: "1.16"
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id003
|
25
68
|
description:
|
26
69
|
email: tim@timmorgan.org
|
27
70
|
executables: []
|
@@ -44,23 +87,29 @@ rdoc_options: []
|
|
44
87
|
require_paths:
|
45
88
|
- lib
|
46
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
47
91
|
requirements:
|
48
92
|
- - ">="
|
49
93
|
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
50
97
|
version: "0"
|
51
|
-
version:
|
52
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
53
100
|
requirements:
|
54
101
|
- - ">="
|
55
102
|
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
56
106
|
version: "0"
|
57
|
-
version:
|
58
107
|
requirements: []
|
59
108
|
|
60
109
|
rubyforge_project:
|
61
|
-
rubygems_version: 1.3.
|
110
|
+
rubygems_version: 1.3.7
|
62
111
|
signing_key:
|
63
112
|
specification_version: 3
|
64
|
-
summary:
|
113
|
+
summary: Ruby wrapper for Wufoo's REST API v3.
|
65
114
|
test_files: []
|
66
115
|
|