github_changelog_generator 1.16.3 → 1.17.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -16
  3. data/bin/github_changelog_generator +1 -1
  4. data/lib/github_changelog_generator/argv_parser.rb +2 -2
  5. data/lib/github_changelog_generator/file_parser_chooser.rb +27 -0
  6. data/lib/github_changelog_generator/generator/entry.rb +3 -3
  7. data/lib/github_changelog_generator/generator/generator.rb +15 -10
  8. data/lib/github_changelog_generator/generator/generator_fetcher.rb +22 -24
  9. data/lib/github_changelog_generator/generator/generator_processor.rb +14 -24
  10. data/lib/github_changelog_generator/generator/generator_tags.rb +24 -34
  11. data/lib/github_changelog_generator/generator/section.rb +9 -4
  12. data/lib/github_changelog_generator/octo_fetcher.rb +38 -36
  13. data/lib/github_changelog_generator/options.rb +12 -2
  14. data/lib/github_changelog_generator/parser.rb +4 -4
  15. data/lib/github_changelog_generator/parser_file.rb +0 -24
  16. data/lib/github_changelog_generator/reader.rb +3 -1
  17. data/lib/github_changelog_generator/ssl_certs/cacert.pem +2 -78
  18. data/lib/github_changelog_generator/task.rb +2 -2
  19. data/lib/github_changelog_generator/version.rb +1 -1
  20. data/lib/github_changelog_generator.rb +18 -16
  21. data/man/git-generate-changelog.html +2 -2
  22. data/spec/github_changelog_generator_spec.rb +32 -0
  23. data/spec/unit/generator/entry_spec.rb +2 -2
  24. data/spec/unit/generator/generator_processor_spec.rb +61 -0
  25. data/spec/unit/generator/generator_spec.rb +151 -0
  26. data/spec/unit/generator/generator_tags_spec.rb +1 -1
  27. data/spec/unit/generator/section_spec.rb +9 -0
  28. data/spec/unit/octo_fetcher_spec.rb +8 -11
  29. data/spec/unit/{parse_file_spec.rb → parser_file_spec.rb} +35 -15
  30. data/spec/unit/reader_spec.rb +9 -0
  31. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -1
  32. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -1
  33. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -1
  34. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -1
  35. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -1
  36. 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
  37. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -1
  38. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -1
  39. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -1
  40. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -1
  41. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -1
  42. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -1
  43. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -1
  44. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -1
  45. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -1
  46. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -1
  47. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -1
  48. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -1
  49. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -1
  50. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -1
  51. metadata +12 -23
@@ -44,4 +44,155 @@ RSpec.describe GitHubChangelogGenerator::Generator do
44
44
  end
45
45
  end
46
46
  end
