newsman 0.1.14 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,29 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ # Copyright (c) 2024 Volodya Lombrozo
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # This class builds entire report based on issues and pull requests passed.
4
25
  class Report
5
- def initialize(user, position, title, additional: ReportItems.new([],[]))
26
+ def initialize(user, position, title, additional: ReportItems.new([], []))
6
27
  @user = user
7
28
  @position = position
8
29
  @title = title
@@ -10,14 +31,30 @@ class Report
10
31
  end
11
32
 
12
33
  def build(achievements, plans, risks, date)
13
- start = "From: #{@user}\nSubject: #{week_of_a_year(@title,
14
- date)}\n\nHi all,\n\nLast week achievements:\n#{achievements}\n\nNext week plans:\n#{plans}\n\nRisks:\n#{risks}\n\nBest regards,\n#{@user}\n#{@position}\n#{date}"
15
-
16
- finish = ''
17
- if !@additional.empty?
18
- finish = "\n------\n" + @additional.to_s
19
- end
20
- return start + finish;
34
+ <<~TEMPLATE
35
+ From: #{@user}
36
+ Subject: #{week_of_a_year(@title, date)}
37
+
38
+ Hi all,
39
+
40
+ Last week achievements:
41
+ #{achievements}
42
+
43
+ Next week plans:
44
+ #{plans}
45
+
46
+ Risks:
47
+ #{risks}
48
+
49
+ Best regards,
50
+ #{@user}
51
+ #{@position}
52
+ #{date}
53
+ TEMPLATE
54
+ end
55
+
56
+ def append_additional(report)
57
+ "#{report}\n#{"------\n#{@additional}" unless @additional.empty?}"
21
58
  end
22
59
  end
23
60
 
@@ -26,9 +63,8 @@ def week_of_a_year(project, today)
26
63
  "WEEK #{number} #{project}"
27
64
  end
28
65
 
29
-
66
+ # Report items inner class.
30
67
  class ReportItems
31
-
32
68
  def initialize(prs, issues)
33
69
  @prs = prs || []
34
70
  @issues = issues || []
@@ -41,7 +77,7 @@ class ReportItems
41
77
 
42
78
  def to_s
43
79
  prs_list = @prs.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
44
- issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
45
- return "Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
80
+ issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
81
+ "Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
46
82
  end
47
83
  end
@@ -1,5 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #
4
+ # Copyright (c) 2024 Volodya Lombrozo
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ # This class prints report to a console.
3
25
  class Stdout
4
26
  def print(report)
5
27
  puts 'Print a report to stdout'
@@ -1,5 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Copyright (c) 2024 Volodya Lombrozo
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # This class knows how to print a report to a separate file.
3
24
  class Txtout
4
25
  def initialize(root = '.')
5
26
  @root = root
data/lib/newsman.rb CHANGED
@@ -1,6 +1,27 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ #
5
+ # Copyright (c) 2024 Volodya Lombrozo
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'), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # 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 NONINFINGEMENT. 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, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
4
25
  require 'octokit'
5
26
  require 'openai'
6
27
  require 'dotenv'
@@ -12,7 +33,9 @@ require_relative 'newsman/txt_output'
12
33
  require_relative 'newsman/html_output'
13
34
  require_relative 'newsman/report'
14
35
  require_relative 'newsman/assistant'
36
+ require_relative 'newsman/github'
15
37
 
38
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
16
39
  def generate
17
40
  # Load all options required
18
41
  # Pay attention that some of them have default values.
@@ -26,7 +49,9 @@ def generate
26
49
  options[:username] = u
27
50
  end
28
51
  opts.on('-r', '--repository REPOSITORIES',
29
- "Specify which repositories to include in a report. You can specify several repositories using a comma separator, for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'") do |r|
52
+ 'Specify which repositories to include in a report.'\
53
+ 'You can specify several repositories using a comma separator,'\
54
+ "for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'") do |r|
30
55
  options[:repositories] = r
31
56
  end
32
57
  opts.on('-p', '--position POSITION',
@@ -34,7 +59,8 @@ def generate
34
59
  options[:position] = p
35
60
  end
36
61
  opts.on('-o', '--output OUTPUT',
37
- "Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html', '-o txt' or even '-o html'") do |o|
62
+ 'Output type. Newsman prints a report to a stdout by default.'\
63
+ "You can choose another options like '-o html', '-o txt' or even '-o html'") do |o|
38
64
  options[:output] = o
39
65
  end
40
66
  opts.on('-t', '--title TITLE', 'Project Title. Empty by default') do |t|
