almanack 0.0.1.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +21 -0
- data/almanac.gemspec +33 -0
- data/lib/almanack/calendar.rb +21 -0
- data/lib/almanack/configuration.rb +29 -0
- data/lib/almanack/event.rb +6 -0
- data/lib/almanack/ical_feed.rb +60 -0
- data/lib/almanack/meetup_group.rb +96 -0
- data/lib/almanack/server.rb +13 -0
- data/lib/almanack/simple_event_collection.rb +11 -0
- data/lib/almanack/themes/origami/public/stylesheets/origami.css +4 -0
- data/lib/almanack/themes/origami/views/events.erb +8 -0
- data/lib/almanack/themes/origami/views/layout.erb +13 -0
- data/lib/almanack/version.rb +3 -0
- data/lib/almanack.rb +23 -0
- data/spec/calendar_spec.rb +44 -0
- data/spec/configuration_spec.rb +45 -0
- data/spec/event_spec.rb +32 -0
- data/spec/features/calendar_feature_spec.rb +35 -0
- data/spec/fixtures/responses/google_calendar.yml +1896 -0
- data/spec/fixtures/responses/meetup.yml +1437 -0
- data/spec/ical_feed_spec.rb +30 -0
- data/spec/meetup_group_spec.rb +26 -0
- data/spec/simple_event_collection_spec.rb +23 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/event_matchers.rb +54 -0
- data/spec/support/server_support.rb +9 -0
- metadata +255 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5ee646213641a7f73f5cd5d2164c92930875b58d
|
4
|
+
data.tar.gz: 474257e5d3e93edd1a5c4b5b4125129c7c645ba2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: caf49861afbd6bd62c5147da62425ed06b822a65ed4e5d543062b2a27e9ae67d9f53e4a88a8235ae590a4554c98475016b83ab9cc8237ac2194c03063d859bc5
|
7
|
+
data.tar.gz: 6d5458aa700b1c152caa5a31f2294a766e0a6ca6ab3eeb673bf4be9213aa806c9982663bc3c8088999130d08d637fccd8690abc7b445a7d8893ce6d1b68fb327
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
rvm:
|
4
|
+
- 2.1.1
|
5
|
+
addons:
|
6
|
+
code_climate:
|
7
|
+
repo_token:
|
8
|
+
secure: "VmXcnoFkthPYiEdyMTgqopGNUirpoZ3/wRych2xm+k8g9yW3IVbnEsK0lLg7InlyUhM3r7IxC4NBTRa33MhkpuCtvQGFpUjt56lhDvLcb0OBLOnpReKpo8VWW/cy0okpiW8LNt488M67WH+Wnlx//Fpkop9/HNM1vTLjysISk/Q="
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Pete Nicholls
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Almanack
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/Aupajo/sinatra-gcal.svg)](https://travis-ci.org/Aupajo/sinatra-gcal)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/Aupajo/sinatra-gcal.png)](https://codeclimate.com/github/Aupajo/sinatra-gcal)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/Aupajo/sinatra-gcal/coverage.png)](https://codeclimate.com/github/Aupajo/sinatra-gcal)
|
6
|
+
|
7
|
+
TODO: Write a gem description
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'almanack'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install almanack
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
### Meetup.com
|
28
|
+
|
29
|
+
You'll need your [Meetup.com API key](https://secure.meetup.com/meetup_api/key).
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it ( http://github.com/Aupajo/sinatra-gcal/fork )
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
desc 'Run a dummy server'
|
9
|
+
task :server do
|
10
|
+
require "almanack"
|
11
|
+
|
12
|
+
today = DateTime.now
|
13
|
+
|
14
|
+
Almanack.config.add_events [
|
15
|
+
{ title: "Hogswatch", start_date: today },
|
16
|
+
{ title: "Soul Cake Tuesday", start_date: today + 10 },
|
17
|
+
{ title: "Eve of Small Gods", start_date: today + 30 },
|
18
|
+
]
|
19
|
+
|
20
|
+
Rack::Handler::WEBrick.run(Almanack::Server)
|
21
|
+
end
|
data/almanac.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'almanack/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "almanack"
|
8
|
+
spec.version = Almanack::VERSION
|
9
|
+
spec.authors = ["Pete Nicholls"]
|
10
|
+
spec.email = ["pete@metanation.com"]
|
11
|
+
spec.summary = %q{Combined events calendar for Google Calendar, iCal, Meetup.com and friends.}
|
12
|
+
spec.homepage = "https://github.com/Aupajo/sinatra-gcal"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "sinatra"
|
21
|
+
spec.add_dependency "ri_cal"
|
22
|
+
spec.add_dependency "addressable"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "rack-test"
|
28
|
+
spec.add_development_dependency "webmock"
|
29
|
+
spec.add_development_dependency "vcr"
|
30
|
+
spec.add_development_dependency "timecop"
|
31
|
+
spec.add_development_dependency "nokogiri"
|
32
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Almanack
|
2
|
+
class Calendar
|
3
|
+
def initialize(config)
|
4
|
+
@config = config
|
5
|
+
end
|
6
|
+
|
7
|
+
def event_sources
|
8
|
+
@config.event_sources
|
9
|
+
end
|
10
|
+
|
11
|
+
def events
|
12
|
+
days_lookahead = 30
|
13
|
+
from_date = DateTime.now
|
14
|
+
to_date = DateTime.now + days_lookahead
|
15
|
+
|
16
|
+
event_sources.map do |event_source|
|
17
|
+
event_source.events_between(from_date..to_date)
|
18
|
+
end.flatten.sort_by(&:start_date)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'ri_cal'
|
4
|
+
|
5
|
+
module Almanack
|
6
|
+
class Configuration
|
7
|
+
attr_reader :event_sources
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
reset!
|
11
|
+
end
|
12
|
+
|
13
|
+
def reset!
|
14
|
+
@event_sources = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_ical_feed(url)
|
18
|
+
@event_sources << IcalFeed.new(url)
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_events(events)
|
22
|
+
@event_sources << SimpleEventCollection.new(events)
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_meetup_group(options)
|
26
|
+
@event_sources << MeetupGroup.new(options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'ri_cal'
|
4
|
+
|
5
|
+
module Almanack
|
6
|
+
class IcalFeed
|
7
|
+
def initialize(url)
|
8
|
+
@url = url
|
9
|
+
end
|
10
|
+
|
11
|
+
def events_between(date_range)
|
12
|
+
occurrences_between(date_range).map do |occurrence|
|
13
|
+
event_from(occurrence)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def each_ical_event(&block)
|
20
|
+
entities.each do |entity|
|
21
|
+
entity.events.each(&block) if entity.respond_to?(:events)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def occurrences_between(date_range)
|
26
|
+
to_date = date_range.max
|
27
|
+
from_date = date_range.min
|
28
|
+
|
29
|
+
occurrences = []
|
30
|
+
|
31
|
+
each_ical_event do |ical_event|
|
32
|
+
ical_event.occurrences(starting: from_date, before: to_date).each do |occurrence|
|
33
|
+
occurrences << occurrence
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
occurrences
|
38
|
+
end
|
39
|
+
|
40
|
+
def event_from(occurrence)
|
41
|
+
Event.new(
|
42
|
+
title: occurrence.summary,
|
43
|
+
start_date: occurrence.dtstart,
|
44
|
+
end_date: occurrence.dtend,
|
45
|
+
description: occurrence.description,
|
46
|
+
location: occurrence.location
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def entities
|
51
|
+
RiCal.parse_string(body)
|
52
|
+
end
|
53
|
+
|
54
|
+
def body
|
55
|
+
uri = URI(@url)
|
56
|
+
Net::HTTP.get(uri)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
require 'addressable/uri'
|
4
|
+
|
5
|
+
module Almanack
|
6
|
+
class MeetupGroup
|
7
|
+
def initialize(options = {})
|
8
|
+
@request_options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def events_between(date_range)
|
12
|
+
events.select do |event|
|
13
|
+
event.start_date >= date_range.min && event.start_date <= date_range.max
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def events
|
20
|
+
request = MeetupAPIRequest.new(@request_options)
|
21
|
+
request.results.map { |result| event_from(result) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def event_from(result)
|
25
|
+
# 3 hours, as recommended by Meetup.com if duration isn't present
|
26
|
+
default_duration_in_ms = 3 * 60 * 60 * 1000
|
27
|
+
|
28
|
+
event_name = [result['group']['name'], result['name']].compact.join(': ')
|
29
|
+
start_time = Time.at(result['time'] / 1000)
|
30
|
+
duration_in_secs = (result['duration'] || default_duration_in_ms) / 1000
|
31
|
+
end_time = start_time + duration_in_secs
|
32
|
+
|
33
|
+
Event.new(
|
34
|
+
title: event_name,
|
35
|
+
start_date: start_time.to_datetime,
|
36
|
+
end_date: end_time.to_datetime,
|
37
|
+
description: result['description'],
|
38
|
+
location: location_from_venue(result['venue']),
|
39
|
+
url: result['event_url']
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def location_from_venue(venue)
|
44
|
+
%w{ name address_1 address_2 address_3 city state country }.map do |attr|
|
45
|
+
venue[attr]
|
46
|
+
end.compact.join(', ')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class MeetupAPIError < StandardError
|
51
|
+
end
|
52
|
+
|
53
|
+
class MeetupAPIException < Exception
|
54
|
+
end
|
55
|
+
|
56
|
+
class MeetupAPIRequest
|
57
|
+
REQUIRED_OPTIONS = [:group_domain, :group_urlname, :group_id]
|
58
|
+
|
59
|
+
attr_accessor :options
|
60
|
+
|
61
|
+
def initialize(options = {})
|
62
|
+
@options = options
|
63
|
+
end
|
64
|
+
|
65
|
+
def results
|
66
|
+
response['results']
|
67
|
+
end
|
68
|
+
|
69
|
+
def uri
|
70
|
+
if !options.has_key?(:key)
|
71
|
+
raise MeetupAPIException, 'Cannot form valid URI, missing :key option'
|
72
|
+
end
|
73
|
+
|
74
|
+
if (options.keys & REQUIRED_OPTIONS).empty?
|
75
|
+
raise MeetupAPIException, "Cannot form valid URI, missing one of: #{REQUIRED_OPTIONS}"
|
76
|
+
end
|
77
|
+
|
78
|
+
endpoint = "https://api.meetup.com/2/events"
|
79
|
+
|
80
|
+
Addressable::URI.parse(endpoint).tap do |uri|
|
81
|
+
uri.query_values = options
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def response
|
86
|
+
json = Net::HTTP.get(uri)
|
87
|
+
data = JSON.parse(json)
|
88
|
+
|
89
|
+
if data['problem']
|
90
|
+
raise MeetupAPIError, data['problem']
|
91
|
+
end
|
92
|
+
|
93
|
+
data
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/almanack.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "almanack/version"
|
3
|
+
require "almanack/server"
|
4
|
+
require "almanack/configuration"
|
5
|
+
require "almanack/calendar"
|
6
|
+
require "almanack/simple_event_collection"
|
7
|
+
require "almanack/meetup_group"
|
8
|
+
require "almanack/ical_feed"
|
9
|
+
require "almanack/event"
|
10
|
+
|
11
|
+
module Almanack
|
12
|
+
def self.config
|
13
|
+
@config ||= Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.calendar
|
17
|
+
@calendar ||= Calendar.new(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reset!
|
21
|
+
config.reset!
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Almanack
|
4
|
+
describe Calendar do
|
5
|
+
|
6
|
+
describe "#events" do
|
7
|
+
describe "with simple events" do
|
8
|
+
it "returns the events" do
|
9
|
+
config = Configuration.new
|
10
|
+
config.add_events [
|
11
|
+
{ title: "Hogswatch" }
|
12
|
+
]
|
13
|
+
|
14
|
+
calendar = Calendar.new(config)
|
15
|
+
|
16
|
+
expect(calendar.events.size).to eq(1)
|
17
|
+
expect(calendar.events.first.title).to eq('Hogswatch')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "with an iCal feed" do
|
22
|
+
it "returns the event occurrences" do
|
23
|
+
config = Configuration.new
|
24
|
+
config.add_ical_feed "https://www.google.com/calendar/ical/61s2re9bfk01abmla4d17tojuo%40group.calendar.google.com/public/basic.ics"
|
25
|
+
|
26
|
+
calendar = Calendar.new(config)
|
27
|
+
|
28
|
+
events = nil
|
29
|
+
|
30
|
+
Timecop.freeze(2014, 4, 3) do
|
31
|
+
VCR.use_cassette('google_calendar') do
|
32
|
+
events = calendar.events
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
expect(events.size).to eq(15)
|
37
|
+
expect(events).to all_have_properties(:title, :start_date)
|
38
|
+
expect(events).to be_in_order
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Almanack
|
4
|
+
describe Configuration do
|
5
|
+
|
6
|
+
describe "#add_events" do
|
7
|
+
it "adds a simple event collection event source" do
|
8
|
+
config = Configuration.new
|
9
|
+
expect(config.event_sources.size).to eq(0)
|
10
|
+
|
11
|
+
config.add_events [
|
12
|
+
{ title: "Hogswatch" }
|
13
|
+
]
|
14
|
+
|
15
|
+
expect(config.event_sources.size).to eq(1)
|
16
|
+
expect(config.event_sources.first).to be_an_instance_of(SimpleEventCollection)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#ical_feed" do
|
21
|
+
it "adds an iCal feed event source" do
|
22
|
+
config = Configuration.new
|
23
|
+
expect(config.event_sources.size).to eq(0)
|
24
|
+
|
25
|
+
config.add_ical_feed "https://www.google.com/calendar/ical/61s2re9bfk01abmla4d17tojuo%40group.calendar.google.com/public/basic.ics"
|
26
|
+
|
27
|
+
expect(config.event_sources.size).to eq(1)
|
28
|
+
expect(config.event_sources.first).to be_an_instance_of(IcalFeed)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#meetup_group" do
|
33
|
+
it "adds a Meetup group event source" do
|
34
|
+
config = Configuration.new
|
35
|
+
expect(config.event_sources.size).to eq(0)
|
36
|
+
|
37
|
+
config.add_meetup_group(group_urlname: "CHC-JS", key: "secrettoken")
|
38
|
+
|
39
|
+
expect(config.event_sources.size).to eq(1)
|
40
|
+
expect(config.event_sources.first).to be_an_instance_of(MeetupGroup)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Almanack
|
4
|
+
describe Event do
|
5
|
+
|
6
|
+
it "has a title" do
|
7
|
+
event = Event.new(title: "Music with rocks in")
|
8
|
+
expect(event.title).to eq("Music with rocks in")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has a start date" do
|
12
|
+
event = Event.new(start_date: DateTime.new(2014, 01, 01))
|
13
|
+
expect(event.start_date).to eq(DateTime.new(2014, 01, 01))
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has a end date" do
|
17
|
+
event = Event.new(end_date: DateTime.new(2014, 01, 02))
|
18
|
+
expect(event.end_date).to eq(DateTime.new(2014, 01, 02))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has a location" do
|
22
|
+
event = Event.new(location: "Street of Cunning Artificers")
|
23
|
+
expect(event.location).to eq("Street of Cunning Artificers")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "has a description" do
|
27
|
+
event = Event.new(description: "Be there or be a rectangular thynge.")
|
28
|
+
expect(event.description).to eq("Be there or be a rectangular thynge.")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Viewing a calendar", :feature do
|
4
|
+
before { Almanack.reset! }
|
5
|
+
|
6
|
+
it "displays all upcoming events" do
|
7
|
+
Almanack.config.add_events [
|
8
|
+
{ title: "Hogswatch" },
|
9
|
+
{ title: "Soul Cake Tuesday" },
|
10
|
+
{ title: "Eve of Small Gods" },
|
11
|
+
]
|
12
|
+
|
13
|
+
get "/"
|
14
|
+
|
15
|
+
expect(last_response).to have_event_on_page("Hogswatch")
|
16
|
+
expect(last_response).to have_event_on_page("Soul Cake Tuesday")
|
17
|
+
expect(last_response).to have_event_on_page("Eve of Small Gods")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "displays events from an iCal feed" do
|
21
|
+
Almanack.config.add_ical_feed "https://www.google.com/calendar/ical/61s2re9bfk01abmla4d17tojuo%40group.calendar.google.com/public/basic.ics"
|
22
|
+
|
23
|
+
Timecop.freeze(2014, 4, 3) do
|
24
|
+
VCR.use_cassette('google_calendar') do
|
25
|
+
get "/"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
expect(last_response).to have_event_on_page("Ruby Meetup @catalyst - Tanks! Guns!")
|
30
|
+
expect(last_response).to have_event_on_page("The Foundation")
|
31
|
+
expect(last_response).to have_event_on_page("WikiHouse/NZ weekly meet-up")
|
32
|
+
expect(last_response).to have_event_on_page("Christchurch Python Meetup")
|
33
|
+
expect(last_response).to have_event_on_page("Coffee & Jam")
|
34
|
+
end
|
35
|
+
end
|