github_changelog_generator 1.15.0.pre.beta → 1.16.1

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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +332 -285
  4. data/Rakefile +1 -1
  5. data/bin/git-generate-changelog +1 -1
  6. data/lib/github_changelog_generator.rb +10 -6
  7. data/lib/github_changelog_generator/generator/entry.rb +218 -0
  8. data/lib/github_changelog_generator/generator/generator.rb +124 -125
  9. data/lib/github_changelog_generator/generator/generator_fetcher.rb +139 -23
  10. data/lib/github_changelog_generator/generator/generator_processor.rb +59 -27
  11. data/lib/github_changelog_generator/generator/generator_tags.rb +25 -21
  12. data/lib/github_changelog_generator/generator/section.rb +124 -0
  13. data/lib/github_changelog_generator/helper.rb +1 -1
  14. data/lib/github_changelog_generator/octo_fetcher.rb +233 -96
  15. data/lib/github_changelog_generator/options.rb +74 -2
  16. data/lib/github_changelog_generator/parser.rb +118 -74
  17. data/lib/github_changelog_generator/parser_file.rb +7 -3
  18. data/lib/github_changelog_generator/reader.rb +2 -2
  19. data/lib/github_changelog_generator/task.rb +4 -3
  20. data/lib/github_changelog_generator/version.rb +1 -1
  21. data/man/git-generate-changelog.1 +144 -45
  22. data/man/git-generate-changelog.1.html +157 -84
  23. data/man/git-generate-changelog.html +19 -7
  24. data/man/git-generate-changelog.md +151 -84
  25. data/spec/files/github-changelog-generator.md +114 -114
  26. data/spec/{install-gem-in-bundler.gemfile → install_gem_in_bundler.gemfile} +2 -0
  27. data/spec/spec_helper.rb +2 -6
  28. data/spec/unit/generator/entry_spec.rb +766 -0
  29. data/spec/unit/generator/generator_processor_spec.rb +103 -41
  30. data/spec/unit/generator/generator_spec.rb +47 -0
  31. data/spec/unit/generator/generator_tags_spec.rb +51 -24
  32. data/spec/unit/generator/section_spec.rb +34 -0
  33. data/spec/unit/octo_fetcher_spec.rb +247 -197
  34. data/spec/unit/options_spec.rb +24 -0
  35. data/spec/unit/parse_file_spec.rb +2 -2
  36. data/spec/unit/reader_spec.rb +4 -4
  37. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
  38. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -1
  39. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -1
  40. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -1
  41. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -1
  42. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -1
  43. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -1
  44. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -1
  45. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -1
  46. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -1
  47. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -1
  48. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -1
  49. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -1
  50. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -1
  51. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -1
  52. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -1
  53. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -1
  54. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -1
  55. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -1
  56. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -1
  57. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -1
  58. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -1
  59. metadata +71 -38
  60. data/bin/ghclgen +0 -5
  61. data/lib/github_changelog_generator/generator/generator_generation.rb +0 -180
  62. data/spec/unit/generator/generator_generation_spec.rb +0 -73
@@ -2,78 +2,140 @@
2
2
 
3
3
  module GitHubChangelogGenerator
4
4
  describe Generator do
5
- let(:default_options) { GitHubChangelogGenerator::Parser.default_options }
5
+ let(:default_options) { GitHubChangelogGenerator::Parser.default_options.merge(verbose: false) }
6
6
  let(:options) { {} }
7
7
  let(:generator) { described_class.new(default_options.merge(options)) }
8
-
9
8
  let(:bad_label) { { "name" => "BAD" } }
10
- let(:bad_issue) { { "labels" => [bad_label] } }
11
9
  let(:good_label) { { "name" => "GOOD" } }
12
- let(:good_issue) { { "labels" => [good_label] } }
13
- let(:unlabeled_issue) { { "labels" => [] } }
14
- let(:issues) { [bad_issue, good_issue, unlabeled_issue] }
15
10
 
16
- describe "#exclude_issues_by_labels" do
17
- subject do
18
- generator.exclude_issues_by_labels(issues)
19
- end
11
+ describe "pull requests" do
12
+ let(:bad_pull_request) { { "pull_request" => {}, "labels" => [bad_label] } }
13
+ let(:good_pull_request) { { "pull_request" => {}, "labels" => [good_label] } }
14
+ let(:unlabeled_pull_request) { { "pull_request" => {}, "labels" => [] } }
15
+ let(:pull_requests) { [bad_pull_request, good_pull_request, unlabeled_pull_request] }
20
16
 
21
- let(:expected_issues) { issues }
17
+ describe "#filter_wo_labels" do
18
+ subject do
19
+ generator.filter_wo_labels(pull_requests)
20
+ end
22
21
 
23
- it { is_expected.to eq(expected_issues) }
22
+ let(:expected_pull_requests) { pull_requests }
24
23
 
25
- context "when 'exclude_lables' is provided" do
26
- let(:options) { { exclude_labels: %w[BAD BOO] } }
27
- let(:expected_issues) { [good_issue, unlabeled_issue] }
24
+ it { is_expected.to eq(expected_pull_requests) }
28
25
 
29
- it { is_expected.to eq(expected_issues) }
30
- end
26
+ context "when 'add_pr_wo_labels' is false" do
27
+ let(:options) { { add_pr_wo_labels: false } }
28
+ let(:expected_pull_requests) { [bad_pull_request, good_pull_request] }
31
29
 
32
- context "with no option given" do
33
- subject(:generator) { described_class.new }
34
- it "passes everything through when no option given" do
35
- result = generator.exclude_issues_by_labels(issues)
30
+ it { is_expected.to eq(expected_pull_requests) }
31
+ end
36
32
 