@@ -45,118 +71,61 @@ def generate
45
71
  def options.require_option(key, message)
46
72
  raise OptionParser::MissingArgument, message if self[key].nil?
47
73
  end
48
-
49
74
  # Check for required options
50
75
  options.require_option(:name, 'Reporter name is required. Please specify using -n or --name.')
51
76
  options.require_option(:username, 'GitHub username is required. Please specify using -u or --username.')
52
77
  options.require_option(:repositories,
53
- 'GitHub repository is required. Please specify one or several repositories using -r or --repositories.')
78
+ 'GitHub repository is required.'\
79
+ ' Please specify one or several repositories using -r or --repositories.')
54
80
  options[:position] ||= 'Software Developer'
55
81
  options[:output] ||= 'stdout'
56
82
  options[:title] ||= ''
57
83
  all_params = options.map { |key, value| "#{key}: #{value}" }.join(', ')
58
84
  puts "Parsed parameters: #{all_params}"
59
-
60
- # Load all required environment variables
61
- Dotenv.load
62
- Dotenv.require_keys('GITHUB_TOKEN', 'OPENAI_TOKEN')
63
-
64
- # Init all required parameters
65
- # Reporter Info
85
+ load_environment_variables
86
+ # Init all required parameters Reporter Info
66
87
  reporter = options[:name]
67
88
  reporter_position = options[:position]
68
89
  # GitHub
69
90
  github_username = options[:username]
70
91
  github_repositories = options[:repositories].split(',').map { |repo| "repo:#{repo}" }.join(' ')
71
-
72
92
  # Your GitHub personal access token
73
93
  # Make sure it has the 'repo'
74
94
  github_token = ENV['GITHUB_TOKEN']
75
95
  # Your OpenAI personal access token
76
96
  openai_token = ENV['OPENAI_TOKEN']
77
97
  # Create a GitHub client instance with your access token
78
- client = Octokit::Client.new(github_token: github_token)
79
- # Calculate the date one week ago
80
- one_week_ago = date_one_week_ago(Date.today)
81
- one_month_ago = Date.today.prev_month.strftime('%Y-%m-%d')
82
- # Display pull request
83
- query = "is:pr author:#{github_username} created:>=#{one_week_ago} #{github_repositories}"
84
- issues_query = "is:issue is:open author:#{github_username} author:0pdd created:>=#{one_month_ago} #{github_repositories}"
85
- puts "Searching pull requests for #{github_username}."
86
- puts "Newsman uses the following request to GitHub to gather the required information about user activity: '#{query}'"
87
- prs = []
88
- pull_requests = client.search_issues(query)
89
- pull_requests.items.each do |pr|
90
- title = pr.title.to_s
91
- description = pr.body.to_s
92
- repository = pr.repository_url.split('/').last
93
- puts "Found PR in #{repository}: #{title}"
94
- # Create a new PullRequest object and add it to the list
95
- pr = PullRequest.new(repository, title, description, url: pr.html_url)
96
- prs << pr
97
- end
98
- raw_prs = prs
99
- prs = prs.map(&:to_s).join("\n\n\n")
100
- grouped_prs = raw_prs.group_by { |pr| pr.repository }
101
-
102
- puts "Searching issues using the following query: '#{issues_query}'"
103
- issues = []
104
- client.search_issues(issues_query).items.each do |issue|
105
- title = issue.title.to_s
106
- body = issue.body.to_s
107
- repository = issue.repository_url.split('/').last
108
- number = issue.number.to_s
109
- puts "Found issue in #{repository}:[##{number}] #{title}"
110
- issues << if issue.user.login == '0pdd'
111
- PddIssue.new(title, body, repository, number, url: issue.html_url)
112
- else
113
- Issue.new(title, body, repository, number, url: issue.html_url)
114
- end
115
- end
116
- raw_issues = issues
117
- issues = issues.map(&:to_s).join("\n\n\n")
118
- grouped_issues = raw_issues.group_by { |iss| iss.repo }
119
-
98
+ github = Github.new(github_token)
99
+ prs = github.pull_requests(github_username, github_repositories)
100
+ issues = github.issues(github_username, github_repositories)
120
101
  puts "\nNow lets test some aggregation using OpenAI\n\n"
121
- openai_client = OpenAI::Client.new(access_token: openai_token)
122
-
123
102
  assistant = Assistant.new(openai_token)