47
+
48
+ describe "#add_first_occurring_tag_to_prs" do
49
+ def sha(num)
50
+ base = num.to_s
51
+ pad_length = 40 - base.length
52
+ "#{'a' * pad_length}#{base}"
53
+ end
54
+
55
+ let(:release_branch_name) { "release" }
56
+ let(:generator) { described_class.new({ release_branch: release_branch_name }) }
57
+ let(:fake_fetcher) do
58
+ instance_double(GitHubChangelogGenerator::OctoFetcher,
59
+ fetch_tag_shas: nil,
60
+ fetch_comments_async: nil)
61
+ end
62
+
63
+ before do
64
+ allow(fake_fetcher)
65
+ .to receive(:commits_in_branch).with(release_branch_name)
66
+ .and_return([sha(1), sha(2), sha(3), sha(4)])
67
+ allow(GitHubChangelogGenerator::OctoFetcher).to receive(:new).and_return(fake_fetcher)
68
+ end
69
+
70
+ it "associates prs to the oldest tag containing the merge commit" do
71
+ prs = [{ "number" => "23", "events" => [{ "event" => "merged", "commit_id" => sha(2) }] }]
72
+ tags = [
73
+ { "name" => "newer2.0", "shas_in_tag" => [sha(1), sha(2), sha(3)] },
74
+ { "name" => "older1.0", "shas_in_tag" => [sha(1), sha(2)] }
75
+ ]
76
+
77
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
78
+
79
+ aggregate_failures do
80
+ expect(prs_left).to be_empty
81
+ expect(prs.first["first_occurring_tag"]).to eq "older1.0"
82
+
83
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
84
+ expect(fake_fetcher).not_to have_received(:fetch_comments_async)
85
+ end
86
+ end
87
+
88
+ it "detects prs merged in the release branch" do
89
+ prs = [{ "number" => "23", "events" => [{ "event" => "merged", "commit_id" => sha(4) }] }]
90
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
91
+
92
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
93
+
94
+ aggregate_failures do
95
+ expect(prs_left).to be_empty
96
+ expect(prs.first["first_occurring_tag"]).to be_nil
97
+
98
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
99
+ expect(fake_fetcher).not_to have_received(:fetch_comments_async)
100
+ end
101
+ end
102
+
103
+ it "detects closed prs marked as rebased in a tag" do
104
+ prs = [{ "number" => "23", "comments" => [{ "body" => "rebased commit: #{sha(2)}" }] }]
105
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
106
+
107
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
108
+
109
+ aggregate_failures do
110
+ expect(prs_left).to be_empty
111
+ expect(prs.first["first_occurring_tag"]).to eq "v1.0"
112
+
113
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
114
+ expect(fake_fetcher).to have_received(:fetch_comments_async)
115
+ end
116
+ end
117
+
118
+ it "detects closed prs marked as rebased in the release branch" do
119
+ prs = [{ "number" => "23", "comments" => [{ "body" => "rebased commit: #{sha(4)}" }] }]
120
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
121
+
122
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
123
+
124
+ aggregate_failures do
125
+ expect(prs_left).to be_empty
126
+ expect(prs.first["first_occurring_tag"]).to be_nil
127
+
128
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
129
+ expect(fake_fetcher).to have_received(:fetch_comments_async)
130
+ end
131
+ end
132
+
133
+ it "leaves prs merged in another branch" do
134
+ prs = [{ "number" => "23", "events" => [{ "event" => "merged", "commit_id" => sha(5) }] }]
135
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
136
+
137
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
138
+
139
+ aggregate_failures do
140
+ expect(prs_left).to eq prs
141
+ expect(prs.first["first_occurring_tag"]).to be_nil
142
+
143
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
144
+ expect(fake_fetcher).to have_received(:fetch_comments_async)
145
+ end
146
+ end
147
+
148
+ it "detects prs merged elsewhere and marked as rebased in a tag" do
149
+ prs = [{ "number" => "23",
150
+ "events" => [{ "event" => "merged", "commit_id" => sha(5) }],
151
+ "comments" => [{ "body" => "rebased commit: #{sha(2)}" }] }]
152
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
153
+
154
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
155
+
156
+ aggregate_failures do
157
+ expect(prs_left).to be_empty
158
+ expect(prs.first["first_occurring_tag"]).to eq "v1.0"
159
+
160
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
161
+ expect(fake_fetcher).to have_received(:fetch_comments_async)
162
+ end
163
+ end
164
+
165
+ it "detects prs merged elsewhere and marked as rebased in the release branch" do
166
+ prs = [{ "number" => "23",
167
+ "events" => [{ "event" => "merged", "commit_id" => sha(5) }],
168
+ "comments" => [{ "body" => "rebased commit: #{sha(4)}" }] }]
169
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
170
+
171
+ prs_left = generator.send(:add_first_occurring_tag_to_prs, tags, prs)
172
+
173
+ aggregate_failures do
174
+ expect(prs_left).to be_empty
175
+ expect(prs.first["first_occurring_tag"]).to be_nil
176
+
177
+ expect(fake_fetcher).to have_received(:fetch_tag_shas)
178
+ expect(fake_fetcher).to have_received(:fetch_comments_async)
179
+ end
180
+ end
181
+
182
+ it "raises an error for closed prs marked as rebased to an unknown commit" do
183
+ prs = [{ "number" => "23", "comments" => [{ "body" => "rebased commit: #{sha(5)}" }] }]
184
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
185
+
186
+ expect { generator.send(:add_first_occurring_tag_to_prs, tags, prs) }
187
+ .to raise_error StandardError, "PR 23 has a rebased SHA comment but that SHA was not found in the release branch or any tags"
188
+ end
189
+
190
+ it "raises an error for prs without merge event or rebase comment" do
191
+ prs = [{ "number" => "23" }]
192
+ tags = [{ "name" => "v1.0", "shas_in_tag" => [sha(1), sha(2)] }]
193
+
194
+ expect { generator.send(:add_first_occurring_tag_to_prs, tags, prs) }
195
+ .to raise_error StandardError, "No merge sha found for PR 23 via the GitHub API"
196
+ end
197
+ end
47
198
  end
@@ -49,7 +49,7 @@ describe GitHubChangelogGenerator::Generator do
49
49
  let(:generator) { described_class.new(default_options.merge(options)) }
50
50
 
51
51
  before do