37
- expect(result).to eq(issues)
33
+ context "when 'add_pr_wo_labels' is true" do
34
+ let(:options) { { add_pr_wo_labels: true } }
35
+
36
+ it { is_expected.to eq(expected_pull_requests) }
38
37
  end
39
38
  end
40
39
  end
41
40
 
42
- describe "#get_filtered_issues" do
43
- subject do
44
- generator.get_filtered_issues(issues)
45
- end
46
-
47
- let(:expected_issues) { issues }
41
+ describe "issues" do
42
+ let(:bad_issue) { { "labels" => [bad_label] } }
43
+ let(:good_issue) { { "labels" => [good_label] } }
44
+ let(:unlabeled_issue) { { "labels" => [] } }
45
+ let(:issues) { [bad_issue, good_issue, unlabeled_issue] }
48
46
 
49
- it { is_expected.to eq(expected_issues) }
47
+ describe "#filter_wo_labels" do
48
+ subject do
49
+ generator.filter_wo_labels(issues)
50
+ end
50
51
 
51
- context "when 'exclude_labels' is provided" do
52
- let(:options) { { exclude_labels: %w[BAD BOO] } }
53
- let(:expected_issues) { [good_issue, unlabeled_issue] }
52
+ let(:expected_issues) { issues }
54
53
 
55
54
  it { is_expected.to eq(expected_issues) }
55
+
56
+ context "when 'add_issues_wo_labels' is false" do
57
+ let(:options) { { add_issues_wo_labels: false } }
58
+ let(:expected_issues) { [bad_issue, good_issue] }
59
+
60
+ it { is_expected.to eq(expected_issues) }
61
+ end
62
+
63
+ context "when 'add_issues_wo_labels' is true" do
64
+ let(:options) { { add_issues_wo_labels: true } }
65
+
66
+ it { is_expected.to eq(expected_issues) }
67
+ end
56
68
  end
57
69
 
58
- context "when 'add_issues_wo_labels' is false" do
59
- let(:options) { { add_issues_wo_labels: false } }
60
- let(:expected_issues) { [bad_issue, good_issue] }
70
+ describe "#exclude_issues_by_labels" do
71
+ subject do
72
+ generator.exclude_issues_by_labels(issues)
73
+ end
74
+
75
+ let(:expected_issues) { issues }
61
76
 
62
77
  it { is_expected.to eq(expected_issues) }
63
78
 
64
- context "with 'exclude_labels'" do
65
- let(:options) { { add_issues_wo_labels: false, exclude_labels: %w[GOOD] } }
66
- let(:expected_issues) { [bad_issue] }
79
+ context "when 'exclude_labels' is provided" do
80
+ let(:options) { { exclude_labels: %w[BAD BOO] } }
81
+ let(:expected_issues) { [good_issue, unlabeled_issue] }
67
82
 
68
83
  it { is_expected.to eq(expected_issues) }
69
84
  end
85
+
86
+ context "with no option given" do
87
+ subject(:generator) { described_class.new }
88
+ it "passes everything through when no option given" do
89
+ result = generator.exclude_issues_by_labels(issues)
90
+
91
+ expect(result).to eq(issues)
92
+ end
93
+ end
70
94
  end
71
95
 
72
- context "when 'include_labels' is specified" do
73
- let(:options) { { include_labels: %w[GOOD] } }
74
- let(:expected_issues) { [good_issue] }
96
+ describe "#get_filtered_issues" do
97
+ subject do
98
+ generator.get_filtered_issues(issues)
99
+ end
100
+
101
+ let(:expected_issues) { issues }
75
102
 
76
103
  it { is_expected.to eq(expected_issues) }
104
+
105
+ context "when 'exclude_labels' is provided" do
106
+ let(:options) { { exclude_labels: %w[BAD BOO] } }
107
+ let(:expected_issues) { [good_issue, unlabeled_issue] }
108
+
109
+ it { is_expected.to eq(expected_issues) }
110
+ end
111
+
112
+ context "when 'add_issues_wo_labels' is false" do
113
+ let(:options) { { add_issues_wo_labels: false } }
114
+ let(:expected_issues) { [bad_issue, good_issue] }
115
+
116
+ it { is_expected.to eq(expected_issues) }
117
+
118
+ context "with 'exclude_labels'" do
119
+ let(:options) { { add_issues_wo_labels: false, exclude_labels: %w[GOOD] } }
120
+ let(:expected_issues) { [bad_issue] }
121
+
122
+ it { is_expected.to eq(expected_issues) }
123
+ end
124
+
125
+ context "with 'include_labels'" do
126
+ let(:options) { { add_issues_wo_labels: false, include_labels: %w[GOOD] } }
127
+ let(:expected_issues) { [good_issue] }
128
+
129
+ it { is_expected.to eq(expected_issues) }
130
+ end
131
+ end
132
+
133
+ context "when 'include_labels' is specified" do
134
+ let(:options) { { include_labels: %w[GOOD] } }
135
+ let(:expected_issues) { [good_issue, unlabeled_issue] }
136
+
137
+ it { is_expected.to eq(expected_issues) }
138
+ end
77
139
  end
78
140
  end
