lazylead 0.6.0 → 0.7.2

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -2
  3. data/.docker/Dockerfile +17 -6
  4. data/.rubocop.yml +102 -1
  5. data/.simplecov +1 -1
  6. data/Guardfile +1 -1
  7. data/Rakefile +6 -3
  8. data/bin/lazylead +3 -1
  9. data/lazylead.gemspec +31 -27
  10. data/lib/lazylead/cc.rb +21 -20
  11. data/lib/lazylead/cli/app.rb +8 -3
  12. data/lib/lazylead/confluence.rb +9 -2
  13. data/lib/lazylead/email.rb +0 -20
  14. data/lib/lazylead/exchange.rb +16 -28
  15. data/lib/lazylead/model.rb +31 -16
  16. data/lib/lazylead/opts.rb +64 -2
  17. data/lib/lazylead/postman.rb +13 -18
  18. data/lib/lazylead/salt.rb +1 -0
  19. data/lib/lazylead/system/jira.rb +9 -2
  20. data/lib/lazylead/task/accuracy/accuracy.rb +10 -14
  21. data/lib/lazylead/task/accuracy/attachment.rb +2 -6
  22. data/lib/lazylead/task/accuracy/logs.rb +9 -4
  23. data/lib/lazylead/task/accuracy/onlyll.rb +147 -0
  24. data/lib/lazylead/task/accuracy/records.rb +1 -1
  25. data/lib/lazylead/task/accuracy/servers.rb +16 -7
  26. data/lib/lazylead/task/accuracy/stacktrace.rb +1 -1
  27. data/lib/lazylead/task/accuracy/testcase.rb +8 -7
  28. data/lib/lazylead/task/fix_version.rb +4 -2
  29. data/lib/lazylead/task/propagate_down.rb +1 -1
  30. data/lib/lazylead/task/svn/diff.rb +13 -12
  31. data/lib/lazylead/task/svn/grep.rb +40 -12
  32. data/lib/lazylead/task/svn/touch.rb +2 -4
  33. data/lib/lazylead/version.rb +1 -1
  34. data/lib/messages/illegal_fixversion_change.erb +8 -2
  35. data/lib/messages/only_ll.erb +107 -0
  36. data/lib/messages/svn_diff.erb +9 -9
  37. data/lib/messages/svn_diff_attachment.erb +19 -9
  38. data/lib/messages/svn_grep.erb +1 -1
  39. data/test/lazylead/cc_test.rb +1 -0
  40. data/test/lazylead/model_test.rb +20 -0
  41. data/test/lazylead/opts_test.rb +47 -0
  42. data/test/lazylead/postman_test.rb +8 -5
  43. data/test/lazylead/smoke_test.rb +13 -0
  44. data/test/lazylead/smtp_test.rb +1 -4
  45. data/test/lazylead/task/accuracy/attachment_test.rb +1 -1
  46. data/test/lazylead/task/accuracy/logs_test.rb +12 -0
  47. data/test/lazylead/task/accuracy/onlyll_test.rb +138 -0
  48. data/test/lazylead/task/accuracy/servers_test.rb +2 -2
  49. data/test/lazylead/task/accuracy/testcase_test.rb +56 -0
  50. data/test/lazylead/task/duedate_test.rb +3 -10
  51. data/test/lazylead/task/fix_version_test.rb +1 -0
  52. data/test/lazylead/task/propagate_down_test.rb +4 -3
  53. data/test/lazylead/task/savepoint_test.rb +9 -6
  54. data/test/lazylead/task/svn/grep_test.rb +43 -1
  55. data/test/test.rb +7 -8
  56. data/upgrades/sqlite/999.testdata.sql +3 -1
  57. metadata +117 -57
@@ -77,7 +77,7 @@
77
77
  .commit * {
78
78
  padding-left: 4px;
79
79
  font-size: 8px;
80
- line-height: 15px;
80
+ line-height: 12px;
81
81
  }
82
82
  </style>
83
83
  <title>SVN log</title>