52
- allow_any_instance_of(GitHubChangelogGenerator::OctoFetcher).to receive(:get_all_tags).and_return(all_tags)
52
+ allow_any_instance_of(GitHubChangelogGenerator::OctoFetcher).to receive(:fetch_all_tags).and_return(all_tags)
53
53
  allow(generator).to receive(:fetch_tags_dates).with(all_tags)
54
54
  allow(generator).to receive(:sort_tags_by_date).with(all_tags).and_return(sorted_tags)
55
55
  generator.fetch_and_filter_tags
@@ -30,5 +30,14 @@ module GitHubChangelogGenerator
30
30
  end
31
31
  end
32
32
  end
33
+
34
+ describe "#normalize_body" do
35
+ context "it should remove CR" do
36
+ let(:body) { "Some content from GitHub\r\n\r\nUser is describing something" }
37
+ it "returns a cleaned body" do
38
+ expect(section.send(:normalize_body, body)).to eq "Some content from GitHub\n\nUser is describing something"
39
+ end
40
+ end
41
+ end
33
42
  end
34
43
  end
@@ -29,9 +29,6 @@ describe GitHubChangelogGenerator::OctoFetcher do
29
29
 
30
30
  context "when raises Octokit::Forbidden" do
31
31
  it "sleeps and retries and then aborts" do
32
- retry_limit = GitHubChangelogGenerator::OctoFetcher::MAX_FORBIDDEN_RETRIES - 1
33
- allow(fetcher).to receive(:sleep_base_interval).exactly(retry_limit).times.and_return(0)
34
-
35
32
  expect(fetcher).to receive(:sys_abort).with("Exceeded retry limit")
36
33
  fetcher.send(:check_github_response) { raise(Octokit::Forbidden) }
37
34
  end
@@ -75,12 +72,12 @@ describe GitHubChangelogGenerator::OctoFetcher do
75
72
  end
76
73
  end
77
74
 
78
- describe "#get_all_tags" do
75
+ describe "#fetch_all_tags" do
79
76
  context "when github_fetch_tags returns tags" do
80
77
  it "returns tags" do
81
78
  mock_tags = ["tag"]
82
79
  allow(fetcher).to receive(:github_fetch_tags).and_return(mock_tags)
83
- expect(fetcher.get_all_tags).to eq(mock_tags)
80
+ expect(fetcher.fetch_all_tags).to eq(mock_tags)
84
81
  end
85
82
  end
86
83
  end
@@ -550,21 +547,21 @@ describe GitHubChangelogGenerator::OctoFetcher do
550
547
  expectations = [
551
548
  %w[sha decfe840d1a1b86e0c28700de5362d3365a29555],
552
549
  ["url",
553
- "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
550
+ "https://api.github.com/repos/github-changelog-generator/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
554
551
  # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
555
552
  ["html_url",
556
- "https://github.com/skywinder/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"],
553
+ "https://github.com/github-changelog-generator/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"],
557
554
  ["author",
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 }],
555
+ { "login" => "skywinder", "node_id" => "MDQ6VXNlcjMzNTY0NzQ=", "id" => 3_356_474, "avatar_url" => "https://avatars.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 }],
559
556
  ["committer",
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 }],
557
+ { "login" => "skywinder", "node_id" => "MDQ6VXNlcjMzNTY0NzQ=", "id" => 3_356_474, "avatar_url" => "https://avatars.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 }],
561
558
  ["parents",
562
559
  [{ "sha" => "7ec095e5e3caceacedabf44d0b9b10da17c92e51",
563
560
  "url" =>
564
- "https://api.github.com/repos/skywinder/changelog_test/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51",
561
+ "https://api.github.com/repos/github-changelog-generator/changelog_test/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51",
565
562
  # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51",
566
563
  "html_url" =>
567
- "https://github.com/skywinder/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51" }]]
564
+ "https://github.com/github-changelog-generator/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51" }]]
568
565
  ]
569
566
 
570
567
  expectations.each do |property, value|
@@ -3,15 +3,18 @@
3
3
  describe GitHubChangelogGenerator::ParserFile do
4
4
  describe ".github_changelog_generator" do
5
5
  let(:options) { {} }
6
+ let(:parser) { described_class.new(options, StringIO.new(file)) }
6
7
 
7
8
  context "when the well-known default file does not exist" do
8
- let(:parser) { GitHubChangelogGenerator::ParserFile.new(options) }
9
+ let(:parser) { described_class.new(options) }
10
+
9
11
  subject { parser.parse! }
12
+
10
13
  it { is_expected.to be_nil }
11
14
  end
12
15
 
13
16
  context "when file is empty" do
