You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
require_relative "../github_feed"
RSpec.describe GithubFeed do
+ describe "#initialization" do+ it "works" do+ feed = GithubFeed.new("rails/rails")+ expect(feed).to be_an_instance_of GithubFeed+ expect(feed.repo_name).to eq "rails/rails"+ end+ end
end
1.2 Make it pass.
github_feed.rb
class GithubFeed
+ attr_reader :repo_name+ def initialize(repo_name)+ @repo_name = repo_name+ end
end
1.3 Simple spec for GithubFeed#recent_comments.
spec/github_feed_spec.rb
expect(feed.repo_name).to eq "rails/rails"
end
end
++ describe "#recent_comments" do+ it "prints from API" do+ feed = GithubFeed.new("rails/rails")++ expect(feed.recent_comments).to match "made a comment on Issue"+ end+ end
end
1.4 Make it pass.
github_feed.rb
def initialize(repo_name)
@repo_name = repo_name
end
++ def recent_comments+ "made a comment on Issue"+ end
end
feed.recent_comments
-## Format:+## Format
<date, format>
-<name> made a comment on Issue #<issue number>+<name> made a comment on Issue #<issue number>
at <link>
> <body at length 30>
-## Example:+## Example
26 Sep 2015
rails-bot made a comment on Issue #123456
at https://github.com/rails/rails/pull/123456#issuecomment-123
@@ -30,6 +33,7 @@ at https://github.com/rails/rails/pull/456789#issuecomment-123
> lorem ipsum..
....
## API
1.7 Turn off RSpec warnings
spec/spec_helper.rb
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
- config.warnings = true+ config.warnings = false
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
1.8 Use HTTP gem.
github_feed.rb
+require "http"+
class GithubFeed
attr_reader :repo_name
@@ -6,6 +8,8 @@ def initialize(repo_name)
end
def recent_comments
+ HTTP.get("https://api.github.com/repos/rails/rails/events")+
"made a comment on Issue"
end
end
1.9 Add webmock and disable all remote connections.
Kernel.srand config.seed
end
++require "webmock/rspec"+WebMock.disable_net_connect!
1.10 Stub GitHub API request.
spec/fixtures/events.json
spec/github_feed_spec.rb
end
describe "#recent_comments" do
+ before do+ stub_request(+ :get, "https://api.github.com/repos/rails/rails/events"+ ).with(+ headers: { "User-Agent"=>"http.rb/0.9.7" }+ ).to_return(+ status: 200, body: File.open("spec/fixtures/events.json")+ )+ end+
it "prints from API" do
feed = GithubFeed.new("rails/rails")
1.11 Failing spec with real values from API response.
spec/github_feed_spec.rb
it "prints from API" do
feed = GithubFeed.new("rails/rails")
- expect(feed.recent_comments).to match "made a comment on Issue"+ expect(feed.recent_comments).to match "sgrif made a comment on Issue #21785"
end
end
end
1.12 Add detailed spec.
spec/github_feed_spec.rb
it "prints from API" do
feed = GithubFeed.new("rails/rails")
- expect(feed.recent_comments).to match "sgrif made a comment on Issue #21785"+ expected =+ <<-COMMENT+27 Sep 2015+sgrif made a comment on Issue #21785+at https://github.com/rails/rails/pull/21785#issuecomment-143571730+ COMMENT++ expect(feed.recent_comments).to match expected
end
end
end
1.13 Make it pass.
github_feed.rb
end
def recent_comments
- HTTP.get("https://api.github.com/repos/rails/rails/events")+ events = JSON.parse(+ HTTP.get("https://api.github.com/repos/#{repo_name}/events")+ )- "made a comment on Issue"+ comments =+ events.map do |event|+ next if event["type"] != "IssueCommentEvent"++ comment = "#{Date.parse(event['created_at']).strftime("%d %b %Y")}\n"+ comment += "#{event['actor']['login']} made a comment on Issue ##{event['payload']['issue']['number']}\n"+ comment += "at #{event['payload']['comment']['html_url']}"+ end++ comments.compact.join("\n")
end
end
1.14 Stub HTTP.get.
spec/github_feed_spec.rb
describe "#recent_comments" do
before do
- stub_request(- :get, "https://api.github.com/repos/rails/rails/events"- ).with(- headers: { "User-Agent"=>"http.rb/0.9.7" }- ).to_return(- status: 200, body: File.open("spec/fixtures/events.json")- )+ expect(HTTP).to receive(:get) { File.read("spec/fixtures/events.json") }
end
it "prints from API" do
1.15 Stub GithubEvent.
spec/github_feed_spec.rb
describe "#recent_comments" do
before do
- expect(HTTP).to receive(:get) { File.read("spec/fixtures/events.json") }+ expect(GithubEvent).to receive(:all).with("rails/rails") { JSON.parse(File.read("spec/fixtures/events.json")) }
end
it "prints from API" do
1.16 Make it pass.
github_feed.rb
end
def recent_comments
- events = JSON.parse(- HTTP.get("https://api.github.com/repos/#{repo_name}/events")- )+ events = GithubEvent.all(@repo_name)
comments =
events.map do |event|
@@ -24,3 +22,8 @@ def recent_comments
comments.compact.join("\n")
end
end
++class GithubEvent+ def self.all(repo_name)+ end+end
1.17 Spec out GithubEvent.all.
spec/github_feed_spec.rb
end
end
end
++RSpec.describe GithubEvent do+ let(:fake_json) { File.read("spec/fixtures/events.json") }++ describe ".all" do+ before do+ stub_request(+ :get, "https://api.github.com/repos/rails/rails/events"+ ).with(+ headers: { "User-Agent" => "http.rb/0.9.7" }+ ).to_return(+ status: 200, body: fake_json+ )+ end++ it "returns results from API" do+ expect(GithubEvent.all("rails/rails")).to eq JSON.parse(fake_json)+ end+ end+end
1.18 Make it pass.
github_feed.rb
class GithubEvent
def self.all(repo_name)
+ JSON.parse(HTTP.get("https://api.github.com/repos/#{repo_name}/events"))
end
end
1.19 Let's use doubles!
spec/github_feed_spec.rb
end
describe "#recent_comments" do
+ let(:fake_events) { [ double(:event, to_s: event_to_s) ] }+ let(:event_to_s) do+ <<-COMMENT+27 Sep 2015+sgrif made a comment on Issue #21785+at https://github.com/rails/rails/pull/21785#issuecomment-143571730+ COMMENT+ end+
before do
- expect(GithubEvent).to receive(:all).with("rails/rails") { JSON.parse(File.read("spec/fixtures/events.json")) }+ expect(GithubEvent).to receive(:all).with("rails/rails") { fake_events }
end
it "prints from API" do
feed = GithubFeed.new("rails/rails")
- expected =- <<-COMMENT-27 Sep 2015-sgrif made a comment on Issue #21785-at https://github.com/rails/rails/pull/21785#issuecomment-143571730- COMMENT-- expect(feed.recent_comments).to match expected+ expect(feed.recent_comments).to match event_to_s
end
end
end
1.20 Make it pass!
github_feed.rb
comments =
events.map do |event|
- next if event["type"] != "IssueCommentEvent"+ # next if event["type"] != "IssueCommentEvent"- comment = "#{Date.parse(event['created_at']).strftime("%d %b %Y")}\n"- comment += "#{event['actor']['login']} made a comment on Issue ##{event['payload']['issue']['number']}\n"- comment += "at #{event['payload']['comment']['html_url']}"+ # comment = "#{Date.parse(event['created_at']).strftime("%d %b %Y")}\n"+ # comment += "#{event['actor']['login']} made a comment on Issue ##{event['payload']['issue']['number']}\n"+ # comment += "at #{event['payload']['comment']['html_url']}"++ event.to_s
end
comments.compact.join("\n")
1.21 Make specs even simpler.
spec/github_feed_spec.rb
end
describe "#recent_comments" do
- let(:fake_events) { [ double(:event, to_s: event_to_s) ] }- let(:event_to_s) do- <<-COMMENT-27 Sep 2015-sgrif made a comment on Issue #21785-at https://github.com/rails/rails/pull/21785#issuecomment-143571730- COMMENT+ let(:fake_events) do+ [double(:event, to_s: "abc"), double(:event, to_s: "def")]
end
before do
@@ -27,7 +22,7 @@
it "prints from API" do
feed = GithubFeed.new("rails/rails")
- expect(feed.recent_comments).to match event_to_s+ expect(feed.recent_comments).to match "abc\ndef"
end
end
end
1.22 Update spec of GithubEvent.all to assert for GithubEvent instances.
spec/github_feed_spec.rb
end
it "returns results from API" do
- expect(GithubEvent.all("rails/rails")).to eq JSON.parse(fake_json)+ events = GithubEvent.all("rails/rails")++ expect(events.count).to eq 30+ expect(events.first).to be_an_instance_of(GithubEvent)+ expect(events.first.raw_data).to eq JSON.parse(fake_json).first
end
end
end
1.23 Make it pass.
github_feed.rb
end
class GithubEvent
+ attr_reader :raw_data++ def initialize(raw_data)+ @raw_data = raw_data+ end+
def self.all(repo_name)
- JSON.parse(HTTP.get("https://api.github.com/repos/#{repo_name}/events"))+ events =+ JSON.parse(HTTP.get("https://api.github.com/repos/#{repo_name}/events"))+ events.map { |event| GithubEvent.new(event) }
end
end
1.24 Spec to_s.
spec/github_feed_spec.rb
expect(events.first.raw_data).to eq JSON.parse(fake_json).first
end
end
++ describe "#to_s" do+ let(:event) { GithubEvent.new(JSON.parse(fake_json).first) }++ it "formats data" do+ expected = "27 Sep 2015\ntimbreitkreutz made a comment on Issue #20602\nat https://github.com/rails/rails/issues/20602#issuecomment-143573857"++ expect(event.to_s).to eq expected+ end+ end
end
1.25 Make it pass.
github_feed.rb
events.map do |event|
# next if event["type"] != "IssueCommentEvent"
- # comment = "#{Date.parse(event['created_at']).strftime("%d %b %Y")}\n"- # comment += "#{event['actor']['login']} made a comment on Issue ##{event['payload']['issue']['number']}\n"- # comment += "at #{event['payload']['comment']['html_url']}"-
event.to_s
end
@@ -37,4 +33,10 @@ def self.all(repo_name)
JSON.parse(HTTP.get("https://api.github.com/repos/#{repo_name}/events"))
events.map { |event| GithubEvent.new(event) }
end
++ def to_s+ "#{Date.parse(raw_data['created_at']).strftime("%d %b %Y")}\n" \+ "#{raw_data['actor']['login']} made a comment on Issue ##{raw_data['payload']['issue']['number']}\n" \+ "at #{raw_data['payload']['comment']['html_url']}"+ end
end
1.26 Spec for filtering of results.
spec/github_feed_spec.rb
expect(events.first).to be_an_instance_of(GithubEvent)
expect(events.first.raw_data).to eq JSON.parse(fake_json).first
end
++ it "filters results" do+ events = GithubEvent.all("rails/rails", only: "IssueCommentEvent")++ expect(events.count).to eq 10+ expect(events.map(&:type).uniq).to eq ["IssueCommentEvent"]+ end
end
describe "#to_s" do
end
def recent_comments
- events = GithubEvent.all(@repo_name)-- comments =- events.map do |event|- # next if event["type"] != "IssueCommentEvent"-- event.to_s- end-- comments.compact.join("\n")+ events = GithubEvent.all(@repo_name, only: "IssueCommentEvent")+ events.map { |event| event.to_s }.join("\n")
end
end
spec/github_feed_spec.rb
end
before do
- expect(GithubEvent).to receive(:all).with("rails/rails") { fake_events }+ expect(GithubEvent).to receive(:all)+ .with("rails/rails", only: "IssueCommentEvent") { fake_events }
end
it "prints from API" do
1.29 Example 2 of using spies.
github_feed.rb
def recent_comments
events = GithubEvent.all(@repo_name, only: "IssueCommentEvent")
- events.map { |event| event.to_s }.join("\n")+ events.map { |event| event.render }.join("\n")
end
end
@@ -32,7 +32,7 @@ def type
raw_data["type"]
end
- def to_s+ def render
"#{Date.parse(raw_data['created_at']).strftime("%d %b %Y")}\n" \
"#{raw_data['actor']['login']} made a comment on Issue ##{raw_data['payload']['issue']['number']}\n" \
"at #{raw_data['payload']['comment']['html_url']}"
spec/github_feed_spec.rb
end
describe "#recent_comments" do
- let(:fake_events) do- [double(:event, to_s: "abc"), double(:event, to_s: "def")]- end+ let(:event_1) { spy(:event) }+ let(:event_2) { spy(:event) }+ let(:fake_events) { [ event_1, event_2 ] }
before do
expect(GithubEvent).to receive(:all)
@@ -22,10 +22,10 @@
it "prints from API" do
feed = GithubFeed.new("rails/rails")
- comments = feed.recent_comments+ feed.recent_comments- expect(GithubEvent).to have_received(:all)- expect(comments).to match "abc\ndef"+ expect(event_1).to have_received(:render)+ expect(event_2).to have_received(:render)
end
end
end
@@ -66,7 +66,7 @@
it "formats data" do
expected = "27 Sep 2015\ntimbreitkreutz made a comment on Issue #20602\nat https://github.com/rails/rails/issues/20602#issuecomment-143573857"
- expect(event.to_s).to eq expected+ expect(event.render).to eq expected
end
end
end
1.30 Example 1 of using spies (partial double).
spec/github_feed_spec.rb
it "prints from API" do
feed = GithubFeed.new("rails/rails")
+ comments = feed.recent_comments- expect(feed.recent_comments).to match "abc\ndef"+ expect(GithubEvent).to have_received(:all)+ expect(comments).to match "abc\ndef"
end
end
end
1.31 Trivial message chain stub.
github_feed.rb
def self.all(repo_name, only: nil)
events =
JSON.parse(HTTP.get("https://api.github.com/repos/#{repo_name}/events"))
- events.map! { |event| GithubEvent.new(event) }- events.select! { |event| event.type == only } if only+ events = events.map { |event| GithubEvent.new(event) }+ events = events.select { |event| event.type == only } if only
events
end
spec/github_feed_spec.rb
let(:fake_json) { File.read("spec/fixtures/events.json") }
describe ".all" do
- before do- stub_request(- :get, "https://api.github.com/repos/rails/rails/events"- ).with(- headers: { "User-Agent" => "http.rb/0.9.7" }- ).to_return(- status: 200, body: fake_json- )- end+ context "webmock" do+ before do+ stub_request(+ :get, "https://api.github.com/repos/rails/rails/events"+ ).with(+ headers: { "User-Agent" => "http.rb/0.9.7" }+ ).to_return(+ status: 200, body: fake_json+ )+ end- it "returns results from API" do- events = GithubEvent.all("rails/rails")+ it "returns results from API" do+ events = GithubEvent.all("rails/rails")- expect(events.count).to eq 30- expect(events.first).to be_an_instance_of(GithubEvent)- expect(events.first.raw_data).to eq JSON.parse(fake_json).first+ expect(events.count).to eq 30+ expect(events.first).to be_an_instance_of(GithubEvent)+ expect(events.first.raw_data).to eq JSON.parse(fake_json).first+ end
end
- it "filters results" do- events = GithubEvent.all("rails/rails", only: "IssueCommentEvent")+ context "doubles" do+ before do+ allow(HTTP).to receive(:get) { HTTP }+ end++ it "filters results" do+ fake_events = double(:events)+ expect(JSON).to receive(:parse) { fake_events }+ allow(fake_events).to receive_message_chain(:map, :select) { fake_events }++ events = GithubEvent.all("rails/rails", only: "IssueCommentEvent")- expect(events.count).to eq 10- expect(events.map(&:type).uniq).to eq ["IssueCommentEvent"]+ expect(events).to eq fake_events+ end
end
end