you_track 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 889ce5a329ead3fe526595b6ccdedb2e9be2f54d
4
- data.tar.gz: 6445d8f1eab01357762bb6a9213000316771a06d
3
+ metadata.gz: 2e542dac4f944908887f1a006dcc1d8de569fbf1
4
+ data.tar.gz: 75a5823009d83ff8bcdf82461c4cea7c6c057a9e
5
5
  SHA512:
6
- metadata.gz: 1f9b2bc53461f95cf91059abbc490cebb36d0b0f0e78bee3a677b4928fa5affae7570ff74823c0885b520948124ca19647b8d694b6fbf0c2d95ba8d829d93e65
7
- data.tar.gz: fa5f0df1b16a46c6a76968c2c3c201d3ee1c536b4c3a01b27ae69036044913c08fc783ef429b755e0fa946262321f7376a75a68fb891903241274df31c6444a4
6
+ metadata.gz: 41e1aaef65378c7e7994db4e34c2890dcea9a7607e093c5fa0516ce72f96cce4a87cf5caf2b787905d27b033ada25b6b18756c4f3119c8aa8f4d0a8957f4234c
7
+ data.tar.gz: 582abf84d61d51abfbfaf56de41041e7a68e4aadf87d740771097cfdfac8cfbe806ab18bd01d7c59ec345e7974c3b83295add502249cd7687e530c8d7166973f
@@ -4,11 +4,110 @@ class YouTrack::Client::Mock
4
4
  def self.data
5
5
  @data ||= Hash.new { |h,k|
6
6
  h[k] = {
7
- :issues => {},
8
- :comments => {},
9
- :users => {},
10
- :projects => {},
7
+ :issues => {},
8
+ :comments => {},
9
+ :users => {},
10
+ :projects => {},
11
+ :project_custom_fields => {},
12
+ :bundles => {
13
+ "States" => {
14
+ "type" => "state",
15
+ "name" => "States",
16
+ "values" => [
17
+ {"resolved" => "false", "value" => "Submitted"},
18
+ {"resolved" => "false", "value" => "Open"},
19
+ {"resolved" => "false", "value" => "In Progress"},
20
+ {"resolved" => "false", "value" => "To be discussed"},
21
+ {"resolved" => "false", "value" => "Reopened"},
22
+ {"resolved" => "true", "value" => "Can't Reproduce"},
23
+ {"resolved" => "true", "value" => "Duplicate"},
24
+ {"resolved" => "true", "value" => "Fixed"},
25
+ {"resolved" => "true", "value" => "Won't fix"},
26
+ {"resolved" => "true", "value" => "Incomplete"},
27
+ {"resolved" => "true", "value" => "Obsolete"},
28
+ {"resolved" => "true", "value" => "Verified"},
29
+ {"resolved" => "false", "value" => "New"}
30
+ ]
31
+ }
32
+ },
11
33
  :custom_fields => {
34
+ "Type" => {
35
+ "name" => "Type",
36
+ "isPrivate" => false,
37
+ "visibleByDefault" => true,
38
+ "autoAttached" => true,
39
+ "type" => "enum[1]",
40
+ "attachBundlePolicy" => 0,
41
+ "defaultBundle" => "Types",
42
+ },
43
+ "Priority" => {
44
+ "name" => "Priority",
45
+ "isPrivate" => false,
46
+ "visibleByDefault" => true,
47
+ "autoAttached" => true,
48
+ "type" => "enum[1]",
49
+ "attachBundlePolicy" => 0,
50
+ "defaultBundle" => "Priorties",
51
+ },
52
+ "State" => {
53
+ "name" => "State",
54
+ "isPrivate" => false,
55
+ "visibleByDefault" => true,
56
+ "autoAttached" => true,
57
+ "type" => "state[1]",
58
+ "attachBundlePolicy" => 0,
59
+ "defaultBundle" => "States",
60
+ },
61
+ "Subsystem" => {
62
+ "name" => "Subsystem",
63
+ "isPrivate" => false,
64
+ "visibleByDefault" => true,
65
+ "autoAttached" => true,
66
+ "type" => "ownedField[1]",
67
+ "attachBundlePolicy" => 1,
68
+ "defaultBundle" => "Subsystems",
69
+ },
70
+ "Fixed in build" => {
71
+ "name" => "Fixed in build",
72
+ "isPrivate" => false,
73
+ "visibleByDefault" => true,
74
+ "autoAttached" => true,
75
+ "type" => "build[1]",
76
+ "attachBundlePolicy" => 1,
77
+ "defaultBundle" => "Builds",
78
+ },
79
+ "Assignee" => {
80
+ "name" => "Assignee",
81
+ "isPrivate" => false,
82
+ "visibleByDefault" => true,
83
+ "autoAttached" => true,
84
+ "type" => "user[1]",
85
+ },
86
+ "Affected versions" => {
87
+ "name" => "Affected versions",
88
+ "isPrivate" => false,
89
+ "visibleByDefault" => true,
90
+ "autoAttached" => true,
91
+ "type" => "version[*]",
92
+ "attachBundlePolicy" => 1,
93
+ "defaultBundle" => "Versions",
94
+ },
95
+ "Fix versions" => {
96
+ "name" => "Fix Versions",
97
+ "isPrivate" => false,
98
+ "visibleByDefault" => true,
99
+ "autoAttached" => true,
100
+ "type" => "version[*]",
101
+ "attachBundlePolicy" => 1,
102
+ "defaultBundle" => "Versions",
103
+ },
104
+ "Due Date" => {
105
+ "name" => "Due Date",
106
+ "isPrivate" => false,
107
+ "visibleByDefault" => true,
108
+ "autoAttached" => true,
109
+ "type" => "date",
110
+ },
12
111
  }
13
112
  }
14
113
  }