79
141
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "github_changelog_generator/generator/generator"
4
+
5
+ RSpec.describe GitHubChangelogGenerator::Generator do
6
+ let(:header) { "# Changelog" }
7
+ let(:generator) { described_class.new({ header: header }) }
8
+ let(:content) do
9
+ <<~'BASE'
10
+ ## [1.3.10](https://github.com/xxx/yyy/tree/1.3.10) (2015-03-18)
11
+
12
+ [Full Changelog](https://github.com/xxx/yyy/compare/1.3.9...1.3.10)
13
+
14
+ **Fixed bugs:**
15
+
16
+
17
+ BASE
18
+ end
19
+ let(:footer) do
20
+ <<~CREDIT
21
+ \\* *This Changelog was automatically generated \
22
+ by [github_changelog_generator]\
23
+ (https://github.com/github-changelog-generator/github-changelog-generator)*
24
+ CREDIT
25
+ end
26
+
27
+ context "when the given base file has previously appended template messages" do
28
+ describe "#remove_old_fixed_string" do
29
+ it "removes old template headers and footers" do
30
+ log = +"#{header}\n\n#{header}\n#{header}#{content}\n\n#{footer}\n#{footer}#{footer}"
31
+
32
+ expect(generator.send(:remove_old_fixed_string, log)).to eq content
33
+ end
34
+ end
35
+ end
36
+
37
+ context "when plain contents string was given" do
38
+ describe "#insert_fixed_string" do
39
+ it "append template messages at header and footer" do
40
+ log = String.new(content)
41
+ ans = "#{header}\n\n#{content}\n\n#{footer}"
42
+
43
+ expect(generator.send(:insert_fixed_string, log)).to eq ans
44
+ end
45
+ end
46
+ end
47
+ end
@@ -13,11 +13,38 @@ describe GitHubChangelogGenerator::Generator do
13
13
  end
14
14
  end
15
15
 
16
+ describe "#detect_link_tag_time" do
17
+ let(:newer_tag) { nil }
18
+
19
+ let(:default_options) { GitHubChangelogGenerator::Parser.default_options.merge(verbose: false) }
20
+ let(:options) do
21
+ {
22
+ future_release: "2.0.0"
23
+ }
24
+ end
25
+ let(:generator) { described_class.new(default_options.merge(options)) }
26
+
27
+ subject do
28
+ generator.detect_link_tag_time(newer_tag)
29
+ end
30
+
31
+ context "When the local date is not the same as the UTC date" do
32
+ before do
33
+ # 2020-12-27T17:00:00-10:00 is 2020-12-28T03:00:00Z.
34
+ # GitHub API date & time use UTC, so this instant when converted as a
35
+ # date should be 2020-12-28.
36
+ expect(Time).to receive(:new).and_return(Time.new(2020, 12, 27, 17, 0, 0, "-10:00"))
37
+ end
38
+
39
+ it { is_expected.to eq(["2.0.0", "2.0.0", Time.gm(2020, 12, 28, 3)]) }
40
+ end
41
+ end
42
+
16
43
  describe "#tag_section_mapping" do
17
44
  let(:all_tags) { tags_from_strings(%w[8 7 6 5 4 3 2 1]) }
18
45
  let(:sorted_tags) { all_tags }
19
46
 
20
- let(:default_options) { GitHubChangelogGenerator::Parser.default_options }
47
+ let(:default_options) { GitHubChangelogGenerator::Parser.default_options.merge(verbose: false) }
21
48
  let(:options) { {} }
22
49
  let(:generator) { described_class.new(default_options.merge(options)) }
23
50
 
@@ -57,10 +84,10 @@ describe GitHubChangelogGenerator::Generator do
57
84
  shared_examples_for "a changelog with some exclusions" do
58
85
  let(:expected_mapping) do
59
86
  {
60
- tag_with_name("8") => [tag_with_name("7"), tag_with_name("8")],
61
- tag_with_name("6") => [tag_with_name("5"), tag_with_name("6")],
87
+ tag_with_name("8") => [tag_with_name("6"), tag_with_name("8")],
88
+ tag_with_name("6") => [tag_with_name("4"), tag_with_name("6")],
62
89
  tag_with_name("4") => [tag_with_name("3"), tag_with_name("4")],
63
- tag_with_name("3") => [tag_with_name("2"), tag_with_name("3")],
90
+ tag_with_name("3") => [tag_with_name("1"), tag_with_name("3")],
64
91
  tag_with_name("1") => [nil, tag_with_name("1")]
65
92
  }
66
93
  end
@@ -130,6 +157,22 @@ describe GitHubChangelogGenerator::Generator do
130
157
  end
131
158
  end
132
159
 
160
+ describe "#filter_included_tags_regex" do
161
+ subject { generator.filter_included_tags(tags_from_strings(%w[1 2 3])) }
162
+
163
+ context "with matching regex" do
164
+ let(:generator) { GitHubChangelogGenerator::Generator.new(include_tags_regex: "[23]") }
165
+ it { is_expected.to be_a Array }
166
+ it { is_expected.to match_array(tags_from_strings(%w[2 3])) }
167
+ end
168
+
169
+ context "with non-matching regex" do
170
+ let(:generator) { GitHubChangelogGenerator::Generator.new(include_tags_regex: "[45]") }
171
+ it { is_expected.to be_a Array }
172
+ it { is_expected.to match_array(tags_from_strings(%w[])) }
173
+ end
174
+ end
175
+
133
176
  describe "#filter_excluded_tags" do
134
177
  subject { generator.filter_excluded_tags(tags_from_strings(%w[1 2 3])) }
135
178
 
@@ -191,24 +234,16 @@ describe GitHubChangelogGenerator::Generator do
191
234
 
192
235
  context "with invalid since tag" do
193
236
  let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") }
194
- it { is_expected.to be_a Array }
195
- it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
237
+ it { expect { subject }.to raise_error(GitHubChangelogGenerator::ChangelogGeneratorError) }
196
238
  end
197
239
  end
198
240
 
199
241
  context "with empty array" do
200
242
  subject { generator.filter_since_tag(tags_from_strings(%w[])) }
201
243
 
202
- context "with valid since tag" do
203
- let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "2") }
204
- it { is_expected.to be_a Array }
205
- it { is_expected.to match_array(tags_from_strings(%w[])) }
206
- end
207
-
208
244
  context "with invalid since tag" do
