backlog-api 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.md +22 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/backlog-api.gemspec +68 -0
- data/lib/backlog.rb +9 -0
- data/lib/backlog/api.rb +132 -0
- data/lib/backlog/client.rb +27 -0
- data/lib/backlog/object.rb +247 -0
- data/spec/backlog/api_spec.rb +519 -0
- data/spec/backlog/client_spec.rb +26 -0
- data/spec/backlog/object_spec.rb +22 -0
- data/spec/backlog_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- metadata +128 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem 'rake', '0.8.7'
|
10
|
+
gem "rspec", "~> 2.3.0"
|
11
|
+
gem "bundler", "~> 1.0.0"
|
12
|
+
gem "jeweler", "~> 1.6.2"
|
13
|
+
gem "rcov", ">= 0"
|
14
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 yoppi
|
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,22 @@
|
|
1
|
+
# backlog-api
|
2
|
+
A library to Easy Access Backlog(http://www.backlog.jp) API from Ruby.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
Ok, you just type
|
6
|
+
|
7
|
+
$ gem install backlog-api
|
8
|
+
|
9
|
+
## How to use
|
10
|
+
First, create backlog client to accessing API.
|
11
|
+
Second, call API
|
12
|
+
|
13
|
+
require 'backlog-api'
|
14
|
+
backlog = Backlog::Client.new("space", "user", "password")
|
15
|
+
# get Project List
|
16
|
+
projects = backlog.get_projects()
|
17
|
+
# get Issue
|
18
|
+
issue = backlog.get_issue("issue_key")
|
19
|
+
|
20
|
+
## Copyright
|
21
|
+
Copyright (c) 2011 yoppi. See LICENSE.txt for further details.
|
22
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "backlog-api"
|
18
|
+
gem.homepage = "http://github.com/yoppi/backlog-api"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Backlog API}
|
21
|
+
gem.description = %Q{A library to Access Backlog Issue from Ruby}
|
22
|
+
gem.email = "y.hirokazu@gmail.com"
|
23
|
+
gem.authors = ["yoppi"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rake/rdoctask'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "backlog-api #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/backlog-api.gemspec
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{backlog-api}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{yoppi}]
|
12
|
+
s.date = %q{2011-10-09}
|
13
|
+
s.description = %q{A library to Access Backlog Issue from Ruby}
|
14
|
+
s.email = %q{y.hirokazu@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"backlog-api.gemspec",
|
28
|
+
"lib/backlog.rb",
|
29
|
+
"lib/backlog/api.rb",
|
30
|
+
"lib/backlog/client.rb",
|
31
|
+
"lib/backlog/object.rb",
|
32
|
+
"spec/backlog/api_spec.rb",
|
33
|
+
"spec/backlog/client_spec.rb",
|
34
|
+
"spec/backlog/object_spec.rb",
|
35
|
+
"spec/backlog_spec.rb",
|
36
|
+
"spec/spec_helper.rb"
|
37
|
+
]
|
38
|
+
s.homepage = %q{http://github.com/yoppi/backlog-api}
|
39
|
+
s.licenses = [%q{MIT}]
|
40
|
+
s.require_paths = [%q{lib}]
|
41
|
+
s.rubygems_version = %q{1.8.7}
|
42
|
+
s.summary = %q{Backlog API}
|
43
|
+
|
44
|
+
if s.respond_to? :specification_version then
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_development_dependency(%q<rake>, ["= 0.8.7"])
|
49
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
50
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
51
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
52
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<rake>, ["= 0.8.7"])
|
55
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
56
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
57
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
58
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<rake>, ["= 0.8.7"])
|
62
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
63
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
64
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
65
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
data/lib/backlog.rb
ADDED
data/lib/backlog/api.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Backlog
|
4
|
+
module API
|
5
|
+
class ArgumentError < StandardError ; end
|
6
|
+
|
7
|
+
def get_projects
|
8
|
+
self.call("backlog.getProjects").map {|project|
|
9
|
+
Backlog::Object::Project.new(project)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
# String | Integer -> Backlog::Object::Project
|
14
|
+
def get_project(project_key)
|
15
|
+
Backlog::Object::Project.new(
|
16
|
+
self.call("backlog.getProject", conv_str_to_int(project_key))
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_components(project_id)
|
21
|
+
self.call("backlog.getComponents", project_id).map {|component|
|
22
|
+
Backlog::Object::Component.new(component)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_versions(project_id)
|
27
|
+
self.call("backlog.getVersions", project_id).map {|version|
|
28
|
+
Backlog::Object::Version.new(version)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_users(project_id)
|
33
|
+
self.call("backlog.getUsers", project_id).map {|user|
|
34
|
+
Backlog::Object::User.new(user)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
# String | Integer -> Backlog::Object::DetailUser
|
39
|
+
def get_user(user_key)
|
40
|
+
Backlog::Object::DetailUser.new(
|
41
|
+
self.call("backlog.getUser", conv_str_to_int(user_key))
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# String | Integer -> Backlog::Object::UserIcon
|
46
|
+
def get_user_icon(user_key)
|
47
|
+
Backlog::Object::UserIcon.new(
|
48
|
+
self.call("backlog.getUserIcon", conv_str_to_int(user_key))
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_issue_types(project_id)
|
53
|
+
self.call("backlog.getIssueTypes", project_id).map {|issue_type|
|
54
|
+
Backlog::Object::IssueType.new(issue_type)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
# String | Integer -> Backlog::Object::Issue
|
59
|
+
def get_issue(issue_key)
|
60
|
+
Backlog::Object::Issue.new(
|
61
|
+
self.call("backlog.getIssue", conv_str_to_int(issue_key))
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_comments(issue_id)
|
66
|
+
self.call("backlog.getComments", issue_id).map {|comment|
|
67
|
+
Backlog::Object::Comment.new(comment)
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_timeline
|
72
|
+
self.call("backlog.getTimeline").map {|timeline|
|
73
|
+
Backlog::Object::Timeline.new(timeline)
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_activity_types
|
78
|
+
self.call("backlog.getActivityTypes").map {|activity_type|
|
79
|
+
Backlog::Object::ActivityType.new(activity_type)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_statuses
|
84
|
+
self.call("backlog.getStatuses").map {|status|
|
85
|
+
Backlog::Object::Status.new(status)
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_resolutions
|
90
|
+
self.call("backlog.getResolutions").map {|resolution|
|
91
|
+
Backlog::Object::Resolution.new(resolution)
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_priorities
|
96
|
+
self.call("backlog.getPriorities").map {|priority|
|
97
|
+
Backlog::Object::Priority.new(priority)
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Integer -> (String|Integer) -> Backlog::Object::CustomFields
|
102
|
+
def get_custom_fields(project_id, issue_type=nil)
|
103
|
+
h = {"project_id" => project_id}
|
104
|
+
if issue_type.instance_of? String
|
105
|
+
h["issue_type"] = issue_type
|
106
|
+
elsif issue_type.instance_of? Integer
|
107
|
+
h["issue_type_id"] = isuissue_type
|
108
|
+
end
|
109
|
+
self.call("backlog.getCustomFields", h).map {|custom_field|
|
110
|
+
Backlog::Object::CustomField.new(custom_field)
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Hash -> Integer
|
115
|
+
def count_issue(condition)
|
116
|
+
raise Backlog::API::ArgumentError, "must specify 'projectId'" unless condition.has_key? "projectId"
|
117
|
+
condition = Backlog::Object::FindCondition.new(condition)
|
118
|
+
self.call("backlog.countIssue", condition.to_h)
|
119
|
+
end
|
120
|
+
|
121
|
+
# String(Integer) -> Integer
|
122
|
+
# String(String) -> String
|
123
|
+
# Integer -> Integer
|
124
|
+
def conv_str_to_int(x)
|
125
|
+
if x.instance_of? String
|
126
|
+
(x.to_i.zero? && x != "0") ? x : x.to_i
|
127
|
+
else
|
128
|
+
x
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'xmlrpc/client'
|
4
|
+
|
5
|
+
module Backlog
|
6
|
+
class Client
|
7
|
+
include API
|
8
|
+
|
9
|
+
BACKLOG_API = "https://%s:%s@%s.backlog.jp/XML-RPC"
|
10
|
+
|
11
|
+
def initialize(space, username, password)
|
12
|
+
@space = space
|
13
|
+
@username = username
|
14
|
+
@password = password
|
15
|
+
@client = XMLRPC::Client.new2(BACKLOG_API % [@username, @password, @space])
|
16
|
+
end
|
17
|
+
attr_reader :space, :username, :password, :client
|
18
|
+
|
19
|
+
def call(method, args=nil)
|
20
|
+
if args
|
21
|
+
@client.call(method, args)
|
22
|
+
else
|
23
|
+
@client.call(method)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Backlog
|
4
|
+
module Object
|
5
|
+
class Serializable
|
6
|
+
def to_h
|
7
|
+
self.instance_variables.inject({}) {|ret, v|
|
8
|
+
ret[v.to_s.gsub(/^@/, '')] = self.instance_variable_get(v.to_s)
|
9
|
+
ret
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Project
|
15
|
+
def initialize(project)
|
16
|
+
@id = project['id']
|
17
|
+
@name = project['name']
|
18
|
+
@key = project['key']
|
19
|
+
@url = project['url']
|
20
|
+
@archived = project['archived']
|
21
|
+
end
|
22
|
+
attr_reader :id, :name, :key, :url, :archived
|
23
|
+
end
|
24
|
+
|
25
|
+
class Component
|
26
|
+
def initialize(component)
|
27
|
+
@id = component['id']
|
28
|
+
@name = component['name']
|
29
|
+
end
|
30
|
+
attr_reader :id, :name
|
31
|
+
end
|
32
|
+
|
33
|
+
class Version
|
34
|
+
def initialize(version)
|
35
|
+
@id = version['id']
|
36
|
+
@name = version['name']
|
37
|
+
@date = version['date']
|
38
|
+
end
|
39
|
+
attr_reader :id, :name, :date
|
40
|
+
end
|
41
|
+
|
42
|
+
class User
|
43
|
+
def initialize(user)
|
44
|
+
@id = user['id']
|
45
|
+
@name = user['name']
|
46
|
+
end
|
47
|
+
attr_reader :id, :name
|
48
|
+
end
|
49
|
+
|
50
|
+
class DetailUser < User
|
51
|
+
def initialize(user)
|
52
|
+
super(user)
|
53
|
+
@lang = user['lang']
|
54
|
+
@updated_on = user['updated_on']
|
55
|
+
end
|
56
|
+
attr_reader :lang, :updated_on
|
57
|
+
end
|
58
|
+
|
59
|
+
class UserIcon
|
60
|
+
def initialize(user_icon)
|
61
|
+
@id = user_icon['id']
|
62
|
+
@content_type = user_icon['content_type']
|
63
|
+
# backlog.getUserIcon['data'] isn't encoded, so encode here.
|
64
|
+
@data = XMLRPC::Base64.encode(user_icon['data']).delete("\n")
|
65
|
+
@updated_on = user_icon['updated_on']
|
66
|
+
end
|
67
|
+
attr_reader :id, :content_type, :data, :updated_on
|
68
|
+
end
|
69
|
+
|
70
|
+
class IssueType
|
71
|
+
def initialize(issue_type)
|
72
|
+
@id = issue_type['id']
|
73
|
+
@name = issue_type['name']
|
74
|
+
@color = issue_type['color']
|
75
|
+
end
|
76
|
+
attr_reader :id, :name, :color
|
77
|
+
end
|
78
|
+
|
79
|
+
class Issue
|
80
|
+
def initialize(issue)
|
81
|
+
@id = issue['id']
|
82
|
+
@key = issue['key']
|
83
|
+
@summary = issue['summary']
|
84
|
+
@description = issue['description']
|
85
|
+
@url = issue['url']
|
86
|
+
@due_date = issue['due_date']
|
87
|
+
@start_date = issue['start_date'],
|
88
|
+
@estimated_hours = issue['estimated_hours']
|
89
|
+
@actual_hours = issue['actual_hours']
|
90
|
+
@issue_type = issue['issue_type'] ? IssueType.new(issue['issue_type']) : nil
|
91
|
+
@priority = issue['priority'] ? Priority.new(issue['priority']) : nil
|
92
|
+
@resolution = issue['resolution'] ? Resolution.new(issue['resolution']) : nil
|
93
|
+
@status = issue['status'] ? Status.new(issue['status']) : nil
|
94
|
+
@components = issue['components'] ? issue['components'].map {|x| Component.new(x) } : []
|
95
|
+
@versions = issue['versions'] ? issue['versions'].map {|x| Version.new(x) } : []
|
96
|
+
@milestones = issue['milestone'] ? issue['milestones'].map {|x| Milestone.new(x)} : []
|
97
|
+
@created_user = issue['created_user'] ? User.new(issue['created_user']) : nil
|
98
|
+
@assigner = issue['assigner'] ? User.new(issue['assigner']) : nil
|
99
|
+
@created_on = issue['created_on']
|
100
|
+
@updated_on = issue['updated_on']
|
101
|
+
@custom_fields = issue['custom_fields']
|
102
|
+
end
|
103
|
+
attr_reader :id, :key, :summary, :description, :url,
|
104
|
+
:due_date, :start_date, :estimated_hours,
|
105
|
+
:actual_hours, :issue_type, :priority,
|
106
|
+
:resolution, :status, :components, :versions,
|
107
|
+
:milestones, :created_user, :assigner,
|
108
|
+
:created_on, :updated_on, :custom_fields
|
109
|
+
end
|
110
|
+
|
111
|
+
class Priority
|
112
|
+
def initialize(priority)
|
113
|
+
@id = priority['id']
|
114
|
+
@name = priority['name']
|
115
|
+
end
|
116
|
+
attr_reader :id, :name
|
117
|
+
end
|
118
|
+
|
119
|
+
class Resolution
|
120
|
+
def initialize(resolution)
|
121
|
+
@id = resolution['id']
|
122
|
+
@name = resolution['name']
|
123
|
+
end
|
124
|
+
attr_reader :id, :name
|
125
|
+
end
|
126
|
+
|
127
|
+
class Status
|
128
|
+
def initialize(status)
|
129
|
+
@id = status['id']
|
130
|
+
@name = status['name']
|
131
|
+
end
|
132
|
+
attr_reader :id, :name
|
133
|
+
end
|
134
|
+
|
135
|
+
class Item
|
136
|
+
def initialize(item)
|
137
|
+
@id = item['id']
|
138
|
+
@name = item['name']
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Milestone
|
143
|
+
def initialize(milestone)
|
144
|
+
@id = milestone['id']
|
145
|
+
@name = milestone['name']
|
146
|
+
@date = milestone['date']
|
147
|
+
end
|
148
|
+
attr_reader :id, :name, :date
|
149
|
+
end
|
150
|
+
|
151
|
+
class Comment
|
152
|
+
def initialize(comment)
|
153
|
+
@id = comment['id']
|
154
|
+
@content = comment['content']
|
155
|
+
@created_user = User.new(comment['created_user'])
|
156
|
+
@created_on = comment['created_on']
|
157
|
+
@updated_on = comment['updated_on']
|
158
|
+
end
|
159
|
+
attr_reader :id, :content, :created_user, :created_on, :updated_on
|
160
|
+
end
|
161
|
+
|
162
|
+
class Timeline
|
163
|
+
def initialize(timeline)
|
164
|
+
@type = timeline['type'] ? ActivityType.new(timeline['type']) : nil
|
165
|
+
@content = timeline['content']
|
166
|
+
@updated_on = timeline['updated_on']
|
167
|
+
@user = timeline['user'] ? User.new(timeline['user']) : nil
|
168
|
+
@issue = timeline['issue'] ? Issue.new(timeline['issue']) : nil
|
169
|
+
end
|
170
|
+
attr_reader :type, :content, :updated_on, :user, :issue
|
171
|
+
end
|
172
|
+
|
173
|
+
class ActivityType
|
174
|
+
def initialize(activity_type)
|
175
|
+
@id = activity_type['id']
|
176
|
+
@name = activity_type['name']
|
177
|
+
end
|
178
|
+
attr_reader :id, :name
|
179
|
+
end
|
180
|
+
|
181
|
+
class CustomField
|
182
|
+
def initialize(custom_field)
|
183
|
+
@id = custom_field['id']
|
184
|
+
@type_id = custom_field['type_id']
|
185
|
+
@name = custom_field['name']
|
186
|
+
@description = custom_field['description']
|
187
|
+
@required = custom_field['required']
|
188
|
+
if custom_field['issue_types']
|
189
|
+
@issue_types = custom_field['issue_types'].map {|issue_type| IssueType.new(issue_type) }
|
190
|
+
end
|
191
|
+
# custom_field type is Number(type_id = 3)
|
192
|
+
@min = custom_field['min']
|
193
|
+
@max = custom_field['max']
|
194
|
+
@initial_value = custom_field['initial_value']
|
195
|
+
@unit = custom_field['unit']
|
196
|
+
# custom_field type is Date(type_id = 4)
|
197
|
+
@initial_value_type = custom_field['initial_value_type']
|
198
|
+
@initial_shift = custom_field['initial_shift']
|
199
|
+
@initial_date = custom_field['initial_date']
|
200
|
+
# custom_field type is List(type_id = 5,6)
|
201
|
+
if custom_field['items']
|
202
|
+
@items = custom_field['items'].map {|item| Item.new(item)}
|
203
|
+
end
|
204
|
+
# custom_field type is CheckBox or RadioButton(type_id = 7,8)
|
205
|
+
@allow_input = custom_field['allow_input']
|
206
|
+
end
|
207
|
+
attr_reader :id, :type_id, :name, :description, :required,
|
208
|
+
:issue_types,
|
209
|
+
:min, :max, :initial_value, :unit,
|
210
|
+
:initial_value_type, :initial_shift, :initial_date,
|
211
|
+
:items,
|
212
|
+
:allow_input
|
213
|
+
end
|
214
|
+
|
215
|
+
class FindCondition < Serializable
|
216
|
+
CONDITION_KEYS = %w[
|
217
|
+
projectId
|
218
|
+
issueTypeId
|
219
|
+
issueType
|
220
|
+
componentId
|
221
|
+
versionId
|
222
|
+
milestoneId
|
223
|
+
statusId
|
224
|
+
priorityId
|
225
|
+
assignerId
|
226
|
+
createdUserId
|
227
|
+
resolutionId
|
228
|
+
created_on_min
|
229
|
+
created_on_max
|
230
|
+
updated_on_min
|
231
|
+
updated_on_max
|
232
|
+
].each {|k|
|
233
|
+
class_eval { attr_reader k.to_sym }
|
234
|
+
}
|
235
|
+
|
236
|
+
def initialize(condition)
|
237
|
+
condition.each {|k, v|
|
238
|
+
self.instance_eval %Q{
|
239
|
+
if CONDITION_KEYS.include? k
|
240
|
+
@#{k} = v
|
241
|
+
end
|
242
|
+
}
|
243
|
+
}
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,519 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
|
5
|
+
describe Backlog::API do
|
6
|
+
before(:each) do
|
7
|
+
@client = Backlog::Client.new("hoge", "yoppi", "test")
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "プロジェクトAPI" do
|
11
|
+
context "プロジェクトの一覧を取得する" do
|
12
|
+
let(:projects) {
|
13
|
+
[{"id" => 100,
|
14
|
+
"name" => "test",
|
15
|
+
"key" => "TEST",
|
16
|
+
"url" => "http://hoge.backlog.jp/TEST",
|
17
|
+
"archived" => false}]
|
18
|
+
}
|
19
|
+
|
20
|
+
before do
|
21
|
+
mock(@client).call.with_any_args { projects }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "プロジェクトのリストを取得できる" do
|
25
|
+
@client.get_projects.class.should == Array
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "プロジェクトを取得する" do
|
30
|
+
let(:project) {
|
31
|
+
{"id" => 100,
|
32
|
+
"name" => "test",
|
33
|
+
"key" => "TEST",
|
34
|
+
"url" => "http://hoge.backlog.jp/TEST",
|
35
|
+
"archived" => false}
|
36
|
+
}
|
37
|
+
|
38
|
+
before do
|
39
|
+
mock(@client).call.with_any_args { project }
|
40
|
+
end
|
41
|
+
|
42
|
+
it "project_idを指定してプロジェクトを取得できる" do
|
43
|
+
@client.get_project(100).class.should == Backlog::Object::Project
|
44
|
+
end
|
45
|
+
|
46
|
+
it "keyを指定してプロジェクトを取得できる" do
|
47
|
+
@client.get_project("key").class.should == Backlog::Object::Project
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "カテゴリAPI" do
|
53
|
+
context "プロジェクトのカテゴリを取得する" do
|
54
|
+
let(:component) {
|
55
|
+
[{"id" => 100,
|
56
|
+
"name" => "カテゴリ名"}]
|
57
|
+
}
|
58
|
+
|
59
|
+
before do
|
60
|
+
mock(@client).call.with_any_args { component }
|
61
|
+
end
|
62
|
+
|
63
|
+
it "指定したプロジェクトのカテゴリが取得できる" do
|
64
|
+
@client.get_components(100).class.should == Array
|
65
|
+
end
|
66
|
+
|
67
|
+
it "取得したカテゴリはすべてカテゴリオブジェクトである" do
|
68
|
+
@client.get_components(100).each {|component|
|
69
|
+
component.class.should == Backlog::Object::Component
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "バージョンAPI" do
|
76
|
+
context "プロジェクトの発生バージョン/マイルストーンを取得する" do
|
77
|
+
let(:version) {
|
78
|
+
[{"id" => 733,
|
79
|
+
"name" => "サイトオープン",
|
80
|
+
"date" => "20110808"}]
|
81
|
+
}
|
82
|
+
|
83
|
+
before do
|
84
|
+
mock(@client).call.with_any_args { version }
|
85
|
+
end
|
86
|
+
|
87
|
+
it "プロジェクトを指定して発生バージョンが取得できる" do
|
88
|
+
@client.get_versions(100).class.should == Array
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "ユーザAPI" do
|
94
|
+
context "プロジェクトの参加メンバーを取得する" do
|
95
|
+
let(:user) {
|
96
|
+
[{"id" => 1000,
|
97
|
+
"name" => "yoppi"}]
|
98
|
+
}
|
99
|
+
|
100
|
+
before do
|
101
|
+
mock(@client).call.with_any_args{ user }
|
102
|
+
end
|
103
|
+
|
104
|
+
it "プロジェクトを指定してその参加メンバーを取得できる" do
|
105
|
+
@client.get_users(100).class.should == Array
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "特定のユーザの情報を取得する" do
|
110
|
+
let(:user) {
|
111
|
+
{"id" => 1000,
|
112
|
+
"name" => "yoppi",
|
113
|
+
"lang" => "ja",
|
114
|
+
"updated_on" => "20110807220000"}
|
115
|
+
}
|
116
|
+
|
117
|
+
before do
|
118
|
+
mock(@client).call.with_any_args { user }
|
119
|
+
end
|
120
|
+
|
121
|
+
it "ユーザIDを指定してそのユーザの情報を取得する" do
|
122
|
+
@client.get_user(100).class.should == Backlog::Object::DetailUser
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "特定のユーザのアイコンを取得する" do
|
127
|
+
let(:user_icon) {
|
128
|
+
{
|
129
|
+
"id" => 1000,
|
130
|
+
"content_type" => "image/gif",
|
131
|
+
"data" => "/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAgACADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDMvWNpEHL5ycCo00rV7+NZrOylkjI+WR2VB+GeTVhGjQj7UHlfP7uN+Ax/Ht7f4VPa+OjoupS2GrSRb5pEaKOINiFWHG7PUng8V51SpKWkS8Jg4RSnUMqa11OwkEd9ZmPJwr5DZP1FNMUjA5P4cf4VtJd6rHbyQa1HBcRnMnnRMeUyTg579uPSqTPAw2wENH2yBkd8E06NR35WZ47CRSdSI3QbG28NXD3K3VzdyyZUxTMNiruU9upwDzx19zXPa3px1DxAuoopQZU5LZ6etd/d2EUwIkwy9RkYwayZrRg4KuVRei8VsoPmuc7xb5bET6hBLZGOVH85YNkc0e5eSSWDAHG0/J2zwazrJVt1IjiOPUD7x/OtG437CAcA8deRTYLWadRicmNONoAGP0qPZ8slYcq7qQfMf//Z",
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
before do
|
136
|
+
mock(@client).call.with_any_args { user_icon }
|
137
|
+
end
|
138
|
+
|
139
|
+
it "ユーザを指定してそのユーザのアイコンが取得できる" do
|
140
|
+
@client.get_user_icon(100).class.should == Backlog::Object::UserIcon
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "イシューAPI" do
|
146
|
+
context "プロジェクトのイシュータイプを取得する" do
|
147
|
+
let(:issue_types) {
|
148
|
+
[{"id" => 2000,
|
149
|
+
"name" => "タスク",
|
150
|
+
"color" => "#7ea800"
|
151
|
+
}]
|
152
|
+
}
|
153
|
+
|
154
|
+
before do
|
155
|
+
mock(@client).call.with_any_args { issue_types }
|
156
|
+
end
|
157
|
+
|
158
|
+
it "プロジェクトを指定してそのイシュータイプのリストを取得する" do
|
159
|
+
@client.get_issue_types(100).class.should == Array
|
160
|
+
end
|
161
|
+
|
162
|
+
it "イシュータイプのリスト要素はすべてイシュータイプオブジェクトである" do
|
163
|
+
@client.get_issue_types(100).each {|issue_type|
|
164
|
+
issue_type.class.should == Backlog::Object::IssueType
|
165
|
+
}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "プロジェクトのイシューを取得する" do
|
170
|
+
let(:issue) {
|
171
|
+
{
|
172
|
+
"id" => 1617103,
|
173
|
+
"key" => "ISSUE-100",
|
174
|
+
"summary" => "トップページのデザイン決定",
|
175
|
+
"description" => "トップページのデザイン決定する",
|
176
|
+
"url" => "https://test.backog.jp/view/ISSUE-100",
|
177
|
+
"due_date" => "20110831",
|
178
|
+
"start_date" => "20110720",
|
179
|
+
"estimated_hours" => "100",
|
180
|
+
"actual_hours" => "200",
|
181
|
+
"issue_type" => {"id" => 2000,
|
182
|
+
"name" => "タスク",
|
183
|
+
"color" => "#7ea800"},
|
184
|
+
"priority" => {"id" => 300, "name" => "中"},
|
185
|
+
"resolution" => {"id" => 400, "name" => "対応済み"},
|
186
|
+
"status" => {"id" => 2, "name" => "処理中"},
|
187
|
+
"components" => [{"id" => 100,
|
188
|
+
"name" => "カテゴリ名"}],
|
189
|
+
"versions" => [{"id" => 733,
|
190
|
+
"name" => "サイトオープン",
|
191
|
+
"date" => "20110808"}],
|
192
|
+
"milestones" => [{"id" => 800,
|
193
|
+
"name" => "8/21リリース",
|
194
|
+
"date" => "20110821"}],
|
195
|
+
"created_user" => {"id" => 1000, "name" => "yoppi"},
|
196
|
+
"assigner" => {"id" => 1000, "name" => "yoppi"},
|
197
|
+
"created_on" => "20110701",
|
198
|
+
"updated_on" => "20110807",
|
199
|
+
"custom_fields" => []
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
before do
|
204
|
+
mock(@client).call.with_any_args { issue }
|
205
|
+
end
|
206
|
+
|
207
|
+
it "課題キーを指定してイシューを取得できる" do
|
208
|
+
@client.get_issue("ISSUE-100").class.should == Backlog::Object::Issue
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "コメントAPI" do
|
214
|
+
context "イシューのコメントを取得する" do
|
215
|
+
let(:comments) {
|
216
|
+
[{"id" => "12889281",
|
217
|
+
"content" => "ここはもっとシンプルなデザインがいいと思いました。",
|
218
|
+
"created_user" => {"id" => 100, "name" => "yoppi"},
|
219
|
+
"created_on" => "20110808165300",
|
220
|
+
"updated_on" => "20110808165300"
|
221
|
+
}]
|
222
|
+
}
|
223
|
+
|
224
|
+
before do
|
225
|
+
mock(@client).call.with_any_args { comments }
|
226
|
+
end
|
227
|
+
|
228
|
+
it "指定したイシューのコメントが取得できる" do
|
229
|
+
@client.get_comments(1000).class.should == Array
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "タイムラインAPI" do
|
235
|
+
context "タイムライン(イシューの更新情報)の一覧を取得する" do
|
236
|
+
let(:timeline) {
|
237
|
+
[{
|
238
|
+
"type" => {"id" => 1, "name" => "更新"},
|
239
|
+
"content" => "着手しました",
|
240
|
+
"updated_on" => "20110807194600",
|
241
|
+
"user" => {"id" => 100, "name" => "yoppi"},
|
242
|
+
"issue" => {"id" => "73", "key" => "ISSUE-100",
|
243
|
+
"summary" => "トップページのデザイン決定",
|
244
|
+
"description" => "トップページのデザイン決定します",
|
245
|
+
"priority" => {"id" => 2, "name" => "中"}}
|
246
|
+
}]
|
247
|
+
}
|
248
|
+
|
249
|
+
before do
|
250
|
+
mock(@client).call.with_any_args { timeline }
|
251
|
+
end
|
252
|
+
|
253
|
+
it "タイムラインの一覧が取得できる" do
|
254
|
+
@client.get_timeline().class.should == Array
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe "イシューの更新情報の種別一覧API" do
|
260
|
+
let(:activity_types) {
|
261
|
+
[
|
262
|
+
{"id" => 100,
|
263
|
+
"name" => "課題"}
|
264
|
+
]
|
265
|
+
}
|
266
|
+
|
267
|
+
before do
|
268
|
+
mock(@client).call.with_any_args { activity_types }
|
269
|
+
end
|
270
|
+
|
271
|
+
it "イシューの更新情報の種別一覧を取得できる" do
|
272
|
+
@client.get_activity_types().class.should == Array
|
273
|
+
end
|
274
|
+
|
275
|
+
it "各種別のオブジェクトであること" do
|
276
|
+
@client.get_activity_types().each {|activity_type|
|
277
|
+
activity_type.class.should == Backlog::Object::ActivityType
|
278
|
+
}
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "イシュー状態API" do
|
283
|
+
let(:statuses) {
|
284
|
+
[{"id" => 4, "name" => "完了"}]
|
285
|
+
}
|
286
|
+
|
287
|
+
before do
|
288
|
+
mock(@client).call.with_any_args { statuses }
|
289
|
+
end
|
290
|
+
|
291
|
+
it "イシューの状態一覧を取得できる" do
|
292
|
+
@client.get_statuses().class.should == Array
|
293
|
+
end
|
294
|
+
|
295
|
+
it "取得したイシューの状態一覧の各状態はStatusオブジェクトであること" do
|
296
|
+
@client.get_statuses().each {|status|
|
297
|
+
status.class.should == Backlog::Object::Status
|
298
|
+
}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe "イシュー完了理由API" do
|
303
|
+
let(:resolutions) {
|
304
|
+
[{"id" => 0, "name" => "対応済み"}]
|
305
|
+
}
|
306
|
+
|
307
|
+
before do
|
308
|
+
mock(@client).call.with_any_args { resolutions }
|
309
|
+
end
|
310
|
+
|
311
|
+
it "イシューの完了理由一覧を取得できる" do
|
312
|
+
@client.get_resolutions().class.should == Array
|
313
|
+
end
|
314
|
+
|
315
|
+
it "取得したイシューの完了理由一覧はResolutionオブジェクトであること" do
|
316
|
+
@client.get_resolutions().each {|resolution|
|
317
|
+
resolution.class.should == Backlog::Object::Resolution
|
318
|
+
}
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "イシューの優先度一覧取得API" do
|
323
|
+
let(:priorities) {
|
324
|
+
[{"id" => 3, "name" => "中"}]
|
325
|
+
}
|
326
|
+
|
327
|
+
before do
|
328
|
+
mock(@client).call.with_any_args { priorities }
|
329
|
+
end
|
330
|
+
|
331
|
+
it "イシューの優先度一覧を取得できる" do
|
332
|
+
@client.get_priorities().class.should == Array
|
333
|
+
end
|
334
|
+
|
335
|
+
it "取得したイシューの各優先度はPriorityオブジェクトであること" do
|
336
|
+
@client.get_priorities().each {|priority|
|
337
|
+
priority.class.should == Backlog::Object::Priority
|
338
|
+
}
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe "カスタム属性の情報取得API" do
|
343
|
+
context "カスタム属性タイプが文字列の場合" do
|
344
|
+
let(:custom_fields_1) {
|
345
|
+
[{"id" => 4,
|
346
|
+
"type_id" => 1,
|
347
|
+
"name" => "OS",
|
348
|
+
"description" => "現象が発生したOS",
|
349
|
+
"required" => 1,
|
350
|
+
"issue_types" => [{"id" => 5, "name" => "バグ", "color" => "#990000"}]}]
|
351
|
+
}
|
352
|
+
|
353
|
+
before do
|
354
|
+
mock(@client).call.with_any_args { custom_fields_1 }
|
355
|
+
end
|
356
|
+
|
357
|
+
it "プロジェクトIDを指定して登録しているカスタム属性の情報を取得できる" do
|
358
|
+
@client.get_custom_fields(100).class.should == Array
|
359
|
+
end
|
360
|
+
|
361
|
+
it "プロジェクトIDをissue_type_idを指定して登録しているカスタム属性の情報を取得できる" do
|
362
|
+
@client.get_custom_fields(100, 10).class.should == Array
|
363
|
+
end
|
364
|
+
|
365
|
+
it "プロジェクトIDをissue_typeを指定して登録しているカスタム属性の情報を取得できる" do
|
366
|
+
@client.get_custom_fields(100, "バグ").class.should == Array
|
367
|
+
end
|
368
|
+
|
369
|
+
it "取得したカスタム属性情報はCustomFieldsオブジェクトであること" do
|
370
|
+
@client.get_custom_fields(100).each {|custom_field|
|
371
|
+
custom_field.class.should == Backlog::Object::CustomField
|
372
|
+
custom_field.id.should == custom_fields_1.first["id"]
|
373
|
+
custom_field.type_id.should == custom_fields_1.first["type_id"]
|
374
|
+
custom_field.name.should == custom_fields_1.first["name"]
|
375
|
+
custom_field.description.should == custom_fields_1.first["description"]
|
376
|
+
custom_field.required.should == custom_fields_1.first["required"]
|
377
|
+
custom_field.issue_types.class.should == Array
|
378
|
+
custom_field.issue_types.each {|issue_type|
|
379
|
+
issue_type.class.should == Backlog::Object::IssueType
|
380
|
+
issue_type.id.should == custom_fields_1.first["issue_types"].first["id"]
|
381
|
+
issue_type.name.should == custom_fields_1.first["issue_types"].first["name"]
|
382
|
+
issue_type.color.should == custom_fields_1.first["issue_types"].first["color"]
|
383
|
+
}
|
384
|
+
}
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
context "カスタム属性タイプが数値の場合" do
|
389
|
+
let(:custom_fields_3) {
|
390
|
+
[{"id" => 10,
|
391
|
+
"type_id" => 3,
|
392
|
+
"name" => "割合",
|
393
|
+
"description" => "発生した割合",
|
394
|
+
"required" => 1,
|
395
|
+
"issue_types" => [{"id" => 5, "name" => "バグ", "color" => "#990000"}],
|
396
|
+
"min" => 0.0,
|
397
|
+
"max" => 100.0,
|
398
|
+
"initial_value" => 0.0,
|
399
|
+
"unit" => "%"
|
400
|
+
}]
|
401
|
+
}
|
402
|
+
|
403
|
+
before do
|
404
|
+
mock(@client).call.with_any_args { custom_fields_3 }
|
405
|
+
end
|
406
|
+
|
407
|
+
it "取得したカスタム属性情報はCustomFieldオブジェクトであること" do
|
408
|
+
@client.get_custom_fields(100).each {|custom_field|
|
409
|
+
custom_field.min.should == custom_fields_3.first["min"]
|
410
|
+
custom_field.max.should == custom_fields_3.first["max"]
|
411
|
+
custom_field.initial_value.should == custom_fields_3.first["initial_value"]
|
412
|
+
custom_field.unit.should == custom_fields_3.first["unit"]
|
413
|
+
}
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context "カスタム属性タイプが日付の場合" do
|
418
|
+
let(:custom_fields_4) {
|
419
|
+
[{"id" => 20,
|
420
|
+
"type_id" => 4,
|
421
|
+
"name" => "日付",
|
422
|
+
"description" => "発生した日付",
|
423
|
+
"required" => 1,
|
424
|
+
"issue_types" => [{"id" => 5, "name" => "バグ", "color" => "#990000"}],
|
425
|
+
"initial_value_type" => 1,
|
426
|
+
"min" => 100.0,
|
427
|
+
"max" => 0.0,
|
428
|
+
}]
|
429
|
+
}
|
430
|
+
|
431
|
+
before do
|
432
|
+
mock(@client).call.with_any_args { custom_fields_4 }
|
433
|
+
end
|
434
|
+
|
435
|
+
it "取得したカスタム属性情報はCustomFieldオブジェクトであること" do
|
436
|
+
@client.get_custom_fields(100).each {|custom_field|
|
437
|
+
custom_field.initial_value_type.should == custom_fields_4.first["initial_value_type"]
|
438
|
+
custom_field.min.should == custom_fields_4.first["min"]
|
439
|
+
custom_field.max.should == custom_fields_4.first["max"]
|
440
|
+
}
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
context "カスタム属性タイプがリストの場合" do
|
445
|
+
let(:custom_fields_5) {
|
446
|
+
[{"id" => 20,
|
447
|
+
"type_id" => 5,
|
448
|
+
"name" => "OS",
|
449
|
+
"description" => "発生したOS",
|
450
|
+
"required" => 1,
|
451
|
+
"issue_types" => [{"id" => 5, "name" => "バグ", "color" => "#990000"}],
|
452
|
+
"items" => [{"id" => 1, "name" => "windows"}]
|
453
|
+
}]
|
454
|
+
}
|
455
|
+
|
456
|
+
before do
|
457
|
+
mock(@client).call.with_any_args { custom_fields_5 }
|
458
|
+
end
|
459
|
+
|
460
|
+
it "取得したカスタム属性情報はCustomFieldオブジェクトであること" do
|
461
|
+
@client.get_custom_fields(100).each {|custom_field|
|
462
|
+
custom_field.items.class == Array
|
463
|
+
custom_field.items.each {|item|
|
464
|
+
item.class.should == Backlog::Object::Item
|
465
|
+
}
|
466
|
+
}
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
context "カスタム属性タイプがチェックボックスの場合" do
|
471
|
+
let(:custom_fields_7) {
|
472
|
+
[{"id" => 20,
|
473
|
+
"type_id" => 5,
|
474
|
+
"name" => "OS",
|
475
|
+
"description" => "発生したOS",
|
476
|
+
"required" => 1,
|
477
|
+
"issue_types" => [{"id" => 5, "name" => "バグ", "color" => "#990000"}],
|
478
|
+
"allow_input" => "1",
|
479
|
+
"items" => [{"id" => 1, "name" => "windows"}]
|
480
|
+
}]
|
481
|
+
}
|
482
|
+
|
483
|
+
before do
|
484
|
+
mock(@client).call.with_any_args { custom_fields_7 }
|
485
|
+
end
|
486
|
+
|
487
|
+
it "取得したカスタム属性情報はCustomFieldオブジェクトであること" do
|
488
|
+
@client.get_custom_fields(100).each {|custom_field|
|
489
|
+
custom_field.allow_input.should == custom_fields_7.first['allow_input']
|
490
|
+
}
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
describe "イシュー件数検索API" do
|
496
|
+
context "クエリにproject_idがない場合" do
|
497
|
+
let(:condition) {
|
498
|
+
{"issueTypeId" => 100}
|
499
|
+
}
|
500
|
+
it "例外が発生する" do
|
501
|
+
expect { @client.count_issue(condition) }.should raise_error(Backlog::API::ArgumentError)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
context "指定した検索条件で検索する" do
|
505
|
+
let(:condition) {
|
506
|
+
{
|
507
|
+
"projectId" => 100,
|
508
|
+
"issueTypeId" => 10
|
509
|
+
}
|
510
|
+
}
|
511
|
+
before do
|
512
|
+
mock(@client).call.with_any_args { 1 }
|
513
|
+
end
|
514
|
+
it "指定した検索条件で検索できる" do
|
515
|
+
@client.count_issue(condition).should == 1
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
|
5
|
+
describe Backlog::Client do
|
6
|
+
context "特定のユーザのプロジェクトでAPIにアクセスする" do
|
7
|
+
let(:space) { 'test' }
|
8
|
+
let(:username) { 'yoppi' }
|
9
|
+
let(:password) { 'hoge' }
|
10
|
+
let(:client) {
|
11
|
+
Backlog::Client.new(space, username, password)
|
12
|
+
}
|
13
|
+
|
14
|
+
it "Backlogにアクセスするクライアントオブジェクトが生成されること" do
|
15
|
+
client.should_not be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "ユーザ名が取得できること" do
|
19
|
+
client.username.should == username
|
20
|
+
end
|
21
|
+
|
22
|
+
it "スペース名が取得できること" do
|
23
|
+
client.space.should == space
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
4
|
+
|
5
|
+
describe Backlog::Object::FindCondition do
|
6
|
+
let(:params) {
|
7
|
+
{
|
8
|
+
"projectId" => 100,
|
9
|
+
"issueTypeId" => 10
|
10
|
+
}
|
11
|
+
}
|
12
|
+
it "指定したHashのパラメータが登録されていること" do
|
13
|
+
o = Backlog::Object::FindCondition.new(params)
|
14
|
+
o.projectId.should == params["projectId"]
|
15
|
+
o.issueTypeId.should == params["issueTypeId"]
|
16
|
+
end
|
17
|
+
it "Hashに変換できること" do
|
18
|
+
h = Backlog::Object::FindCondition.new(params).to_h
|
19
|
+
h["projectId"].should == params["projectId"]
|
20
|
+
h["issueTypeId"].should == params["issueTypeId"]
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rr'
|
6
|
+
require 'pry'
|
7
|
+
|
8
|
+
require 'backlog'
|
9
|
+
|
10
|
+
# Requires supporting files with custom matchers and macros, etc,
|
11
|
+
# in ./support/ and its subdirectories.
|
12
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.mock_with :rr
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: backlog-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- yoppi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-10-09 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - "="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.8.7
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.3.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: bundler
|
39
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.0.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: jeweler
|
50
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.6.2
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rcov
|
61
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *id005
|
70
|
+
description: A library to Access Backlog Issue from Ruby
|
71
|
+
email: y.hirokazu@gmail.com
|
72
|
+
executables: []
|
73
|
+
|
74
|
+
extensions: []
|
75
|
+
|
76
|
+
extra_rdoc_files:
|
77
|
+
- LICENSE.txt
|
78
|
+
- README.md
|
79
|
+
files:
|
80
|
+
- .document
|
81
|
+
- .rspec
|
82
|
+
- Gemfile
|
83
|
+
- LICENSE.txt
|
84
|
+
- README.md
|
85
|
+
- Rakefile
|
86
|
+
- VERSION
|
87
|
+
- backlog-api.gemspec
|
88
|
+
- lib/backlog.rb
|
89
|
+
- lib/backlog/api.rb
|
90
|
+
- lib/backlog/client.rb
|
91
|
+
- lib/backlog/object.rb
|
92
|
+
- spec/backlog/api_spec.rb
|
93
|
+
- spec/backlog/client_spec.rb
|
94
|
+
- spec/backlog/object_spec.rb
|
95
|
+
- spec/backlog_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
homepage: http://github.com/yoppi/backlog-api
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
hash: -1065371427
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: "0"
|
120
|
+
requirements: []
|
121
|
+
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 1.8.7
|
124
|
+
signing_key:
|
125
|
+
specification_version: 3
|
126
|
+
summary: Backlog API
|
127
|
+
test_files: []
|
128
|
+
|