@@ -5,12 +5,13 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
5
5
  attribute :comment_count, alias: "commentsCount", type: :integer
6
6
  attribute :comments, type: :array
7
7
  attribute :created_at, alias: "created", parser: ms_time
8
- attribute :custom_fields, default: [], parser: lambda { |v, _| Hash[v] }
8
+ attribute :custom_fields, default: {}, parser: lambda { |v, _| Hash[v] }
9
9
  attribute :description
10
10
  attribute :project_id, alias: "projectShortName"
11
11
  attribute :project_index, alias: "numberInProject", type: :integer
12
12
  attribute :reporter, alias: "reporterFullName"
13
13
  attribute :reporter_username, alias: "reporterName"
14
+ attribute :resolved, parser: ms_time
14
15
  attribute :summary
15
16
  attribute :tags, alias: "tag", type: :array
16
17
  attribute :updated_at, alias: "updated", parser: ms_time
@@ -20,9 +21,6 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
20
21
 
21
22
  attr_accessor :permitted_group
22
23
 
23
- # CREATE https://confluence.jetbrains.com/display/YTD6/Create+New+Issue
24
- # UPDATE https://confluence.jetbrains.com/display/YTD6/Update+an+Issue
25
-
26
24
  def comments
27
25
  service.comments.load(service.get_issue_comments(self.identity).body)
28
26
  end
@@ -32,6 +30,24 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
32
30
  comments.detect { |c| c.text == comment }
33
31
  end
34
32
 
33
+ def assignee=(user)
34
+ user_id = user.is_a?(YouTrack::Client::User) ? user.identity : user
35
+ service.apply_issue_command("id" => self.identity, "command" => "Assignee #{user_id}")
36
+ self.reload
37
+ end
38
+
39
+ def assignee
40
+ if user_id = self.custom_fields["Assignee"]
41
+ service.users.new(
42
+ service.get_user(user_id).body
43
+ )
44
+ end
45
+ end
46
+
47
+ def resolved?
48
+ !! self.resolved
49
+ end
50
+
35
51
  def state
