taskmapper-unfuddle 0.7.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/.document +5 -0
- data/.rvmrc +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +57 -0
- data/LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/lib/provider/comment.rb +45 -0
- data/lib/provider/project.rb +50 -0
- data/lib/provider/ticket.rb +53 -0
- data/lib/provider/unfuddle.rb +39 -0
- data/lib/taskmapper-unfuddle.rb +5 -0
- data/lib/unfuddle/unfuddle-api.rb +153 -0
- data/spec/comments_spec.rb +76 -0
- data/spec/fixtures/comments/0.xml +11 -0
- data/spec/fixtures/comments/2.xml +11 -0
- data/spec/fixtures/comments/3.xml +11 -0
- data/spec/fixtures/comments/create.xml +11 -0
- data/spec/fixtures/comments.xml +13 -0
- data/spec/fixtures/projects/33041.xml +30 -0
- data/spec/fixtures/projects/33042.xml +30 -0
- data/spec/fixtures/projects/create.xml +30 -0
- data/spec/fixtures/projects.xml +32 -0
- data/spec/fixtures/tickets/476814.xml +33 -0
- data/spec/fixtures/tickets/476816.xml +29 -0
- data/spec/fixtures/tickets/476834.xml +31 -0
- data/spec/fixtures/tickets/create.xml +31 -0
- data/spec/fixtures/tickets.xml +433 -0
- data/spec/projects_spec.rb +60 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/taskmapper-unfuddle_spec.rb +27 -0
- data/spec/tickets_spec.rb +77 -0
- data/taskmapper-unfuddle.gemspec +92 -0
- metadata +166 -0
data/.document
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.2@taskmapper-unfuddle --create
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem "taskmapper", "~> 0.8"
|
7
|
+
gem "addressable", "~> 2.2"
|
8
|
+
# Add dependencies to develop your gem here.
|
9
|
+
# Include everything needed to run rake, tests, features, etc.
|
10
|
+
group :development do
|
11
|
+
gem "rspec", "~> 2.8"
|
12
|
+
gem "bundler", "~> 1.1"
|
13
|
+
gem "jeweler", "~> 1.6"
|
14
|
+
gem "simplecov", "~> 0.5", :platforms => :ruby_19
|
15
|
+
gem "rcov", "~> 1.0", :platforms => :ruby_18
|
16
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.2.3)
|
5
|
+
activesupport (= 3.2.3)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activeresource (3.2.3)
|
8
|
+
activemodel (= 3.2.3)
|
9
|
+
activesupport (= 3.2.3)
|
10
|
+
activesupport (3.2.3)
|
11
|
+
i18n (~> 0.6)
|
12
|
+
multi_json (~> 1.0)
|
13
|
+
addressable (2.2.8)
|
14
|
+
builder (3.0.0)
|
15
|
+
diff-lcs (1.1.3)
|
16
|
+
git (1.2.5)
|
17
|
+
hashie (1.2.0)
|
18
|
+
i18n (0.6.0)
|
19
|
+
jeweler (1.8.3)
|
20
|
+
bundler (~> 1.0)
|
21
|
+
git (>= 1.2.5)
|
22
|
+
rake
|
23
|
+
rdoc
|
24
|
+
json (1.7.3)
|
25
|
+
multi_json (1.3.5)
|
26
|
+
rake (0.9.2.2)
|
27
|
+
rcov (1.0.0)
|
28
|
+
rdoc (3.12)
|
29
|
+
json (~> 1.4)
|
30
|
+
rspec (2.10.0)
|
31
|
+
rspec-core (~> 2.10.0)
|
32
|
+
rspec-expectations (~> 2.10.0)
|
33
|
+
rspec-mocks (~> 2.10.0)
|
34
|
+
rspec-core (2.10.0)
|
35
|
+
rspec-expectations (2.10.0)
|
36
|
+
diff-lcs (~> 1.1.3)
|
37
|
+
rspec-mocks (2.10.1)
|
38
|
+
simplecov (0.6.4)
|
39
|
+
multi_json (~> 1.0)
|
40
|
+
simplecov-html (~> 0.5.3)
|
41
|
+
simplecov-html (0.5.3)
|
42
|
+
taskmapper (0.8.0)
|
43
|
+
activeresource (~> 3.0)
|
44
|
+
activesupport (~> 3.0)
|
45
|
+
hashie (~> 1.2)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
addressable (~> 2.2)
|
52
|
+
bundler (~> 1.1)
|
53
|
+
jeweler (~> 1.6)
|
54
|
+
rcov (~> 1.0)
|
55
|
+
rspec (~> 2.8)
|
56
|
+
simplecov (~> 0.5)
|
57
|
+
taskmapper (~> 0.8)
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Hybrid Group
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# taskmapper-unfuddle
|
2
|
+
|
3
|
+
TaskMapper provider for Unfuddle.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Instantiate the TaskMapper instance
|
8
|
+
|
9
|
+
unfuddle = TaskMapper.new(:unfuddle, :username => "user", :password => "p4ss!", :account => 'unfud')
|
10
|
+
|
11
|
+
if this gives you trouble when trying to access projects or tickets, you can set the protocol explicitly. By default,
|
12
|
+
as of version 0.4.0, the protocol is 'https'. Some older projects may need to set to 'http'.
|
13
|
+
|
14
|
+
unfuddle = TaskMapper.new(:unfuddle, :username => "user", :password => "p4ss!", :account => 'unfud', :protocol => 'http')
|
15
|
+
|
16
|
+
## Note on Patches/Pull Requests
|
17
|
+
|
18
|
+
* Fork the project.
|
19
|
+
* Make your feature addition or bug fix.
|
20
|
+
* Add tests for it. This is important so I don't break it in a
|
21
|
+
future version unintentionally.
|
22
|
+
* Commit, do not mess with rakefile, version, or history.
|
23
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
24
|
+
* Send me a pull request. Bonus points for topic branches.
|
25
|
+
|
26
|
+
## Copyright
|
27
|
+
|
28
|
+
Copyright (c) 2010 [Hybrid Group](http://hybridgroup.com). See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "taskmapper-unfuddle"
|
8
|
+
gem.summary = %Q{The Unfuddle provider for taskmapper.}
|
9
|
+
gem.description = %Q{Unfuddle provider for taskmapper implemented with ActiveResource}
|
10
|
+
gem.email = "luis@hybridgroup.com"
|
11
|
+
gem.homepage = "http://github.com/hybridgroup/taskmapper-unfuddle"
|
12
|
+
gem.authors = ["Luis Hurtado"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rspec/core'
|
21
|
+
require 'rspec/core/rake_task'
|
22
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
23
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
27
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
28
|
+
spec.rcov = true
|
29
|
+
end
|
30
|
+
|
31
|
+
task :default => :spec
|
32
|
+
|
33
|
+
require 'rake/rdoctask' # TODO This produces a warning
|
34
|
+
require 'rdoc/task'
|
35
|
+
Rake::RDocTask.new do |rdoc|
|
36
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
37
|
+
|
38
|
+
rdoc.rdoc_dir = 'rdoc'
|
39
|
+
rdoc.title = "taskmapper-kanbanpad#{version}"
|
40
|
+
rdoc.rdoc_files.include('README*')
|
41
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
42
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.7.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Unfuddle
|
3
|
+
# The comment class for taskmapper-unfuddle
|
4
|
+
#
|
5
|
+
# Do any mapping between TaskMapper and your system's comment model here
|
6
|
+
# versions of the ticket.
|
7
|
+
#
|
8
|
+
class Comment < TaskMapper::Provider::Base::Comment
|
9
|
+
API = UnfuddleAPI::Comment # The class to access the api's comments
|
10
|
+
# declare needed overloaded methods here
|
11
|
+
|
12
|
+
def initialize(*options)
|
13
|
+
@system_data ||= {}
|
14
|
+
@cache ||= {}
|
15
|
+
first = options.shift
|
16
|
+
case first
|
17
|
+
when Hash
|
18
|
+
super first.to_hash
|
19
|
+
else
|
20
|
+
@system_data[:client] = first
|
21
|
+
super first.attributes.merge!(
|
22
|
+
:project_id => first.prefix_options[:project_id],
|
23
|
+
:ticket_id => first.prefix_options[:ticket_id])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def author
|
28
|
+
@author ||= begin
|
29
|
+
UnfuddleAPI::People.find(self[:author_id]).username
|
30
|
+
rescue
|
31
|
+
''
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def created_at
|
36
|
+
@created_at ||= self[:created_at] ? Time.parse(self[:created_at]) : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def updated_at
|
40
|
+
@updated_at ||= self[:updated_at] ? Time.parse(self[:updated_at]) : nil
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Unfuddle
|
3
|
+
# Project class for taskmapper-unfuddle
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class Project < TaskMapper::Provider::Base::Project
|
7
|
+
API = UnfuddleAPI::Project # The class to access the api's projects
|
8
|
+
# declare needed overloaded methods here
|
9
|
+
|
10
|
+
def initialize(*options)
|
11
|
+
@system_data ||= {}
|
12
|
+
@cache ||= {}
|
13
|
+
first = options.shift
|
14
|
+
case first
|
15
|
+
when Hash
|
16
|
+
super(first.to_hash)
|
17
|
+
else
|
18
|
+
@system_data[:client] = first
|
19
|
+
super(first.attributes)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
self.title
|
25
|
+
end
|
26
|
+
|
27
|
+
def created_at
|
28
|
+
@created_at ||= self[:created_at] ? Time.parse(self[:created_at]) : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def updated_at
|
32
|
+
@updated_at ||= self[:updated_at] ? Time.parse(self[:updated_at]) : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# copy from this.copy(that) copies that into this
|
36
|
+
def copy(project)
|
37
|
+
project.tickets.each do |ticket|
|
38
|
+
copy_ticket = self.ticket!(:title => ticket.title, :description => ticket.description)
|
39
|
+
ticket.comments.each do |comment|
|
40
|
+
copy_ticket.comment!(:body => comment.body)
|
41
|
+
sleep 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Unfuddle
|
3
|
+
# Ticket class for taskmapper-unfuddle
|
4
|
+
#
|
5
|
+
|
6
|
+
class Ticket < TaskMapper::Provider::Base::Ticket
|
7
|
+
API = UnfuddleAPI::Ticket # The class to access the api's tickets
|
8
|
+
# declare needed overloaded methods here
|
9
|
+
|
10
|
+
def initialize(*options)
|
11
|
+
@system_data ||= {}
|
12
|
+
@cache ||= {}
|
13
|
+
first = options.shift
|
14
|
+
case first
|
15
|
+
when Hash
|
16
|
+
super first.to_hash
|
17
|
+
else
|
18
|
+
@system_data[:client] = first
|
19
|
+
super first.attributes.merge! :project_id => first.prefix_options[:project_id]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def title
|
24
|
+
self.summary
|
25
|
+
end
|
26
|
+
|
27
|
+
def created_at
|
28
|
+
@created_at ||= self[:created_at] ? Time.parse(self[:created_at]) : nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def updated_at
|
32
|
+
@updated_at ||= self[:updated_at] ? Time.parse(self[:updated_at]) : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def assignee
|
36
|
+
@assignee ||= begin
|
37
|
+
UnfuddleAPI::People.find(self[:assignee_id]).username
|
38
|
+
rescue
|
39
|
+
''
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def requestor
|
44
|
+
@requestor ||= begin
|
45
|
+
UnfuddleAPI::People.find(self[:reporter_id]).username
|
46
|
+
rescue
|
47
|
+
''
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
# This is the Unfuddle Provider for taskmapper
|
3
|
+
module Unfuddle
|
4
|
+
include TaskMapper::Provider::Base
|
5
|
+
TICKET_API = UnfuddleAPI::Ticket # The class to access the api's tickets
|
6
|
+
PROJECT_API = UnfuddleAPI::Project # The class to access the api's projects
|
7
|
+
|
8
|
+
# This is for cases when you want to instantiate using TaskMapper::Provider::Unfuddle.new(auth)
|
9
|
+
def self.new(auth = {})
|
10
|
+
TaskMapper.new(:unfuddle, auth)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Providers must define an authorize method. This is used to initialize and set authentication
|
14
|
+
# parameters to access the API
|
15
|
+
def authorize(auth = {})
|
16
|
+
@authentication ||= TaskMapper::Authenticator.new(auth)
|
17
|
+
auth = @authentication
|
18
|
+
if (auth.account.nil? and auth.subdomain.nil?) or auth.username.nil? or auth.password.nil?
|
19
|
+
raise "Please provide at least an account (subdomain), username and password)"
|
20
|
+
end
|
21
|
+
UnfuddleAPI.protocol = auth.protocol if auth.protocol?
|
22
|
+
UnfuddleAPI.account = auth.account || auth.subdomain
|
23
|
+
UnfuddleAPI.authenticate(auth.username, auth.password)
|
24
|
+
end
|
25
|
+
|
26
|
+
# declare needed overloaded methods here
|
27
|
+
|
28
|
+
def valid?
|
29
|
+
begin
|
30
|
+
PROJECT_API.find(:first)
|
31
|
+
true
|
32
|
+
rescue
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'uri'
|
5
|
+
require 'addressable/uri'
|
6
|
+
|
7
|
+
module URI
|
8
|
+
def decode(*args)
|
9
|
+
Addressable::URI.decode(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def escape(*args)
|
13
|
+
Addressable::URI.escape(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse(*args)
|
17
|
+
Addressable::URI.parse(*args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
rescue LoadError => e
|
21
|
+
puts "Install the Addressable gem (with dependencies) to support accounts with subdomains."
|
22
|
+
puts "# sudo gem install addressable --development"
|
23
|
+
puts e.message
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'active_support'
|
27
|
+
require 'active_resource'
|
28
|
+
|
29
|
+
# Ruby lib for working with the Unfuddle API's XML interface.
|
30
|
+
# The first thing you need to set is the account name. This is the same
|
31
|
+
# as the web address for your account.
|
32
|
+
#
|
33
|
+
# UnfuddleAPI.account = 'activereload'
|
34
|
+
#
|
35
|
+
# Then, you should set the authentication with HTTP Basic Authentication.
|
36
|
+
#
|
37
|
+
# # with basic authentication
|
38
|
+
# UnfuddleAPI.authenticate('rick', 'spacemonkey')
|
39
|
+
#
|
40
|
+
#
|
41
|
+
# This library is a small wrapper around the REST interface. You should read the docs at
|
42
|
+
# http://unfuddle.com/docs/api
|
43
|
+
#
|
44
|
+
module UnfuddleAPI
|
45
|
+
class Error < StandardError; end
|
46
|
+
class << self
|
47
|
+
attr_accessor :username, :password, :host_format, :domain_format, :protocol, :port
|
48
|
+
attr_reader :account
|
49
|
+
|
50
|
+
# Sets the account name, and updates all the resources with the new domain.
|
51
|
+
def account=(name)
|
52
|
+
resources.each do |klass|
|
53
|
+
klass.site = klass.site_format % (host_format % [protocol, domain_format % name, ":#{port}"])
|
54
|
+
end
|
55
|
+
@account = name
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sets up basic authentication credentials for all the resources.
|
59
|
+
def authenticate(username, password)
|
60
|
+
@username = username
|
61
|
+
@password = password
|
62
|
+
self::Base.user = username
|
63
|
+
self::Base.password = password
|
64
|
+
end
|
65
|
+
|
66
|
+
def resources
|
67
|
+
@resources ||= []
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
self.host_format = '%s://%s%s/api/v1'
|
72
|
+
self.domain_format = '%s.unfuddle.com'
|
73
|
+
self.protocol = 'https'
|
74
|
+
self.port = ''
|
75
|
+
|
76
|
+
class Base < ActiveResource::Base
|
77
|
+
self.format = :xml
|
78
|
+
def self.inherited(base)
|
79
|
+
UnfuddleAPI.resources << base
|
80
|
+
class << base
|
81
|
+
attr_accessor :site_format
|
82
|
+
end
|
83
|
+
base.site_format = '%s'
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Find projects
|
89
|
+
#
|
90
|
+
# UnfuddleAPI::Project.find(:all) # find all projects for the current account.
|
91
|
+
# UnfuddleAPI::Project.find(44) # find individual project by ID
|
92
|
+
#
|
93
|
+
# Creating a Project
|
94
|
+
#
|
95
|
+
# project = UnfuddleAPI::Project.new(:name => 'Ninja Whammy Jammy')
|
96
|
+
# project.save
|
97
|
+
# # => true
|
98
|
+
#
|
99
|
+
#
|
100
|
+
# Updating a Project
|
101
|
+
#
|
102
|
+
# project = UnfuddleAPI::Project.find(44)
|
103
|
+
# project.name = "Lighthouse Issues"
|
104
|
+
# project.public = false
|
105
|
+
# project.save
|
106
|
+
#
|
107
|
+
# Finding tickets
|
108
|
+
#
|
109
|
+
# project = LighthouseAPI::Project.find(44)
|
110
|
+
# project.tickets
|
111
|
+
#
|
112
|
+
class Project < Base
|
113
|
+
def tickets(options = {})
|
114
|
+
Ticket.find(:all, :params => options.update(:project_id => id))
|
115
|
+
end
|
116
|
+
|
117
|
+
def messages(options = {})
|
118
|
+
Message.find(:all, :params => options.update(:project_id => id))
|
119
|
+
end
|
120
|
+
|
121
|
+
def milestones(options = {})
|
122
|
+
Milestone.find(:all, :params => options.update(:project_id => id))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Find tickets
|
127
|
+
#
|
128
|
+
# UnfuddleAPI::Ticket.find(:all, :params => { :project_id => 44 })
|
129
|
+
# UnfuddleAPI::Ticket.find(:all, :params => { :project_id => 44, :q => "status:closed" })
|
130
|
+
#
|
131
|
+
# project = UnfuddleAPI::Project.find(44)
|
132
|
+
# project.tickets
|
133
|
+
# project.tickets(:q => "status:closed")
|
134
|
+
# project.tickets(:params => {:status => 'closed'})
|
135
|
+
#
|
136
|
+
#
|
137
|
+
#
|
138
|
+
class Ticket < Base
|
139
|
+
site_format << '/projects/:project_id'
|
140
|
+
end
|
141
|
+
|
142
|
+
class Comment < Base
|
143
|
+
site_format << '/projects/:project_id/tickets/:ticket_id'
|
144
|
+
end
|
145
|
+
|
146
|
+
class Message < Base
|
147
|
+
site_format << '/projects/:project_id'
|
148
|
+
end
|
149
|
+
|
150
|
+
class People < Base
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe TaskMapper::Provider::Unfuddle::Comment do
|
4
|
+
before(:each) do
|
5
|
+
@headers = {'Authorization' => 'Basic Zm9vOjAwMDAwMA==', 'Accept' => 'application/xml'}
|
6
|
+
@headers_post_put = {'Authorization' => 'Basic Zm9vOjAwMDAwMA==', 'Content-Type' => 'application/xml'}
|
7
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
8
|
+
mock.get '/api/v1/projects/33042.xml', @headers, fixture_for('projects/33042'), 200
|
9
|
+
mock.get '/api/v1/projects/33042/tickets/476834.xml', @headers, fixture_for('tickets/476834'), 200
|
10
|
+
end
|
11
|
+
@project = taskmapper.project(project_id)
|
12
|
+
@ticket = @project.ticket(ticket_id)
|
13
|
+
end
|
14
|
+
let(:project_id) { 33042 }
|
15
|
+
let(:ticket_id) { 476834 }
|
16
|
+
let(:taskmapper) { TaskMapper.new(:unfuddle, :account => 'taskmapper', :password => '000000', :username => 'foo') }
|
17
|
+
let(:comment_class) { TaskMapper::Provider::Unfuddle::Comment }
|
18
|
+
|
19
|
+
describe "Retrieving all comments" do
|
20
|
+
before(:each) do
|
21
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
22
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments.xml', @headers, fixture_for('comments'), 200
|
23
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments/0.xml', @headers, fixture_for('comments/0'), 200
|
24
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments/2.xml', @headers, fixture_for('comments/2'), 200
|
25
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments/3.xml', @headers, fixture_for('comments/3'), 200
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when calling #comments to a ticket instance" do
|
30
|
+
subject { @ticket.comments }
|
31
|
+
it { should be_an_instance_of Array }
|
32
|
+
it { subject.first.should be_an_instance_of comment_class }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when calling #comments with an array of id's" do
|
36
|
+
subject { @ticket.comments([0,2,3]) }
|
37
|
+
it { should be_an_instance_of Array }
|
38
|
+
it { subject.first.id.should be_eql 0 }
|
39
|
+
it { subject.last.id.should be_eql 3 }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when calling #comments with a hash of attributes" do
|
43
|
+
subject { @ticket.comments :parent_id => @ticket.id }
|
44
|
+
it { should be_an_instance_of Array }
|
45
|
+
it { subject.first.should be_an_instance_of comment_class }
|
46
|
+
it { subject.first.id.should be_eql 2 }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Retrieve a single comment" do
|
51
|
+
before(:each) do
|
52
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
53
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments/0.xml', @headers, fixture_for('comments/0'), 200
|
54
|
+
mock.get '/api/v1/projects/33042/tickets/476834/comments.xml', @headers, fixture_for('comments'), 200
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when calling #comment with an id" do
|
59
|
+
subject { @ticket.comment 0 }
|
60
|
+
it { should be_an_instance_of comment_class }
|
61
|
+
it { subject.id.should be_eql 0 }
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when calling #comment with an attribute hash" do
|
65
|
+
subject { @ticket.comment :parent_id => @ticket.id }
|
66
|
+
it { should be_an_instance_of comment_class }
|
67
|
+
it { subject.id.should be_eql 2 }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should be able to create a comment" do
|
72
|
+
pending
|
73
|
+
@comment = @ticket.comment!(:body => 'New comment created.', :body_format => 'markdown')
|
74
|
+
@comment.should be_an_instance_of(@klass)
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<author-id type="integer">47763</author-id>
|
4
|
+
<body>I found Devise as a very complete solution for authentication, also found that it takes care of sessions expiration(Timeoutable) and sign in tracking(Trackable) too (http://github.com/plataformatec/devise), and the better is that it seems not to be a very difficult task to get it implemented in the app.</body>
|
5
|
+
<body-format>markdown</body-format>
|
6
|
+
<id type="integer">0</id>
|
7
|
+
<parent-id type="integer">476834</parent-id>
|
8
|
+
<parent-type>Ticket</parent-type>
|
9
|
+
<created-at>2009-11-26T17:19:22Z</created-at>
|
10
|
+
<updated-at>2009-11-26T17:19:22Z</updated-at>
|
11
|
+
</comment>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<author-id type="integer">47763</author-id>
|
4
|
+
<body>This is comment 2.</body>
|
5
|
+
<body-format>markdown</body-format>
|
6
|
+
<id type="integer">2</id>
|
7
|
+
<parent-id type="integer">476834</parent-id>
|
8
|
+
<parent-type>Ticket</parent-type>
|
9
|
+
<created-at>2009-11-26T17:19:22Z</created-at>
|
10
|
+
<updated-at>2009-11-26T17:19:22Z</updated-at>
|
11
|
+
</comment>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<author-id type="integer">47763</author-id>
|
4
|
+
<body>This is comment 3.</body>
|
5
|
+
<body-format>markdown</body-format>
|
6
|
+
<id type="integer">3</id>
|
7
|
+
<parent-id type="integer">476834</parent-id>
|
8
|
+
<parent-type>Ticket</parent-type>
|
9
|
+
<created-at>2009-11-26T17:19:22Z</created-at>
|
10
|
+
<updated-at>2009-11-26T17:19:22Z</updated-at>
|
11
|
+
</comment>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<author-id type="integer">47763</author-id>
|
4
|
+
<body>New comment created.</body>
|
5
|
+
<body-format>markdown</body-format>
|
6
|
+
<id type="integer">4</id>
|
7
|
+
<parent-id type="integer">476834</parent-id>
|
8
|
+
<parent-type>Ticket</parent-type>
|
9
|
+
<created-at>2009-11-26T17:19:22Z</created-at>
|
10
|
+
<updated-at>2009-11-26T17:19:22Z</updated-at>
|
11
|
+
</comment>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comments type="array">
|
3
|
+
<comment>
|
4
|
+
<author-id type="integer">47763</author-id>
|
5
|
+
<body>I found Devise as a very complete solution for authentication, also found that it takes care of sessions expiration(Timeoutable) and sign in tracking(Trackable) too (http://github.com/plataformatec/devise), and the better is that it seems not to be a very difficult task to get it implemented in the app.</body>
|
6
|
+
<body-format>markdown</body-format>
|
7
|
+
<id type="integer">2</id>
|
8
|
+
<parent-id type="integer">476834</parent-id>
|
9
|
+
<parent-type>Ticket</parent-type>
|
10
|
+
<created-at>2009-11-26T17:19:22Z</created-at>
|
11
|
+
<updated-at>2009-11-26T17:19:22Z</updated-at>
|
12
|
+
</comment>
|
13
|
+
</comments>
|