@@ -89,17 +89,17 @@
89
89
  <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
90
90
  <div class="commit">
91
91
  <% commit.split("\n").reject(&:blank?).each_with_index do |line, index| %>
92
- <% if index.zero? %>
93
- <% details = line.split("|").map(&:strip).reject(&:blank?) %>
94
- <p style="background: gainsboro;">
92
+ <p style="background: gainsboro;">
93
+ <% if index.zero? %>
94
+ <% details = line.split("|").map(&:strip).reject(&:blank?) %>
95
95
  <a href="<%= commit_url %><%= details[0][1..-1] %>"><%= details[0] %></a>
96
96
  by <a href="<%= user %><%= details[1] %>"><%= details[1] %></a>
97
97
  at <span style="color: #275a90;"><%= details[2] %></span>
98
- </p>
99
- <% end %>
100
- <% if index == 1 %>
101
- <p style="background: gainsboro;"><%= line %></p>
102
- <% end %>
98
+ <% end %>
99
+ <% if index == 1 %>
100
+ <span style="padding-left: 4px"><%= line %></span>
101
+ <% end %>
102
+ </p>
103
103
  <% end %>
104
104
  </div>
105
105
  <% end %>
@@ -64,7 +64,7 @@
64
64
  padding: 36px
65
65
  }
66
66
 
