require 'spec_helper' module Calagator describe Source::Parser, type: :model do around do |example| Timecop.freeze("2000-01-01") do example.run end end before do Calagator.meetup_api_key = "foo" end describe "when reading content" do it "should read from a normal URL" do stub_request(:get, "http://a.real/~url").to_return(body: "42") expect(Source::Parser.read_url("http://a.real/~url")).to eq "42" end it "should raise an error when unauthorized" do stub_request(:get, "http://a.private/~url").to_return(status: [401, "Forbidden"]) expect { Source::Parser.read_url("http://a.private/~url") }.to raise_error Source::Parser::HttpAuthenticationRequiredError end end describe "when subclassing" do it "should demand that #to_events is implemented" do expect{ Source::Parser.new.to_events }.to raise_error NotImplementedError end end describe "when parsing events" do before do Calagator.facebook_access_token = "fake_access_token" end it "should have site-specific parsers first, then generics" do expect(Source::Parser.parsers.to_a).to eq [ Source::Parser::Facebook, Source::Parser::Meetup, Source::Parser::Hcal, Source::Parser::Ical, ] end it "should use first successful parser's results" do events = [double] body = { name: "event", start_time: "2010-01-01 12:00:00 UTC", end_time: "2010-01-01 13:00:00 UTC" }.to_json stub_request(:get, "https://graph.facebook.com/omg?access_token=fake_access_token").to_return(body: body, headers: { content_type: "application/json" }) expect(Source::Parser.to_events(url: "http://www.facebook.com/events/omg")).to have(1).event end end describe "checking duplicates when importing" do describe "with two identical events" do before :each do @venue_size_before_import = Venue.count url = "http://mysample.hcal/" @cal_source = Source.new(title: "Calendar event feed", url: url) @cal_content = (%{
}) stub_request(:get, url).to_return(body: @cal_content) @events = @cal_source.to_events @created_events = @cal_source.create_events! end it "should only parse one event" do expect(@events.size).to eq 1 end it "should create only one event" do expect(@created_events.size).to eq 1 end it "should create only one venue" do expect(Venue.count).to eq @venue_size_before_import + 1 end end describe "with an event" do it "should retrieve an existing event if it's an exact duplicate" do url = "http://mysample.hcal/" hcal_source = Source.new(title: "Calendar event feed", url: url) stub_request(:get, url).to_return(body: read_sample('hcal_event_duplicates_fixture.xml')) event = hcal_source.to_events.first event.save! event2 = hcal_source.to_events.first expect(event2).not_to be_a_new_record end it "an event with a orphaned exact duplicate should should remove duplicate marking" do orphan = Event.create!(:title => "orphan", :start_time => Time.parse("July 14 2008"), :duplicate_of_id => 7142008 ) cal_content = %(
) url = "http://mysample.hcal/" stub_request(:get, url).to_return(body: cal_content) cal_source = Source.new(title: "Calendar event feed", url: url) imported_event = cal_source.create_events!.first expect(imported_event).not_to be_marked_as_duplicate end end describe "should create two events when importing two non-identical events" do # This behavior is tested under # describe Source::Parser::Hcal, "with hCalendar events" do # 'it "should parse a page with multiple events" ' end describe "two identical events with different venues" do before(:each) do cal_content = %(
) url = "http://mysample.hcal/" stub_request(:get, url).to_return(body: cal_content) cal_source = Source.new(title: "Calendar event feed", url: url) @parsed_events = cal_source.to_events @created_events = cal_source.create_events! end it "should parse two events" do expect(@parsed_events.size).to eq 2 end it "should create two events" do expect(@created_events.size).to eq 2 end it "should have different venues for the parsed events" do expect(@parsed_events[0].venue).not_to eq @parsed_events[1].venue end it "should have different venues for the created events" do expect(@created_events[0].venue).not_to eq @created_events[1].venue end end it "should use an existing venue when importing an event whose venue matches a squashed duplicate" do dummy_source = Source.create!(:title => "Dummy", :url => "http://IcalEventWithSquashedVenue.com/") master_venue = Venue.create!(:title => "Master") squashed_venue = Venue.create!( :title => "Squashed Duplicate Venue", :duplicate_of_id => master_venue.id) cal_content = %(
) url = "http://mysample.hcal/" stub_request(:get, url).to_return(body: cal_content) source = Source.new(title: "Event with squashed venue", url: url) event = source.to_events.first expect(event.venue.title).to eq "Master" end it "should use an existing venue when importing an event with a matching machine tag that describes a venue" do venue = Venue.create!(:title => "Custom Urban Airship", :tag_list => "meetup:venue=774133") meetup_url = "http://www.meetup.com/pdxpython/events/ldhnqyplbnb/" api_url = "https://api.meetup.com/2/event/ldhnqyplbnb?key=foo&sign=true&fields=topics" stub_request(:get, api_url).to_return(body: read_sample('meetup.json'), headers: { content_type: "application/json" }) source = Source.new(title: "Event with duplicate machine-tagged venue", url: meetup_url) event = source.to_events.first expect(event.venue).to eq venue end describe "choosing parsers by matching URLs" do { "Calagator::Source::Parser::Facebook" => "http://facebook.com/event.php?eid=247619485255249", "Calagator::Source::Parser::Meetup" => "http://www.meetup.com/pdxweb/events/23287271/" }.each do |parser_name, url| it "should only invoke the #{parser_name} parser when given #{url}" do parser = parser_name.constantize expect_any_instance_of(parser).to receive(:to_events).and_return([Event.new]) Source::Parser.parsers.reject{|p| p == parser }.each do |other_parser| expect_any_instance_of(other_parser).not_to receive :to_events end stub_request(:get, url) Source.new(:title => parser_name, :url => url).to_events end end end end describe "labels" do it "should have labels" do expect(Source::Parser.labels).not_to be_blank end it "should have labels for each parser" do expect(Source::Parser.labels.size).to eq Source::Parser.parsers.size end it "should use the label of the parser, as a string" do label = Source::Parser.parsers.first.label.to_s expect(Source::Parser.labels).to include label end it "should have sorted labels" do labels = Source::Parser.labels sorted = labels.sort_by(&:downcase) expect(labels).to eq sorted end end end end