36
52
  custom_fields["State"]
37
53
  end
@@ -18,4 +18,8 @@ class YouTrack::Client::Request
18
18
  values = params.values_at(*requirements)
19
19
  values.size == 1 ? values.first : values
20
20
  end
21
+
22
+ def ms_time(time=Time.now)
23
+ time.to_i * 1000
24
+ end
21
25
  end
@@ -1,36 +1,50 @@
1
1
  class YouTrack::Client::ApplyIssueCommand < YouTrack::Client::Request
2
- def real(params={})
3
- id = params.delete("id")
2
+ include YouTrack::Client::ParameterRequest
4
3
 
4
+ def identity
5
+ params.fetch("id")
6
+ end
7
+
8
+ def real
5
9
  service.request(
6
- :path => "/issue/#{id}/execute",
10
+ :path => "/issue/#{identity}/execute",
7
11
  :query => params,
8
12
  :method => :post,
9
13
  )
10
14
  end
11
15
 
12
- def mock(params={})
13
- id = params.delete("id")
14
- issue = find(:issues, id)
16
+ def mock
17
+ issue = find(:issues, identity)
15
18
  comment_id = "#{Cistern::Mock.random_numbers(2)}-#{Cistern::Mock.random_numbers(5)}"
16
19
 
17
- if params["comment"]
18
- comment = {
20
+ if comment = params["comment"]
21
+ service.data[:comments][comment_id] = {
19
22
  "id" => comment_id,
20
23
  "author" => service.username,
21
24
  "deleted" => false,
22
- "text" => params["comment"],
25
+ "text" => comment,
23
26
  "shownForIssuer" => false,
24
- "created" => Time.now.to_i * 1000,
25
- "issueId" => id,
27
+ "created" => ms_time,
28
+ "issueId" => identity,
26
29
  }
27
- service.data[:comments][comment_id] = comment
28
30
  end
29
31
 
30
32
  if params["command"]
31
33
  commands = params["command"].split.each_slice(2).map { |a| [a[0], a[1]] }
32
- commands.each do |command|
33
- issue["custom_fields"].detect { |f| f[0] == command[0] }[1] = command[1]
34
+ commands.each do |field, value|
35
+ prototype = service.data[:custom_fields].fetch(field)
36
+
37
+ bundle_value = if bundle = service.data[:bundles][prototype["defaultBundle"]]
38
+ bundle["values"].find { |v| v["value"] == value }
39
+ else # @fixme explode
40
+ {}
41
+ end
42
+
43
+ if bundle_value["resolved"] == "true"
44
+ issue["resolved"] = ms_time(Time.now)
45
+ end
46
+
47
+ issue["custom_fields"].find { |name, _| name == field }[1] = value
34
48
  end
35
49
  end
36
50
 
@@ -1,3 +1,4 @@
1
+ # https://confluence.jetbrains.com/display/YTD6/Create+New+Issue
1
2
  class YouTrack::Client::CreateIssue < YouTrack::Client::Request
2
3
  def real(params)
3
4
  service.request(
@@ -12,31 +13,44 @@ class YouTrack::Client::CreateIssue < YouTrack::Client::Request
12
13
 
13
14
  issue = Cistern::Hash.slice(params, "project", "description", "summary")
14
15
 
15
- project = issue["projectShortName"] = issue.delete("project")
16
+ project_id = issue["projectShortName"] = issue.delete("project")
17
+ find(:projects, project_id)
16
18
 
17
19
  index = service.data[:issues].size + 1
18
- project_index = service.data[:issues].values.select { |i| i["projectShortName"] == project }.size
20
+ project_index = service.data[:issues].values.select { |i| i["projectShortName"] == project_id }.size
19
21
 
20
- identity = "#{project}-#{index}"
22
+ identity = "#{project_id}-#{index}"
21
23
 
22
24
  issue.merge!(
23
25
  "id" => identity,
24
26
  "tag" => "",
25
27
  "numberInProject" => project_index,
26
- "created" => Time.now.to_i * 1000,
27
- "updated" => Time.now.to_i * 1000,
28
+ "created" => ms_time(Time.now),
29
+ "updated" => ms_time(Time.now),
28
30
  "updaterName" => service.username,
29
31
  "updaterFullName" => service.username.capitalize,
30
32
  "reporterName" => service.username,
31
33
  "reporterFullName" => service.username.capitalize,
32
34
  "commentsCount" => "0",
33
35
  "votes" => "0",
34
- "custom_fields" => [
35
- ["State", "Open"],
36
- ], # @fixme need these
37
36
  "attachments" => [],
37
+ "custom_fields" => [],
38
38
  )
39
39
 
40
+ service.data[:project_custom_fields][project_id].each { |prototype|
41
+ default = if bundle = service.data[:bundles][prototype["defaultBundle"]]
42
+ bundle["values"][prototype["attachBundlePolicy"].to_i]
43
+ else
44
+ {}
45
+ end
46
+
47
+ if default["resolved"] == "true"
48
+ issue["resolved"] = ms_time(Time.now)
49
+ end
50
+
51
+ issue["custom_fields"] << [ prototype["name"], default["value"] ]
52
+ }
53
+
40
54
  service.data[:issues][identity] = issue
41
55
 
42
56
  service.response(
@@ -31,10 +31,7 @@ class YouTrack::Client::CreateProject < YouTrack::Client::Request
31
31
  "versions" => [],
32
32
  }.merge(Cistern::Hash.slice(params, "description"))
33
33
 
34
- # @hack
35
- service.data[:custom_fields][identity] = [
36
- {"name" => "Fix versions", "url" => service.url_for("/admin/project/#{identity}/customfield/Fix versions")}
37
- ]
34
+ service.data[:project_custom_fields][identity] = service.data[:custom_fields].values.select { |v| v["autoAttached"] }
38
35
 
39
36
  service.response(status: 201)
40
37
  end
@@ -1,3 +1,4 @@
1
+ # https://confluence.jetbrains.com/display/YTD6/GET+Project+Custom+Fields
1
2
  class YouTrack::Client::GetProjectCustomFields < YouTrack::Client::Request
2
3
  def real(id)
3
4
  service.request(
@@ -7,6 +8,17 @@ class YouTrack::Client::GetProjectCustomFields < YouTrack::Client::Request
7
8
  end
8
9
 
9
10
  def mock(id)
10
- service.response(body: find(:custom_fields, id))
11
+ prototypes = find(:project_custom_fields, id)
12
+
13
+ body = prototypes.inject([]) { |r,p|
14
+ name = p.fetch("name")
15
+
16
+ r << {
17
+ "name" => name,
18
+ "url" => service.url_for("/admin/project/#{id}/#{name}"),
19
+ }
20
+ }
21
+
22
+ service.response(body: body)
11
23
  end
12
24
  end
@@ -1,19 +1,33 @@
1
+ # https://confluence.jetbrains.com/display/YTD6/Update+an+Issue
1
2
  class YouTrack::Client::UpdateIssue < YouTrack::Client::Request
2
- def real(params={})
3
- id = params.delete("id")
3
+ include YouTrack::Client::ParameterRequest
4
+
5
+ def self.accepted_attributes
6
+ # issueID # string ID of an issue that should be updated.
7
+ @_accepted_attributes ||= [
8
+ "summary", # string New summary for the specified issue.
9
+ "description", # string Updated description for the specified issue.
10
+ ]
11
+ end
12
+
13
+ def identity
14
+ params.fetch("id")
15
+ end
16
+
17
+ def accepted_attributes
18
+ Cistern::Hash.slice(params, *self.class.accepted_attributes)
19
+ end
20
+
21
+ def real
4
22
  service.request(
5
- :path => "/issue/#{id}",
23
+ :path => "/issue/#{params.fetch("id")}",
6
24
  :method => :post,
7
- :query => params,
25
+ :query => accepted_attributes,
8
26
  )
9
27
  end
10
28
 
11
- def mock(params={})
12
- id = params.delete("id")
13
- issue = find(:issues, id)
14
-
15
- issue.merge!(params)
16
- service.data[:issues][id] = issue
29
+ def mock
30
+ find(:issues, identity).merge!(accepted_attributes)
17
31
 
18
32
  service.response
19
33
  end
@@ -7,9 +7,10 @@ parsers = %w(
7
7
  comments
8
8
  issue
9
9
  issues
10
+ project_custom_fields
10
11
  projects
12
+ state_bundle
11
13
  user
12
- project_custom_fields
13
14
  )
14
15
 
15
16
  parsers.each do |parser|
@@ -6,8 +6,6 @@ class YouTrack::Parser::Base
6
6
  end
7
7
 
8
8
  def parse_fields(fields)
9
- fields.inject({}) { |r, f|
10
- r.merge(f["name"] => f["value"])
11
- }
9
+ fields.inject({}) { |r, f| r.merge(f["name"] => f["value"]) }
12
10
  end
13
11
  end
@@ -6,6 +6,15 @@ class YouTrack::Parser::IssueParser < YouTrack::Parser::Base
6
6
  }
7
7
  end
8
8
 
9
+ def parse_user_fields(user_fields)
10
+ user_fields.inject({}) { |r, a|
11
+ outer_value = a["value"]
12
+ value = outer_value.delete("__content__")
13
+
14
+ r.merge(a["name"] => {"value" => value}.merge(outer_value))
15
+ }
16
+ end
17
+
9
18
  def parse
10
19
  results = raw["issue"].dup
11
20
 
@@ -16,9 +25,14 @@ class YouTrack::Parser::IssueParser < YouTrack::Parser::Base
16
25
  custom_fields = fields - attachments
17
26
 
18
27
  results.merge!(parse_fields(standard_fields))
19
- results["custom_fields"] = parse_fields(custom_fields)
20
- results["attachments"] = parse_attachments(attachments)
21
- results["comments"] = results.delete("comment")
28
+
29
+ user_fields = custom_fields.select { |k| k["xsi:type"] == "MultiUserField" }
30
+
31
+ custom_fields -= user_fields
32
+
33
+ results["custom_fields"] = parse_fields(custom_fields).merge(parse_user_fields(user_fields))
34
+ results["attachments"] = parse_attachments(attachments)
35
+ results["comments"] = results.delete("comment")
22
36
 
23
37
  results
24
38
  end
@@ -0,0 +1,16 @@
1
+ class YouTrack::Parser::StateBundleParser < YouTrack::Parser::Base
2
+ def parse
3
+ bundle = raw["stateBundle"]
4
+
5
+ states = bundle.delete("state")
6
+
7
+ bundle["states"] = states.inject([]) { |r,h|
8
+ r << {
9
+ "resolved" => h["isResolved"],
10
+ "value" => h["__content__"],
11
+ }
12
+ }
13
+
14
+ bundle
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module YouTrack
2
- VERSION = "0.4.4"
2
+ VERSION = "0.4.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: you_track
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lane
@@ -166,6 +166,7 @@ files:
166
166
  - lib/you_track/parser/issues_parser.rb
167
167
  - lib/you_track/parser/project_custom_fields_parser.rb
168
168
  - lib/you_track/parser/projects_parser.rb
169
+ - lib/you_track/parser/state_bundle_parser.rb
169
170
  - lib/you_track/parser/user_parser.rb
170
171
  - lib/you_track/version.rb
171
172
  - you_track.gemspec