px_github_changelog_generator 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +9 -0
  3. data/README.md +357 -0
  4. data/Rakefile +19 -0
  5. data/bin/git-generate-changelog +5 -0
  6. data/bin/github_changelog_generator +5 -0
  7. data/lib/github_changelog_generator/argv_parser.rb +225 -0
  8. data/lib/github_changelog_generator/file_parser_chooser.rb +27 -0
  9. data/lib/github_changelog_generator/generator/entry.rb +218 -0
  10. data/lib/github_changelog_generator/generator/generator.rb +177 -0
  11. data/lib/github_changelog_generator/generator/generator_fetcher.rb +202 -0
  12. data/lib/github_changelog_generator/generator/generator_processor.rb +237 -0
  13. data/lib/github_changelog_generator/generator/generator_tags.rb +210 -0
  14. data/lib/github_changelog_generator/generator/section.rb +129 -0
  15. data/lib/github_changelog_generator/helper.rb +37 -0
  16. data/lib/github_changelog_generator/octo_fetcher.rb +535 -0
  17. data/lib/github_changelog_generator/options.rb +159 -0
  18. data/lib/github_changelog_generator/parser.rb +89 -0
  19. data/lib/github_changelog_generator/parser_file.rb +101 -0
  20. data/lib/github_changelog_generator/reader.rb +88 -0
  21. data/lib/github_changelog_generator/ssl_certs/cacert.pem +3138 -0
  22. data/lib/github_changelog_generator/task.rb +68 -0
  23. data/lib/github_changelog_generator/version.rb +5 -0
  24. data/lib/github_changelog_generator.rb +49 -0
  25. data/man/git-generate-changelog.1 +393 -0
  26. data/man/git-generate-changelog.1.html +359 -0
  27. data/man/git-generate-changelog.html +270 -0
  28. data/man/git-generate-changelog.md +274 -0
  29. data/spec/files/angular.js.md +9395 -0
  30. data/spec/files/bundler.md +1911 -0
  31. data/spec/files/config_example +5 -0
  32. data/spec/files/github-changelog-generator.md +305 -0
  33. data/spec/github_changelog_generator_spec.rb +32 -0
  34. data/spec/install_gem_in_bundler.gemfile +5 -0
  35. data/spec/spec_helper.rb +74 -0
  36. data/spec/unit/generator/entry_spec.rb +766 -0
  37. data/spec/unit/generator/generator_processor_spec.rb +203 -0
  38. data/spec/unit/generator/generator_spec.rb +47 -0
  39. data/spec/unit/generator/generator_tags_spec.rb +337 -0
  40. data/spec/unit/generator/section_spec.rb +43 -0
  41. data/spec/unit/octo_fetcher_spec.rb +590 -0
  42. data/spec/unit/options_spec.rb +67 -0
  43. data/spec/unit/parser_file_spec.rb +94 -0
  44. data/spec/unit/parser_spec.rb +54 -0
  45. data/spec/unit/reader_spec.rb +120 -0
  46. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
  47. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -0
  48. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -0
  49. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -0
  50. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -0
  51. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -0
  52. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -0
  53. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -0
  54. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -0
  55. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -0
  56. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -0
  57. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -0
  58. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -0
  59. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -0
  60. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -0
  61. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -0
  62. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -0
  63. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -0
  64. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -0
  65. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -0
  66. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -0
  67. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -0
  68. metadata +250 -0