67
- .commit {
67
+ .commit, .table-of-contents {
68
68
  min-width: 100%;
69
69
  border-radius: 3.5px;
70
70
  overflow: hidden;
@@ -74,26 +74,36 @@
74
74
  border: 1px solid #BCC6CC;
75
75
  }
76
76
 
77
- .commit * {
77
+ .commit *, .table-of-contents * {
78
78
  padding-left: 4px;
79
79
  font-size: 8px;
80
80
  line-height: 15px;
81
81
  }
82
+
83
+ .table-of-contents {
84
+ border: none;
85
+ }
82
86
  </style>
83
87
  <title>SVN log</title>
84
88
  </head>
85
89
  <body>
86
90
  <p>Hi,</p>
87
- <p>The following file(s) changed since <code><%= since_rev %></code> rev in <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
91
+ <p>Commit(s) since <code><%= since_rev %></code> revision in <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
92
+ <div id="table-of-contents" class="table-of-contents">
93
+ <ul>
94
+ <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
95
+ <% details = commit.split("\n").reject(&:blank?).first.split("|").map(&:strip).reject(&:blank?) %>
96
+ <li><a href="#<%= details[0] %>"><%= details[0] %></a> by <%= details[1] %> at <%= details[2] %></li>
97
+ <% end %>
98
+ </ul>
99
+ </div>
88
100
  <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
89
101
  <div class="commit">
90
102
  <% commit.split("\n").reject(&:blank?).each_with_index do |line, index| %>
91
103
  <% if index.zero? %>
92
104
  <% details = line.split("|").map(&:strip).reject(&:blank?) %>
93
- <p style="background: gainsboro;">
94
- <a href="<%= commit_url %><%= details[0][1 .. -1] %>"><%= details[0] %></a>
95
- by <a href="<%= user %><%= details[1] %>"><%= details[1] %></a>
96
- at <span style="color: #275a90;"><%= details[2] %></span>
105
+ <p style="background: gainsboro;" id="<%= details[0] %>"><a href="<%= commit_url %><%= details[0][1..-1] %>"><%= details[0] %></a> by <a href="<%= user %><%= details[1] %>"><%= details[1] %></a> at <span style="color: #275a90;"><%= details[2] %></span>
106
+ <a href="#table-of-contents">&#8593;</a>
97
107
  </p>
98
108
  <% else %>
99
109
  <% if line.start_with?("+++") || line.start_with?("---") %>
@@ -103,12 +113,12 @@
103
113
  <% elsif line.start_with?("-") %>
104
114
  <p style="<%= "background: lightsalmon;" %>"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
105
115
  <% else %>
106
- <p style="background: gainsboro;"><%= line.gsub(/[<>]/,'<' => '&lt;', '>' => '&gt;') %></p>
116
+ <p style="background: gainsboro;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
107
117
  <% end %>
108
118
  <% end %>
109
119
  <% end %>
110
120
  </div>
111
- <br/><br/><br/>
121
+ <br/>
112
122
  <% end %>
113
123
  <p>Posted by
114
124
  <a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
@@ -93,7 +93,7 @@
93
93
  by <a href="<%= user %><%= commit.author %>"><%= commit.author %></a>
94
94
  at <span style="color: #275a90;"><%= commit.time %></span>
95
95
  </p>
96
- <% commit.lines[2..-1].each do |line| %>
96
+ <% commit.diff(text.split(",")).each do |line| %>
97
97
  <% if line.start_with?("+++") || line.start_with?("---") %>
98
98
  <p style="background: gainsboro;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
99
99
  <% elsif text.split(",").any? { |t| line.include? t } %>
@@ -49,6 +49,7 @@ module Lazylead
49
49
  assert Lazylead::CC.new.undefined? "type" => " "
50
50
  end
51
51
  end
52
+
52
53
  class PlainCcTest < Lazylead::Test
53
54
  test "cc has valid email" do
54
55
  assert_equal "a@fake.com", Lazylead::PlainCC.new("a@fake.com").cc.first
@@ -72,5 +72,25 @@ module Lazylead
72
72
  )
73
73
  assert_equal "value", ORM::Task.find(171).props["envkey"]
74
74
  end
75
+
76
+ test "task properties are parsed despite on wrong config" do
77
+ CLI::App.new(Log.new, NoSchedule.new).run(
78
+ home: ".",
79
+ sqlite: "test/resources/#{no_ext(__FILE__)}.#{__method__}.db",
80
+ vcs4sql: "upgrades/sqlite",
81
+ testdata: true
82
+ )
83
+ refute ORM::Task.find(260).to_h?
84
+ end
85
+
86
+ test "second ticketing system is found" do
87
+ CLI::App.new(Log.new, NoSchedule.new).run(
88
+ home: ".",
89
+ sqlite: "test/resources/#{no_ext(__FILE__)}.#{__method__}.db",
90
+ vcs4sql: "upgrades/sqlite",
91
+ testdata: true
92
+ )
93
+ assert_kind_of Jira, ORM::Task.find(270).second_sys
94
+ end
75
95
  end
76
96
  end
@@ -66,5 +66,52 @@ module Lazylead
66
66
  test "except keys" do
67
67
  assert_equal 1, Opts.new("one" => "1", "two" => "2").except("one").size
68
68
  end
69
+
70
+ test "attachment is blank" do
71
+ assert_empty Opts.new("attachments" => "").msg_attachments
72
+ end
73
+
74
+ test "attachment is nil" do
75
+ assert_empty Opts.new("attachments" => nil).msg_attachments
76
+ end
77
+
78
+ test "attachment is absent" do
79
+ assert_empty Opts.new({}).msg_attachments
80
+ end
81
+
82
+ test "attachment is present" do
83
+ assert_equal %w[readme.md],
84
+ Opts.new("attachments" => "readme.md").msg_attachments
85
+ end
86
+
87
+ test "attachments are present" do
88
+ assert_equal %w[readme.md license.txt],
89
+ Opts.new("attachments" => "readme.md,license.txt")
90
+ .msg_attachments
91
+ end
92
+
93
+ test "attachments are present as symbol" do
94
+ assert_equal %w[readme.md license.txt],
95
+ Opts.new(attachments: " readme.md , license.txt ")
96
+ .msg_attachments
97
+ end
98
+
99
+ test "attachments is present as array" do
100
+ assert_equal %w[readme.md license.txt],
101
+ Opts.new(attachments: %w[readme.md license.txt])
102
+ .msg_attachments
103
+ end
104
+
105
+ test "value has numeric value" do
106
+ assert Opts.new("key" => "1").numeric? "key"
107
+ end
108
+
109
+ test "text value is not a numeric" do
110
+ refute Opts.new("key" => "val").numeric? "key"
111
+ end
112
+
113
+ test "nil is not a numeric" do
114
+ refute Opts.new("key" => nil).numeric? "key"
115
+ end
69
116
  end
70
117
  end
@@ -24,6 +24,7 @@
24
24
 
25
25
  require_relative "../test"
26
26
  require_relative "../../lib/lazylead/log"
27
+ require_relative "../../lib/lazylead/opts"
27
28
  require_relative "../../lib/lazylead/salt"
28
29
  require_relative "../../lib/lazylead/smtp"
29
30
  require_relative "../../lib/lazylead/postman"
@@ -46,11 +47,13 @@ module Lazylead
46
47
  smtp_pass: ENV["LL_SMTP_PASS"]
47
48
  ).enable
