newsman 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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