ical_importer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/.rvmrc +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +34 -0
- data/README.md +74 -0
- data/Rakefile +13 -0
- data/ical_importer.gemspec +25 -0
- data/lib/ical_importer/builder.rb +22 -0
- data/lib/ical_importer/collector.rb +25 -0
- data/lib/ical_importer/date_exclusion.rb +11 -0
- data/lib/ical_importer/local_event.rb +59 -0
- data/lib/ical_importer/parser.rb +75 -0
- data/lib/ical_importer/recurrence_event_builder.rb +37 -0
- data/lib/ical_importer/remote_event.rb +54 -0
- data/lib/ical_importer/single_event_builder.rb +128 -0
- data/lib/ical_importer/version.rb +3 -0
- data/lib/ical_importer.rb +11 -0
- data/spec/ical_importer/builder_spec.rb +45 -0
- data/spec/ical_importer/collector_spec.rb +21 -0
- data/spec/ical_importer/date_exclusion_spec.rb +30 -0
- data/spec/ical_importer/local_event_spec.rb +126 -0
- data/spec/ical_importer/parser_spec.rb +126 -0
- data/spec/ical_importer/recurrence_event_builder_spec.rb +57 -0
- data/spec/ical_importer/remote_event_spec.rb +69 -0
- data/spec/ical_importer/single_event_builder_spec.rb +18 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/mn_twins.ics +1412 -0
- data/spec/support/test.ics +40 -0
- metadata +187 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module IcalImporter
|
3
|
+
describe DateExclusion do
|
4
|
+
subject { DateExclusion.new(attributes) }
|
5
|
+
describe "#initialize" do
|
6
|
+
describe "set the one valid attribute" do
|
7
|
+
let(:attributes) { { :date_exclusion => "yerp" } }
|
8
|
+
it "sets the date exlcusion" do
|
9
|
+
subject.date_exclusion.should == "yerp"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "try to set valid/invalid attributes" do
|
14
|
+
let(:attributes) { { :date_exclusion => "yerp", :not_me => "nope" } }
|
15
|
+
it "sets the date exlcusion" do
|
16
|
+
subject.date_exclusion.should == "yerp"
|
17
|
+
expect { subject.not_me }.to raise_error(NoMethodError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "set the one valid attribute" do
|
22
|
+
let(:attributes) { { :not_me => "yerp", :or_me => "nope" } }
|
23
|
+
it "sets the date exlcusion" do
|
24
|
+
expect { subject.not_me }.to raise_error(NoMethodError)
|
25
|
+
expect { subject.or_me }.to raise_error(NoMethodError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module IcalImporter
|
3
|
+
describe LocalEvent do
|
4
|
+
subject { LocalEvent.new(attributes) }
|
5
|
+
describe "#init" do
|
6
|
+
let(:attributes) { {} }
|
7
|
+
it { should respond_to :uid }
|
8
|
+
it { should respond_to :title }
|
9
|
+
it { should respond_to :description }
|
10
|
+
it { should respond_to :location }
|
11
|
+
it { should respond_to :start_date_time }
|
12
|
+
it { should respond_to :end_date_time }
|
13
|
+
it { should respond_to :utc }
|
14
|
+
it { should respond_to :date_exclusions }
|
15
|
+
it { should respond_to :recur_end_date }
|
16
|
+
it { should respond_to :recur_month_repeat_by }
|
17
|
+
it { should respond_to :recur_interval }
|
18
|
+
it { should respond_to :recur_interval_value }
|
19
|
+
it { should respond_to :recur_end_date }
|
20
|
+
it { should respond_to :recurrence_id }
|
21
|
+
it { should respond_to :all_day_event }
|
22
|
+
it { should respond_to :recurrence }
|
23
|
+
it { should respond_to :recur_week_sunday }
|
24
|
+
it { should respond_to :recur_week_monday }
|
25
|
+
it { should respond_to :recur_week_tuesday }
|
26
|
+
it { should respond_to :recur_week_wednesday }
|
27
|
+
it { should respond_to :recur_week_thursday }
|
28
|
+
it { should respond_to :recur_week_friday }
|
29
|
+
it { should respond_to :recur_week_saturday }
|
30
|
+
it { should respond_to :uid= }
|
31
|
+
it { should respond_to :title= }
|
32
|
+
it { should respond_to :description= }
|
33
|
+
it { should respond_to :location= }
|
34
|
+
it { should respond_to :start_date_time= }
|
35
|
+
it { should respond_to :end_date_time= }
|
36
|
+
it { should respond_to :utc= }
|
37
|
+
it { should respond_to :date_exclusions= }
|
38
|
+
it { should respond_to :recur_end_date= }
|
39
|
+
it { should respond_to :recur_month_repeat_by= }
|
40
|
+
it { should respond_to :recur_interval= }
|
41
|
+
it { should respond_to :recur_interval_value= }
|
42
|
+
it { should respond_to :recur_end_date= }
|
43
|
+
it { should respond_to :recurrence_id= }
|
44
|
+
it { should respond_to :all_day_event= }
|
45
|
+
it { should respond_to :recurrence= }
|
46
|
+
it { should respond_to :recur_week_sunday= }
|
47
|
+
it { should respond_to :recur_week_monday= }
|
48
|
+
it { should respond_to :recur_week_tuesday= }
|
49
|
+
it { should respond_to :recur_week_wednesday= }
|
50
|
+
it { should respond_to :recur_week_thursday= }
|
51
|
+
it { should respond_to :recur_week_friday= }
|
52
|
+
it { should respond_to :recur_week_saturday= }
|
53
|
+
|
54
|
+
describe "#get_attributes" do
|
55
|
+
let(:attributes) { { :uid => 1, :title => 'winner', :utc => true } }
|
56
|
+
it "selects some attributes" do
|
57
|
+
subject.get_attributes(['utc', :uid]).should == { :uid => 1, :utc => true }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "gets and empty hash" do
|
61
|
+
subject.get_attributes(['doesnt exist']).should == { }
|
62
|
+
end
|
63
|
+
|
64
|
+
it "sends an empty array" do
|
65
|
+
subject.get_attributes([]).should == { }
|
66
|
+
end
|
67
|
+
|
68
|
+
it "doesn't send an array" do
|
69
|
+
expect { subject.get_attributes({}) }.to raise_error(ArgumentError, "Must be an Array")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#to_hash" do
|
74
|
+
let(:attributes) { { :uid => 1, :title => "winner" } }
|
75
|
+
it "should return all of the attributes" do
|
76
|
+
subject.to_hash.should == {
|
77
|
+
:uid => 1,
|
78
|
+
:title => "winner",
|
79
|
+
:description => nil,
|
80
|
+
:location => nil,
|
81
|
+
:start_date_time => nil,
|
82
|
+
:end_date_time => nil,
|
83
|
+
:utc => nil,
|
84
|
+
:date_exclusions => [], # Set in initializer
|
85
|
+
:recur_end_date => nil,
|
86
|
+
:recur_month_repeat_by => nil,
|
87
|
+
:recur_interval => nil,
|
88
|
+
:recur_interval_value => nil,
|
89
|
+
:recur_end_date => nil,
|
90
|
+
:recurrence_id => nil,
|
91
|
+
:all_day_event => nil,
|
92
|
+
:recurrence => nil,
|
93
|
+
:recur_week_sunday => nil,
|
94
|
+
:recur_week_monday => nil,
|
95
|
+
:recur_week_tuesday => nil,
|
96
|
+
:recur_week_wednesday => nil,
|
97
|
+
:recur_week_thursday => nil,
|
98
|
+
:recur_week_friday => nil,
|
99
|
+
:recur_week_saturday => nil
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#attributes=" do
|
105
|
+
let(:attributes) { { :uid => 1, :title => "winner" } }
|
106
|
+
it "sets a few attributes" do
|
107
|
+
subject.attributes = { :uid => 2, :description => "we got 'em" }
|
108
|
+
subject.uid.should == 2
|
109
|
+
subject.attributes[:uid].should == 2
|
110
|
+
subject.title.should == "winner"
|
111
|
+
subject.attributes[:title].should == "winner"
|
112
|
+
subject.description.should == "we got 'em"
|
113
|
+
subject.attributes[:description].should == "we got 'em"
|
114
|
+
end
|
115
|
+
|
116
|
+
it "sets the acceptable attributes, not the unacceptable" do
|
117
|
+
subject.attributes = { :dont => "use", :me => "ha", :uid => 3 }
|
118
|
+
subject.uid.should == 3
|
119
|
+
subject.attributes[:uid].should == 3
|
120
|
+
subject.attributes[:dont].should == nil
|
121
|
+
subject.attributes[:me].should == nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timeout'
|
3
|
+
module IcalImporter
|
4
|
+
describe Parser do
|
5
|
+
subject { Parser.new(url) }
|
6
|
+
let(:url) { "http://some_url" }
|
7
|
+
let(:bare_stuff) { stub :pos= => true }
|
8
|
+
before do
|
9
|
+
::Timeout.stub!(:timeout).and_yield
|
10
|
+
RemoteEvent.any_instance.stub :all_day_event? => true
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
it "parses with rical" do
|
15
|
+
Parser.any_instance.stub(:open_ical).and_return bare_stuff
|
16
|
+
RiCal.should_receive(:parse).with bare_stuff
|
17
|
+
Parser.new(url)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#should_parse?" do
|
22
|
+
it "should parse" do
|
23
|
+
subject.stub :bare_feed => bare_stuff
|
24
|
+
subject.should_parse?.should == true
|
25
|
+
end
|
26
|
+
|
27
|
+
context "empty base_feed" do
|
28
|
+
it "is false" do
|
29
|
+
subject.stub :base_feed => nil
|
30
|
+
subject.should_parse?.should == false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#worth_parsing?" do
|
36
|
+
it "should be parsed" do
|
37
|
+
feed = stub :present? => true, :first => true
|
38
|
+
subject.stub :feed => feed, :should_parse? => true
|
39
|
+
subject.worth_parsing?.should == true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#all_events" do
|
44
|
+
let(:url) { sample_ics_path }
|
45
|
+
it "has all 3 events" do
|
46
|
+
subject.parse
|
47
|
+
subject.all_events.count.should == 3
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#single_events" do
|
52
|
+
let(:url) { sample_ics_path }
|
53
|
+
it "has the 3 singluar events" do
|
54
|
+
subject.parse
|
55
|
+
subject.single_events.count.should == 3
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Need to find a good example feed with recurrence_id set
|
60
|
+
describe "#recurrence_events" do
|
61
|
+
let(:url) { sample_ics_path }
|
62
|
+
it "has 0 recurrence_events" do
|
63
|
+
subject.parse
|
64
|
+
subject.recurrence_events.count.should == 0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#parse" do
|
69
|
+
let(:url) { sample_ics_path }
|
70
|
+
it "returns 3 events" do
|
71
|
+
subject.parse.count.should == 3
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can use a block to manipulate events" do
|
75
|
+
count = 0
|
76
|
+
subject.parse do |e|
|
77
|
+
e.should be_an_instance_of LocalEvent
|
78
|
+
count += 1
|
79
|
+
end
|
80
|
+
count.should == 3
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#open_ical" do
|
85
|
+
it 'cleans up and tries to open an HTTP URL' do
|
86
|
+
subject.stub :open => bare_stuff
|
87
|
+
subject.send(:open_ical).should == bare_stuff
|
88
|
+
end
|
89
|
+
|
90
|
+
it "fails with an invalid protocol" do
|
91
|
+
expect { subject.send(:open_ical, 'wrong_proto') }.to raise_error(ArgumentError, "Must be http or https")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#prepped_uri" do
|
96
|
+
it "spits back the http URL" do
|
97
|
+
subject.send(:prepped_uri, 'http').should == url
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "https" do
|
101
|
+
let(:url) { "https://some_url" }
|
102
|
+
it "spits back the https URL" do
|
103
|
+
subject.send(:prepped_uri, 'https').should == url
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "webcal" do
|
108
|
+
let(:base_url) { "://some_url" }
|
109
|
+
let(:http_url) { "http#{base_url}" }
|
110
|
+
let(:url) { "webcal#{base_url}" }
|
111
|
+
it "spits back the http URL" do
|
112
|
+
subject.send(:prepped_uri, 'http').should == http_url
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "Webcal" do
|
117
|
+
let(:base_url) { "://some_url" }
|
118
|
+
let(:http_url) { "http#{base_url}" }
|
119
|
+
let(:url) { "Webcal#{base_url}" }
|
120
|
+
it "spits back the http URL" do
|
121
|
+
subject.send(:prepped_uri, 'http').should == http_url
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module IcalImporter
|
3
|
+
describe RecurrenceEventBuilder do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "should set up basic accessors" do
|
6
|
+
subject.events_to_build.should == []
|
7
|
+
subject.built_events.should == []
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#<<" do
|
12
|
+
it "adds event" do
|
13
|
+
new_event = stub(:is_a? => true)
|
14
|
+
subject << new_event
|
15
|
+
subject.events_to_build.should == [new_event]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "fails with incorrect event type" do
|
19
|
+
new_event = stub(:is_a? => false)
|
20
|
+
expect { subject.<<(new_event) }.to raise_error(ArgumentError, "Must be a RiCal Event")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#build" do
|
25
|
+
it "wraps builds the events and fills in the attribute" do
|
26
|
+
event_list = [stub, stub]
|
27
|
+
RemoteEvent.stub(:new).and_return(event_list[0], event_list[1])
|
28
|
+
subject.stub :events_to_build => event_list
|
29
|
+
subject.should_receive(:build_new_local_event).with(event_list[0]).ordered.and_return("boom1")
|
30
|
+
subject.should_receive(:build_new_local_event).with(event_list[1]).ordered.and_return("boom2")
|
31
|
+
subject.build
|
32
|
+
subject.built_events.should == %w[boom1 boom2]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#build_new_local_event" do
|
37
|
+
let(:remote_event) { stub :summary => "birthdayy",
|
38
|
+
:uid => 1,
|
39
|
+
:description => "do stuff",
|
40
|
+
:location => "here",
|
41
|
+
:start_date_time => "today",
|
42
|
+
:end_date_time => "tomorrow",
|
43
|
+
:recurrence_id => 1
|
44
|
+
}
|
45
|
+
it "creates a new event" do
|
46
|
+
RemoteEvent.stub(:new => remote_event)
|
47
|
+
local_event = subject.send(:build_new_local_event, remote_event)
|
48
|
+
local_event.title.should == "birthdayy"
|
49
|
+
local_event.description.should == "do stuff"
|
50
|
+
local_event.location.should == "here"
|
51
|
+
local_event.start_date_time.should == "today"
|
52
|
+
local_event.end_date_time.should == "tomorrow"
|
53
|
+
local_event.recurrence.should == true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module IcalImporter
|
3
|
+
describe RemoteEvent do
|
4
|
+
subject { RemoteEvent.new(event) }
|
5
|
+
let(:event) { stub :dtstart => stub(:tzid => nil) }
|
6
|
+
it { should respond_to :description }
|
7
|
+
it { should respond_to :recurs? }
|
8
|
+
it { should respond_to :rrule_property }
|
9
|
+
it { should respond_to :exdate }
|
10
|
+
describe "#initialize" do
|
11
|
+
describe "dtstart tzid nil" do
|
12
|
+
it "sets utc and event" do
|
13
|
+
subject.event.should == event
|
14
|
+
subject.utc?.should == true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "dtstart tzid == :floating" do
|
19
|
+
let(:event) { stub :dtstart => stub(:tzid => :floating) }
|
20
|
+
it "sets utc and event" do
|
21
|
+
subject.event.should == event
|
22
|
+
subject.utc?.should == false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#start_date_time" do
|
28
|
+
describe "with string date" do
|
29
|
+
let(:event) { stub :dtstart => "20120715" }
|
30
|
+
it "gets the date time" do
|
31
|
+
subject.start_date_time.should == event.dtstart.to_datetime
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "with an actual DateTime" do
|
36
|
+
let(:event) { stub :dtstart => "20120715".to_datetime }
|
37
|
+
it "uses the datetime because it is already that" do
|
38
|
+
subject.start_date_time.should == event.dtstart
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "without a floating tzid" do
|
43
|
+
let(:event) { stub :dtstart => stub(
|
44
|
+
:is_a? => true,
|
45
|
+
:tzid => nil,
|
46
|
+
:time => "20120715".to_datetime,
|
47
|
+
:utc => "20120715".to_datetime.utc) }
|
48
|
+
it "uses the utc time of the datetime" do
|
49
|
+
subject.start_date_time.should == event.dtstart.time.utc
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#event_attributes" do
|
55
|
+
let(:event) { RiCal.parse(sample_ics).first.events.first }
|
56
|
+
it "fills in some attributes" do
|
57
|
+
subject.event_attributes.should == {
|
58
|
+
:uid => "1629F7A5-5A69-43CB-899E-4CE9BD5F069F",
|
59
|
+
:title => "Recurring Event",
|
60
|
+
:utc => true,
|
61
|
+
:description => nil,
|
62
|
+
:location => "",
|
63
|
+
:start_date_time => "Wed, 14 Sep 2016 00:00:00 +0000".to_datetime,
|
64
|
+
:end_date_time => "Thu, 15 Sep 2016 00:00:00 +0000".to_datetime,
|
65
|
+
:all_day_event => true}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module IcalImporter
|
3
|
+
describe SingleEventBuilder do
|
4
|
+
subject { SingleEventBuilder.new(event) }
|
5
|
+
let(:event) { RiCal.parse(sample_ics('mn_twins')).first.events.first }
|
6
|
+
describe "#build" do
|
7
|
+
it "builds an event" do
|
8
|
+
new_event = subject.build
|
9
|
+
new_event.should be_a LocalEvent
|
10
|
+
new_event.title.should == "Spring Training: Tampa Bay 3 - Minnesota 7"
|
11
|
+
new_event.utc?.should == true
|
12
|
+
new_event.description.should == "Spring Training: Tampa Bay 3 - Minnesota 7\n\nClick below for game previews, wraps and boxscores plus video, tickets, stats, gameday and more!\nhttp://mlb.mlb.com/mlb/gameday/index.jsp?gid=2012_03_03_tbamlb_minmlb_1\n\nWatch or Listen with MLB.TV: http://mlb.mlb.com/schedule/index.jsp?c_id=min&m=03&y=2012\n\nLocal Radio: 1500 ESPN"
|
13
|
+
new_event.location.should == "Lee County Sports Complex, Hammond County Stadium, Lee County"
|
14
|
+
new_event.all_day_event.should == false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
require 'ical_importer'
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
config.filter_run :focus
|
12
|
+
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = 'random'
|
18
|
+
end
|
19
|
+
|
20
|
+
def sample_ics(file_name=nil)
|
21
|
+
File.open sample_ics_path(file_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def sample_ics_path(file_name=nil)
|
25
|
+
File.join(File.dirname(__FILE__), 'support', "#{file_name || 'test'}.ics")
|
26
|
+
end
|