48
49
  Postman.new.send(
49
- "to" => ENV["LL_SMTP_TO"],
50
- "from" => ENV["LL_SMTP_FROM"],
51
- "attachments" => ["readme.md"],
52
- "subject" => "[LL] Attachments",
53
- "template" => "lib/messages/savepoint.erb"
50
+ Opts.new(
51
+ "to" => ENV["LL_SMTP_TO"],
52
+ "from" => ENV["LL_SMTP_FROM"],
53
+ "attachments" => ["readme.md"],
54
+ "subject" => "[LL] Attachments",
55
+ "template" => "lib/messages/savepoint.erb"
56
+ )
54
57
  )
55
58
  end
56
59
  end
@@ -22,6 +22,8 @@
22
22
  # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
23
23
  # OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
+ require "inifile"
26
+ require "tempfile"
25
27
  require_relative "../test"
26
28
 
27
29
  module Lazylead
@@ -34,5 +36,16 @@ module Lazylead
34
36
  test "ENV has no key" do
35
37
  refute env? "c"
36
38
  end
39
+ test "ini file found" do
40
+ Tempfile.create do |f|
41
+ f << "EnvTest=value"
42
+ f.flush
43
+ IniFile.new(filename: f).each { |_, k, v| ENV[k] = v }
44
+ assert_equal "value", ENV["EnvTest"]
45
+ end
46
+ end
47
+ test "ini file not found" do
48
+ assert_empty IniFile.new(filename: "absent.ini").to_h
49
+ end
37
50
  end
38
51
  end
@@ -38,10 +38,7 @@ module Lazylead
38
38
  subject "The fake!"
39
39
  body "Fake body"
40
40
  end
41
- assert_equal 1,
42
- Mail::TestMailer.deliveries
43
- .filter { |m| m.subject.eql? "The fake!" }
44
- .length
41
+ assert_equal(1, Mail::TestMailer.deliveries.count { |m| m.subject.eql? "The fake!" })
45
42
  end
46
43
 
47
44
  # @todo #43/DEV email-related properties should be exported to the CI env
@@ -34,7 +34,7 @@ module Lazylead
34
34
  super "", 0, ""
35
35
  end
36
36
 
37
- def matching(attach)
37
+ def matches?(attach)
38
38
  "ConfigServerLogWithException.txt".eql? attach.attrs["filename"]
39
39
  end
40
40
  end
@@ -134,5 +134,17 @@ module Lazylead
134
134
  )
135
135
  )
136
136
  end
137
+
138
+ test "filename contain word logs" do
139
+ assert Logs.new.passed(
140
+ OpenStruct.new(
141
+ attachments: [
142
+ OpenStruct.new(
143
+ attrs: { "size" => 10_241, "filename" => "the some logs]here.gz" }
144
+ )
145
+ ]
146
+ )
147
+ )
148
+ end
137
149
  end
138
150
  end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The MIT License
