confuddle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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