taskmapper-mingle 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +54 -0
- data/LICENSE.txt +20 -0
- data/README.md +77 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/lib/mingle/mingle-api.rb +228 -0
- data/lib/provider/comment.rb +47 -0
- data/lib/provider/mingle.rb +38 -0
- data/lib/provider/project.rb +62 -0
- data/lib/provider/ticket.rb +102 -0
- data/lib/taskmapper-mingle.rb +5 -0
- data/spec/comments_spec.rb +40 -0
- data/spec/fixtures/cards.xml +83 -0
- data/spec/fixtures/cards/42.xml +41 -0
- data/spec/fixtures/cards/43.xml +42 -0
- data/spec/fixtures/cards/create.xml +42 -0
- data/spec/fixtures/comments.xml +20 -0
- data/spec/fixtures/comments/create.xml +10 -0
- data/spec/fixtures/projects.xml +57 -0
- data/spec/fixtures/projects/another_project_.xml +29 -0
- data/spec/fixtures/projects/create.xml +29 -0
- data/spec/fixtures/projects/test_project.xml +29 -0
- data/spec/projects_spec.rb +56 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/taskmapper-mingle_spec.rb +19 -0
- data/spec/tickets_spec.rb +72 -0
- data/taskmapper-mingle.gemspec +81 -0
- metadata +160 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
# This is the Mingle Provider for taskmapper
|
3
|
+
module Mingle
|
4
|
+
include TaskMapper::Provider::Base
|
5
|
+
TICKET_API = MingleAPI::Card # The class to access the api's cards
|
6
|
+
PROJECT_API = MingleAPI::Project # The class to access the api's projects
|
7
|
+
|
8
|
+
# This is for cases when you want to instantiate using TaskMapper::Provider::Mingle.new(auth)
|
9
|
+
def self.new(auth = {})
|
10
|
+
TaskMapper.new(:mingle, 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
|
+
|
16
|
+
def authorize(auth = {})
|
17
|
+
@authentication ||= TaskMapper::Authenticator.new(auth)
|
18
|
+
auth = @authentication
|
19
|
+
if auth.server.blank? and auth.login.blank? and auth.password.blank?
|
20
|
+
raise "Please provide server, login and password"
|
21
|
+
end
|
22
|
+
MingleAPI::Base.format = :xml
|
23
|
+
MingleAPI.authenticate(auth.server, auth.login, auth.password)
|
24
|
+
end
|
25
|
+
# declare needed overloaded methods here
|
26
|
+
def valid?
|
27
|
+
begin
|
28
|
+
PROJECT_API.find(:first)
|
29
|
+
true
|
30
|
+
rescue
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Mingle
|
3
|
+
# Project class for taskmapper-mingle
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class Project < TaskMapper::Provider::Base::Project
|
7
|
+
API = MingleAPI::Project # The class to access the api's projects
|
8
|
+
# declare needed overloaded methods here
|
9
|
+
|
10
|
+
def id
|
11
|
+
self[:identifier]
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(*options)
|
15
|
+
@system_data ||= {}
|
16
|
+
@cache ||= {}
|
17
|
+
first = options.first
|
18
|
+
case first
|
19
|
+
when Hash
|
20
|
+
super first.to_hash
|
21
|
+
else
|
22
|
+
@system_data[:client] = first
|
23
|
+
super first.attributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def tickets(*options)
|
28
|
+
begin
|
29
|
+
if options.first.is_a? Hash
|
30
|
+
#options[0].merge!(:params => {:id => id})
|
31
|
+
super(*options)
|
32
|
+
elsif options.empty?
|
33
|
+
tickets = MingleAPI::Card.find(:all, :params => {:identifier => id}).collect { |ticket| TaskMapper::Provider::Mingle::Ticket.new ticket }
|
34
|
+
else
|
35
|
+
super(*options)
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def ticket!(*options)
|
43
|
+
options[0].merge!(:identifier => id) if options.first.is_a?(Hash)
|
44
|
+
provider_parent(self.class)::Ticket.create(*options)
|
45
|
+
end
|
46
|
+
|
47
|
+
# copy from this.copy(that) copies that into this
|
48
|
+
def copy(project)
|
49
|
+
project.tickets.each do |ticket|
|
50
|
+
copy_ticket = self.ticket!(:name => ticket.title, :description => ticket.description)
|
51
|
+
ticket.comments.each do |comment|
|
52
|
+
copy_ticket.comment!(:content => comment.body)
|
53
|
+
sleep 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Mingle
|
3
|
+
# Ticket class for taskmapper-mingle
|
4
|
+
#
|
5
|
+
API = MingleAPI::Card
|
6
|
+
|
7
|
+
class Ticket < TaskMapper::Provider::Base::Ticket
|
8
|
+
# declare needed overloaded methods herea
|
9
|
+
|
10
|
+
def initialize(*object)
|
11
|
+
if object.first
|
12
|
+
args = object
|
13
|
+
object = args.shift
|
14
|
+
identifier = args.shift
|
15
|
+
@system_data = {:client => object}
|
16
|
+
unless object.is_a? Hash
|
17
|
+
hash = {:number => object.number,
|
18
|
+
:name => object.name,
|
19
|
+
:description => object.description,
|
20
|
+
:card_type_name => object.card_type.nil? ? "Card" : object.card_type.name,
|
21
|
+
:identifier => identifier,
|
22
|
+
:created_on => object.created_on,
|
23
|
+
:modified_on => object.modified_on,
|
24
|
+
:properties => object.properties}
|
25
|
+
else
|
26
|
+
hash = object
|
27
|
+
end
|
28
|
+
super hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.create(*options)
|
33
|
+
card = API.new(*options)
|
34
|
+
ticket = self.new card
|
35
|
+
card.save
|
36
|
+
ticket
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.find_by_id(identifier, number)
|
40
|
+
self.search(identifier, {'number' => number}).first
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.search(identifier, options = {}, limit = 1000)
|
44
|
+
tickets = API.find(:all, :params => {:identifier => identifier}).collect { |ticket| self.new ticket, identifier }
|
45
|
+
search_by_attribute(tickets, options, limit)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.find_by_attributes(identifier, attributes = {})
|
49
|
+
self.search(identifier, attributes)
|
50
|
+
end
|
51
|
+
|
52
|
+
def number
|
53
|
+
self[:number].to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
def id
|
57
|
+
self[:id].to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def name
|
61
|
+
self[:name]
|
62
|
+
end
|
63
|
+
|
64
|
+
def identifier
|
65
|
+
self[:identifier]
|
66
|
+
end
|
67
|
+
|
68
|
+
def title
|
69
|
+
self[:name]
|
70
|
+
end
|
71
|
+
|
72
|
+
def description
|
73
|
+
self[:description]
|
74
|
+
end
|
75
|
+
|
76
|
+
def status
|
77
|
+
self.properties[1].value
|
78
|
+
end
|
79
|
+
|
80
|
+
def comments(*options)
|
81
|
+
begin
|
82
|
+
if options.empty?
|
83
|
+
comments = MingleAPI::Comment.find(:all, :params => {:identifier => identifier, :number => number}).collect { |comment| TaskMapper::Provider::Mingle::Comment.new comment }
|
84
|
+
else
|
85
|
+
super(*options)
|
86
|
+
end
|
87
|
+
rescue
|
88
|
+
[]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#def comment(*options)
|
93
|
+
|
94
|
+
def comment!(*options)
|
95
|
+
options[0].update(:identifier => identifier, :number => number) if options.first.is_a?(Hash)
|
96
|
+
Comment.create(*options)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "TaskMapper::Provider::Mingle::Comment" do
|
4
|
+
before(:all) do
|
5
|
+
headers = {'Authorization' => 'Basic MDAwMDAwOg==', 'Accept' => 'application/xml'}
|
6
|
+
headers_post = {'Authorization' => 'Basic MDAwMDAwOg==', 'Content-Type' => 'application/xml'}
|
7
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
8
|
+
mock.get '/api/v2/projects/test_project.xml', headers, fixture_for('projects/test_project'), 200
|
9
|
+
mock.get '/api/v2/projects/test_project/cards.xml', headers, fixture_for('cards'), 200
|
10
|
+
mock.get '/api/v2/projects/test_project/cards/42.xml', headers, fixture_for('cards/42'), 200
|
11
|
+
mock.get '/api/v2/projects/test_project/cards/42/comments.xml', headers, fixture_for('comments'), 200
|
12
|
+
mock.post '/api/v2/projects/test_project/cards/42/comments.xml?comment[content]=New%20comment%20created.', headers_post, fixture_for('comments/create'), 200
|
13
|
+
end
|
14
|
+
@identifier = 'test_project'
|
15
|
+
@number = 42
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
@taskmapper = TaskMapper.new(:mingle, {:name => 'anymoto', :login => '000000', :server => 'localhost:8080'})
|
20
|
+
@project = @taskmapper.project(@identifier)
|
21
|
+
@ticket = @project.ticket(@number)
|
22
|
+
@ticket.identifier = @project.identifier
|
23
|
+
@klass = TaskMapper::Provider::Mingle::Comment
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to load all comments" do
|
27
|
+
@comments = @ticket.comments
|
28
|
+
@comments.should be_an_instance_of(Array)
|
29
|
+
@comments.first.should be_an_instance_of(@klass)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return the class" do
|
33
|
+
@ticket.comment.should == @klass
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to create a comment" do
|
37
|
+
@comment = @ticket.comment!(:content => 'New comment created.')
|
38
|
+
@comment.should be_an_instance_of(@klass)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<cards type="array">
|
3
|
+
<card>
|
4
|
+
<name>Ticket 1</name>
|
5
|
+
<description>
|
6
|
+
</description>
|
7
|
+
<card_type>
|
8
|
+
<name>Story</name>
|
9
|
+
</card_type>
|
10
|
+
<id type="integer">409</id>
|
11
|
+
<number type="integer">42</number>
|
12
|
+
<project url="http://myserver.com/api/v2/projects/test_project.xml">
|
13
|
+
<name>test project</name>
|
14
|
+
<identifier>test_project</identifier>
|
15
|
+
</project>
|
16
|
+
<version type="integer">1</version>
|
17
|
+
<project_card_rank type="integer">1</project_card_rank>
|
18
|
+
<created_on type="datetime">2009-10-14T09:14:54Z</created_on>
|
19
|
+
<modified_on type="datetime">2009-10-14T09:14:54Z</modified_on>
|
20
|
+
<modified_by url="http://myserver.com/api/v2/users/1.xml">
|
21
|
+
<name>anne</name>
|
22
|
+
<login>anne</login>
|
23
|
+
</modified_by>
|
24
|
+
<created_by url="http://myserver.com/api/v2/users/2.xml">
|
25
|
+
<name>jane</name>
|
26
|
+
<login>jane</login>
|
27
|
+
</created_by>
|
28
|
+
<properties type="array">
|
29
|
+
<property type_description="Managed text list" hidden="false">
|
30
|
+
<name>Status</name>
|
31
|
+
<value>Closed</value>
|
32
|
+
</property>
|
33
|
+
<property type_description="Managed number list" hidden="false">
|
34
|
+
<name>Estimate</name>
|
35
|
+
<value>4</value>
|
36
|
+
</property>
|
37
|
+
<property type_description="Managed text list" hidden="false">
|
38
|
+
<name>Priority</name>
|
39
|
+
<value nil="true"/>
|
40
|
+
</property>
|
41
|
+
</properties>
|
42
|
+
</card>
|
43
|
+
<card>
|
44
|
+
<name>Automatically update event status when event date has passed</name>
|
45
|
+
<description>
|
46
|
+
</description>
|
47
|
+
<card_type>
|
48
|
+
<name>Story</name>
|
49
|
+
</card_type>
|
50
|
+
<id type="integer">410</id>
|
51
|
+
<number type="integer">43</number>
|
52
|
+
<project url="http://myserver.com/api/v2/projects/test_project.xml">
|
53
|
+
<name>test project</name>
|
54
|
+
<identifier>test_project</identifier>
|
55
|
+
</project>
|
56
|
+
<version type="integer">1</version>
|
57
|
+
<project_card_rank type="integer">1</project_card_rank>
|
58
|
+
<created_on type="datetime">2009-10-14T09:14:54Z</created_on>
|
59
|
+
<modified_on type="datetime">2009-10-14T09:14:54Z</modified_on>
|
60
|
+
<modified_by url="http://myserver.com/api/v2/users/1.xml">
|
61
|
+
<name>anne</name>
|
62
|
+
<login>anne</login>
|
63
|
+
</modified_by>
|
64
|
+
<created_by url="http://myserver.com/api/v2/users/2.xml">
|
65
|
+
<name>jane</name>
|
66
|
+
<login>jane</login>
|
67
|
+
</created_by>
|
68
|
+
<properties type="array">
|
69
|
+
<property type_description="Managed text list" hidden="false">
|
70
|
+
<name>Status</name>
|
71
|
+
<value>Closed</value>
|
72
|
+
</property>
|
73
|
+
<property type_description="Managed number list" hidden="false">
|
74
|
+
<name>Estimate</name>
|
75
|
+
<value>4</value>
|
76
|
+
</property>
|
77
|
+
<property type_description="Managed text list" hidden="false">
|
78
|
+
<name>Priority</name>
|
79
|
+
<value nil="true"/>
|
80
|
+
</property>
|
81
|
+
</properties>
|
82
|
+
</card>
|
83
|
+
</cards>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<card>
|
3
|
+
<name>As an API user, I would like to lookup a card in Mingle, given that I know the card number.</name>
|
4
|
+
<description>
|
5
|
+
</description>
|
6
|
+
<card_type>
|
7
|
+
<name>Story</name>
|
8
|
+
</card_type>
|
9
|
+
<number type="integer">42</number>
|
10
|
+
<project url="http://myserver.com/api/v2/projects/test_project.xml">
|
11
|
+
<name>test project</name>
|
12
|
+
<identifier>test_project</identifier>
|
13
|
+
</project>
|
14
|
+
<version type="integer">1</version>
|
15
|
+
<project_card_rank type="integer">1</project_card_rank>
|
16
|
+
<created_on type="datetime">2009-10-14T09:14:54Z</created_on>
|
17
|
+
<modified_on type="datetime">2009-10-14T09:14:54Z</modified_on>
|
18
|
+
<modified_by url="http://myserver.com/api/v2/users/1.xml">
|
19
|
+
<name>anne</name>
|
20
|
+
<login>anne</login>
|
21
|
+
</modified_by>
|
22
|
+
<created_by url="http://myserver.com/api/v2/users/2.xml">
|
23
|
+
<name>jane</name>
|
24
|
+
<login>jane</login>
|
25
|
+
</created_by>
|
26
|
+
<properties type="array">
|
27
|
+
<property type_description="Managed text list" hidden="false">
|
28
|
+
<name>Status</name>
|
29
|
+
<value>Closed</value>
|
30
|
+
</property>
|
31
|
+
<property type_description="Managed number list" hidden="false">
|
32
|
+
<name>Estimate</name>
|
33
|
+
<value>4</value>
|
34
|
+
</property>
|
35
|
+
<property type_description="Managed text list" hidden="false">
|
36
|
+
<name>Priority</name>
|
37
|
+
<value nil="true"/>
|
38
|
+
</property>
|
39
|
+
</properties>
|
40
|
+
</card>
|
41
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<card>
|
3
|
+
<name>Automatically update event status when event date has passed</name>
|
4
|
+
<description>
|
5
|
+
</description>
|
6
|
+
<card_type>
|
7
|
+
<name>Story</name>
|
8
|
+
</card_type>
|
9
|
+
<id type="integer">410</id>
|
10
|
+
<number type="integer">43</number>
|
11
|
+
<project url="http://localhost:8080/api/v2/projects/test_project.xml">
|
12
|
+
<name>test project</name>
|
13
|
+
<identifier>test_project</identifier>
|
14
|
+
</project>
|
15
|
+
<version type="integer">1</version>
|
16
|
+
<project_card_rank type="integer">1</project_card_rank>
|
17
|
+
<created_on type="datetime">2009-10-14T09:14:54Z</created_on>
|
18
|
+
<modified_on type="datetime">2009-10-14T09:14:54Z</modified_on>
|
19
|
+
<modified_by url="http://localhost:8080/api/v2/users/1.xml">
|
20
|
+
<name>anne</name>
|
21
|
+
<login>anne</login>
|
22
|
+
</modified_by>
|
23
|
+
<created_by url="http://localhost:8080/api/v2/users/2.xml">
|
24
|
+
<name>jane</name>
|
25
|
+
<login>jane</login>
|
26
|
+
</created_by>
|
27
|
+
<properties type="array">
|
28
|
+
<property type_description="Managed text list" hidden="false">
|
29
|
+
<name>Status</name>
|
30
|
+
<value>Closed</value>
|
31
|
+
</property>
|
32
|
+
<property type_description="Managed number list" hidden="false">
|
33
|
+
<name>Estimate</name>
|
34
|
+
<value>4</value>
|
35
|
+
</property>
|
36
|
+
<property type_description="Managed text list" hidden="false">
|
37
|
+
<name>Priority</name>
|
38
|
+
<value nil="true"/>
|
39
|
+
</property>
|
40
|
+
</properties>
|
41
|
+
</card>
|
42
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<card>
|
3
|
+
<name>Show event details in event list</name>
|
4
|
+
<description>
|
5
|
+
</description>
|
6
|
+
<card_type>
|
7
|
+
<name>Story</name>
|
8
|
+
</card_type>
|
9
|
+
<id type="integer">411</id>
|
10
|
+
<number type="integer">44</number>
|
11
|
+
<project url="http://localhost:8080/api/v2/projects/test_project.xml">
|
12
|
+
<name>test project</name>
|
13
|
+
<identifier>test_project</identifier>
|
14
|
+
</project>
|
15
|
+
<version type="integer">1</version>
|
16
|
+
<project_card_rank type="integer">1</project_card_rank>
|
17
|
+
<created_on type="datetime">2009-10-14T09:14:54Z</created_on>
|
18
|
+
<modified_on type="datetime">2009-10-14T09:14:54Z</modified_on>
|
19
|
+
<modified_by url="http://localhost:8080/api/v2/users/1.xml">
|
20
|
+
<name>anne</name>
|
21
|
+
<login>anne</login>
|
22
|
+
</modified_by>
|
23
|
+
<created_by url="http://localhost:8080/api/v2/users/2.xml">
|
24
|
+
<name>jane</name>
|
25
|
+
<login>jane</login>
|
26
|
+
</created_by>
|
27
|
+
<properties type="array">
|
28
|
+
<property type_description="Managed text list" hidden="false">
|
29
|
+
<name>Status</name>
|
30
|
+
<value>Closed</value>
|
31
|
+
</property>
|
32
|
+
<property type_description="Managed number list" hidden="false">
|
33
|
+
<name>Estimate</name>
|
34
|
+
<value>4</value>
|
35
|
+
</property>
|
36
|
+
<property type_description="Managed text list" hidden="false">
|
37
|
+
<name>Priority</name>
|
38
|
+
<value nil="true"/>
|
39
|
+
</property>
|
40
|
+
</properties>
|
41
|
+
</card>
|
42
|
+
|