4
+ #
5
+ # Copyright (c) 2019-2020 Yurii Dubinka
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"),
9
+ # to deal in the Software without restriction, including without limitation
10
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ # and/or sell copies of the Software, and to permit persons to whom
12
+ # the Software is furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
23
+ # OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ require_relative "../../../test"
26
+ require_relative "../../../../lib/lazylead/opts"
27
+ require_relative "../../../../lib/lazylead/smtp"
28
+ require_relative "../../../../lib/lazylead/postman"
29
+ require_relative "../../../../lib/lazylead/system/jira"
30
+ require_relative "../../../../lib/lazylead/task/accuracy/onlyll"
31
+
32
+ module Lazylead
33
+ class OnlyLLTest < Lazylead::Test
34
+ # In current tests the grid label is 'PullRequest'.
35
+ # The default grid labels are 0%, 10%, 20%, etc., the reason why
36
+ # 'PullRequest' label is used here as we don't have 0%, 10%, etc.
37
+ # on https://jira.spring.io.
38
+ test "grid label found" do
39
+ assert Labels.new(
40
+ NoAuthJira.new("https://jira.spring.io").issues("key=XD-3725").first,
41
+ Opts.new("grid" => "PullRequest, ,")
42
+ ).exists?
43
+ end
44
+
45
+ test "grid label set by ll" do
46
+ assert Labels.new(
47
+ NoAuthJira.new("https://jira.spring.io")
48
+ .issues("key=XD-3725", expand: "changelog")
49
+ .first,
50
+ Opts.new("grid" => "PullRequest", "author" => "grussell")
51
+ ).valid?
52
+ end
53
+
54
+ test "email notification" do
55
+ Lazylead::Smtp.new.enable
56
+ Lazylead::Task::OnlyLL.new.run(
57
+ NoAuthJira.new("https://jira.spring.io"),
58
+ Postman.new,
59
+ Opts.new(
60
+ "from" => "ll@fake.com",
61
+ "to" => "lead@fake.com",
62
+ "grid" => "PullRequest",
63
+ "author" => "LL",
64
+ "jql" => "key=XD-3725",
65
+ "max_results" => 200,
66
+ "subject" => "[LL] Only",
67
+ "fields" => "priority,summary,reporter,labels",
68
+ "template" => "lib/messages/only_ll.erb"
69
+ )
70
+ )
71
+ assert_email "[LL] Only",
72
+ %w[XD-3725 Blocker EmbeddedHeadersMessageConverter]
73
+ end
74
+
75
+ test "detect score" do
76
+ assert_equal "PullRequest",
77
+ Labels.new(
78
+ NoAuthJira.new("https://jira.spring.io")
79
+ .issues("key=XD-3725", expand: "changelog")
80
+ .first,
81
+ Opts.new(
82
+ "grid" => "PullRequest",
83
+ "author" => "grussell"
84
+ )
85
+ ).score
86
+ end
87
+
88
+ test "multiple scores in the same ticket" do
89
+ assert_equal "10%",
90
+ Labels.new(
91
+ Struct.new(:key) do
92
+ def history
93
+ [{ "id" => "287906", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=sy", "name" => "sy", "key" => "sy", "emailAddress" => "san at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=32" }, "displayName" => "sy an", "active" => true, "timeZone" => "America/Los_Angeles" }, "created" => "2015-12-17T18:12:35.853+0000", "items" => [{ "field" => "Fix Version", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "15424", "toString" => "1.3.1" }] }, { "id" => "287913", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=ll", "name" => "ll", "key" => "ll", "emailAddress" => "ll at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=32" }, "displayName" => "Y LL", "active" => true, "timeZone" => "America/New_York" }, "created" => "2015-12-17T18:14:34.085+0000", "items" => [{ "field" => "assignee", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "ll", "toString" => "Y LL" }] }, { "id" => "287915", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=sy", "name" => "sy", "key" => "sy", "emailAddress" => "san at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=32" }, "displayName" => "sy an", "active" => true, "timeZone" => "America/Los_Angeles" }, "created" => "2015-12-17T18:19:36.118+0000", "items" => [{ "field" => "Sprint", "fieldtype" => "custom", "from" => nil, "fromString" => nil, "to" => "106", "toString" => "Sprint 64" }] }, { "id" => "287916", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=sy", "name" => "sy", "key" => "sy", "emailAddress" => "san at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=32" }, "displayName" => "sy an", "active" => true, "timeZone" => "America/Los_Angeles" }, "created" => "2015-12-17T18:19:36.162+0000", "items" => [{ "field" => "Rank", "fieldtype" => "custom", "from" => "", "fromString" => "", "to" => "", "toString" => "Ranked higher" }] }, { "id" => "287921", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=ll", "name" => "ll", "key" => "ll", "emailAddress" => "ll at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=32" }, "displayName" => "Y LL", "active" => true, "timeZone" => "America/New_York" }, "created" => "2015-12-17T18:30:47.508+0000", "items" => [{ "field" => "status", "fieldtype" => "jira", "from" => "10000", "fromString" => "To Do", "to" => "3", "toString" => "In Progress" }] }, { "id" => "287922", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=ll", "name" => "ll", "key" => "ll", "emailAddress" => "ll at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/0037f772e271b0d90bd62361768cb820?d=mm&s=32" }, "displayName" => "Y LL", "active" => true, "timeZone" => "America/New_York" }, "created" => "2015-12-17T18:31:54.137+0000", "items" => [{ "field" => "Pull Request URL", "fieldtype" => "custom", "from" => nil, "fromString" => nil, "to" => nil, "toString" => "https://github.com/spring-projects/spring-xd/pull/1872" }, { "field" => "labels", "fieldtype" => "jira", "from" => nil, "fromString" => "", "to" => nil, "toString" => "10% 20%" }] }, { "id" => "288214", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=sy", "name" => "sy", "key" => "sy", "emailAddress" => "san at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=32" }, "displayName" => "sy an", "active" => true, "timeZone" => "America/Los_Angeles" }, "created" => "2015-12-25T00:16:09.649+0000", "items" => [{ "field" => "status", "fieldtype" => "jira", "from" => "3", "fromString" => "In Progress", "to" => "10006", "toString" => "In PR" }] }, { "id" => "288215", "author" => { "self" => "https://jira.spring.io/rest/api/2/user?username=sy", "name" => "sy", "key" => "sy", "emailAddress" => "san at pivotal dot io", "avatarUrls" => { "48x48" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=48", "24x24" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=24", "16x16" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=16", "32x32" => "https://www.gravatar.com/avatar/f0373ebca801ca4b2746732b451f497c?d=mm&s=32" }, "displayName" => "sy an", "active" => true, "timeZone" => "America/Los_Angeles" }, "created" => "2015-12-25T00:16:17.499+0000", "items" => [{ "field" => "Actual Story Points", "fieldtype" => "custom", "from" => nil, "fromString" => nil, "to" => nil, "toString" => "1" }, { "field" => "resolution", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "8", "toString" => "Complete" }, { "field" => "status", "fieldtype" => "jira", "from" => "10006", "fromString" => "In PR", "to" => "10001", "toString" => "Done" }] }]
94
+ end
95
+ end.new("XD-3725"),
96
+ Opts.new("grid" => "10%,20%,30%", "author" => "ll")
97
+ ).score
98
+ end
99
+
100
+ test "sort of percents" do
101
+ assert_equal %w[10% 20% 30%], %w[30% 10% 20%].sort
102
+ end
103
+
104
+ test "ensure that violators found" do
105
+ assert_equal "Aron set 40%",
106
+ Labels.new(
107
+ Struct.new(:key) do
108
+ def history
109
+ [
110
+ { "author" => { "name" => "sy", "key" => "sy", "displayName" => "S N" }, "items" => [{ "field" => "Fix Version", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "15424", "toString" => "1.3.1" }] },
111
+ { "author" => { "name" => "ll", "key" => "ll", "displayName" => "L L" }, "items" => [{ "field" => "assignee", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "ll", "toString" => "ll" }] },
112
+ { "author" => { "name" => "sy", "key" => "sy", "displayName" => "S N" }, "items" => [{ "field" => "Sprint", "fieldtype" => "custom", "from" => nil, "fromString" => nil, "to" => "106", "toString" => "Sprint 64" }] },
113
+ { "author" => { "name" => "sy", "key" => "sy", "displayName" => "S N" }, "items" => [{ "field" => "Rank", "fieldtype" => "custom", "from" => "", "fromString" => "", "to" => "", "toString" => "Ranked higher" }] },
114
+ { "author" => { "name" => "ll", "key" => "ll", "displayName" => "L L" }, "items" => [{ "field" => "status", "fieldtype" => "jira", "from" => "10000", "fromString" => "To Do", "to" => "3", "toString" => "In Progress" }] },
115
+ { "author" => { "name" => "ll", "key" => "ll", "displayName" => "L L" }, "items" => [{ "field" => "assignee", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "ll", "toString" => "ll" }, { "field" => "labels", "fieldtype" => "jira", "from" => nil, "fromString" => "", "to" => nil, "toString" => "20%" }] },
116
+ { "author" => { "name" => "sy", "key" => "sy", "displayName" => "S N" }, "items" => [{ "field" => "Actual Story Points", "fieldtype" => "custom", "from" => nil, "fromString" => nil, "to" => nil, "toString" => "1" }, { "field" => "resolution", "fieldtype" => "jira", "from" => nil, "fromString" => nil, "to" => "8", "toString" => "Complete" }, { "field" => "status", "fieldtype" => "jira", "from" => "10006", "fromString" => "In PR", "to" => "10001", "toString" => "Done" }] },
117
+ { "author" => { "name" => "ap", "key" => "ap", "displayName" => "Aron" }, "items" => [{ "field" => "labels", "fieldtype" => "jira", "from" => nil, "fromString" => "", "to" => nil, "toString" => "abc 40%" }] },
118
+ { "author" => { "name" => "sy", "key" => "sy", "displayName" => "S N" }, "items" => [{ "field" => "status", "fieldtype" => "jira", "from" => "3", "fromString" => "In Progress", "to" => "10006", "toString" => "In PR" }] }
119
+ ]
120
+ end
121
+ end.new("XD-3725"),
122
+ Opts.new("grid" => "10%,20%,30%,40%", "author" => "ll")
123
+ ).violators.first
124
+ end
125
+
126
+ test "violators should consider already existing LL grid labels" do
127
+ assert_equal "Aron set 40%",
128
+ Labels.new(
129
+ Struct.new(:key) do
130
+ def history
131
+ [{ "author" => { "name" => "ap", "key" => "ap", "displayName" => "Aron" }, "items" => [{ "field" => "labels", "fromString" => "0%", "toString" => "0% abc 40%" }] }]
132
+ end
133
+ end.new("XD-3725"),
134
+ Opts.new("grid" => "10%,20%,30%,40%", "author" => "ll")
135
+ ).violators.first
136
+ end
137
+ end
138
+ end
@@ -42,7 +42,7 @@ module Lazylead
42
42
  end
43
43
 
44
44
  test "url to failed entity found in description" do
45
- assert Servers.new(envs: [%r{(http|https):\/\/\w+\:\d+\/.{10,}}]).passed(
45
+ assert Servers.new(envs: [%r{(http|https)://\w+:\d+/.{10,}}]).passed(
46
46
  Task.new(
47
47
  "1. Open the dedicated app
48
48
  2. Click on https://server:6900/object?id=2000
@@ -53,7 +53,7 @@ module Lazylead
53
53
  end
54
54
 
55
55
  test "url to failed entity not present in description" do
56
- refute Servers.new(envs: [%r{(http|https):\/\/\w+\:\d+\/.{10,}}]).passed(
56
+ refute Servers.new(envs: [%r{(http|https)://\w+:\d+/.{10,}}]).passed(
57
57
  Task.new(
58
58
  "1. Open the dedicated app
59
59
  2. Click on https://server:6900/