124
-
125
- old_way = false
126
- if old_way
127
- answer = assistant.old_prev_results(prs)
128
- issues_full_answer = assistant.old_next_plans(issues)
129
- risks_full_answer = assistant.old_risks(prs)
130
- else
131
- puts "Assistant builds a report using a new approach, using groupping"
132
- # Build previous results
133
- answer = ""
134
- grouped_prs.each do |repository, rprs|
135
- puts "Building a results report for the repository: #{repository}"
136
- answer = answer + assistant.prev_results(rprs.map(&:to_s).join("\n\n\n"))
137
- end
138
- # Build next plans
139
- issues_full_answer = ""
140
- grouped_issues.each do |repository, rissues|
141
- puts "Building a future plans report for the repository: #{repository}"
142
- issues_full_answer = issues_full_answer + assistant.next_plans(rissues.map(&:to_s).join("\n\n\n"))
143
- end
144
- # Find risks
145
- risks_full_answer = assistant.risks(prs)
103
+ # Build previous results
104
+ answer = ''
105
+ prs.group_by(&:repository).each do |repository, rprs|
106
+ puts "Building a results report for the repository: #{repository}"
107
+ answer = "#{answer}\n#{assistant.prev_results(join(rprs))}"
146
108
  end
147
-
148
- full_answer = Report.new(
149
- reporter,
150
- reporter_position,
109
+ # Build next plans
110
+ issues_full_answer = ''
111
+ issues.group_by(&:repo).each do |repository, rissues|
112
+ puts "Building a future plans report for the repository: #{repository}"
113
+ issues_full_answer = "#{issues_full_answer}\n#{assistant.next_plans(join(rissues))}"
114
+ end
115
+ # Build report
116
+ report = Report.new(
117
+ reporter,
118
+ reporter_position,
151
119
  options[:title],
152
- additional: ReportItems.new(raw_prs, raw_issues)
153
- ).build(
154
- answer,
155
- issues_full_answer,
156
- risks_full_answer,
157
- Date.today
120
+ additional: ReportItems.new(prs, issues)
158
121
  )
159
-
122
+ full_answer = assistant.format(report.build(
123
+ answer,
124
+ issues_full_answer,
125
+ assistant.risks(join(prs)),
126
+ Date.today
127
+ ))
128
+ full_answer = report.append_additional(full_answer)
160
129
  output_mode = options[:output]
161
130
  puts "Output mode is '#{output_mode}'"
162
131
  if output_mode.eql? 'txt'
@@ -173,20 +142,15 @@ def generate
173
142
  output.print(full_answer)
174
143
  end
175
144
  end
145
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
176
146
 
177
- def date_one_week_ago(today)
178
- # Convert today to a Date object if it's not already
179
- today = Date.parse(today) unless today.is_a?(Date)
180
- # Subtract 7 days to get the date one week ago
181
- one_week_ago = today - 7
182
- # Format the date as "YYYY-MM-DD"
183
- one_week_ago.strftime('%Y-%m-%d')
184
- # Return the formatted date
147
+ def load_environment_variables
148
+ Dotenv.load
149
+ Dotenv.require_keys('GITHUB_TOKEN', 'OPENAI_TOKEN')
185
150
  end
186
151
 
187
- def week_of_a_year(project, today)
188
- number = today.strftime('%U').to_i + 1
189
- "WEEK #{number} #{project}"
152
+ def join(items)
153
+ "[#{items.map(&:to_json).join(',')}]"
190
154
  end
191
155
 
192
156
  # Execute the function only if this script is run directly like `./newsman.rb`
@@ -26,8 +26,13 @@ require_relative '../lib/newsman/assistant'
26
26
 
27
27
  class TestAssistant < Minitest::Test
28
28
  def test_creates_default_assistant
29
- assistant = Assistant::new('test-token');
30
- assert_equal "I'm an assistant that can work with OpenAI client. Please, use me, if you need any help. I'm using gpt-3.5-turbo, with 0.3 temperature.", assistant.say_hello
29
+ assistant = Assistant.new('test-token')
30
+ expected = <<~EXPECTED
31
+ I'm an assistant that can work with OpenAI client.
32
+ Please, use me, if you need any help.
33
+ I'm using gpt-3.5-turbo, with 0.3 temperature.
34
+ EXPECTED
35
+ assert_equal expected,
36
+ assistant.say_hello
31
37
  end
32
38
  end
33
-
data/test/test_htmlout.rb CHANGED
@@ -42,7 +42,7 @@ List is here:<br/>
42
42
 
43
43
  </body>
44
44
  </html>
45
- "
45
+ ".freeze
46
46
 
47
47
  def test_writes_to_a_html_file
48
48
  Dir.mktmpdir do |temp_dir|
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright (c) 2024 Volodya Lombrozo
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../lib/newsman/issues'
26
+
27
+ class TestIssue < Minitest::Test
28
+ def test_converts_issue_to_json
29
+ issue = Issue.new(
30
+ 'AnnotationsApplication.java:32-35: Check default values...',
31
+ 'TEST_BODY',
32
+ 'jeo-maven-plugin',
33
+ 531
34
+ )
35
+ expected = <<~JSON.chomp
36
+ {"number":531,"title":"AnnotationsApplication.java:32-35: Check default values...","description":"TEST_BODY","repository":"jeo-maven-plugin","url":"undefined"}
37
+ JSON
38
+ assert_equal expected, issue.to_json
39
+ end
40
+
41
+ def test_important_issue
42
+ issue = Issue.new(
43
+ 'Important Issue Title',
44
+ 'Important Issue Body',
45
+ 'jeo-maven-plugin',
46
+ 531,
47
+ labels: ['soon']
48
+ )
49
+ assert issue.important?
50
+ end
51
+
52
+ def test_unimportant_issue
53
+ issue = Issue.new(
54
+ 'Unimportant Issue Title',
55
+ 'Unimportant Issue Body',
56
+ 'jeo-maven-plugin',
57
+ 531,
58
+ labels: ['not-soon']
59
+ )
60
+ assert !issue.important?
61
+ end
62
+ end
@@ -25,7 +25,7 @@ require 'minitest/autorun'
25
25
  require_relative '../lib/newsman/issues'
26
26
 
27
27
  class TestPddIssue < Minitest::Test
28
- TEST_BODY = "
28
+ TEST_BODY = <<~BODY
29
29
  The puzzle `531-462261de` from #531 has to be resolved:
30
30
 
31
31
  https://github.com/objectionary/jeo-maven-plugin/blob/5a42b2c9f7e0ff01cbb2c4626e1dc5dc3f8aa7b8/src/it/annotations/src/main/java/org/eolang/jeo/annotations/AnnotationsApplication.java#L32-L35
@@ -34,11 +34,18 @@ class TestPddIssue < Minitest::Test
34
34
 
35
35
  Estimate: 90 minutes, role: DEV.
36
36
 
37
- If you have any technical questions, don't ask me, submit new tickets instead. The task will be \"done\" when the problem is fixed and the text of the puzzle is _removed_ from the source code. Here is more about [PDD](http://www.yegor256.com/2009/03/04/pdd.html) and [about me](http://www.yegor256.com/2017/04/05/pdd-in-action.html).
38
- "
37
+ If you have any technical questions, don't ask me, submit new tickets instead.
38
+ The task will be "done" when the problem is fixed and the text of the puzzle is _removed_ from the source code.
39
+ Here is more about [PDD](http://www.yegor256.com/2009/03/04/pdd.html) and [about me](http://www.yegor256.com/2017/04/05/pdd-in-action.html).
40
+ BODY
39
41
 
40
- EXPECTED_DESCRIPTION = [" * @todo #531:90min Check default values for annotation properties.\n",
41
- " * We still encounter some problems with annotation processing.\n", " * Especially with Autowired annotation from Spring Framework.\n", " * It's relatively simple annotation, but it's not processed correctly.\n", " */\n"].freeze
42
+ EXPECTED_DESCRIPTION = [
43
+ " * @todo #531:90min Check default values for annotation properties.\n",
44
+ " * We still encounter some problems with annotation processing.\n",
45
+ " * Especially with Autowired annotation from Spring Framework.\n",
46
+ " * It's relatively simple annotation, but it's not processed correctly.\n",
47
+ " */\n"
48
+ ].freeze
42
49
 
43
50
  def test_parses_pdd_issue
44
51
  issue = PddIssue.new('AnnotationsApplication.java:32-35: Check default values...',
@@ -46,4 +53,27 @@ class TestPddIssue < Minitest::Test
46
53
  'jeo-maven-plugin', 531)
47
54
  assert_equal(EXPECTED_DESCRIPTION, issue.extract_real_body)
48
55
  end
56
+
57
+ def test_converts_to_json
58
+ issue = PddIssue.new('AnnotationsApplication.java:32-35: Check default values...',
59
+ 'TEST_BODY',
60
+ 'jeo-maven-plugin', 531)
61
+ expected = <<~JSON.chomp
62
+ {"number":531,"title":"AnnotationsApplication.java:32-35: Check default values...","description":"TEST_BODY","repository":"jeo-maven-plugin","url":"undefined"}
63
+ JSON
64
+ assert_equal(
65
+ expected,
66
+ issue.to_json
67
+ )
68
+ end
69
+
70
+ def test_important_issue
71
+ issue = PddIssue.new('Title', 'Body', 'jeo-maven-plugin', 531, labels: ['soon'])
72
+ assert issue.important?
73
+ end
74
+
75
+ def test_unimportant_issue
76
+ issue = PddIssue.new('Title', 'Body', 'jeo-maven-plugin', 531)
77
+ assert !issue.important?
78
+ end
49
79
  end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright (c) 2024 Volodya Lombrozo
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../lib/newsman/pull_request'
26
+
27
+ class TestPullRequest < Minitest::Test
28
+ def test_converts_pr_to_json
29
+ pr = PullRequest.new(
30
+ 'jeo-maven-plugin',
31
+ 'Interesting Title',
32
+ 'Pr description'
33
+ )
34
+ assert_equal(
35
+ '{"title":"Interesting Title","description":"Pr description","repository":"jeo-maven-plugin","url":"undefined"}',
36
+ pr.to_json
37
+ )
38
+ end
39
+ end
data/test/test_report.rb CHANGED
@@ -27,42 +27,50 @@ require_relative '../lib/newsman/issues'
27
27
  require_relative '../lib/newsman/pull_request'
28
28
 
29
29
  class TestReport < Minitest::Test
30
- def test_report
31
- expected = "From: User
32
- Subject: WEEK 11 Project
30
+ REPORT_EXAMPLE = <<~EXPECTED
31
+ From: User
32
+ Subject: WEEK 11 Project
33
+
34
+ Hi all,
33
35
 
34
- Hi all,
36
+ Last week achievements:
37
+ repository-a:
38
+ - Did a lot of for (a) repository
35
39
 
36
- Last week achievements:
37
- repository-a:
38
- - Did a lot of for (a) repository
40
+ Next week plans:
41
+ repository-b:
42
+ - I will do a lot for repository (b)
39
43
 
40
- Next week plans:
41
- repository-b:
42
- - I will do a lot for repository (b)
44
+ Risks:
45
+ - <todo>
43
46
 
44
- Risks:
45
- - <todo>
47
+ Best regards,
48
+ User
49
+ Developer
50
+ 2024-03-14
51
+ EXPECTED
46
52
 
47
- Best regards,
48
- User
49
- Developer
50
- 2024-03-14"
53
+ def test_report
54
+ expected = REPORT_EXAMPLE
51
55
  report = Report.new('User', 'Developer', 'Project')
52
56
  out = report.build("repository-a:\n - Did a lot of for (a) repository",
53
- "repository-b:\n - I will do a lot for repository (b)", '- <todo>', Date.new(2024, 3, 14))
57
+ "repository-b:\n - I will do a lot for repository (b)",
58
+ '- <todo>',
59
+ Date.new(2024, 3, 14))
54
60
  assert_equal expected, out
55
61
  end
56
62
 
57
63
  def test_report_items
58
- expected = "Closed Pull Requests:\n - title: title, repo: repo, url: http://some.url.com\n\nOpen Issues:\n - title: title, repo: repo, number: #123, url: http://google.com\n"
59
- issues = [ Issue::new('title', 'body', 'repo', '123', url: 'http://google.com')]
60
- prs = [ PullRequest::new('repo', 'title', 'body', url: 'http://some.url.com') ]
61
- actual = ReportItems.new(prs, issues).to_s
64
+ expected = <<~EXPECTED
65
+ Closed Pull Requests:
66
+ - title: title, repo: repo, url: http://some.url.com
62
67
 
63
- puts actual
68
+ Open Issues:
69
+ - title: title, repo: repo, number: #123, url: http://google.com, labels: []
70
+ EXPECTED
71
+ issues = [Issue.new('title', 'body', 'repo', '123', url: 'http://google.com')]
72
+ prs = [PullRequest.new('repo', 'title', 'body', url: 'http://some.url.com')]
73
+ actual = ReportItems.new(prs, issues).to_s
64
74
  assert_equal expected, actual
65
75
  end
66
-
67
-
68
76
  end
@@ -22,7 +22,7 @@
22
22
  # SOFTWARE.
23
23
 
24
24
  require 'minitest/autorun'
25
- require_relative '../lib/newsman'
25
+ require_relative '../lib/newsman/github'
26
26
 
27
27
  class TestDateOneWeekAgo < Minitest::Test
28
28
  def test_date_one_week_ago