taskmapper-github 0.10.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.
@@ -0,0 +1,129 @@
1
+ module TaskMapper::Provider
2
+ module Github
3
+ # Ticket class for taskmapper-github
4
+
5
+ class Ticket < TaskMapper::Provider::Base::Ticket
6
+
7
+ @@allowed_states = %w{open close}
8
+ attr_accessor :prefix_options
9
+ # declare needed overloaded methods here
10
+
11
+ def initialize(*object)
12
+ if object.first
13
+ object = object.first
14
+ unless object.is_a? Hash
15
+ hash = {:id => object.number,
16
+ :status => object.state,
17
+ :description => object.body,
18
+ :user => object.user,
19
+ :project_id => object.project_id}
20
+ else
21
+ hash = object
22
+ end
23
+ super hash
24
+ end
25
+ end
26
+
27
+ def id
28
+ self.number
29
+ end
30
+
31
+ def status
32
+ self.state
33
+ end
34
+
35
+ def description
36
+ self.body
37
+ end
38
+
39
+ def description=(val)
40
+ self.body = val
41
+ end
42
+
43
+ def author
44
+ self.user.respond_to?('login') ? self.user.login : self.user
45
+ end
46
+
47
+ def requestor
48
+ self.user.respond_to?('login') ? self.user.login : self.user
49
+ end
50
+
51
+ def assignee
52
+ self.user.respond_to?('login') ? self.user.login : self.user
53
+ end
54
+
55
+ def self.find_by_id(project_id, number)
56
+ issue = TaskMapper::Provider::Github.api.issue(project_id, number)
57
+ issue.merge!(:project_id => project_id)
58
+ self.new issue
59
+ end
60
+
61
+ def self.find(project_id, *options)
62
+ if options[0].empty?
63
+ self.find_all(project_id)
64
+ elsif options[0].first.is_a? Array
65
+ options[0].first.collect { |number| self.find_by_id(project_id, number) }
66
+ elsif options[0].first.is_a? Hash
67
+ self.find_by_attributes(project_id, options[0].first)
68
+ end
69
+ end
70
+
71
+ def self.find_by_attributes(project_id, attributes = {})
72
+ issues = self.find_all(project_id)
73
+ search_by_attribute(issues, attributes)
74
+ end
75
+
76
+ def self.find_all(project_id)
77
+ issues = []
78
+ issues += TaskMapper::Provider::Github.api.issues(project_id)
79
+ issues += TaskMapper::Provider::Github.api.issues(project_id, {:state => "closed"})
80
+ issues.collect do |issue|
81
+ issue.merge!(:project_id => project_id)
82
+ Ticket.new issue
83
+ end
84
+ end
85
+
86
+ def self.open(project_id, *options)
87
+ ticket_hash = options.first
88
+ body = ticket_hash.delete(:description)
89
+ title = ticket_hash.delete(:title)
90
+ new_issue = TaskMapper::Provider::Github.api.create_issue(project_id, title, body, options.first)
91
+ new_issue.merge!(:project_id => project_id)
92
+ self.new new_issue
93
+ end
94
+
95
+ def created_at
96
+ begin
97
+ Time.parse(self[:created_at])
98
+ rescue
99
+ self[:created_at]
100
+ end
101
+ end
102
+
103
+ def updated_at
104
+ begin
105
+ Time.parse(self[:updated_at])
106
+ rescue
107
+ self[:updated_at]
108
+ end
109
+ end
110
+
111
+ def save
112
+ TaskMapper::Provider::Github.api.update_issue(project_id, number, title, description)
113
+ true
114
+ end
115
+
116
+ def reopen
117
+ Ticket.new(project_id, TaskMapper::Provider::Github.api.reopen_issue(project_id, number))
118
+ end
119
+
120
+ def close
121
+ Ticket.new(project_id, TaskMapper::Provider::Github.api.close_issue(project_id, number))
122
+ end
123
+
124
+ def comment!(attributes)
125
+ Comment.create(project_id, number, attributes)
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,8 @@
1
+ #require YOUR_PROVIDER_API
2
+ require 'octokit'
3
+ require 'active_support/core_ext/string'
4
+ require 'net/http'
5
+
6
+ %w{ github ticket project comment }.each do |f|
7
+ require File.dirname(__FILE__) + '/provider/' + f + '.rb';
8
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe TaskMapper::Provider::Github::Comment do
4
+
5
+ before(:each) do
6
+ @github = TaskMapper.new(:github, {:login => 'taskmapper-user', :password => 'Tm123456'})
7
+ stub_get('https://taskmapper-user:Tm123456@github.com/api/v2/json/organizations/repositories', 'repositories.json')
8
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo', 'project.json')
9
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo/issues','issues.json')
10
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo/issues?state=closed','closed_issues.json')
11
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo/issues/1/comments', 'comments.json')
12
+ stub_post('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo/issues/1/comments', 'comments/3951282.json')
13
+ stub_post('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo/issues/comments/3951282', 'comments/3951282_update.json')
14
+ @project = @github.project('tmtest-repo')
15
+ @ticket = @project.tickets.first
16
+ @klass = TaskMapper::Provider::Github::Comment
17
+ @api = Octokit::Client
18
+ end
19
+
20
+ it "should be able to load all comments" do
21
+ comments = @ticket.comments
22
+ comments.should be_an_instance_of(Array)
23
+ comments.first.should be_an_instance_of(@klass)
24
+ comments.first.body.should == "for testing"
25
+ end
26
+
27
+ it "should be able to create a new comment" do
28
+ comment = @ticket.comment!(:body => 'for testing')
29
+ comment.should be_an_instance_of(@klass)
30
+ comment.body.should == 'for testing'
31
+ end
32
+
33
+ #see bug 116 tm-github: Bug Ticket#comments returning comments with weird text in the body
34
+ it "should be able to load a ticket and clean comment body" do
35
+ comments = @ticket.comments.map(&:body).should == ["for testing", "test comment"]
36
+ end
37
+
38
+ it "should be able to update comments" do
39
+ comment = @ticket.comments.first
40
+ comment.body = "updated comment"
41
+ comment.save.should be_true
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ [
2
+
3
+ ]
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo/issues/comments/3951282",
4
+ "created_at": "2012-02-13T22:49:55Z",
5
+ "body": "for testing",
6
+ "updated_at": "2012-02-13T22:49:55Z",
7
+ "id": 3951282,
8
+ "user": {
9
+ "url": "https://api.github.com/users/taskmapper-user",
10
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
11
+ "login": "taskmapper-user",
12
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
13
+ "id": 1434902
14
+ }
15
+ },
16
+ {
17
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo/issues/comments/3951282",
18
+ "created_at": "2012-02-13T22:49:55Z",
19
+ "body": "--- \nbody: test comment\n",
20
+ "updated_at": "2012-02-13T22:49:55Z",
21
+ "id": 3951283,
22
+ "user": {
23
+ "url": "https://api.github.com/users/taskmapper-user",
24
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
25
+ "login": "taskmapper-user",
26
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
27
+ "id": 1434902
28
+ }
29
+ }
30
+ ]
@@ -0,0 +1,16 @@
1
+ {
2
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo/issues/comments/3951282",
3
+ "created_at": "2012-02-13T22:49:55Z",
4
+ "body": {
5
+ "body": "for testing"
6
+ },
7
+ "updated_at": "2012-02-13T22:49:55Z",
8
+ "id": 3951282,
9
+ "user": {
10
+ "url": "https://api.github.com/users/taskmapper-user",
11
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
12
+ "login": "taskmapper-user",
13
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
14
+ "id": 1434902
15
+ }
16
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo/issues/comments/3951282",
3
+ "created_at": "2012-02-13T22:49:55Z",
4
+ "body": "for testing",
5
+ "updated_at": "2012-02-13T22:49:55Z",
6
+ "id": 3951282,
7
+ "user": {
8
+ "url": "https://api.github.com/users/taskmapper-user",
9
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
10
+ "login": "taskmapper-user",
11
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
12
+ "id": 1434902
13
+ }
14
+ }
@@ -0,0 +1,32 @@
1
+ [
2
+ {
3
+ "title": "for testing",
4
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo/issues/1",
5
+ "closed_at": null,
6
+ "created_at": "2012-02-13T22:45:27Z",
7
+ "milestone": null,
8
+ "labels": [
9
+
10
+ ],
11
+ "number": 1,
12
+ "body": "",
13
+ "html_url": "https://github.com/taskmapper-user/tmtest-repo/issues/1",
14
+ "updated_at": "2012-02-13T22:49:55Z",
15
+ "comments": 1,
16
+ "state": "open",
17
+ "pull_request": {
18
+ "diff_url": null,
19
+ "patch_url": null,
20
+ "html_url": null
21
+ },
22
+ "assignee": null,
23
+ "id": 3210729,
24
+ "user": {
25
+ "url": "https://api.github.com/users/taskmapper-user",
26
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
27
+ "login": "taskmapper-user",
28
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
29
+ "id": 1434902
30
+ }
31
+ }
32
+ ]
@@ -0,0 +1 @@
1
+ {"issue":{"comments":1,"position":1.0,"number":1,"state":"open","updated_at":"2012/02/13 14:49:55 -0800","labels":[],"user":"taskmapper-user","body":"","title":"for testing","html_url":"https://github.com/taskmapper-user/tmtest-repo/issues/1","created_at":"2012/02/13 14:45:27 -0800","votes":0,"gravatar_id":"42bd18419413dfbd6e7ec4fefdec94ae"}}
@@ -0,0 +1 @@
1
+ {"issue":{"comments":1,"position":1.0,"number":1,"state":"open","updated_at":"2012/02/13 14:49:55 -0800","labels":[],"user":"taskmapper-user","body":"","title":"for testing","html_url":"https://github.com/taskmapper-user/tmtest-repo/issues/1","created_at":"2012/02/13 14:45:27 -0800","votes":0,"gravatar_id":"42bd18419413dfbd6e7ec4fefdec94ae"}}
@@ -0,0 +1,34 @@
1
+ {
2
+ "watchers": 1,
3
+ "url": "https://api.github.com/repos/taskmapper-user/tmtest-repo",
4
+ "master_branch": null,
5
+ "created_at": "2012-02-13T22:20:10Z",
6
+ "html_url": "https://github.com/taskmapper-user/tmtest-repo",
7
+ "ssh_url": "git@github.com:taskmapper-user/tmtest-repo.git",
8
+ "description": "",
9
+ "has_wiki": true,
10
+ "clone_url": "https://github.com/taskmapper-user/tmtest-repo.git",
11
+ "forks": 1,
12
+ "fork": false,
13
+ "pushed_at": null,
14
+ "git_url": "git://github.com/taskmapper-user/tmtest-repo.git",
15
+ "mirror_url": null,
16
+ "open_issues": 1,
17
+ "private": false,
18
+ "svn_url": "https://github.com/taskmapper-user/tmtest-repo",
19
+ "homepage": "",
20
+ "size": 0,
21
+ "has_issues": true,
22
+ "updated_at": "2012-02-13T22:20:10Z",
23
+ "owner": {
24
+ "url": "https://api.github.com/users/taskmapper-user",
25
+ "gravatar_id": "42bd18419413dfbd6e7ec4fefdec94ae",
26
+ "login": "taskmapper-user",
27
+ "avatar_url": "https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
28
+ "id": 1434902
29
+ },
30
+ "name": "tmtest-repo",
31
+ "id": 3434734,
32
+ "has_downloads": true,
33
+ "language": null
34
+ }
@@ -0,0 +1,34 @@
1
+ [{
2
+ "watchers":"1",
3
+ "url":"https://api.github.com/repos/taskmapper-user/tmtest-repo",
4
+ "created_at":"2012-02-13T22:20:10Z",
5
+ "mirror_url":"null",
6
+ "has_wiki":"true",
7
+ "html_url":"https://github.com/taskmapper-user/tmtest-repo",
8
+ "ssh_url":"git@github.com:taskmapper-user/tmtest-repo.git",
9
+ "description":"",
10
+ "forks":"1",
11
+ "clone_url":"https://github.com/taskmapper-user/tmtest-repo.git",
12
+ "fork":false,
13
+ "open_issues":"1",
14
+ "private":false,
15
+ "homepage":"",
16
+ "size":"0",
17
+ "has_issues":true,
18
+ "master_branch":"null",
19
+ "pushed_at":"null",
20
+ "updated_at":"2012-02-13T22:20:10Z",
21
+ "owner": {
22
+ "url":"https://api.github.com/users/taskmapper-user",
23
+ "avatar_url":"https://secure.gravatar.com/avatar/42bd18419413dfbd6e7ec4fefdec94ae?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
24
+ "gravatar_id":"42bd18419413dfbd6e7ec4fefdec94ae",
25
+ "login":"taskmapper-user",
26
+ "id":"1434902"
27
+ },
28
+ "name":"tmtest-repo",
29
+ "has_downloads":true,
30
+ "id":"3434734",
31
+ "git_url":"git://github.com/taskmapper-user/tmtest-repo.git",
32
+ "svn_url":"https://github.com/taskmapper-user/tmtest-repo",
33
+ "language":"null"
34
+ }]
@@ -0,0 +1 @@
1
+ {"repositories":[]}
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe TaskMapper::Provider::Github::Project do
4
+
5
+ before(:all) do
6
+ @repo_name = "tmtest-repo"
7
+ @returned_repo = "taskmapper-user/tmtest-repo"
8
+ @klass = TaskMapper::Provider::Github::Project
9
+ end
10
+
11
+ before(:each) do
12
+ @github = TaskMapper.new(:github, :login => 'taskmapper-user', :password => 'Tm123456')
13
+ end
14
+
15
+ it "should be able to load all projects" do
16
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/users/taskmapper-user/repos', 'projects.json')
17
+ stub_get('https://taskmapper-user:Tm123456@github.com/api/v2/json/organizations/repositories', 'repositories.json')
18
+ @projects = @github.projects
19
+ @projects.should be_an_instance_of(Array)
20
+ @projects.first.should be_an_instance_of(@klass)
21
+ end
22
+
23
+ it "should be able to load all projects based on an array of name(id)" do
24
+ stub_get('https://taskmapper-user:Tm123456@api.github.com/repos/taskmapper-user/tmtest-repo', 'project.json')
25
+ @projects = @github.projects([@repo_name])
26
+ @projects.should be_an_instance_of(Array)
27
+ @projects.first.should be_an_instance_of(@klass)
28
+ @projects.first.id.should == @returned_repo
29
+ end
30
+
31
+ it "should be able to load a single project based on a single name(id)" do
32
+ @project = @github.projects(@repo_name)
33
+ @project.should be_an_instance_of(@klass)
34
+ @project.id.should == @returned_repo
35
+ end
36
+
37
+ it "should be able to find by name(id)" do
38
+ @project = @github.project(@repo_name)
39
+ @project.should be_an_instance_of(@klass)
40
+ @project.id.should == @returned_repo
41
+ end
42
+
43
+ it "should be able to find by attributes" do
44
+ @projects = @github.projects(:name => 'tmtest-repo')
45
+ @projects.should be_an_instance_of(Array)
46
+ @projects.first.id.should be_eql(@returned_repo)
47
+ end
48
+ end
49
+
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,35 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'rubygems'
5
+ require 'taskmapper'
6
+ require 'active_support/core_ext/string'
7
+ require 'rspec'
8
+ require 'taskmapper-github'
9
+ require 'fakeweb'
10
+
11
+ RSpec.configure do |config|
12
+ config.color_enabled = true
13
+ end
14
+
15
+ FakeWeb.allow_net_connect = false
16
+
17
+ def fixture_file(filename)
18
+ return '' if filename == ''
19
+ file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
20
+ File.read(file_path)
21
+ end
22
+
23
+
24
+ def stub_request(method, url, filename, status=nil)
25
+ options = {:body => ""}
26
+ options.merge!({:body => fixture_file(filename)}) if filename
27
+ options.merge!({:body => status.last}) if status
28
+ options.merge!({:status => status}) if status
29
+
30
+ FakeWeb.register_uri(method, url, options)
31
+ end
32
+
33
+ def stub_get(*args); stub_request(:get, *args) end
34
+ def stub_post(*args); stub_request(:post, *args) end
35
+ def stub_delete(*args); stub_request(:delete, *args) end