209
245
  let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") }
210
- it { is_expected.to be_a Array }
211
- it { is_expected.to match_array(tags_from_strings(%w[])) }
246
+ it { expect { subject }.to raise_error(GitHubChangelogGenerator::ChangelogGeneratorError) }
212
247
  end
213
248
  end
214
249
  end
@@ -225,24 +260,16 @@ describe GitHubChangelogGenerator::Generator do
225
260
 
226
261
  context "with invalid due tag" do
227
262
  let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") }
228
- it { is_expected.to be_a Array }
229
- it { is_expected.to match_array(tags_from_strings(%w[1 2 3])) }
263
+ it { expect { subject }.to raise_error(GitHubChangelogGenerator::ChangelogGeneratorError) }
230
264
  end
231
265
  end
232
266
 
233
267
  context "with empty array" do
234
268
  subject { generator.filter_due_tag(tags_from_strings(%w[])) }
235
269
 
236
- context "with valid due tag" do
237
- let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "2") }
238
- it { is_expected.to be_a Array }
239
- it { is_expected.to match_array(tags_from_strings(%w[])) }
240
- end
241
-
242
270
  context "with invalid due tag" do
243
271
  let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") }
244
- it { is_expected.to be_a Array }
245
- it { is_expected.to match_array(tags_from_strings(%w[])) }
272
+ it { expect { subject }.to raise_error(GitHubChangelogGenerator::ChangelogGeneratorError) }
246
273
  end
247
274
  end
248
275
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitHubChangelogGenerator
4
+ RSpec.describe Section do
5
+ let(:options) { {} }
6
+ subject(:section) { described_class.new(options) }
7
+
8
+ describe "#encapsulate_string" do
9
+ let(:string) { "" }
10
+
11
+ context "with the empty string" do
12
+ it "returns the string" do
13
+ expect(section.send(:encapsulate_string, string)).to eq string
14
+ end
15
+ end
16
+
17
+ context "with a string with an escape-needing character in it" do
18
+ let(:string) { "<Inside> and outside" }
19
+
20
+ it "returns the string escaped" do
21
+ expect(section.send(:encapsulate_string, string)).to eq '\\<Inside\\> and outside'
22
+ end
23
+ end
24
+
25
+ context "with a backticked string with an escape-needing character in it" do
26
+ let(:string) { 'back `\` slash' }
27
+
28
+ it "returns the string" do
29
+ expect(section.send(:encapsulate_string, string)).to eq 'back `\` slash'
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -6,7 +6,7 @@ INVALID_TOKEN = "0000000000000000"
6
6
  describe GitHubChangelogGenerator::OctoFetcher do
7
7
  let(:options) do
8
8
  {
9
- user: "skywinder",
9
+ user: "github-changelog-generator",
10
10
  project: "changelog_test"
11
11
  }
12
12
  end
@@ -85,11 +85,54 @@ describe GitHubChangelogGenerator::OctoFetcher do
85
85
  end
86
86
  end
87
87
 
88
+ describe "#fetch_tag_shas" do
89
+ let(:commits) do
90
+ [
91
+ { sha: "0", parents: [{ sha: "1" }, { sha: "6" }] },
92
+ { sha: "1", parents: [{ sha: "2" }] },
93
+ { sha: "2", parents: [{ sha: "3" }] },
94
+ { sha: "3", parents: [{ sha: "4" }] },
95
+ { sha: "4", parents: [{ sha: "5" }] },
96
+ { sha: "5", parents: [] },
97
+ { sha: "6", parents: [{ sha: "7" }, { sha: "8" }] },
98
+ { sha: "7", parents: [{ sha: "9" }, { sha: "10" }] },
99
+ { sha: "8", parents: [{ sha: "11" }, { sha: "12" }] },
100
+ { sha: "9", parents: [] },
101
+ { sha: "10", parents: [] },
102
+ { sha: "11", parents: [] },
103
+ { sha: "12", parents: [] }
104
+ ]
105
+ end
106
+
107
+ let(:tag0) { { "name" => "tag-0", "commit" => { "sha" => "0" } } }
108
+ let(:tag1) { { "name" => "tag-1", "commit" => { "sha" => "1" } } }
109
+ let(:tag6) { { "name" => "tag-6", "commit" => { "sha" => "6" } } }
110
+
111
+ before do
112
+ allow(fetcher).to receive(:commits).and_return(commits)
113
+ end
114
+
115
+ it "should find all shas with single parents" do
116
+ fetcher.fetch_tag_shas([tag1])
117
+ expect(tag1["shas_in_tag"]).to eq(Set.new(%w[1 2 3 4 5]))
118
+ end
119
+
120
+ it "should find all shas with multiple parents" do
121
+ fetcher.fetch_tag_shas([tag6])
122
+ expect(tag6["shas_in_tag"]).to eq(Set.new(%w[6 7 8 9 10 11 12]))
123
+ end
124
+
125
+ it "should find all shas with mixed parents" do
126
+ fetcher.fetch_tag_shas([tag0])
127
+ expect(tag0["shas_in_tag"]).to eq(Set.new(%w[0 1 2 3 4 5 6 7 8 9 10 11 12]))
128
+ end
129
+ end
130
+
88
131
  describe "#github_fetch_tags" do
