help_spot 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
1
  pkg
2
2
  doc
3
3
  *.gem
4
- config/help_spot.yml
4
+ *.gemspec
data/README.rdoc CHANGED
@@ -6,20 +6,22 @@ For information on HelpSpot: http://www.userscape.com/products/helpspot/
6
6
 
7
7
  Details of HelpSpot's API are at: http://www.userscape.com/helpdesk/index.php?pg=kb.book&id=6
8
8
 
9
- == License
9
+ = Installation
10
10
 
11
- Licensed under the MIT License. See the included LICENSE file.
11
+ A gem has been pushed to gemcutter[http://gemcutter.org/]
12
12
 
13
- = Usage
13
+ Once you have gemcutter setup as a gem source:
14
14
 
15
- == Installation
15
+ gem install help_spot
16
16
 
17
- Copy the <tt>config/help_spot.yml.sample</tt> file to <tt>THE_ROOT_DIR_OF_YOUR_APP/config/help_spot.yml</tt>. Edit the file to have some sensible values.
17
+ = Usage
18
18
 
19
- Somewhere in your application, you'll want to do this once:
19
+ help_spot = HelpSpot.new("https://support.yourwebsite.com/api/", "user@localhost.com", "sekrit")
20
20
 
21
- <tt>HelpSpot.configure</tt>
21
+ == Documentation
22
22
 
23
- In my app, it also turns out it's useful to do this once:
23
+ Documentation is hosted at rdoc.info[http://rdoc.info/projects/jnewland/help_spot]
24
+
25
+ == License
24
26
 
25
- <tt>HELPSPOT_CATEGORIES = HelpSpot.category_key_value_pairs</tt>
27
+ Licensed under the MIT License. See the included LICENSE file.
data/Rakefile CHANGED
@@ -1,21 +1,25 @@
1
- require 'rubygems'
2
- require 'rake'
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'help_spot/version'
3
3
 
4
4
  begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
+ gem.version = HelpSpot::VERSION
7
8
  gem.name = "help_spot"
8
- gem.summary = %Q{A package for interacting with UserScape's HelpSpot product.}
9
- gem.description = %Q{A package for interacting with UserScape's HelpSpot product.}
9
+ gem.summary = %Q{API wrapper for HelpSpot}
10
+ gem.description = %Q{API wrapper for HelpSpot}
10
11
  gem.email = "jnewland@gmail.com"
11
12
  gem.homepage = "http://github.com/jnewland/help_spot"
12
- gem.authors = ["Jamie Wilson","Jesse Newland"]
13
- gem.add_development_dependency "rspec"
13
+ gem.authors = ["Jesse Newland"]
14
+ gem.add_development_dependency "rspec", "= 1.3.0"
15
+ gem.add_development_dependency "fakeweb"
16
+ gem.add_dependency "hashie", "~> 0.1.8"
17
+ gem.add_dependency "httparty", "~> 0.5.0"
14
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
19
  end
16
20
  Jeweler::GemcutterTasks.new
17
21
  rescue LoadError
18
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
23
  end
20
24
 
21
25
  require 'spec/rake/spectask'
@@ -36,14 +40,10 @@ task :default => :spec
36
40
 
37
41
  require 'rake/rdoctask'
38
42
  Rake::RDocTask.new do |rdoc|
39
- if File.exist?('VERSION')
40
- version = File.read('VERSION')
41
- else
42
- version = ""
43
- end
43
+ version = HelpSpot::VERSION
44
44
 
45
45
  rdoc.rdoc_dir = 'rdoc'
46
46
  rdoc.title = "help_spot #{version}"
47
47
  rdoc.rdoc_files.include('README*')
48
48
  rdoc.rdoc_files.include('lib/**/*.rb')
49
- end
49
+ end
data/TODO ADDED
@@ -0,0 +1,35 @@
1
+ Unimplemented API Methods
2
+
3
+ private.customer.getPasswordByEmail
4
+ private.customer.setPasswordByEmail
5
+ private.request.addTimeEvent
6
+ private.request.deleteTimeEvent
7
+ private.request.getTimeEvents
8
+ private.request.getMailboxes
9
+ private.request.merge
10
+ private.filter.getColumnNames
11
+ private.timetracker.search
12
+ private.user.getFilters
13
+ private.user.preferences
14
+ private.util.getActiveStaff
15
+ customer.getRequests
16
+ request.create
17
+ request.update
18
+ request.getCategories
19
+ request.getCustomFields
20
+ request.get
21
+ forums.list
22
+ forums.get
23
+ forums.getTopics
24
+ forums.getPosts
25
+ forums.createTopic
26
+ forums.createPost
27
+ forums.search
28
+ kb.list
29
+ kb.get
30
+ kb.getBookTOC
31
+ kb.getPage
32
+ kb.search
33
+ kb.voteHelpful
34
+ kb.voteNotHelpful
35
+ util.getFieldLabels
@@ -0,0 +1,3 @@
1
+ class HelpSpot
2
+ VERSION = '0.0.3'
3
+ end
data/lib/help_spot.rb CHANGED
@@ -1,200 +1,87 @@
1
- require 'uri'
2
- require 'net/http'
3
- require 'net/https'
4
- require 'json'
5
-
6
- ##
7
- # help_spot
8
- #
9
- # A partial basic implementation of a HelpSpot API interface
10
- #
11
- # == Using help_spot
12
- #
13
- # === Basics
14
- #
15
- # Copy and edit the included config file. Include the gem in your app. Call the configure method. Hit the API.
16
- #
17
- # require 'help_spot'
18
- # HelpSpot.configure(:config_file => '/path/to/help_spot.yml')
19
- # HelpSpot.forums_list
20
- #
21
- # => [{"xForumId"=>"1", "fClosed"=>"0", "sForumName"=>"The First Forum", "iOrder"=>"0", "sDescription"=>"A test forum"}, {"xForumId"=>"2", "fClosed"=>"0", "sForumName"=>"Secondary Forum", "iOrder"=>"0", "sDescription"=>"Forum #2"}]
22
- #
23
-
24
- module HelpSpot
25
- class << self
26
-
27
- # Loads the config file.
28
- #
29
- # == Options
30
- # * config_file (optional)
31
- # Defaults to '/config/help_spot.yml'
32
- # Shouldn't be required when using merb or Rails.
33
- #
34
- def configure(args={})
35
- # work out the default app_root
36
- if defined?(Merb)
37
- app_root = Merb.root
38
- elsif defined?(Rails)
39
- app_root = RAILS_ROOT
40
- else
41
- app_root = '.'
42
- end
43
-
44
- config_file = args[:config_file] || '/config/help_spot.yml'
45
- yml_file = app_root+config_file
46
-
47
- raise yml_file+" not found" unless File.exist? yml_file
48
- @config = YAML.load_file(yml_file)
49
- end
50
-
51
- # sends a feedback request to HelpSpot and returns the request ID number and access key
52
- #
53
- # == Options
54
- # In addition to note you must also have at least one of the following set: first_name, last_name, user_id, email or phone
55
- # * note
56
- # The body of the ticket
57
- # * category
58
- # * first_name
59
- # * last_name
60
- # * user_id
61
- # * email
62
- # * phone
63
- # * urgent
64
- # A boolean flag. Defaults to false.
65
- #
66
- def create(args)
67
- help_form = {:tNote => args[:note],
68
- :xCategory => args[:category],
69
- :sFirstName => args[:first_name],
70
- :sLastName => args[:last_name],
71
- :sUserId => args[:user_id],
72
- :sEmail => args[:email],
73
- :sPhone => args[:phone],
74
- :fUrgent => args[:urgent]}.reject!{|k,v| v == nil}
75
-
76
- JSON.parse(api_request('request.create', 'POST', help_form))['xRequest'] rescue []
77
- end
78
-
79
- # Returns an array of tickets belonging to a given user id.
80
- #
81
- # == Authentication
82
- # This method does require authentication.
83
- #
84
- # == Options
85
- # * user_id
86
- # The user who's tickets you wish to view.
87
- #
88
- def get_by_user_id(args)
89
- JSON.parse(api_request('private.request.search', 'GET', {:sUserId => args[:user_id]}))['request'] rescue nil
90
- end
91
-
92
- # Returns ticket categories.
93
- #
94
- # == Authentication
95
- # This method does require authentication.
96
- #
97
- # == Options
98
- # * include_deleted
99
- # true if you want to include deleted categories.
100
- #
101
- def categories(args={})
102
- res = api_request('private.request.getCategories', 'GET')
103
- res = JSON.parse(res)['category'] rescue []
104
-
105
- unless args[:include_deleted] and args[:include_deleted] == true
106
- res.reject!{|k, v| v['fDeleted'] == '1'} rescue []
107
- end
108
-
109
- return res
110
- end
111
-
112
- # Returns an array of non-deleted categories, as key value pairs. Useful for select lists.
113
- #
114
- # == Authentication
115
- # This method does require authentication.
116
- #
117
- def category_key_value_pairs
118
- categories.collect{|k,v| [k,v['sCategory']]} rescue []
119
- end
120
-
121
- # Returns non-deleted categories, with a list of predefined categories removed
122
- #
123
- def category_key_value_pairs_without(categories=nil)
124
- categories ||= @config['hidden_categories'] rescue nil
125
-
126
- orig_categories = category_key_value_pairs
127
- if categories
128
- categories.each do |category|
129
- orig_categories.reject!{|i| i[1] == category}
130
- end
131
- end
132
- orig_categories
133
- end
134
-
135
- # Returns an array of forums
136
- #
137
- def forums_list
138
- JSON.parse(HelpSpot.api_request('forums.list'))['forum'] rescue []
139
- end
140
-
141
- # Returns an array of forums
142
- #
143
- # == Options
144
- # * forum_id
145
- # The numeric id of the forum you want.
146
- def forum_get(args)
147
- JSON.parse(HelpSpot.api_request('forums.get', 'GET', :xForumId => args[:forum_id])) rescue []
1
+ require 'hashie'
2
+ require 'httparty'
3
+ require 'help_spot/version'
4
+
5
+ class HelpSpot
6
+ include HTTParty
7
+ format :xml
8
+ mattr_inheritable :base
9
+
10
+ def initialize(base, user, pass)
11
+ self.class.base_uri base
12
+ self.class.basic_auth user, pass
13
+ end
14
+
15
+ # Verify authentication credentials
16
+ #
17
+ def authenticated?
18
+ version = api_request(:get, 'private.version')
19
+ return false if version.errors
20
+ return true if version.results.version
21
+ false
22
+ end
23
+
24
+ def create_request(options = {})
25
+ raise ArgumentError unless options[:tNote] && options[:xCategory]
26
+ raise ArgumentError unless options[:sFirstName] || options[:sLastName] || options[:sUserId] || options[:sEmail] || options[:sPhone]
27
+ api_request(:post, 'private.request.create', options, :item => 'request').xRequest.to_i
28
+ end
29
+
30
+ def update_request(id, options = {})
31
+ api_request(:post, 'private.request.update', options.merge(:xRequest => id), :item => 'request').xRequest.to_i
32
+ end
33
+
34
+ def request(id, options = {})
35
+ response = api_request(:get, 'private.request.get', options.merge(:xRequest => id), :item => 'request')
36
+ #munge even further the request history
37
+ response.request_history = response.request_history.map { |item| item[1].first }
38
+ response
39
+ end
40
+
41
+ def search_requests(options = {})
42
+ api_request(:get, 'private.request.search', options, {:collection => 'requests', :item => 'request'})
43
+ end
44
+
45
+ def categories
46
+ api_request(:get, 'private.request.getCategories', {:fDeleted => 0}, {:collection => 'categories', :item => 'category'})
47
+ end
48
+
49
+ def status_types
50
+ api_request(:get, 'private.request.getStatusTypes', {:fActiveOnly => 1}, {:collection => 'results', :item => 'status'})
51
+ end
52
+
53
+ def custom_fields(options = {})
54
+ api_request(:get, 'private.request.getCustomFields', options, {:collection => 'customfields', :item => 'field'})
55
+ end
56
+
57
+ def filter(id, options = {})
58
+ api_request(:get, 'private.filter.get', options.merge(:xFilter => id), {:collection => 'filter', :item => 'request'})
59
+ end
60
+
61
+ private
62
+
63
+ def api_request(http_method, method, options = {}, munge_options = {})
64
+ parsed_options = {}
65
+ if http_method == :get
66
+ parsed_options[:query] = options
67
+ else
68
+ parsed_options[:query] = {}
69
+ parsed_options[:body] = options
148
70
  end
149
-
150
- # Returns an array of topics from a given forum
151
- #
152
- # == Options
153
- # * forum_id
154
- # The numeric id of the forum you want.
155
- # * start
156
- # record set position to start at
157
- # * length
158
- # how many records to return
159
- #
160
- def forum_get_topics(args={})
161
- JSON.parse(HelpSpot.api_request('forums.getTopics', 'GET', {:xForumId => args[:forum_id]}.merge(args)))['topic'] rescue []
162
- end
163
-
164
- # Returns an array of posts from a given topic
165
- #
166
- # == Options
167
- # * topic_id
168
- # The numeric id of the topic
169
- #
170
- def forum_get_topic_posts(args={})
171
- JSON.parse(HelpSpot.api_request('forums.getPosts', 'GET', :xTopicId => args[:topic_id]))['post'] rescue []
172
- end
173
-
174
- def api_request(api_method, http_method='POST', args={})
175
- api_params = {:method => api_method, :output => 'json'}.merge(args)
176
- query_params = api_params.collect{|k,v| [k.to_s, v.to_s]} # [URI.encode(k.to_s),URI.encode(v.to_s.gsub(/\ /, '+'))]
177
- built_query = query_params.collect{|i| i.join('=')}.join('&') # make a query string
178
-
179
- ru = URI::parse(@config['root_url']) # where ru = ROOT_URL
180
- merged_query = [built_query, (ru.query == '' ? nil : ru.query)].compact.join('&') # merge our generated query string with the ROOT_URL's query string
181
-
182
- url = URI::HTTP.new(ru.scheme, ru.userinfo, ru.host, ru.port, ru.registry, ru.path, ru.opaque, merged_query, ru.fragment)
183
-
184
- request = nil
185
- if http_method == 'POST'
186
- request = Net::HTTP::Post.new(url.path)
187
- request.set_form_data(query_params)
71
+ parsed_options[:query].merge!(:method => method)
72
+ response = self.class.send(http_method, '/index.php', parsed_options)
73
+ if munge_options[:collection]
74
+ return [] unless collection = response[munge_options[:collection]][munge_options[:item]]
75
+ if collection.is_a?(Array)
76
+ collection.map { |item| Hashie::Mash.new(item) }
188
77
  else
189
- request = Net::HTTP::Get.new(url.path+'?'+url.query)
78
+ Hashie::Mash.new(collection)
190
79
  end
191
- request.basic_auth @config['username'], @config['password']
192
- http = Net::HTTP.new(url.host, url.port)
193
- http.use_ssl = (url.scheme == 'https')
194
- response = http.start { |h| h.request(request) }
195
-
196
- response.body
80
+ elsif munge_options[:item]
81
+ Hashie::Mash.new(response[munge_options[:item]])
82
+ else
83
+ Hashie::Mash.new(response)
197
84
  end
85
+ end
198
86
 
199
- end # class
200
- end # module
87
+ end
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <errors>
3
+ <error>
4
+ <id>2</id>
5
+ <description>User authentication failed</description>
6
+ </error>
7
+ </errors>
@@ -0,0 +1,53 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <filter>
3
+ <request>
4
+ <xRequest>12624</xRequest>
5
+ <fOpenedVia>Email</fOpenedVia>
6
+ <xOpenedViaId>Customer.Service</xOpenedViaId>
7
+ <xPersonOpenedBy />
8
+ <xPersonAssignedTo>Henry Yount</xPersonAssignedTo>
9
+ <fOpen>1</fOpen>
10
+ <xStatus>Active</xStatus>
11
+ <fUrgent>0</fUrgent>
12
+ <xCategory>Feature Request</xCategory>
13
+ <dtGMTOpened>July 12, 2007</dtGMTOpened>
14
+ <dtGMTClosed />
15
+ <sRequestPassword>pgupzu</sRequestPassword>
16
+ <sTitle>Upload documents over 1gig</sTitle>
17
+ <sUserId>8389332</sUserId>
18
+ <sFirstName>Harry</sFirstName>
19
+ <sLastName>Waterman</sLastName>
20
+ <sEmail>hw@example.com</sEmail>
21
+ <sPhone>845.555.1234</sPhone>
22
+ <iLastReplyBy>0</iLastReplyBy>
23
+ <fTrash>0</fTrash>
24
+ <dtGMTTrashed />
25
+ <fullname>Harry Waterman</fullname>
26
+ <tNote>I would like to be able to upload documents over 1 gigabyte.</tNote>
27
+ </request>
28
+ <request>
29
+ <xRequest>12451</xRequest>
30
+ <fOpenedVia>Phone</fOpenedVia>
31
+ <xOpenedViaId />
32
+ <xPersonOpenedBy>Tiffany Prince</xPersonOpenedBy>
33
+ <xPersonAssignedTo>Henry Yount</xPersonAssignedTo>
34
+ <fOpen>0</fOpen>
35
+ <xStatus>Problem Solved</xStatus>
36
+ <fUrgent>0</fUrgent>
37
+ <xCategory>Feature Request</xCategory>
38
+ <dtGMTOpened>September 19, 2007</dtGMTOpened>
39
+ <dtGMTClosed>September 30, 2007</dtGMTClosed>
40
+ <sRequestPassword>vyzfua</sRequestPassword>
41
+ <sTitle>Improved searching</sTitle>
42
+ <sUserId />
43
+ <sFirstName>Sarah</sFirstName>
44
+ <sLastName>Ryan</sLastName>
45
+ <sEmail />
46
+ <sPhone />
47
+ <iLastReplyBy>0</iLastReplyBy>
48
+ <fTrash>0</fTrash>
49
+ <dtGMTTrashed />
50
+ <fullname>Sarah Ryan</fullname>
51
+ <tNote>I would like to see the searching imrpoved in the upcoming release.</tNote>
52
+ </request>
53
+ </filter>
@@ -0,0 +1,89 @@
1
+ <request>
2
+ <xRequest>12745</xRequest>
3
+ <fOpenedVia>Web Service</fOpenedVia>
4
+ <xOpenedViaId>0</xOpenedViaId>
5
+ <xPersonOpenedBy />
6
+ <xPersonAssignedTo>Ian Landsman</xPersonAssignedTo>
7
+ <fOpen>1</fOpen>
8
+ <xStatus>Active</xStatus>
9
+ <fUrgent>0</fUrgent>
10
+ <xCategory>Bugs</xCategory>
11
+ <dtGMTOpened>September 24, 2007</dtGMTOpened>
12
+ <dtGMTClosed />
13
+ <sRequestPassword>itetxb</sRequestPassword>
14
+ <sTitle />
15
+ <sUserId>12345</sUserId>
16
+ <sFirstName />
17
+ <sLastName />
18
+ <sEmail />
19
+ <sPhone />
20
+ <iLastReplyBy>Ian Landsman</iLastReplyBy>
21
+ <fTrash>0</fTrash>
22
+ <dtGMTTrashed />
23
+ <fullname> </fullname>
24
+ <request_history>
25
+ <item>
26
+ <xRequestHistory>1378</xRequestHistory>
27
+ <xRequest>12745</xRequest>
28
+ <xPerson>Ian Landsman</xPerson>
29
+ <dtGMTChange>Tue, September 25, 2007, 11:00 AM</dtGMTChange>
30
+ <fPublic>1</fPublic>
31
+ <fInitial>0</fInitial>
32
+ <tLog />
33
+ <tNote><p>An HTML note example</p></tNote>
34
+ <tEmailHeaders />
35
+ <fNoteIsHTML>1</fNoteIsHTML>
36
+ <fMergedFromRequest>0</fMergedFromRequest>
37
+ <files>
38
+ <file>
39
+ <sFileMimeType>application/pdf</sFileMimeType>
40
+ <sFilename>Invoice.pdf</sFilename>
41
+ <xDocumentId>60</xDocumentId>
42
+ <public_url>http://www.domain.com/index.php?pg=file&from=3&id=60&reqid=12745&reqhisid=1378</public_url>
43
+ <private_url>http://www.domain.com/admin.php?pg=file&from=0&id=60&showfullsize=1&download=1</private_url>
44
+ </file>
45
+ </files>
46
+ </item>
47
+ <item>
48
+ <xRequestHistory>1377</xRequestHistory>
49
+ <xRequest>12745</xRequest>
50
+ <xPerson>Ian Landsman</xPerson>
51
+ <dtGMTChange>Tue, September 25, 2007, 11:00 AM</dtGMTChange>
52
+ <fPublic>0</fPublic>
53
+ <fInitial>0</fInitial>
54
+ <tLog>Category changed from "" to "Bugs"</tLog>
55
+ <tNote />
56
+ <tEmailHeaders />
57
+ <fNoteIsHTML>0</fNoteIsHTML>
58
+ <fMergedFromRequest>0</fMergedFromRequest>
59
+ </item>
60
+ <item>
61
+ <xRequestHistory>1376</xRequestHistory>
62
+ <xRequest>12745</xRequest>
63
+ <xPerson> </xPerson>
64
+ <dtGMTChange>Mon, September 24, 2007, 08:03 PM</dtGMTChange>
65
+ <fPublic>1</fPublic>
66
+ <fInitial>0</fInitial>
67
+ <tLog />
68
+ <tNote>Plain text update to the request.</tNote>
69
+ <tEmailHeaders />
70
+ <fNoteIsHTML>0</fNoteIsHTML>
71
+ <fMergedFromRequest>0</fMergedFromRequest>
72
+ <files />
73
+ </item>
74
+ <item>
75
+ <xRequestHistory>1375</xRequestHistory>
76
+ <xRequest>12745</xRequest>
77
+ <xPerson> </xPerson>
78
+ <dtGMTChange>Mon, September 24, 2007, 07:44 PM</dtGMTChange>
79
+ <fPublic>1</fPublic>
80
+ <fInitial>1</fInitial>
81
+ <tLog />
82
+ <tNote>This is the request.</tNote>
83
+ <tEmailHeaders />
84
+ <fNoteIsHTML>0</fNoteIsHTML>
85
+ <fMergedFromRequest>0</fMergedFromRequest>
86
+ <files />
87
+ </item>
88
+ </request_history>
89
+ </request>
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <categories>
3
+ <category>
4
+ <xCategory>1</xCategory>
5
+ <sCategory>Pre Sales Question</sCategory>
6
+ <fDeleted>0</fDeleted>
7
+ <fAllowPublicSubmit>1</fAllowPublicSubmit>
8
+ <xPersonDefault>1</xPersonDefault>
9
+ <fAutoAssignTo>0</fAutoAssignTo>
10
+ <sPersonList>
11
+ <person>
12
+ <xPerson>3</xPerson>
13
+ <fullname>Steve Benson</fullname>
14
+ <assigned_requests>6</assigned_requests>
15
+ </person>
16
+ <person>
17
+ <xPerson>4</xPerson>
18
+ <fullname>Tiffany Prince</fullname>
19
+ <assigned_requests>7</assigned_requests>
20
+ </person>
21
+ <person>
22
+ <xPerson>5</xPerson>
23
+ <fullname>Henry Yount</fullname>
24
+ <assigned_requests>8</assigned_requests>
25
+ </person>
26
+ </sPersonList>
27
+ <sCustomFieldList>
28
+ <xCustomField>2</xCustomField>
29
+ <xCustomField>13</xCustomField>
30
+ </sCustomFieldList>
31
+ <reportingTags>
32
+ <tag>
33
+ <xReportingTag>5</xReportingTag>
34
+ <sReportingTag>Pricing</sReportingTag>
35
+ </tag>
36
+ <tag>
37
+ <xReportingTag>9</xReportingTag>
38
+ <sReportingTag>Support Options</sReportingTag>
39
+ </tag>
40
+ <tag>
41
+ <xReportingTag>7</xReportingTag>
42
+ <sReportingTag>System Requirements</sReportingTag>
43
+ </tag>
44
+ </reportingTags>
45
+ </category>
46
+ </categories>
@@ -0,0 +1,52 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <customfields>
3
+ <field>
4
+ <xCustomField>10</xCustomField>
5
+ <fieldName>Ajax Lookup</fieldName>
6
+ <isRequired>1</isRequired>
7
+ <isPublic>0</isPublic>
8
+ <fieldType>ajax</fieldType>
9
+ <iOrder>0</iOrder>
10
+ <sTxtSize />
11
+ <lrgTextRows />
12
+ <listItems />
13
+ <iDecimalPlaces>0</iDecimalPlaces>
14
+ <sRegex />
15
+ <sAjaxUrl>http://www.domain.com/ajax_field_lookup.php</sAjaxUrl>
16
+ <isAlwaysVisible>0</isAlwaysVisible>
17
+ </field>
18
+ <field>
19
+ <xCustomField>7</xCustomField>
20
+ <fieldName>VIP Customer</fieldName>
21
+ <isRequired>0</isRequired>
22
+ <isPublic>1</isPublic>
23
+ <fieldType>checkbox</fieldType>
24
+ <iOrder>0</iOrder>
25
+ <sTxtSize />
26
+ <lrgTextRows />
27
+ <listItems />
28
+ <iDecimalPlaces>0</iDecimalPlaces>
29
+ <sRegex />
30
+ <sAjaxUrl />
31
+ <isAlwaysVisible>0</isAlwaysVisible>
32
+ </field>
33
+ <field>
34
+ <xCustomField>2</xCustomField>
35
+ <fieldName>Database Type</fieldName>
36
+ <isRequired>0</isRequired>
37
+ <isPublic>1</isPublic>
38
+ <fieldType>select</fieldType>
39
+ <iOrder>0</iOrder>
40
+ <sTxtSize />
41
+ <lrgTextRows />
42
+ <listItems>
43
+ <item>MySQL</item>
44
+ <item>MS SQL Server</item>
45
+ <item>PostgreSQL</item>
46
+ </listItems>
47
+ <iDecimalPlaces>0</iDecimalPlaces>
48
+ <sRegex />
49
+ <sAjaxUrl />
50
+ <isAlwaysVisible>0</isAlwaysVisible>
51
+ </field>
52
+ </customfields>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <results>
3
+ <status>
4
+ <sStatus>Active</sStatus>
5
+ <xStatus>1</xStatus>
6
+ </status>
7
+ <status>
8
+ <sStatus>Problem Solved</sStatus>
9
+
10
+ <xStatus>3</xStatus>
11
+ </status>
12
+ <status>
13
+ <sStatus>Not Fixable</sStatus>
14
+ <xStatus>4</xStatus>
15
+ </status>
16
+ <status>
17
+
18
+ <sStatus>Customer Unreachable</sStatus>
19
+ <xStatus>5</xStatus>
20
+ </status>
21
+ <status>
22
+ <sStatus>Customer Found Solution</sStatus>
23
+ <xStatus>6</xStatus>
24
+ </status>
25
+
26
+ <status>
27
+ <sStatus>Software Bug</sStatus>
28
+ <xStatus>7</xStatus>
29
+ </status>
30
+ <status>
31
+ <sStatus>SPAM</sStatus>
32
+ <xStatus>2</xStatus>
33
+
34
+ </status>
35
+ </results>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <request>
3
+ <xRequest>12746</xRequest>
4
+ </request>
@@ -0,0 +1,52 @@
1
+ <requests>
2
+ <request>
3
+ <xRequest>12650</xRequest>
4
+ <fOpenedVia>Phone</fOpenedVia>
5
+ <xOpenedViaId>0</xOpenedViaId>
6
+ <xPersonOpenedBy>Ian Landsman</xPersonOpenedBy>
7
+ <xPersonAssignedTo>Ian Landsman</xPersonAssignedTo>
8
+ <fOpen>1</fOpen>
9
+ <xStatus>Active</xStatus>
10
+ <fUrgent>1</fUrgent>
11
+ <xCategory>Bugs</xCategory>
12
+ <dtGMTOpened>January 16, 2006</dtGMTOpened>
13
+ <dtGMTClosed />
14
+ <sRequestPassword>oxvgys</sRequestPassword>
15
+ <sTitle>RE: Update on Your Request</sTitle>
16
+ <sUserId />
17
+ <sFirstName />
18
+ <sLastName>landsman</sLastName>
19
+ <sEmail />
20
+ <sPhone />
21
+ <iLastReplyBy>0</iLastReplyBy>
22
+ <fTrash>0</fTrash>
23
+ <dtGMTTrashed />
24
+ <fullname> landsman</fullname>
25
+ <tNote><span class="initsubject">Some text here</span> - Help with printer issue please.</tNote>
26
+ </request>
27
+ <request>
28
+ <xRequest>12733</xRequest>
29
+ <fOpenedVia>Web Service</fOpenedVia>
30
+ <xOpenedViaId>0</xOpenedViaId>
31
+ <xPersonOpenedBy />
32
+ <xPersonAssignedTo>Ian Landsman</xPersonAssignedTo>
33
+ <fOpen>1</fOpen>
34
+ <xStatus>Active</xStatus>
35
+ <fUrgent>0</fUrgent>
36
+ <xCategory>Bugs</xCategory>
37
+ <dtGMTOpened>September 13, 2007</dtGMTOpened>
38
+ <dtGMTClosed />
39
+ <sRequestPassword>bwpkqv</sRequestPassword>
40
+ <sTitle />
41
+ <sUserId>567</sUserId>
42
+ <sFirstName />
43
+ <sLastName />
44
+ <sEmail />
45
+ <sPhone />
46
+ <iLastReplyBy>0</iLastReplyBy>
47
+ <fTrash>0</fTrash>
48
+ <dtGMTTrashed />
49
+ <fullname> </fullname>
50
+ <tNote><span class="initsubject">Text Here</span> - Need printer assistance.</tNote>
51
+ </request>
52
+ </requests>
@@ -0,0 +1,4 @@
1
+ <results>
2
+ <version>1.3</version>
3
+ <min_version>1.0</min_version>
4
+ </results>
@@ -1,7 +1,87 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "HelpSpot" do
4
- it "fails" do
5
- fail "hey buddy, you should probably rename this file and start specing for real"
4
+ it "should provide a version constant" do
5
+ HelpSpot::VERSION.should be_instance_of(String)
6
6
  end
7
- end
7
+ before :each do
8
+ @help_spot = HelpSpot.new("https://support.local/api/", "foobar@localhost.com", "sekrit")
9
+ end
10
+ describe "verifying authentcation" do
11
+ it "returns true when properly authenticated" do
12
+ @help_spot.stub_get('/api/index.php?method=private.version', 'version.xml')
13
+ @help_spot.authenticated?.should be_true
14
+ end
15
+ it "returns false when not properly authenticated" do
16
+ @help_spot.stub_http_response_with('error.xml')
17
+ @help_spot.authenticated?.should be_false
18
+ end
19
+ end
20
+
21
+ describe 'requests' do
22
+ describe "being created" do
23
+ before(:each) do
24
+ @help_spot.stub_post('/api/index.php?method=private.request.create', 'request.id.xml')
25
+ end
26
+ it "require a note, a category, and some contact info" do
27
+ lambda { @help_spot.create_request() }.should raise_exception
28
+ lambda { @help_spot.create_request(:tNote => 'foo') }.should raise_exception
29
+ lambda { @help_spot.create_request(:xCategory => 1) }.should raise_exception
30
+ lambda { @help_spot.create_request(:tNote => 'foo', :xCategory => 1) }.should raise_exception
31
+ %w(sFirstName sLastName sUserId sEmail sPhone).each do |valid_contact_info|
32
+ lambda { @help_spot.create_request(:tNote => 'foo', :xCategory => 1, valid_contact_info.intern => 'foo') }.should_not raise_exception
33
+ end
34
+ end
35
+ it "return the request id" do
36
+ @help_spot.create_request(:tNote => 'foo', :xCategory => 1, :sEmail => 'needy@customer.com').should == 12746
37
+ end
38
+ end
39
+ describe "being updated" do
40
+ before(:each) do
41
+ @help_spot.stub_post('/api/index.php?method=private.request.update', 'request.id.xml')
42
+ end
43
+ it "return the request id" do
44
+ @help_spot.update_request(12746, :tNote => 'foo', :xCategory => 1, :sEmail => 'needy@customer.com').should == 12746
45
+ end
46
+ end
47
+ it "should be accessible" do
48
+ @help_spot.stub_get('/api/index.php?method=private.request.get&xRequest=12745', 'request.get.xml')
49
+ request = @help_spot.request(12745)
50
+ request.xPersonAssignedTo.should == 'Ian Landsman'
51
+ request.request_history.first.xPerson.should == 'Ian Landsman'
52
+ end
53
+ it "should be searchable" do
54
+ @help_spot.stub_get('/api/index.php?method=private.request.search&sSearch=printer', 'request.search.xml')
55
+ requests = @help_spot.search_requests(:sSearch => 'printer')
56
+ requests.first.xPersonAssignedTo.should == 'Ian Landsman'
57
+ end
58
+ end
59
+ describe 'categories' do
60
+ it "can be listed" do
61
+ @help_spot.stub_get('/api/index.php?method=private.request.getCategories&fDeleted=0', 'request.getCategories.xml')
62
+ categories = @help_spot.categories
63
+ categories.sCategory.should == 'Pre Sales Question'
64
+ end
65
+ end
66
+ describe 'statuses' do
67
+ it "can be listed" do
68
+ @help_spot.stub_get('/api/index.php?method=private.request.getStatusTypes&fActiveOnly=1', 'request.getStatusTypes.xml')
69
+ statues = @help_spot.status_types
70
+ statues.first.sStatus.should == 'Active'
71
+ end
72
+ end
73
+ describe 'custom fields' do
74
+ it "can be listed" do
75
+ @help_spot.stub_get('/api/index.php?method=private.request.getCustomFields', 'request.getCustomFields.xml')
76
+ fields = @help_spot.custom_fields
77
+ fields.first.fieldName.should == 'Ajax Lookup'
78
+ end
79
+ end
80
+ describe 'filters' do
81
+ it "can have their requests retrieved" do
82
+ @help_spot.stub_get('/api/index.php?method=private.filter.get&xFilter=1234', 'filter.get.xml')
83
+ requests = @help_spot.filter(1234)
84
+ requests.first.tNote.should == 'I would like to be able to upload documents over 1 gigabyte.'
85
+ end
86
+ end
87
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --backtrace
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,52 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
1
  require 'help_spot'
4
2
  require 'spec'
5
3
  require 'spec/autorun'
4
+ require 'fakeweb'
6
5
 
7
- Spec::Runner.configure do |config|
8
-
9
- end
6
+ FakeWeb.allow_net_connect = false
7
+
8
+ class HelpSpot
9
+
10
+ def help_spot_url(path)
11
+ uri = URI.parse(self.class.default_options[:base_uri])
12
+ uri.path, uri.query = path.split('?')
13
+ uri.userinfo = "#{self.class.default_options[:basic_auth][:username]}:#{self.class.default_options[:basic_auth][:password]}".gsub(/@/, '%40')
14
+ uri.to_s
15
+ end
16
+
17
+ def file_fixture(filename)
18
+ open(File.join(File.dirname(__FILE__), 'fixtures', "#{filename.to_s}")).read
19
+ end
20
+
21
+ def stub_get(path, filename, status=nil)
22
+ options = {:body => file_fixture(filename)}
23
+ options.merge!({:status => status}) unless status.nil?
24
+ FakeWeb.register_uri(:get, help_spot_url(path), options)
25
+ end
26
+
27
+ def stub_post(path, filename)
28
+ FakeWeb.register_uri(:post, help_spot_url(path), :body => file_fixture(filename))
29
+ end
30
+
31
+ def stub_put(path, filename)
32
+ FakeWeb.register_uri(:put, help_spot_url(path), :body => file_fixture(filename))
33
+ end
34
+
35
+ def stub_delete(path, filename)
36
+ FakeWeb.register_uri(:delete, help_spot_url(path), :body => file_fixture(filename))
37
+ end
38
+
39
+ def stub_http_response_with(filename)
40
+ format = filename.split('.').last.intern
41
+ data = file_fixture(filename)
42
+
43
+ response = Net::HTTPOK.new("1.1", 200, "Content for you")
44
+ response.stub!(:body).and_return(data)
45
+
46
+ http_request = HTTParty::Request.new(Net::HTTP::Get, 'http://localhost', :format => format)
47
+ http_request.stub!(:perform_actual_request).and_return(response)
48
+
49
+ HTTParty::Request.should_receive(:new).at_least(1).and_return(http_request)
50
+ end
51
+
52
+ end
metadata CHANGED
@@ -1,29 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: help_spot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
- - Jamie Wilson
8
7
  - Jesse Newland
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
11
 
13
- date: 2009-10-11 00:00:00 -04:00
12
+ date: 2010-01-24 00:00:00 -05:00
14
13
  default_executable:
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: rspec
18
17
  type: :development
19
18
  version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.3.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: fakeweb
27
+ type: :development
28
+ version_requirement:
20
29
  version_requirements: !ruby/object:Gem::Requirement
21
30
  requirements:
22
31
  - - ">="
23
32
  - !ruby/object:Gem::Version
24
33
  version: "0"
25
34
  version:
26
- description: A package for interacting with UserScape's HelpSpot product.
35
+ - !ruby/object:Gem::Dependency
36
+ name: hashie
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.1.8
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: httparty
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.5.0
54
+ version:
55
+ description: API wrapper for HelpSpot
27
56
  email: jnewland@gmail.com
28
57
  executables: []
29
58
 
@@ -32,17 +61,26 @@ extensions: []
32
61
  extra_rdoc_files:
33
62
  - LICENSE
34
63
  - README.rdoc
64
+ - TODO
35
65
  files:
36
66
  - .gitignore
37
- - History.txt
38
67
  - LICENSE
39
68
  - README.rdoc
40
69
  - Rakefile
41
- - VERSION
42
- - config/help_spot.yml.sample
43
- - help_spot.gemspec
70
+ - TODO
44
71
  - lib/help_spot.rb
72
+ - lib/help_spot/version.rb
73
+ - spec/fixtures/error.xml
74
+ - spec/fixtures/filter.get.xml
75
+ - spec/fixtures/request.get.xml
76
+ - spec/fixtures/request.getCategories.xml
77
+ - spec/fixtures/request.getCustomFields.xml
78
+ - spec/fixtures/request.getStatusTypes.xml
79
+ - spec/fixtures/request.id.xml
80
+ - spec/fixtures/request.search.xml
81
+ - spec/fixtures/version.xml
45
82
  - spec/help_spot_spec.rb
83
+ - spec/spec.opts
46
84
  - spec/spec_helper.rb
47
85
  has_rdoc: true
48
86
  homepage: http://github.com/jnewland/help_spot
@@ -68,10 +106,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
106
  requirements: []
69
107
 
70
108
  rubyforge_project:
71
- rubygems_version: 1.3.3
109
+ rubygems_version: 1.3.5
72
110
  signing_key:
73
111
  specification_version: 3
74
- summary: A package for interacting with UserScape's HelpSpot product.
112
+ summary: API wrapper for HelpSpot
75
113
  test_files:
76
114
  - spec/help_spot_spec.rb
77
115
  - spec/spec_helper.rb
data/History.txt DELETED
@@ -1,14 +0,0 @@
1
- == 0.0.2 2009-10-11
2
-
3
- * Add to SSL
4
- * Release to Gemcutter
5
-
6
- == 0.0.1.4 2009-02-09
7
-
8
- * Pushed to github
9
-
10
- == 0.0.1 2009-01-05
11
-
12
- * 1 major enhancement:
13
- * Initial release
14
-
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.2
@@ -1,6 +0,0 @@
1
- root_url: http://www.example.com/helpspot/api/index.php?format=json
2
- username: helpspot_user@example.com
3
- password: my_p@ssw0rd
4
- hidden_categories:
5
- - Deactivations
6
- - 'Contact Us'
data/help_spot.gemspec DELETED
@@ -1,54 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{help_spot}
8
- s.version = "0.0.2"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Jamie Wilson", "Jesse Newland"]
12
- s.date = %q{2009-10-11}
13
- s.description = %q{A package for interacting with UserScape's HelpSpot product.}
14
- s.email = %q{jnewland@gmail.com}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".gitignore",
21
- "History.txt",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "config/help_spot.yml.sample",
27
- "help_spot.gemspec",
28
- "lib/help_spot.rb",
29
- "spec/help_spot_spec.rb",
30
- "spec/spec_helper.rb"
31
- ]
32
- s.homepage = %q{http://github.com/jnewland/help_spot}
33
- s.rdoc_options = ["--charset=UTF-8"]
34
- s.require_paths = ["lib"]
35
- s.rubygems_version = %q{1.3.3}
36
- s.summary = %q{A package for interacting with UserScape's HelpSpot product.}
37
- s.test_files = [
38
- "spec/help_spot_spec.rb",
39
- "spec/spec_helper.rb"
40
- ]
41
-
42
- if s.respond_to? :specification_version then
43
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
- s.specification_version = 3
45
-
46
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
- s.add_development_dependency(%q<rspec>, [">= 0"])
48
- else
49
- s.add_dependency(%q<rspec>, [">= 0"])
50
- end
51
- else
52
- s.add_dependency(%q<rspec>, [">= 0"])
53
- end
54
- end