14
- let(:parser) { GitHubChangelogGenerator::ParserFile.new(options, StringIO.new("")) }
17
+ let(:file) { "" }
15
18
 
16
19
  it "does not change the options" do
17
20
  expect { parser.parse! }.to_not(change { options })
@@ -19,19 +22,26 @@ describe GitHubChangelogGenerator::ParserFile do
19
22
  end
20
23
 
21
24
  context "when file is incorrect" do
22
- let(:options_before_change) { options.dup }
23
- let(:file) { StringIO.new("unreleased_label=staging\nunreleased: false") }
24
- let(:parser) do
25
- GitHubChangelogGenerator::ParserFile.new(options, file)
25
+ let(:file) do
26
+ <<~FILE.strip
27
+ unreleased_label=staging
28
+ unreleased: false
29
+ FILE
26
30
  end
31
+
27
32
  it { expect { parser.parse! }.to raise_error(/line #2/) }
28
33
  end
29
34
 
30
35
  context "allows empty lines and comments with semi-colon or pound sign" do
31
- let(:file) { StringIO.new("\n \n# Comment on first line\nunreleased_label=staging\n; Comment on third line\nunreleased=false") }
32
- let(:parser) do
33
- GitHubChangelogGenerator::ParserFile.new(options, file)
36
+ let(:file) do
37
+ "\n \n#{<<~REMAINING.strip}"
38
+ # Comment on first line
39
+ unreleased_label=staging
40
+ ; Comment on third line
41
+ unreleased=false
42
+ REMAINING
34
43
  end
44
+
35
45
  it { expect { parser.parse! }.not_to raise_error }
36
46
  end
37
47
 
@@ -39,22 +49,32 @@ describe GitHubChangelogGenerator::ParserFile do
39
49
  let(:default_options) { GitHubChangelogGenerator::Parser.default_options.merge(verbose: false) }
40
50
  let(:options) { {}.merge(default_options) }
41
51
  let(:options_before_change) { options.dup }
42
- let(:file) { StringIO.new("unreleased_label=staging\nunreleased=false\nheader==== Changelog ===") }
43
- let(:parser) { GitHubChangelogGenerator::ParserFile.new(options, file) }
52
+ let(:file) do
53
+ <<~FILE.strip
54
+ unreleased_label=staging
55
+ unreleased=false
56
+ header==== Changelog ===
57
+ max_issues=123
58
+ simple-list=true
59
+ FILE
60
+ end
44
61
 
45
62
  it "changes the options" do
46
63
  expect { parser.parse! }.to change { options }
47
64
  .from(options_before_change)
48
65
  .to(options_before_change.merge(unreleased_label: "staging",
49
66
  unreleased: false,
50
- header: "=== Changelog ==="))
67
+ header: "=== Changelog ===",
68
+ max_issues: 123,
69
+ simple_list: true))
51
70
  end
52
71
 
53
72
  context "turns exclude-labels into an Array", bug: "#327" do
54
73
  let(:file) do
55
- line1 = "exclude-labels=73a91042-da6f-11e5-9335-1040f38d7f90,7adf83b4-da6f-11e5-ae18-1040f38d7f90\n"
56
- line2 = "header_label=# My changelog\n"
57
- StringIO.new(line1 + line2)
74
+ <<~FILE
75
+ exclude-labels=73a91042-da6f-11e5-9335-1040f38d7f90,7adf83b4-da6f-11e5-ae18-1040f38d7f90
76
+ header_label=# My changelog
77
+ FILE
58
78
  end
59
79
 
60
80
  it "reads exclude_labels into an Array" do
@@ -38,6 +38,15 @@ describe GitHubChangelogGenerator::Reader do
38
38
  it { is_expected.to include("url" => "https://github.com/github-changelog-generator/Github-Changelog-Generator/tree/1.3.10") }
39
39
  it { is_expected.to include("date" => "2015-03-18") }
40
40
  end
41
+ context "when given a named link" do
42
+ subject { @reader.parse_heading("## [1.3.10]") }
43
+ it { is_expected.to include("version" => "1.3.10") }
44
+ end
45
+ context "when given a named link with date" do
46
+ subject { @reader.parse_heading("## [1.3.10] (2015-03-18)") }
47
+ it { is_expected.to include("version" => "1.3.10") }
48
+ it { is_expected.to include("date" => "2015-03-18") }
49
+ end
41
50
  context "when no url and date is provided" do
42
51
  subject { @reader.parse_heading("## foobar") }
43
52
  it { is_expected.to include("version" => "foobar", "url" => nil, "date" => nil) }