confuddle 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 (65) hide show
  1. data/.gitignore +18 -0
  2. data/.passwd_to_unfuddle.example.yml +7 -0
  3. data/README.md +40 -0
  4. data/bin/un +833 -0
  5. data/bin/un.cmd +1 -0
  6. data/confuddle.gemspec +22 -0
  7. data/lib/graft/README.rdoc +138 -0
  8. data/lib/graft/Rakefile +43 -0
  9. data/lib/graft/lib/graft/core_ext/hash.rb +9 -0
  10. data/lib/graft/lib/graft/json.rb +14 -0
  11. data/lib/graft/lib/graft/json/attribute.rb +18 -0
  12. data/lib/graft/lib/graft/json/model.rb +28 -0
  13. data/lib/graft/lib/graft/model.rb +43 -0
  14. data/lib/graft/lib/graft/version.rb +13 -0
  15. data/lib/graft/lib/graft/xml.rb +19 -0
  16. data/lib/graft/lib/graft/xml/attribute.rb +55 -0
  17. data/lib/graft/lib/graft/xml/model.rb +49 -0
  18. data/lib/graft/lib/graft/xml/type.rb +91 -0
  19. data/lib/graft/test/test_helper.rb +38 -0
  20. data/lib/graft/test/unit/core_ext/hash_test.rb +29 -0
  21. data/lib/graft/test/unit/json/attribute_test.rb +51 -0
  22. data/lib/graft/test/unit/json/model_test.rb +86 -0
  23. data/lib/graft/test/unit/xml/attribute_test.rb +161 -0
  24. data/lib/graft/test/unit/xml/model_test.rb +173 -0
  25. data/lib/graft/test/unit/xml/type_test.rb +65 -0
  26. data/lib/unfuzzle/.gitignore +4 -0
  27. data/lib/unfuzzle/README.rdoc +129 -0
  28. data/lib/unfuzzle/Rakefile +39 -0
  29. data/lib/unfuzzle/lib/unfuzzle.rb +87 -0
  30. data/lib/unfuzzle/lib/unfuzzle/comment.rb +37 -0
  31. data/lib/unfuzzle/lib/unfuzzle/component.rb +31 -0
  32. data/lib/unfuzzle/lib/unfuzzle/milestone.rb +54 -0
  33. data/lib/unfuzzle/lib/unfuzzle/person.rb +20 -0
  34. data/lib/unfuzzle/lib/unfuzzle/priority.rb +30 -0
  35. data/lib/unfuzzle/lib/unfuzzle/project.rb +62 -0
  36. data/lib/unfuzzle/lib/unfuzzle/request.rb +75 -0
  37. data/lib/unfuzzle/lib/unfuzzle/response.rb +25 -0
  38. data/lib/unfuzzle/lib/unfuzzle/severity.rb +31 -0
  39. data/lib/unfuzzle/lib/unfuzzle/ticket.rb +156 -0
  40. data/lib/unfuzzle/lib/unfuzzle/ticket_report.rb +29 -0
  41. data/lib/unfuzzle/lib/unfuzzle/time_entry.rb +75 -0
  42. data/lib/unfuzzle/lib/unfuzzle/version.rb +13 -0
  43. data/lib/unfuzzle/test/fixtures/component.xml +8 -0
  44. data/lib/unfuzzle/test/fixtures/components.xml +17 -0
  45. data/lib/unfuzzle/test/fixtures/milestone.xml +12 -0
  46. data/lib/unfuzzle/test/fixtures/milestones.xml +25 -0
  47. data/lib/unfuzzle/test/fixtures/project.xml +17 -0
  48. data/lib/unfuzzle/test/fixtures/projects.xml +35 -0
  49. data/lib/unfuzzle/test/fixtures/severities.xml +24 -0
  50. data/lib/unfuzzle/test/fixtures/severity.xml +8 -0
  51. data/lib/unfuzzle/test/fixtures/ticket.xml +25 -0
  52. data/lib/unfuzzle/test/fixtures/tickets.xml +51 -0
  53. data/lib/unfuzzle/test/test_helper.rb +60 -0
  54. data/lib/unfuzzle/test/unit/unfuzzle/component_test.rb +36 -0
  55. data/lib/unfuzzle/test/unit/unfuzzle/milestone_test.rb +100 -0
  56. data/lib/unfuzzle/test/unit/unfuzzle/priority_test.rb +25 -0
  57. data/lib/unfuzzle/test/unit/unfuzzle/project_test.rb +87 -0
  58. data/lib/unfuzzle/test/unit/unfuzzle/request_test.rb +104 -0
  59. data/lib/unfuzzle/test/unit/unfuzzle/response_test.rb +37 -0
  60. data/lib/unfuzzle/test/unit/unfuzzle/severity_test.rb +36 -0
  61. data/lib/unfuzzle/test/unit/unfuzzle/ticket_test.rb +181 -0
  62. data/lib/unfuzzle/test/unit/unfuzzle_test.rb +39 -0
  63. data/lib/unfuzzle/unfuzzle.gemspec +31 -0
  64. data/lib/version.rb +3 -0
  65. metadata +176 -0