89
132
  context "when wrong token provided", :vcr do
90
133
  let(:options) do
91
134
  {
92
- user: "skywinder",
135
+ user: "github-changelog-generator",
93
136
  project: "changelog_test",
94
137
  token: INVALID_TOKEN
95
138
  }
@@ -102,39 +145,39 @@ describe GitHubChangelogGenerator::OctoFetcher do
102
145
 
103
146
  context "when API call is valid", :vcr do
104
147
  it "should return tags" do
105
- expected_tags = [{ "name" => "v0.0.3",
148
+ expected_tags = [{ "name" => "v0.0.3",
106
149
  "zipball_url" =>
107
150
  "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3",
108
151
  "tarball_url" =>
109
152
  "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3",
110
- "commit" =>
153
+ "commit" =>
111
154
  { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90",
112
155
  "url" =>
113
156
  "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } },
114
- { "name" => "v0.0.2",
157
+ { "name" => "v0.0.2",
115
158
  "zipball_url" =>
116
159
  "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.2",
117
160
  "tarball_url" =>
118
161
  "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.2",
119
- "commit" =>
162
+ "commit" =>
120
163
  { "sha" => "9b35bb13dcd15b68e7bcbf10cde5eb937a54f710",
121
164
  "url" =>
122
165
  "https://api.github.com/repos/skywinder/changelog_test/commits/9b35bb13dcd15b68e7bcbf10cde5eb937a54f710" } },
123
- { "name" => "v0.0.1",
166
+ { "name" => "v0.0.1",
124
167
  "zipball_url" =>
125
168
  "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.1",
126
169
  "tarball_url" =>
127
170
  "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.1",
128
- "commit" =>
171
+ "commit" =>
129
172
  { "sha" => "4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d",
130
173
  "url" =>
131
174
  "https://api.github.com/repos/skywinder/changelog_test/commits/4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d" } },
132
- { "name" => "0.0.4",
175
+ { "name" => "0.0.4",
133
176
  "zipball_url" =>
134
177
  "https://api.github.com/repos/skywinder/changelog_test/zipball/0.0.4",
135
178
  "tarball_url" =>
136
179
  "https://api.github.com/repos/skywinder/changelog_test/tarball/0.0.4",
137
- "commit" =>
180
+ "commit" =>
138
181
  { "sha" => "ece0c3ab7142b21064b885061c55ede00ef6ce94",
139
182
  "url" =>
140
183
  "https://api.github.com/repos/skywinder/changelog_test/commits/ece0c3ab7142b21064b885061c55ede00ef6ce94" } }]
@@ -160,54 +203,54 @@ describe GitHubChangelogGenerator::OctoFetcher do
160
203
  it "returns issue with proper key/values" do
161
204
  issues, _pull_requests = fetcher.fetch_closed_issues_and_pr
162
205
 
163
- expected_issue = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
206
+ expected_issue = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
164
207
  "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
165
- "labels_url" =>
208
+ "labels_url" =>
166
209
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}",
167
- "comments_url" =>
210
+ "comments_url" =>
168
211
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments",
169
- "events_url" =>
212
+ "events_url" =>
170
213
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/events",
171
- "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
172
- "id" => 95_419_412,
173
- "number" => 14,
174
- "title" => "Issue closed from commit from PR",
175
- "user" =>
176
- { "login" => "skywinder",
177
- "id" => 3_356_474,
178
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
179
- "gravatar_id" => "",
180
- "url" => "https://api.github.com/users/skywinder",
181
- "html_url" => "https://github.com/skywinder",
182
- "followers_url" => "https://api.github.com/users/skywinder/followers",
183
- "following_url" =>
214
+ "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
215
+ "id" => 95_419_412,
216
+ "number" => 14,
217
+ "title" => "Issue closed from commit from PR",
218
+ "user" =>
219
+ { "login" => "skywinder",
220
+ "id" => 3_356_474,
221
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
222
+ "gravatar_id" => "",
223
+ "url" => "https://api.github.com/users/skywinder",
224
+ "html_url" => "https://github.com/skywinder",
225
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
226
+ "following_url" =>
184
227
  "https://api.github.com/users/skywinder/following{/other_user}",
185
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
186
- "starred_url" =>
228
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
229
+ "starred_url" =>
187
230
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
188
- "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
189
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
190
- "repos_url" => "https://api.github.com/users/skywinder/repos",
191
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
231
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
232
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
233
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
234
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
192
235
  "received_events_url" =>
193
236
  "https://api.github.com/users/skywinder/received_events",
194
- "type" => "User",
195
- "site_admin" => false },
196
- "labels" => [],
197
- "state" => "closed",
198
- "locked" => false,
199
- "assignee" => nil,
237
+ "type" => "User",
238
+ "site_admin" => false },
239
+ "labels" => [],
240
+ "state" => "closed",
241
+ "locked" => false,
242
+ "assignee" => nil,
200
243
  "assignees" => [],
201
- "milestone" => nil,
202
- "comments" => 0,
203
- "created_at" => "2015-07-16T12:06:08Z",
204
- "updated_at" => "2015-07-16T12:21:42Z",
205
- "closed_at" => "2015-07-16T12:21:42Z",
206
- "body" => "" }
244
+ "milestone" => nil,
245
+ "comments" => 0,
246
+ "created_at" => "2015-07-16T12:06:08Z",
247
+ "updated_at" => "2015-07-16T12:21:42Z",
248
+ "closed_at" => "2015-07-16T12:21:42Z",
249
+ "body" => "" }
207
250
 
208
251
  # Convert times to Time
209
252
  expected_issue.each_pair do |k, v|
210
- expected_issue[k] = Time.parse(v) if v =~ /^2015-/
253
+ expected_issue[k] = Time.parse(v) if v.to_s.start_with?("2015-")
211
254
  end
212
255
 
213
256
  expect(issues.first).to eq(expected_issue)
@@ -216,60 +259,60 @@ describe GitHubChangelogGenerator::OctoFetcher do
216
259
  it "returns pull request with proper key/values" do
217
260
  _issues, pull_requests = fetcher.fetch_closed_issues_and_pr
218
261
 
219
- expected_pr = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/21",
262
+ expected_pr = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/21",
220
263
  "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
221
- "labels_url" =>
264
+ "labels_url" =>
222
265
  "https://api.github.com/repos/skywinder/changelog_test/issues/21/labels{/name}",
223
- "comments_url" =>
266
+ "comments_url" =>
224
267
  "https://api.github.com/repos/skywinder/changelog_test/issues/21/comments",
225
- "events_url" =>
268
+ "events_url" =>
226
269
  "https://api.github.com/repos/skywinder/changelog_test/issues/21/events",
227
- "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
228
- "id" => 124_925_759,
229
- "number" => 21,
230
- "title" => "Merged br (should appear in change log with #20)",
231
- "user" =>
232
- { "login" => "skywinder",
233
- "id" => 3_356_474,
234
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
235
- "gravatar_id" => "",
236
- "url" => "https://api.github.com/users/skywinder",
237
- "html_url" => "https://github.com/skywinder",
238
- "followers_url" => "https://api.github.com/users/skywinder/followers",
239
- "following_url" =>
270
+ "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
271
+ "id" => 124_925_759,
272
+ "number" => 21,
273
+ "title" => "Merged br (should appear in change log with #20)",
274
+ "user" =>
275
+ { "login" => "skywinder",
276
+ "id" => 3_356_474,
277
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
278
+ "gravatar_id" => "",
279
+ "url" => "https://api.github.com/users/skywinder",
280
+ "html_url" => "https://github.com/skywinder",
281
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
282
+ "following_url" =>
240
283
  "https://api.github.com/users/skywinder/following{/other_user}",
241
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
242
- "starred_url" =>
284
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
285
+ "starred_url" =>
243
286
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
244
- "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
245
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
246
- "repos_url" => "https://api.github.com/users/skywinder/repos",
247
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
287
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
288
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
289
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
290
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
248
291
  "received_events_url" =>
249
292
  "https://api.github.com/users/skywinder/received_events",
250
- "type" => "User",
251
- "site_admin" => false },
252
- "labels" => [],
253
- "state" => "closed",
254
- "locked" => false,
255
- "assignee" => nil,
293
+ "type" => "User",
294
+ "site_admin" => false },
295
+ "labels" => [],
296
+ "state" => "closed",
297
+ "locked" => false,
298
+ "assignee" => nil,
256
299
  "assignees" => [],
257
- "milestone" => nil,
258
- "comments" => 0,
259
- "created_at" => "2016-01-05T09:24:08Z",
260
- "updated_at" => "2016-01-05T09:26:53Z",
261
- "closed_at" => "2016-01-05T09:24:27Z",
262
- "pull_request" =>
263
- { "url" => "https://api.github.com/repos/skywinder/changelog_test/pulls/21",
264
- "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
265
- "diff_url" => "https://github.com/skywinder/changelog_test/pull/21.diff",
300
+ "milestone" => nil,
301
+ "comments" => 0,
302
+ "created_at" => "2016-01-05T09:24:08Z",
303
+ "updated_at" => "2016-01-05T09:26:53Z",
304
+ "closed_at" => "2016-01-05T09:24:27Z",
305
+ "pull_request" =>
306
+ { "url" => "https://api.github.com/repos/skywinder/changelog_test/pulls/21",
307
+ "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
308
+ "diff_url" => "https://github.com/skywinder/changelog_test/pull/21.diff",
266
309
  "patch_url" => "https://github.com/skywinder/changelog_test/pull/21.patch" },
267
- "body" =>
310
+ "body" =>
268
311
  "to test https://github.com/skywinder/github-changelog-generator/pull/305\r\nshould appear in change log with #20" }
269
312
 
270
313
  # Convert times to Time
271
314
  expected_pr.each_pair do |k, v|
272
- expected_pr[k] = Time.parse(v) if v =~ /^2016-01/
315
+ expected_pr[k] = Time.parse(v) if v.to_s.start_with?("2016-01")
273
316
  end
274
317
 
275
318
  expect(pull_requests.first).to eq(expected_pr)
@@ -308,51 +351,51 @@ describe GitHubChangelogGenerator::OctoFetcher do
308
351
  describe "#fetch_events_async" do
309
352
  context "when API call is valid", :vcr do
310
353
  it "populates issues" do
311
- issues = [{ "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
354
+ issues = [{ "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
312
355
  "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
313
- "labels_url" =>
356
+ "labels_url" =>
314
357
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}",
315
- "comments_url" =>
358
+ "comments_url" =>
316
359
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments",
317
- "events_url" =>
360
+ "events_url" =>
318
361
  "https://api.github.com/repos/skywinder/changelog_test/issues/14/events",
319
- "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
320
- "id" => 95_419_412,
321
- "number" => 14,
322
- "title" => "Issue closed from commit from PR",
323
- "user" =>
324
- { "login" => "skywinder",
325
- "id" => 3_356_474,
326
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
327
- "gravatar_id" => "",
328
- "url" => "https://api.github.com/users/skywinder",
329
- "html_url" => "https://github.com/skywinder",
330
- "followers_url" => "https://api.github.com/users/skywinder/followers",
331
- "following_url" =>
362
+ "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
363
+ "id" => 95_419_412,
364
+ "number" => 14,
365
+ "title" => "Issue closed from commit from PR",
366
+ "user" =>
367
+ { "login" => "skywinder",
368
+ "id" => 3_356_474,
369
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
370
+ "gravatar_id" => "",
371
+ "url" => "https://api.github.com/users/skywinder",
372
+ "html_url" => "https://github.com/skywinder",
373
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
374
+ "following_url" =>
332
375
  "https://api.github.com/users/skywinder/following{/other_user}",
333
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
334
- "starred_url" =>
376
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
377
+ "starred_url" =>
335
378
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
336
- "subscriptions_url" =>
379
+ "subscriptions_url" =>
337
380
  "https://api.github.com/users/skywinder/subscriptions",
338
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
339
- "repos_url" => "https://api.github.com/users/skywinder/repos",
340
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
381
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
382
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
383
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
341
384
  "received_events_url" =>
342
385
  "https://api.github.com/users/skywinder/received_events",
343
- "type" => "User",
344
- "site_admin" => false },
345
- "labels" => [],
346
- "state" => "closed",
347
- "locked" => false,
348
- "assignee" => nil,
386
+ "type" => "User",
387
+ "site_admin" => false },
388
+ "labels" => [],
389
+ "state" => "closed",
390
+ "locked" => false,
391
+ "assignee" => nil,
349
392
  "assignees" => [],
350
- "milestone" => nil,
351
- "comments" => 0,
352
- "created_at" => "2015-07-16T12:06:08Z",
353
- "updated_at" => "2015-07-16T12:21:42Z",
354
- "closed_at" => "2015-07-16T12:21:42Z",
355
- "body" => "" }]
393
+ "milestone" => nil,
394
+ "comments" => 0,
395
+ "created_at" => "2015-07-16T12:06:08Z",
396
+ "updated_at" => "2015-07-16T12:21:42Z",
397
+ "closed_at" => "2015-07-16T12:21:42Z",
398
+ "body" => "" }]
356
399
 
357
400
  # Check that they are blank to begin with
358
401
  expect(issues.first["events"]).to be_nil
@@ -360,63 +403,63 @@ describe GitHubChangelogGenerator::OctoFetcher do
360
403
  fetcher.fetch_events_async(issues)
361
404
  issue_events = issues.first["events"]
362
405
 
363
- expected_events = [{ "id" => 357_462_189,
364
- "url" =>
406
+ expected_events = [{ "id" => 357_462_189,
407
+ "url" =>
365
408
  "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189",
366
- "actor" =>
367
- { "login" => "skywinder",
368
- "id" => 3_356_474,
369
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
370
- "gravatar_id" => "",
371
- "url" => "https://api.github.com/users/skywinder",
372
- "html_url" => "https://github.com/skywinder",
373
- "followers_url" => "https://api.github.com/users/skywinder/followers",
374
- "following_url" =>
409
+ "actor" =>
410
+ { "login" => "skywinder",
411
+ "id" => 3_356_474,
412
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
413
+ "gravatar_id" => "",
414
+ "url" => "https://api.github.com/users/skywinder",
415
+ "html_url" => "https://github.com/skywinder",
416
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
417
+ "following_url" =>
375
418
  "https://api.github.com/users/skywinder/following{/other_user}",
376
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
377
- "starred_url" =>
419
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
420
+ "starred_url" =>
378
421
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
379
- "subscriptions_url" =>
422
+ "subscriptions_url" =>
380
423
  "https://api.github.com/users/skywinder/subscriptions",
381
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
382
- "repos_url" => "https://api.github.com/users/skywinder/repos",
383
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
424
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
425
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
426
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
384
427
  "received_events_url" =>
385
428
  "https://api.github.com/users/skywinder/received_events",
386
- "type" => "User",
387
- "site_admin" => false },
388
- "event" => "referenced",
389
- "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
429
+ "type" => "User",
430
+ "site_admin" => false },
431
+ "event" => "referenced",
432
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
390
433
  "commit_url" =>
391
434
  "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
392
435
  "created_at" => "2015-07-16T12:21:16Z" },
393
- { "id" => 357_462_542,
394
- "url" =>
436
+ { "id" => 357_462_542,
437
+ "url" =>
395
438
  "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462542",
396
- "actor" =>
397
- { "login" => "skywinder",
398
- "id" => 3_356_474,
399
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
400
- "gravatar_id" => "",
401
- "url" => "https://api.github.com/users/skywinder",
402
- "html_url" => "https://github.com/skywinder",
403
- "followers_url" => "https://api.github.com/users/skywinder/followers",
404
- "following_url" =>
439
+ "actor" =>
440
+ { "login" => "skywinder",
441
+ "id" => 3_356_474,
442
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
443
+ "gravatar_id" => "",
444
+ "url" => "https://api.github.com/users/skywinder",
445
+ "html_url" => "https://github.com/skywinder",
446
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
447
+ "following_url" =>
405
448
  "https://api.github.com/users/skywinder/following{/other_user}",
406
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
407
- "starred_url" =>
449
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
450
+ "starred_url" =>
408
451
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
409
- "subscriptions_url" =>
452
+ "subscriptions_url" =>
410
453
  "https://api.github.com/users/skywinder/subscriptions",
411
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
412
- "repos_url" => "https://api.github.com/users/skywinder/repos",
413
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
454
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
455
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
456
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
414
457
  "received_events_url" =>
415
458
  "https://api.github.com/users/skywinder/received_events",
416
- "type" => "User",
417
- "site_admin" => false },
418
- "event" => "closed",
419
- "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
459
+ "type" => "User",
460
+ "site_admin" => false },
461
+ "event" => "closed",
462
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
420
463
  "commit_url" =>
421
464
  "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
422
465
  "created_at" => "2015-07-16T12:21:42Z" }]
@@ -424,7 +467,7 @@ describe GitHubChangelogGenerator::OctoFetcher do
424
467
  # Convert times to Time
425
468
  expected_events.map! do |event|
426
469
  event.each_pair do |k, v|
427
- event[k] = Time.parse(v) if v =~ /^201[56]-/
470
+ event[k] = Time.parse(v) if v.to_s =~ /^201[56]-/
428
471
  end
429
472
  end
430
473
 
@@ -436,17 +479,21 @@ describe GitHubChangelogGenerator::OctoFetcher do
436
479
  describe "#fetch_date_of_tag" do
437
480
  context "when API call is valid", :vcr do
438
481
  it "returns date" do
439
- tag = { "name" => "v0.0.3",
482
+ tag = { "name" => "v0.0.3",
440
483
  "zipball_url" =>
441
484
  "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3",
442
485
  "tarball_url" =>
443
486
  "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3",
444
- "commit" =>
487
+ "commit" =>
445
488
  { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90",
446
489
  "url" =>
447
490
  "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } }
448
491
 
449
- dt = fetcher.fetch_date_of_tag(tag)
492
+ skywinder = GitHubChangelogGenerator::OctoFetcher.new(
493
+ user: "skywinder",
494
+ project: "changelog_test"
495
+ )
496
+ dt = skywinder.fetch_date_of_tag(tag)
450
497
  expect(dt).to eq(Time.parse("2015-03-04 19:01:48 UTC"))
451
498
  end
452
499
  end
@@ -469,36 +516,36 @@ describe GitHubChangelogGenerator::OctoFetcher do
469
516
  describe "#fetch_commit" do
470
517
  context "when API call is valid", :vcr do
471
518
  it "returns commit" do
472
- event = { "id" => 357_462_189,
473
- "url" =>
519
+ event = { "id" => 357_462_189,
520
+ "url" =>
474
521
  "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189",
475
- "actor" =>
476
- { "login" => "skywinder",
477
- "id" => 3_356_474,
478
- "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
479
- "gravatar_id" => "",
480
- "url" => "https://api.github.com/users/skywinder",
481
- "html_url" => "https://github.com/skywinder",
482
- "followers_url" => "https://api.github.com/users/skywinder/followers",
483
- "following_url" =>
522
+ "actor" =>
523
+ { "login" => "github-changelog-generator",
524
+ "id" => 3_356_474,
525
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
526
+ "gravatar_id" => "",
527
+ "url" => "https://api.github.com/users/skywinder",
528
+ "html_url" => "https://github.com/skywinder",
529
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
530
+ "following_url" =>
484
531
  "https://api.github.com/users/skywinder/following{/other_user}",
485
- "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
486
- "starred_url" =>
532
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
533
+ "starred_url" =>
487
534
  "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
488
- "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
489
- "organizations_url" => "https://api.github.com/users/skywinder/orgs",
490
- "repos_url" => "https://api.github.com/users/skywinder/repos",
491
- "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
535
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
536
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
537
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
538
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
492
539
  "received_events_url" =>
493
540
  "https://api.github.com/users/skywinder/received_events",
494
- "type" => "User",
495
- "site_admin" => false },
496
- "event" => "referenced",
497
- "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
541
+ "type" => "User",
542
+ "site_admin" => false },
543
+ "event" => "referenced",
544
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
498
545
  "commit_url" =>
499
546
  "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
500
547
  "created_at" => "2015-07-16T12:21:16Z" }
501
- commit = fetcher.fetch_commit(event)
548
+ commit = fetcher.fetch_commit(event["commit_id"])
502
549
 
503
550
  expectations = [
504
551
  %w[sha decfe840d1a1b86e0c28700de5362d3365a29555],
@@ -508,9 +555,9 @@ describe GitHubChangelogGenerator::OctoFetcher do
508
555
  ["html_url",
509
556
  "https://github.com/skywinder/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"],
510
557
  ["author",
511
- { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }],
558
+ { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars2.githubusercontent.com/u/3356474?v=4", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }],
512
559
  ["committer",
513
- { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }],
560
+ { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars2.githubusercontent.com/u/3356474?v=4", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }],
514
561
  ["parents",
515
562
  [{ "sha" => "7ec095e5e3caceacedabf44d0b9b10da17c92e51",
516
563
  "url" =>
@@ -520,19 +567,22 @@ describe GitHubChangelogGenerator::OctoFetcher do
520
567
  "https://github.com/skywinder/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51" }]]
521
568
  ]
522
569
 
523
- expectations.each do |property, val|
524
- expect(commit[property]).to eq(val)
570
+ expectations.each do |property, value|
571
+ case value
572
+ when String, Array
573
+ expect(commit[property]).to eq(value)
574
+ when Hash
575
+ expect(commit[property]).to include(value)
576
+ end
525
577
  end
526
578
  end
527
579
  end
528
580
  end
529
581
 
530
- describe "#commits_before" do
582
+ describe "#commits" do
531
583
  context "when API is valid", :vcr do
532
- let(:start_time) { Time.parse("Wed Mar 4 18:47:17 2015 +0200") }
533
-
534
584
  subject do
535
- fetcher.commits_before(start_time)
585
+ fetcher.commits
536
586
  end
537
587
 
538
588
  it "returns commits" do