@@ -0,0 +1,590 @@
1
+ # frozen_string_literal: true
2
+
3
+ VALID_TOKEN = "0123456789abcdef"
4
+ INVALID_TOKEN = "0000000000000000"
5
+
6
+ describe GitHubChangelogGenerator::OctoFetcher do
7
+ let(:options) do
8
+ {
9
+ user: "github-changelog-generator",
10
+ project: "changelog_test"
11
+ }
12
+ end
13
+
14
+ let(:fetcher) { GitHubChangelogGenerator::OctoFetcher.new(options) }
15
+
16
+ describe "#check_github_response" do
17
+ context "when returns successfully" do
18
+ it "returns block value" do
19
+ expect(fetcher.send(:check_github_response) { 1 + 1 }).to eq(2)
20
+ end
21
+ end
22
+
23
+ context "when raises Octokit::Unauthorized" do
24
+ it "aborts" do
25
+ expect(fetcher).to receive(:sys_abort).with("Error: wrong GitHub token")
26
+ fetcher.send(:check_github_response) { raise(Octokit::Unauthorized) }
27
+ end
28
+ end
29
+
30
+ context "when raises Octokit::Forbidden" do
31
+ it "sleeps and retries and then aborts" do
32
+ expect(fetcher).to receive(:sys_abort).with("Exceeded retry limit")
33
+ fetcher.send(:check_github_response) { raise(Octokit::Forbidden) }
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "#fetch_github_token" do
39
+ token = GitHubChangelogGenerator::OctoFetcher::CHANGELOG_GITHUB_TOKEN
40
+ context "when token in ENV exist" do
41
+ before { stub_const("ENV", ENV.to_hash.merge(token => VALID_TOKEN)) }
42
+ subject { fetcher.send(:fetch_github_token) }
43
+ it { is_expected.to eq(VALID_TOKEN) }
44
+ end
45
+
46
+ context "when token in ENV is nil" do
47
+ before { stub_const("ENV", ENV.to_hash.merge(token => nil)) }
48
+ subject { fetcher.send(:fetch_github_token) }
49
+ it { is_expected.to be_nil }
50
+ end
51
+
52
+ context "when token in options and ENV is nil" do
53
+ let(:options) { { token: VALID_TOKEN } }
54
+
55
+ before do
56
+ stub_const("ENV", ENV.to_hash.merge(token => nil))
57
+ end
58
+
59
+ subject { fetcher.send(:fetch_github_token) }
60
+ it { is_expected.to eq(VALID_TOKEN) }
61
+ end
62
+
63
+ context "when token in options and ENV specified" do
64
+ let(:options) { { token: VALID_TOKEN } }
65
+
66
+ before do
67
+ stub_const("ENV", ENV.to_hash.merge(token => "no_matter_what"))
68
+ end
69
+
70
+ subject { fetcher.send(:fetch_github_token) }
71
+ it { is_expected.to eq(VALID_TOKEN) }
72
+ end
73
+ end
74
+
75
+ describe "#fetch_all_tags" do
76
+ context "when github_fetch_tags returns tags" do
77
+ it "returns tags" do
78
+ mock_tags = ["tag"]
79
+ allow(fetcher).to receive(:github_fetch_tags).and_return(mock_tags)
80
+ expect(fetcher.fetch_all_tags).to eq(mock_tags)
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "#fetch_tag_shas" do
86
+ let(:commits) do
87
+ [
88
+ { sha: "0", parents: [{ sha: "1" }, { sha: "6" }] },
89
+ { sha: "1", parents: [{ sha: "2" }] },
90
+ { sha: "2", parents: [{ sha: "3" }] },
91
+ { sha: "3", parents: [{ sha: "4" }] },
92
+ { sha: "4", parents: [{ sha: "5" }] },
93
+ { sha: "5", parents: [] },
94
+ { sha: "6", parents: [{ sha: "7" }, { sha: "8" }] },
95
+ { sha: "7", parents: [{ sha: "9" }, { sha: "10" }] },
96
+ { sha: "8", parents: [{ sha: "11" }, { sha: "12" }] },
97
+ { sha: "9", parents: [] },
98
+ { sha: "10", parents: [] },
99
+ { sha: "11", parents: [] },
100
+ { sha: "12", parents: [] }
101
+ ]
102
+ end
103
+
104
+ let(:tag0) { { "name" => "tag-0", "commit" => { "sha" => "0" } } }
105
+ let(:tag1) { { "name" => "tag-1", "commit" => { "sha" => "1" } } }
106
+ let(:tag6) { { "name" => "tag-6", "commit" => { "sha" => "6" } } }
107
+
108
+ before do
109
+ allow(fetcher).to receive(:commits).and_return(commits)
110
+ end
111
+
112
+ it "should find all shas with single parents" do
113
+ fetcher.fetch_tag_shas([tag1])
114
+ expect(tag1["shas_in_tag"]).to eq(Set.new(%w[1 2 3 4 5]))
115
+ end
116
+
117
+ it "should find all shas with multiple parents" do
118
+ fetcher.fetch_tag_shas([tag6])
119
+ expect(tag6["shas_in_tag"]).to eq(Set.new(%w[6 7 8 9 10 11 12]))
120
+ end
121
+
122
+ it "should find all shas with mixed parents" do
123
+ fetcher.fetch_tag_shas([tag0])
124
+ expect(tag0["shas_in_tag"]).to eq(Set.new(%w[0 1 2 3 4 5 6 7 8 9 10 11 12]))
125
+ end
126
+ end
127
+
128
+ describe "#github_fetch_tags" do
129
+ context "when wrong token provided", :vcr do
130
+ let(:options) do
131
+ {
132
+ user: "github-changelog-generator",
133
+ project: "changelog_test",
134
+ token: INVALID_TOKEN
135
+ }
136
+ end
137
+
138
+ it "should raise Unauthorized error" do
139
+ expect { fetcher.github_fetch_tags }.to raise_error SystemExit, "Error: wrong GitHub token"
140
+ end
141
+ end
142
+
143
+ context "when API call is valid", :vcr do
144
+ it "should return tags" do
145
+ expected_tags = [{ "name" => "v0.0.3",
146
+ "zipball_url" =>
147
+ "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3",
148
+ "tarball_url" =>
149
+ "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3",
150
+ "commit" =>
151
+ { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90",
152
+ "url" =>
153
+ "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } },
154
+ { "name" => "v0.0.2",
155
+ "zipball_url" =>
156
+ "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.2",
157
+ "tarball_url" =>
158
+ "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.2",
159
+ "commit" =>
160
+ { "sha" => "9b35bb13dcd15b68e7bcbf10cde5eb937a54f710",
161
+ "url" =>
162
+ "https://api.github.com/repos/skywinder/changelog_test/commits/9b35bb13dcd15b68e7bcbf10cde5eb937a54f710" } },
163
+ { "name" => "v0.0.1",
164
+ "zipball_url" =>
165
+ "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.1",
166
+ "tarball_url" =>
167
+ "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.1",
168
+ "commit" =>
169
+ { "sha" => "4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d",
170
+ "url" =>
171
+ "https://api.github.com/repos/skywinder/changelog_test/commits/4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d" } },
172
+ { "name" => "0.0.4",
173
+ "zipball_url" =>
174
+ "https://api.github.com/repos/skywinder/changelog_test/zipball/0.0.4",
175
+ "tarball_url" =>
176
+ "https://api.github.com/repos/skywinder/changelog_test/tarball/0.0.4",
177
+ "commit" =>
178
+ { "sha" => "ece0c3ab7142b21064b885061c55ede00ef6ce94",
179
+ "url" =>
180
+ "https://api.github.com/repos/skywinder/changelog_test/commits/ece0c3ab7142b21064b885061c55ede00ef6ce94" } }]
181
+
182
+ expect(fetcher.github_fetch_tags).to eq(expected_tags)
183
+ end
184
+
185
+ it "should return tags count" do
186
+ tags = fetcher.github_fetch_tags
187
+ expect(tags.size).to eq(4)
188
+ end
189
+ end
190
+ end
191
+
192
+ describe "#fetch_closed_issues_and_pr" do
193
+ context "when API call is valid", :vcr do
194
+ it "returns issues" do
195
+ issues, pull_requests = fetcher.fetch_closed_issues_and_pr
196
+ expect(issues.size).to eq(7)
197
+ expect(pull_requests.size).to eq(14)
198
+ end
199
+
200
+ it "returns issue with proper key/values" do
201
+ issues, _pull_requests = fetcher.fetch_closed_issues_and_pr
202
+
203
+ expected_issue = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
204
+ "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
205
+ "labels_url" =>
206
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}",
207
+ "comments_url" =>
208
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments",
209
+ "events_url" =>
210
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/events",
211
+ "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
212
+ "id" => 95_419_412,
213
+ "number" => 14,
214
+ "title" => "Issue closed from commit from PR",
215
+ "user" =>
216
+ { "login" => "skywinder",
217
+ "id" => 3_356_474,
218
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
219
+ "gravatar_id" => "",
220
+ "url" => "https://api.github.com/users/skywinder",
221
+ "html_url" => "https://github.com/skywinder",
222
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
223
+ "following_url" =>
224
+ "https://api.github.com/users/skywinder/following{/other_user}",
225
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
226
+ "starred_url" =>
227
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
228
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
229
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
230
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
231
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
232
+ "received_events_url" =>
233
+ "https://api.github.com/users/skywinder/received_events",
234
+ "type" => "User",
235
+ "site_admin" => false },
236
+ "labels" => [],
237
+ "state" => "closed",
238
+ "locked" => false,
239
+ "assignee" => nil,
240
+ "assignees" => [],
241
+ "milestone" => nil,
242
+ "comments" => 0,
243
+ "created_at" => "2015-07-16T12:06:08Z",
244
+ "updated_at" => "2015-07-16T12:21:42Z",
245
+ "closed_at" => "2015-07-16T12:21:42Z",
246
+ "body" => "" }
247
+
248
+ # Convert times to Time
249
+ expected_issue.each_pair do |k, v|
250
+ expected_issue[k] = Time.parse(v) if v.to_s.start_with?("2015-")
251
+ end
252
+
253
+ expect(issues.first).to eq(expected_issue)
254
+ end
255
+
256
+ it "returns pull request with proper key/values" do
257
+ _issues, pull_requests = fetcher.fetch_closed_issues_and_pr
258
+
259
+ expected_pr = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/21",
260
+ "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
261
+ "labels_url" =>
262
+ "https://api.github.com/repos/skywinder/changelog_test/issues/21/labels{/name}",
263
+ "comments_url" =>
264
+ "https://api.github.com/repos/skywinder/changelog_test/issues/21/comments",
265
+ "events_url" =>
266
+ "https://api.github.com/repos/skywinder/changelog_test/issues/21/events",
267
+ "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
268
+ "id" => 124_925_759,
269
+ "number" => 21,
270
+ "title" => "Merged br (should appear in change log with #20)",
271
+ "user" =>
272
+ { "login" => "skywinder",
273
+ "id" => 3_356_474,
274
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
275
+ "gravatar_id" => "",
276
+ "url" => "https://api.github.com/users/skywinder",
277
+ "html_url" => "https://github.com/skywinder",
278
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
279
+ "following_url" =>
280
+ "https://api.github.com/users/skywinder/following{/other_user}",
281
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
282
+ "starred_url" =>
283
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
284
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
285
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
286
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
287
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
288
+ "received_events_url" =>
289
+ "https://api.github.com/users/skywinder/received_events",
290
+ "type" => "User",
291
+ "site_admin" => false },
292
+ "labels" => [],
293
+ "state" => "closed",
294
+ "locked" => false,
295
+ "assignee" => nil,
296
+ "assignees" => [],
297
+ "milestone" => nil,
298
+ "comments" => 0,
299
+ "created_at" => "2016-01-05T09:24:08Z",
300
+ "updated_at" => "2016-01-05T09:26:53Z",
301
+ "closed_at" => "2016-01-05T09:24:27Z",
302
+ "pull_request" =>
303
+ { "url" => "https://api.github.com/repos/skywinder/changelog_test/pulls/21",
304
+ "html_url" => "https://github.com/skywinder/changelog_test/pull/21",
305
+ "diff_url" => "https://github.com/skywinder/changelog_test/pull/21.diff",
306
+ "patch_url" => "https://github.com/skywinder/changelog_test/pull/21.patch" },
307
+ "body" =>
308
+ "to test https://github.com/skywinder/github-changelog-generator/pull/305\r\nshould appear in change log with #20" }
309
+
310
+ # Convert times to Time
311
+ expected_pr.each_pair do |k, v|
312
+ expected_pr[k] = Time.parse(v) if v.to_s.start_with?("2016-01")
313
+ end
314
+
315
+ expect(pull_requests.first).to eq(expected_pr)
316
+ end
317
+
318
+ it "returns issues with labels" do
319
+ issues, _pull_requests = fetcher.fetch_closed_issues_and_pr
320
+ expected = [[], [], ["Bug"], [], ["enhancement"], ["some label"], []]
321
+ expect(issues.map { |i| i["labels"].map { |l| l["name"] } }).to eq(expected)
322
+ end
323
+
324
+ it "returns pull_requests with labels" do
325
+ _issues, pull_requests = fetcher.fetch_closed_issues_and_pr
326
+ expected = [[], [], [], [], [], ["enhancement"], [], [], ["invalid"], [], [], [], [], ["invalid"]]
327
+ expect(pull_requests.map { |i| i["labels"].map { |l| l["name"] } }).to eq(expected)
328
+ end
329
+ end
330
+ end
331
+
332
+ describe "#fetch_closed_pull_requests" do
333
+ context "when API call is valid", :vcr do
334
+ it "returns pull requests" do
335
+ pull_requests = fetcher.fetch_closed_pull_requests
336
+ expect(pull_requests.size).to eq(14)
337
+ end
338
+
339
+ it "returns correct pull request keys" do
340
+ pull_requests = fetcher.fetch_closed_pull_requests
341
+
342
+ pr = pull_requests.first
343
+ expect(pr.keys).to eq(%w[url id html_url diff_url patch_url issue_url number state locked title user body created_at updated_at closed_at merged_at merge_commit_sha assignee assignees milestone commits_url review_comments_url review_comment_url comments_url statuses_url head base _links])
344
+ end
345
+ end
346
+ end
347
+
348
+ describe "#fetch_events_async" do
349
+ context "when API call is valid", :vcr do
350
+ it "populates issues" do
351
+ issues = [{ "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14",
352
+ "repository_url" => "https://api.github.com/repos/skywinder/changelog_test",
353
+ "labels_url" =>
354
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}",
355
+ "comments_url" =>
356
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments",
357
+ "events_url" =>
358
+ "https://api.github.com/repos/skywinder/changelog_test/issues/14/events",
359
+ "html_url" => "https://github.com/skywinder/changelog_test/issues/14",
360
+ "id" => 95_419_412,
361
+ "number" => 14,
362
+ "title" => "Issue closed from commit from PR",
363
+ "user" =>
364
+ { "login" => "skywinder",
365
+ "id" => 3_356_474,
366
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
367
+ "gravatar_id" => "",
368
+ "url" => "https://api.github.com/users/skywinder",
369
+ "html_url" => "https://github.com/skywinder",
370
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
371
+ "following_url" =>
372
+ "https://api.github.com/users/skywinder/following{/other_user}",
373
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
374
+ "starred_url" =>
375
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
376
+ "subscriptions_url" =>
377
+ "https://api.github.com/users/skywinder/subscriptions",
378
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
379
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
380
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
381
+ "received_events_url" =>
382
+ "https://api.github.com/users/skywinder/received_events",
383
+ "type" => "User",
384
+ "site_admin" => false },
385
+ "labels" => [],
386
+ "state" => "closed",
387
+ "locked" => false,
388
+ "assignee" => nil,
389
+ "assignees" => [],
390
+ "milestone" => nil,
391
+ "comments" => 0,
392
+ "created_at" => "2015-07-16T12:06:08Z",
393
+ "updated_at" => "2015-07-16T12:21:42Z",
394
+ "closed_at" => "2015-07-16T12:21:42Z",
395
+ "body" => "" }]
396
+
397
+ # Check that they are blank to begin with
398
+ expect(issues.first["events"]).to be_nil
399
+
400
+ fetcher.fetch_events_async(issues)
401
+ issue_events = issues.first["events"]
402
+
403
+ expected_events = [{ "id" => 357_462_189,
404
+ "url" =>
405
+ "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189",
406
+ "actor" =>
407
+ { "login" => "skywinder",
408
+ "id" => 3_356_474,
409
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
410
+ "gravatar_id" => "",
411
+ "url" => "https://api.github.com/users/skywinder",
412
+ "html_url" => "https://github.com/skywinder",
413
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
414
+ "following_url" =>
415
+ "https://api.github.com/users/skywinder/following{/other_user}",
416
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
417
+ "starred_url" =>
418
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
419
+ "subscriptions_url" =>
420
+ "https://api.github.com/users/skywinder/subscriptions",
421
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
422
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
423
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
424
+ "received_events_url" =>
425
+ "https://api.github.com/users/skywinder/received_events",
426
+ "type" => "User",
427
+ "site_admin" => false },
428
+ "event" => "referenced",
429
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
430
+ "commit_url" =>
431
+ "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
432
+ "created_at" => "2015-07-16T12:21:16Z" },
433
+ { "id" => 357_462_542,
434
+ "url" =>
435
+ "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462542",
436
+ "actor" =>
437
+ { "login" => "skywinder",
438
+ "id" => 3_356_474,
439
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
440
+ "gravatar_id" => "",
441
+ "url" => "https://api.github.com/users/skywinder",
442
+ "html_url" => "https://github.com/skywinder",
443
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
444
+ "following_url" =>
445
+ "https://api.github.com/users/skywinder/following{/other_user}",
446
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
447
+ "starred_url" =>
448
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
449
+ "subscriptions_url" =>
450
+ "https://api.github.com/users/skywinder/subscriptions",
451
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
452
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
453
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
454
+ "received_events_url" =>
455
+ "https://api.github.com/users/skywinder/received_events",
456
+ "type" => "User",
457
+ "site_admin" => false },
458
+ "event" => "closed",
459
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
460
+ "commit_url" =>
461
+ "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
462
+ "created_at" => "2015-07-16T12:21:42Z" }]
463
+
464
+ # Convert times to Time
465
+ expected_events.map! do |event|
466
+ event.each_pair do |k, v|
467
+ event[k] = Time.parse(v) if v.to_s =~ /^201[56]-/
468
+ end
469
+ end
470
+
471
+ expect(issue_events).to eq(expected_events)
472
+ end
473
+ end
474
+ end
475
+
476
+ describe "#fetch_date_of_tag" do
477
+ context "when API call is valid", :vcr do
478
+ it "returns date" do
479
+ tag = { "name" => "v0.0.3",
480
+ "zipball_url" =>
481
+ "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3",
482
+ "tarball_url" =>
483
+ "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3",
484
+ "commit" =>
485
+ { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90",
486
+ "url" =>
487
+ "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } }
488
+
489
+ skywinder = GitHubChangelogGenerator::OctoFetcher.new(
490
+ user: "skywinder",
491
+ project: "changelog_test"
492
+ )
493
+ dt = skywinder.fetch_date_of_tag(tag)
494
+ expect(dt).to eq(Time.parse("2015-03-04 19:01:48 UTC"))
495
+ end
496
+ end
497
+ end
498
+
499
+ describe "#querystring_as_hash" do
500
+ it "works on the blank URL" do
501
+ expect { fetcher.send(:querystring_as_hash, "") }.not_to raise_error
502
+ end
503
+
504
+ it "where there are no querystring params" do
505
+ expect { fetcher.send(:querystring_as_hash, "http://example.com") }.not_to raise_error
506
+ end
507
+
508
+ it "returns a String-keyed Hash of querystring params" do
509
+ expect(fetcher.send(:querystring_as_hash, "http://example.com/o.html?str=18&wis=12")).to include("wis" => "12", "str" => "18")
510
+ end
511
+ end
512
+
513
+ describe "#fetch_commit" do
514
+ context "when API call is valid", :vcr do
515
+ it "returns commit" do
516
+ event = { "id" => 357_462_189,
517
+ "url" =>
518
+ "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189",
519
+ "actor" =>
520
+ { "login" => "github-changelog-generator",
521
+ "id" => 3_356_474,
522
+ "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3",
523
+ "gravatar_id" => "",
524
+ "url" => "https://api.github.com/users/skywinder",
525
+ "html_url" => "https://github.com/skywinder",
526
+ "followers_url" => "https://api.github.com/users/skywinder/followers",
527
+ "following_url" =>
528
+ "https://api.github.com/users/skywinder/following{/other_user}",
529
+ "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}",
530
+ "starred_url" =>
531
+ "https://api.github.com/users/skywinder/starred{/owner}{/repo}",
532
+ "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions",
533
+ "organizations_url" => "https://api.github.com/users/skywinder/orgs",
534
+ "repos_url" => "https://api.github.com/users/skywinder/repos",
535
+ "events_url" => "https://api.github.com/users/skywinder/events{/privacy}",
536
+ "received_events_url" =>
537
+ "https://api.github.com/users/skywinder/received_events",
538
+ "type" => "User",
539
+ "site_admin" => false },
540
+ "event" => "referenced",
541
+ "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555",
542
+ "commit_url" =>
543
+ "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555",
544
+ "created_at" => "2015-07-16T12:21:16Z" }
545
+ commit = fetcher.fetch_commit(event["commit_id"])
546
+
547
+ expectations = [
548
+ %w[sha decfe840d1a1b86e0c28700de5362d3365a29555],
549
+ ["url",
550
+ "https://api.github.com/repos/github-changelog-generator/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
551
+ # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/decfe840d1a1b86e0c28700de5362d3365a29555"],
552
+ ["html_url",
553
+ "https://github.com/github-changelog-generator/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"],
554
+ ["author",
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 }],
556
+ ["committer",
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 }],
558
+ ["parents",
559
+ [{ "sha" => "7ec095e5e3caceacedabf44d0b9b10da17c92e51",
560
+ "url" =>
561
+ "https://api.github.com/repos/github-changelog-generator/changelog_test/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51",
562
+ # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51",
563
+ "html_url" =>
564
+ "https://github.com/github-changelog-generator/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51" }]]
565
+ ]
566
+
567
+ expectations.each do |property, value|
568
+ case value
569
+ when String, Array
570
+ expect(commit[property]).to eq(value)
571
+ when Hash
572
+ expect(commit[property]).to include(value)
573
+ end
574
+ end
575
+ end
576
+ end
577
+ end
578
+
579
+ describe "#commits" do
580
+ context "when API is valid", :vcr do
581
+ subject do
582
+ fetcher.commits
583
+ end
584
+
585
+ it "returns commits" do
586
+ expect(subject.last["sha"]).to eq("4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d")
587
+ end
588
+ end
589
+ end
590
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe GitHubChangelogGenerator::Options do
4
+ describe "#initialize" do
5
+ context "with known options" do
6
+ it "instantiates successfully" do
7
+ expect(described_class.new(user: "olle")[:user]).to eq("olle")
8
+ end
9
+ end
10
+
11
+ context "with unknown options" do
12
+ it "raises an error" do
13
+ expect do
14
+ described_class.new(
15
+ project: "rails",
16
+ strength: "super-strength",
17
+ wisdom: "deep"
18
+ )
19
+ end.to raise_error("[:strength, :wisdom]")
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "#[]=(key, value)" do
25
+ let(:options) { described_class.new(project: "rails") }
26
+
27
+ context "with known options" do
28
+ it "sets the option value" do
29
+ expect do
30
+ options[:project] = "trails"
31
+ end.to change { options[:project] }.to "trails"
32
+ end
33
+ end
34
+
35
+ context "with unknown options" do
36
+ it "raises an error" do
37
+ expect do
38
+ options[:charisma] = 8
39
+ end.to raise_error(":charisma")
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#write_to_file?" do
45
+ subject { options.write_to_file? }
46
+
47
+ let(:options) { described_class.new(output: output) }
48
+
49
+ context "with filename" do
50
+ let(:output) { "CHANGELOG.md" }
51
+
52
+ it { is_expected.to eq true }
53
+ end
54
+
55
+ context "with nil" do
56
+ let(:output) { nil }
57
+
58
+ it { is_expected.to eq false }
59
+ end
60
+
61
+ context "with empty string" do
62
+ let(:output) { "" }
63
+
64
+ it { is_expected.to eq false }
65
+ end
66
+ end
67
+ end