@@ -0,0 +1,173 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class EmptyXmlModel
4
+ include Graft::Xml::Model
5
+ end
6
+
7
+ class XmlModelWithAttributes
8
+ include Graft::Xml::Model
9
+
10
+ attribute :name
11
+ attribute :description, :from => 'desc'
12
+ attribute :rating, :from => 'rating@value'
13
+ attribute :size, :from => "node[@type='size']@value"
14
+
15
+ end
16
+
17
+ class XmlModelWithAttributeType
18
+ include Graft::Xml::Model
19
+
20
+ attribute :id, :type => :integer
21
+ end
22
+
23
+ class XmlModelTest < Test::Unit::TestCase
24
+
25
+ context "The EmptyXmlModel class" do
26
+ should "have an empty list of attributes if none are supplied" do
27
+ EmptyXmlModel.attributes.should == []
28
+ end
29
+
30
+ should "be able to return a collection of XML nodes" do
31
+ xml =<<-XML
32
+ <?xml version="1.0" encoding="UTF-8"?>
33
+ <things>
34
+ <thing><id>1</id></thing>
35
+ <thing><id>2</id></thing>
36
+ </things>
37
+ XML
38
+
39
+ document = Hpricot.XML(xml)
40
+
41
+ EmptyXmlModel.expects(:data_from).with(xml).returns(document)
42
+
43
+ EmptyXmlModel.expects(:new).with((document/'things/thing').first).returns('model_1')
44
+ EmptyXmlModel.expects(:new).with((document/'things/thing').last).returns('model_2')
45
+
46
+ collection = EmptyXmlModel.collection_from(xml, 'things/thing')
47
+ collection.should == ['model_1', 'model_2']
48
+ end
49
+
50
+ should "be able to retrieve data from the source XML string" do
51
+ xml = '<name>Graft</name>'
52
+ Hpricot.expects(:XML).with(xml).returns('document')
53
+
54
+ EmptyXmlModel.data_from(xml).should == 'document'
55
+ end
56
+
57
+ should "be able to retrieve data from the source document data" do
58
+ document = Hpricot.XML('<name>Graft</name>')
59
+ EmptyXmlModel.data_from(document).should == document
60
+ end
61
+
62
+ end
63
+
64
+ context "The XmlModelWithAttributes class" do
65
+ should "know the names of all its attributes" do
66
+ XmlModelWithAttributes.attributes.map {|a| a.name.to_s }.should == %w(name description rating size)
67
+ end
68
+ end
69
+
70
+ context "The XmlModelWithAttributeType class" do
71
+ should "know that it's attribute is of type :integer" do
72
+ attribute = XmlModelWithAttributeType.attributes.first
73
+ attribute.type_class.should == Graft::Xml::Type::Integer
74
+ end
75
+
76
+ should "be able to generate an XML representation of itself" do
77
+
78
+ m = XmlModelWithAttributeType.new
79
+ m.id = 1
80
+
81
+ xml = String.new
82
+ xml << '<?xml version="1.0" encoding="UTF-8"?>'
83
+ xml << '<model>'
84
+ xml << '<id>1</id>'
85
+ xml << '</model>'
86
+
87
+ m.to_xml('model').should == xml
88
+
89
+ end
90
+ end
91
+
92
+ context "An instance of the EmptyXmlModel class" do
93
+
94
+ should "return an empty hash when calling :to_hash" do
95
+ m = EmptyXmlModel.new
96
+ m.to_hash.should == {}
97
+ end
98
+
99
+ end
100
+
101
+ context "An instance of the XmlModelWithAttributes class" do
102
+
103
+ setup { @simple_xml = '<name>Graft</name>' }
104
+
105
+ should "have default reader method for :name" do
106
+ XmlModelWithAttributes.new.respond_to?(:name).should be(true)
107
+ end
108
+
109
+ should "be able to populate its data on initialization" do
110
+ xml = Hpricot.XML(@simple_xml)
111
+ XmlModelWithAttributes.new(xml).name.should == 'Graft'
112
+ end
113
+
114
+ should "have a reference to the original document" do
115
+ xml = Hpricot.XML(@simple_xml)
116
+ XmlModelWithAttributes.new(xml).source_data.should == xml
117
+ end
118
+
119
+ should "be able to populate from an XML string" do
120
+ XmlModelWithAttributes.new(@simple_xml).name.should == 'Graft'
121
+ end
122
+
123
+ should "return a hash representation of itself" do
124
+ m = XmlModelWithAttributes.new
125
+
126
+ m.name = 'name'
127
+ m.description = 'description'
128
+ m.rating = '5'
129
+ m.size = 'large'
130
+
131
+ m.to_hash.should == {
132
+ 'name' => 'name',
133
+ 'description' => 'description',
134
+ 'rating' => '5',
135
+ 'size' => 'large'
136
+ }
137
+ end
138
+
139
+ context "when populating data from an XML document" do
140
+
141
+ setup do
142
+ xml = <<-XML
143
+ <name>Graft</name>
144
+ <desc>A sweet Ruby library</desc>
145
+ <rating value="100" />
146
+ <node type="color" value="blue" />
147
+ <node type="size" value="large" />
148
+ XML
149
+
150
+ @model = XmlModelWithAttributes.new
151
+ @model.populate_from(Hpricot.XML(xml))
152
+ end
153
+
154
+ should "have the correct value for :name" do
155
+ @model.name.should == 'Graft'
156
+ end
157
+
158
+ should "have the correct value for :description" do
159
+ @model.description.should == 'A sweet Ruby library'
160
+ end
161
+
162
+ should "have the correct value for :rating" do
163
+ @model.rating.should == '100'
164
+ end
165
+
166
+ # should "have the correct value for :size" do
167
+ # @model.size.should == 'large'
168
+ # end
169
+
170
+ end
171
+ end
172
+
173
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ module Graft
4
+ module Xml
5
+
6
+ class StringTest < Test::Unit::TestCase
7
+ context "An instance of the Graft::Xml::Type::String class" do
8
+
9
+ should_convert 'a string', :to => 'a string'
10
+ should_convert '', :to => nil
11
+
12
+ end
13
+ end
14
+
15
+ class BooleanTest < Test::Unit::TestCase
16
+ context "An instance of the Graft::Xml::Type::Boolean class" do
17
+
18
+ should_convert 'true', :to => true
19
+ should_convert 'false', :to => false
20
+ should_convert '0', :to => false
21
+ should_convert '1', :to => true
22
+ should_convert '', :to => nil
23
+
24
+ should_fail_when_converting 'foo'
25
+
26
+ end
27
+ end
28
+
29
+ class IntegerTest < Test::Unit::TestCase
30
+ context "An instance of the Graft::Xml::Type::Integer class" do
31
+
32
+ should_convert '1', :to => 1
33
+ should_convert '', :to => nil
34
+
35
+ should_fail_when_converting 'foo'
36
+
37
+ end
38
+ end
39
+
40
+ class DateTest < Test::Unit::TestCase
41
+
42
+ context "An instance of the Graft::Xml::Type::Date class" do
43
+
44
+ should_convert '2008-08-01', :to => Date.parse('2008-08-01')
45
+ should_convert '', :to => nil
46
+
47
+ end
48
+
49
+ end
50
+
51
+ class TimeTest < Test::Unit::TestCase
52
+
53
+ context "An instance of the Graft::Xml::Type::Time class" do
54
+
55
+ should_convert '2008-07-28T16:57:10Z', :to => Time.parse('2008-07-28T16:57:10Z')
56
+ should_convert '2008-12-25 18:26:55', :to => Time.parse('2008-12-25 18:26:55')
57
+ should_convert '1230274722', :to => Time.at(1230274722)
58
+ should_convert '', :to => nil
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ /pkg/
3
+ /doc/
4
+ /coverage/
@@ -0,0 +1,129 @@
1
+ = Unfuzzle
2
+
3
+ == Description
4
+
5
+ The Unfuzzle gem provides an interface to the Unfuddle XML API
6
+
7
+ == Installation
8
+
9
+ sudo gem install vigetlabs-unfuzzle --source=http://gems.github.com
10
+
11
+ == Usage
12
+
13
+ To get started, you'll need your Unfuddle subdomain and a valid username /
14
+ password combination:
15
+
16
+ require 'unfuzzle'
17
+
18
+ Unfuzzle.subdomain = 'viget'
19
+ Unfuzzle.username = 'bopbip'
20
+ Unfuzzle.password = 'bleep'
21
+
22
+ Once that is configured, you can start accessing data from the API.
23
+
24
+ === Projects
25
+
26
+ Pulling back a list of projects is simple. Based on the currently logged-in
27
+ user, you can see which ones he has access to:
28
+
29
+ projects = Unfuzzle.projects # => [#<Unfuzzle::Project:0x11e9280 ...> , ...]
30
+
31
+ If you don't want all projects, you can find one by its slug (or short name):
32
+
33
+ Unfuzzle.project('salty') # => #<Unfuzzle::Project:0x11e9280 ...>
34
+
35
+ Or by ID:
36
+
37
+ Unfuzzle.project(1) # => #<Unfuzzle::Project:0x11e9280 ...>
38
+
39
+ There are a few attributes available for a project:
40
+
41
+ project = Unfuzzle.projects.first
42
+ project.id # => 123
43
+ project.slug # => "salty"
44
+ project.name # => "Salty Co."
45
+ project.archived? # => false
46
+ project.created_at.strftime('%Y-%m-%d') # => "2008-07-28"
47
+
48
+ To see a list of additional attributes, take a look at the documentation for
49
+ Project.
50
+
51
+ === Milestones
52
+
53
+ Each project can have milestones. You can access these from a single project:
54
+
55
+ project.milestones # => [#<Unfuzzle::Milestone:0x10bdca8 ...>, ...]
56
+
57
+ Milestones have attributes:
58
+
59
+ milestone = project.milestones.first
60
+ milestone.id # => 1
61
+ milestone.name # => "Milestone #1"
62
+ milestone.due_on.strftime('%m/%d/%Y') # => "07/30/2008"
63
+
64
+ A full list is available in the Milestone documentation.
65
+
66
+ === Tickets
67
+
68
+ Tickets exist for a project:
69
+
70
+ ticket = project.tickets.first
71
+ ticket.title # => "Ticket #23"
72
+ ticket.number # => 23
73
+ ticket.description # => "Yo dawg, I hear you like tickets in your project ..."
74
+ ticket.status # => "closed"
75
+
76
+ And can also be associated to a milestone for the project:
77
+
78
+ ticket = project.milestones.first.tickets.first
79
+ ticket.title # => "Ticket #1"
80
+ ticket.number # => 1
81
+ ticket.description # => "Wash my car"
82
+ ticket.status # => "closed"
83
+
84
+ Unfuddle has additional associations for a ticket, including component, severity,
85
+ and priority:
86
+
87
+ ticket.component # => #<Unfuzzle::Component:0x12c5b54 ...>
88
+ ticket.component_name # => "User Accounts"
89
+ ticket.severity # => #<Unfuzzle::Severity:0x12a357c ...>
90
+ ticket.severity_name # => "Development"
91
+ ticket.priority # => #<Unfuzzle::Priority:0x12811fc @id=3>
92
+ ticket.priority_name # => "Normal"
93
+
94
+ See the Ticket documentation for more information.
95
+
96
+ == Updating
97
+
98
+ Currently, only ticket updating is supported and only for a subset of the data:
99
+
100
+ ticket.title = 'This is a new title' # => "This is a new title"
101
+ ticket.update # => #<Unfuzzle::Response:0x1275280 ...>
102
+
103
+ This will update the title of the ticket. Other fields that can be updated include
104
+ description and status.
105
+
106
+ == License
107
+
108
+ Copyright (c) 2009 Patrick Reagan of Viget Labs (mailto:patrick.reagan@viget.com)
109
+
110
+ Permission is hereby granted, free of charge, to any person
111
+ obtaining a copy of this software and associated documentation
112
+ files (the "Software"), to deal in the Software without
113
+ restriction, including without limitation the rights to use,
114
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
115
+ copies of the Software, and to permit persons to whom the
116
+ Software is furnished to do so, subject to the following
117
+ conditions:
118
+
119
+ The above copyright notice and this permission notice shall be
120
+ included in all copies or substantial portions of the Software.
121
+
122
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
123
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
124
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
125
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
126
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
127
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
128
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
129
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+
5
+ require './lib/unfuzzle/version'
6
+
7
+ task :default => :test
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'unfuzzle'
11
+ s.version = Unfuzzle::Version.to_s
12
+ s.has_rdoc = true
13
+ s.extra_rdoc_files = %w(README.rdoc)
14
+ s.rdoc_options = %w(--main README.rdoc)
15
+ s.summary = "This gem provides an interface to the Unfuddle XML API"
16
+ s.author = 'Patrick Reagan'
17
+ s.email = 'patrick.reagan@viget.com'
18
+ s.homepage = 'http://www.viget.com/extend'
19
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
20
+
21
+ s.add_dependency('graft', '>= 0.1.1')
22
+ end
23
+
24
+ Rake::GemPackageTask.new(spec) do |pkg|
25
+ pkg.gem_spec = spec
26
+ end
27
+
28
+ Rake::TestTask.new do |t|
29
+ t.libs << 'test'
30
+ t.test_files = FileList["test/**/*_test.rb"]
31
+ t.verbose = true
32
+ end
33
+
34
+ desc 'Generate the gemspec to serve this Gem from Github'
35
+ task :github do
36
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
37
+ File.open(file, 'w') {|f| f << spec.to_ruby }
38
+ puts "Created gemspec: #{file}"
39
+ end
@@ -0,0 +1,87 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'net/https'
6
+ require 'json'
7
+ require 'builder'
8
+ require File.dirname(__FILE__) + '/../../graft/lib/graft/xml'
9
+
10
+ Dir[File.dirname(__FILE__) + "/unfuzzle/*.rb"].each { |x| require x }
11
+
12
+ # = Unfuzzle: A simple wrapper around the Unfuddle JSON API
13
+ #
14
+ # == Quick Start
15
+ #
16
+ # To get started, you need to set the subdomain and a valid username /
17
+ # password combination:
18
+ #
19
+ # require 'rubygems'
20
+ # require 'unfuzzle'
21
+ #
22
+ # Unfuzzle.subdomain = 'viget'
23
+ # Unfuzzle.username = 'bopbip'
24
+ # Unfuzzle.password = 'bleep'
25
+ #
26
+ # From there, you can start accessing a list of projects:
27
+ #
28
+ # >> Unfuzzle.projects
29
+ # => [#<Unfuzzle::Project:0x5f5c44 @id=1, @name="BlipCo", ...>, ... ]
30
+ #
31
+ # Or a specific project by its 'short name':
32
+ #
33
+ # >> Unfuzzle.project('sample')
34
+ # => #<Unfuzzle::Project:0x123f888 @id=2, @name="Sample Project", ... >
35
+ #
36
+ # For more usage documentation, see README.doc.
37
+ #
38
+ module Unfuzzle
39
+
40
+ # Set the subdomain for all requests
41
+ def self.subdomain=(subdomain)
42
+ @subdomain = subdomain
43
+ end
44
+
45
+ # Set the username for all requests. Data retrieved from the API will be
46
+ # scoped to the data that this user has access to.
47
+ def self.username=(username)
48
+ @username = username
49
+ end
50
+
51
+ # Set the password for the supplied username
52
+ def self.password=(password)
53
+ @password = password
54
+ end
55
+
56
+ # Use SSL: yes or no
57
+ def self.use_ssl=(value)
58
+ @use_ssl = value
59
+ end
60
+
61
+ # Retrieve a project for the current user by its ID or slug
62
+ def self.project(id_or_slug)
63
+ id_or_slug.is_a?(String) ? Project.find_by_slug(id_or_slug) : Project.find_by_id(id_or_slug)
64
+ end
65
+
66
+ # Get a list of all projects for this user
67
+ def self.projects
68
+ Project.all
69
+ end
70
+
71
+ def self.subdomain # :nodoc:
72
+ @subdomain
73
+ end
74
+
75
+ def self.username # :nodoc:
76
+ @username
77
+ end
78
+
79
+ def self.password # :nodoc:
80
+ @password
81
+ end
82
+
83
+ def self.use_ssl # :nodoc:
84
+ @use_ssl
85
+ end
86
+
87
+ end