calagator 0.0.1.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +23 -0
- data/README.md +75 -0
- data/Rakefile +12 -0
- data/app/assets/images/confused-alligator-sm.png +0 -0
- data/app/assets/images/disk.png +0 -0
- data/app/assets/images/edit.png +0 -0
- data/app/assets/images/external_sites/epdx.png +0 -0
- data/app/assets/images/external_sites/external.gif +0 -0
- data/app/assets/images/external_sites/facebook.png +0 -0
- data/app/assets/images/external_sites/foursquare.png +0 -0
- data/app/assets/images/external_sites/gowalla.png +0 -0
- data/app/assets/images/external_sites/lanyrd.png +0 -0
- data/app/assets/images/external_sites/meetup.png +0 -0
- data/app/assets/images/external_sites/plancast.png +0 -0
- data/app/assets/images/external_sites/shizzow.png +0 -0
- data/app/assets/images/external_sites/upcoming.png +0 -0
- data/app/assets/images/external_sites/yelp.png +0 -0
- data/app/assets/images/feed.png +0 -0
- data/app/assets/images/heart.png +0 -0
- data/app/assets/images/icon_ical.gif +0 -0
- data/app/assets/images/information.png +0 -0
- data/app/assets/images/nav_marker.gif +0 -0
- data/app/assets/images/nav_marker.png +0 -0
- data/app/assets/images/plus.png +0 -0
- data/app/assets/images/redx.png +0 -0
- data/app/assets/images/site-icon.png +0 -0
- data/app/assets/images/spinner.gif +0 -0
- data/app/assets/images/star.png +0 -0
- data/app/assets/images/subnav_marker.gif +0 -0
- data/app/assets/images/subnav_marker.png +0 -0
- data/app/assets/images/tag_blue.png +0 -0
- data/app/assets/images/tag_icons/angular.png +0 -0
- data/app/assets/images/tag_icons/beer.png +0 -0
- data/app/assets/images/tag_icons/bitcoin.png +0 -0
- data/app/assets/images/tag_icons/free.png +0 -0
- data/app/assets/images/tag_icons/golang.png +0 -0
- data/app/assets/images/tag_icons/html.png +0 -0
- data/app/assets/images/tag_icons/javascript.png +0 -0
- data/app/assets/images/tag_icons/linux.png +0 -0
- data/app/assets/images/tag_icons/php.png +0 -0
- data/app/assets/images/tag_icons/pizza.png +0 -0
- data/app/assets/images/tag_icons/python.png +0 -0
- data/app/assets/images/tag_icons/rails.png +0 -0
- data/app/assets/images/tag_icons/ruby.png +0 -0
- data/app/assets/images/tag_icons/sass.png +0 -0
- data/app/assets/images/tag_icons/swift.png +0 -0
- data/app/assets/images/transmit_blue.png +0 -0
- data/app/assets/images/weekday_background.gif +0 -0
- data/app/assets/javascripts/calagator.js +18 -0
- data/app/assets/javascripts/calagator/forms.js +60 -0
- data/app/assets/stylesheets/calagator.scss +8 -0
- data/app/assets/stylesheets/calagator/common.scss +14 -0
- data/app/assets/stylesheets/calagator/datepicker.scss +177 -0
- data/app/assets/stylesheets/calagator/errors.css +110 -0
- data/app/assets/stylesheets/calagator/forms.scss +4 -0
- data/app/assets/stylesheets/calagator/reset.css +40 -0
- data/app/assets/stylesheets/calagator/theme.css +0 -0
- data/app/controllers/calagator/admin_controller.rb +27 -0
- data/app/controllers/calagator/application_controller.rb +82 -0
- data/app/controllers/calagator/events_controller.rb +171 -0
- data/app/controllers/calagator/site_controller.rb +35 -0
- data/app/controllers/calagator/sources_controller.rb +94 -0
- data/app/controllers/calagator/venues_controller.rb +133 -0
- data/app/controllers/calagator/versions_controller.rb +20 -0
- data/app/helpers/calagator/application_helper.rb +128 -0
- data/app/helpers/calagator/events_helper.rb +184 -0
- data/app/helpers/calagator/google_event_export_helper.rb +67 -0
- data/app/helpers/calagator/mapping_helper.rb +103 -0
- data/app/helpers/calagator/sources_helper.rb +10 -0
- data/app/helpers/calagator/tags_helper.rb +42 -0
- data/app/helpers/calagator/time_range_helper.rb +166 -0
- data/app/models/calagator/event.rb +246 -0
- data/app/models/calagator/event/cloner.rb +39 -0
- data/app/models/calagator/event/ical_renderer.rb +155 -0
- data/app/models/calagator/event/overview.rb +45 -0
- data/app/models/calagator/event/saver.rb +58 -0
- data/app/models/calagator/event/search.rb +72 -0
- data/app/models/calagator/event/search_engine.rb +28 -0
- data/app/models/calagator/event/search_engine/apache_sunspot.rb +106 -0
- data/app/models/calagator/event/search_engine/sql.rb +107 -0
- data/app/models/calagator/source.rb +115 -0
- data/app/models/calagator/source/importer.rb +46 -0
- data/app/models/calagator/source/parser.rb +128 -0
- data/app/models/calagator/source/parser/facebook.rb +67 -0
- data/app/models/calagator/source/parser/hcal.rb +108 -0
- data/app/models/calagator/source/parser/http_authentication_required_error.rb +6 -0
- data/app/models/calagator/source/parser/ical.rb +186 -0
- data/app/models/calagator/source/parser/meetup.rb +72 -0
- data/app/models/calagator/source/parser/not_found.rb +9 -0
- data/app/models/calagator/source/parser/plancast.rb +59 -0
- data/app/models/calagator/venue.rb +161 -0
- data/app/models/calagator/venue/geocoder.rb +51 -0
- data/app/models/calagator/venue/search.rb +63 -0
- data/app/models/calagator/venue/search_engine.rb +24 -0
- data/app/models/calagator/venue/search_engine/apache_sunspot.rb +85 -0
- data/app/models/calagator/venue/search_engine/sql.rb +68 -0
- data/app/models/event/search_engine/base.rb +0 -0
- data/app/observers/calagator/cache_observer.rb +37 -0
- data/app/views/calagator/admin/events.html.erb +28 -0
- data/app/views/calagator/admin/index.html.erb +8 -0
- data/app/views/calagator/events/_feed_item.html.erb +62 -0
- data/app/views/calagator/events/_form.html.erb +63 -0
- data/app/views/calagator/events/_gcal_reminder.html.erb +1 -0
- data/app/views/calagator/events/_hcal.html.erb +41 -0
- data/app/views/calagator/events/_item.html.erb +120 -0
- data/app/views/calagator/events/_list.html.erb +30 -0
- data/app/views/calagator/events/_list_item.html.erb +37 -0
- data/app/views/calagator/events/_search_section.html.erb +15 -0
- data/app/views/calagator/events/_subnav.html.erb +13 -0
- data/app/views/calagator/events/_table.html.erb +74 -0
- data/app/views/calagator/events/duplicates.html.erb +58 -0
- data/app/views/calagator/events/edit.html.erb +3 -0
- data/app/views/calagator/events/index.atom.builder +32 -0
- data/app/views/calagator/events/index.html.erb +51 -0
- data/app/views/calagator/events/index.kml.erb +20 -0
- data/app/views/calagator/events/new.html.erb +7 -0
- data/app/views/calagator/events/search.html.erb +25 -0
- data/app/views/calagator/events/show.html.erb +81 -0
- data/app/views/calagator/site/_appropriateness_message.html.erb +15 -0
- data/app/views/calagator/site/_description.html.erb +3 -0
- data/app/views/calagator/site/about.html.erb +7 -0
- data/app/views/calagator/site/defunct.html.erb +15 -0
- data/app/views/calagator/site/export.html.erb +4 -0
- data/app/views/calagator/site/index.html.erb +40 -0
- data/app/views/calagator/site/opensearch.xml.builder +8 -0
- data/app/views/calagator/sources/_subnav.html.erb +0 -0
- data/app/views/calagator/sources/edit.html.erb +12 -0
- data/app/views/calagator/sources/import.html.erb +10 -0
- data/app/views/calagator/sources/index.html.erb +22 -0
- data/app/views/calagator/sources/new.html.erb +32 -0
- data/app/views/calagator/sources/show.html.erb +16 -0
- data/app/views/calagator/venues/_form.html.erb +57 -0
- data/app/views/calagator/venues/_subnav.html.erb +10 -0
- data/app/views/calagator/venues/duplicates.html.erb +65 -0
- data/app/views/calagator/venues/edit.html.erb +3 -0
- data/app/views/calagator/venues/index.html.erb +93 -0
- data/app/views/calagator/venues/index.kml.erb +15 -0
- data/app/views/calagator/venues/map.html.erb +4 -0
- data/app/views/calagator/venues/new.html.erb +5 -0
- data/app/views/calagator/venues/show.html.erb +113 -0
- data/app/views/calagator/versions/_chooser.html.erb +28 -0
- data/app/views/calagator/versions/_edit_with_chooser.html.erb +16 -0
- data/app/views/layouts/calagator/application.html.erb +110 -0
- data/config/deploy/local.rb +37 -0
- data/config/deploy/lucca.rb +33 -0
- data/config/initializers/dates.rb +7 -0
- data/config/initializers/formtastic.rb +82 -0
- data/config/initializers/geokit.rb +74 -0
- data/config/initializers/ics_renderer.rb +6 -0
- data/config/initializers/load_tag_model_extensions.rb +3 -0
- data/config/initializers/mime_types.rb +9 -0
- data/config/initializers/observers.rb +1 -0
- data/config/initializers/search_engine.rb +4 -0
- data/config/initializers/set_default_url_host.rb +5 -0
- data/config/initializers/time_get_zone.rb +8 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +55 -0
- data/config/secrets.yml.blag +75 -0
- data/config/sunspot.yml +23 -0
- data/db/development.sqlite3 +0 -0
- data/db/development.sqlite3.bak +0 -0
- data/db/development.sqlite3.old +0 -0
- data/db/development~20111112@110950.sqlite3 +0 -0
- data/db/migrate/001_create_events.rb +17 -0
- data/db/migrate/002_create_venues.rb +17 -0
- data/db/migrate/003_create_sources.rb +16 -0
- data/db/migrate/004_add_detailed_fields_to_venue.rb +19 -0
- data/db/migrate/005_add_end_time_to_events.rb +9 -0
- data/db/migrate/006_add_source_id_to_events.rb +9 -0
- data/db/migrate/008_add_source_id_to_venues.rb +10 -0
- data/db/migrate/009_add_duplicate_of_column_to_venues.rb +9 -0
- data/db/migrate/010_add_duplicate_of_column_to_events.rb +9 -0
- data/db/migrate/011_change_lat_long_type.rb +12 -0
- data/db/migrate/012_add_source_reimport.rb +9 -0
- data/db/migrate/013_change_end_time_to_duration.rb +11 -0
- data/db/migrate/014_remove_format_type_from_source.rb +9 -0
- data/db/migrate/015_create_updates.rb +15 -0
- data/db/migrate/016_remove_next_update_from_source.rb +9 -0
- data/db/migrate/20080705163959_change_duration_to_end_time.rb +11 -0
- data/db/migrate/20080705164959_create_tags_and_taggings.rb +28 -0
- data/db/migrate/20081011181519_create_versioned_events.rb +25 -0
- data/db/migrate/20081011193124_create_versioned_venues.rb +32 -0
- data/db/migrate/20081115190515_add_rrule_to_events.rb +15 -0
- data/db/migrate/20090912082129_create_versions.rb +18 -0
- data/db/migrate/20110219205156_add_closed_flag_to_venues.rb +9 -0
- data/db/migrate/20110220001008_add_wifi_flag_to_venues.rb +9 -0
- data/db/migrate/20110220011427_add_access_notes_to_venues.rb +9 -0
- data/db/migrate/20110220031117_add_events_count_to_venues.rb +8 -0
- data/db/migrate/20110604174521_add_venue_details_to_events.rb +9 -0
- data/db/migrate/20110717231316_acts_as_taggable_on_migration.rb +50 -0
- data/db/migrate/20120709092821_cleanup.rb +14 -0
- data/db/migrate/20120831234448_specify_venues_latitude_and_longitude_precision.rb +11 -0
- data/db/migrate/20150206085809_remove_updates.rb +13 -0
- data/db/migrate/20150207231355_add_locked_status_to_events.rb +5 -0
- data/db/production.sqlite3 +0 -0
- data/db/schema.rb +102 -0
- data/db/seeds.rb +16 -0
- data/db/test.sqlite3 +0 -0
- data/db/test2.sqlite3 +0 -0
- data/lib/calagator.rb +30 -0
- data/lib/calagator/blacklist_validator.rb +69 -0
- data/lib/calagator/decode_html_entities_hack.rb +33 -0
- data/lib/calagator/duplicate_checking.rb +133 -0
- data/lib/calagator/duplicate_checking/controller_actions.rb +38 -0
- data/lib/calagator/duplicate_checking/duplicate_finder.rb +83 -0
- data/lib/calagator/duplicate_checking/duplicate_squasher.rb +74 -0
- data/lib/calagator/engine.rb +30 -0
- data/lib/calagator/strip_whitespace.rb +19 -0
- data/lib/calagator/tag_model_extensions.rb +104 -0
- data/lib/calagator/url_prefixer.rb +9 -0
- data/lib/calagator/version.rb +3 -0
- data/lib/generators/calagator/install_generator.rb +39 -0
- data/lib/generators/calagator/templates/config/calagator.rb +26 -0
- data/lib/generators/calagator/templates/config/secrets.yml.sample +83 -0
- data/lib/secrets_reader.rb +76 -0
- data/lib/tasks/spec_db.rake +53 -0
- data/lib/tasks/sunspot_reindex_calagator.rake +6 -0
- data/lib/tasks/sunspot_solr_restart_enhancements.rake +19 -0
- data/lib/tasks/update_counter_caches.rake +13 -0
- data/lib/templates/erb/scaffold/_form.html.erb +11 -0
- data/lib/theme_reader.rb +17 -0
- data/lib/wait_for_solr.rb +25 -0
- data/spec/controllers/calagator/application_controller_spec.rb +47 -0
- data/spec/controllers/calagator/events_controller_spec.rb +794 -0
- data/spec/controllers/calagator/site_controller_spec.rb +59 -0
- data/spec/controllers/calagator/sources_controller_spec.rb +439 -0
- data/spec/controllers/calagator/venues_controller_spec.rb +319 -0
- data/spec/controllers/calagator/versions_controller_spec.rb +82 -0
- data/spec/controllers/squash_many_duplicates_examples.rb +49 -0
- data/spec/dummy/Gemfile +39 -0
- data/spec/dummy/Gemfile.lock +195 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/stylesheets/application.css +14 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +62 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/calagator.rb +26 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +59 -0
- data/spec/dummy/config/secrets.yml +83 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150309023304_create_events.calagator.rb +18 -0
- data/spec/dummy/db/migrate/20150309023305_create_venues.calagator.rb +18 -0
- data/spec/dummy/db/migrate/20150309023306_create_sources.calagator.rb +17 -0
- data/spec/dummy/db/migrate/20150309023307_add_detailed_fields_to_venue.calagator.rb +20 -0
- data/spec/dummy/db/migrate/20150309023308_add_end_time_to_events.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023309_add_source_id_to_events.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023310_add_source_id_to_venues.calagator.rb +11 -0
- data/spec/dummy/db/migrate/20150309023311_add_duplicate_of_column_to_venues.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023312_add_duplicate_of_column_to_events.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023313_change_lat_long_type.calagator.rb +13 -0
- data/spec/dummy/db/migrate/20150309023314_add_source_reimport.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023315_change_end_time_to_duration.calagator.rb +12 -0
- data/spec/dummy/db/migrate/20150309023316_remove_format_type_from_source.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023317_create_updates.calagator.rb +16 -0
- data/spec/dummy/db/migrate/20150309023318_remove_next_update_from_source.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023319_change_duration_to_end_time.calagator.rb +12 -0
- data/spec/dummy/db/migrate/20150309023320_create_tags_and_taggings.calagator.rb +29 -0
- data/spec/dummy/db/migrate/20150309023321_create_versioned_events.calagator.rb +26 -0
- data/spec/dummy/db/migrate/20150309023322_create_versioned_venues.calagator.rb +33 -0
- data/spec/dummy/db/migrate/20150309023323_add_rrule_to_events.calagator.rb +16 -0
- data/spec/dummy/db/migrate/20150309023324_create_versions.calagator.rb +19 -0
- data/spec/dummy/db/migrate/20150309023325_add_closed_flag_to_venues.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023326_add_wifi_flag_to_venues.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023327_add_access_notes_to_venues.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023328_add_events_count_to_venues.calagator.rb +9 -0
- data/spec/dummy/db/migrate/20150309023329_add_venue_details_to_events.calagator.rb +10 -0
- data/spec/dummy/db/migrate/20150309023330_acts_as_taggable_on_migration.calagator.rb +51 -0
- data/spec/dummy/db/migrate/20150309023331_cleanup.calagator.rb +15 -0
- data/spec/dummy/db/migrate/20150309023332_specify_venues_latitude_and_longitude_precision.calagator.rb +12 -0
- data/spec/dummy/db/migrate/20150309023333_remove_updates.calagator.rb +14 -0
- data/spec/dummy/db/migrate/20150309023334_add_locked_status_to_events.calagator.rb +6 -0
- data/spec/dummy/db/schema.rb +95 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/doc/README_FOR_APP +2 -0
- data/spec/dummy/log/development.log +273 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/test/performance/browsing_test.rb +12 -0
- data/spec/dummy/test/test_helper.rb +13 -0
- data/spec/factories.rb +93 -0
- data/spec/features/add_event_spec.rb +99 -0
- data/spec/features/add_venue_spec.rb +34 -0
- data/spec/features/admin_auth_spec.rb +22 -0
- data/spec/features/admin_lock_event_spec.rb +41 -0
- data/spec/features/import_events_from_feed_spec.rb +43 -0
- data/spec/features/managing_event_spec.rb +111 -0
- data/spec/features/managing_venue_spec.rb +71 -0
- data/spec/features/search_event_spec.rb +27 -0
- data/spec/helpers/calagator/application_helper_spec.rb +82 -0
- data/spec/helpers/calagator/events_helper_spec.rb +172 -0
- data/spec/helpers/calagator/google_event_export_helper_spec.rb +70 -0
- data/spec/helpers/calagator/sources_helper_spec.rb +12 -0
- data/spec/helpers/calagator/tags_helper_spec.rb +85 -0
- data/spec/helpers/calagator/time_range_helper_spec.rb +59 -0
- data/spec/lib/calagator/blacklist_validator_spec.rb +65 -0
- data/spec/lib/calagator/decode_html_entities_hack_spec.rb +54 -0
- data/spec/lib/calagator/settings_spec.rb +20 -0
- data/spec/lib/calagator/url_prefixer_spec.rb +33 -0
- data/spec/lib/secrets_reader_spec.rb +65 -0
- data/spec/models/calagator/event/cloner_spec.rb +43 -0
- data/spec/models/calagator/event/overview_spec.rb +79 -0
- data/spec/models/calagator/event/search_spec.rb +103 -0
- data/spec/models/calagator/event_search_spec.rb +149 -0
- data/spec/models/calagator/event_spec.rb +859 -0
- data/spec/models/calagator/source/parser_facebook_spec.rb +73 -0
- data/spec/models/calagator/source/parser_hcal_spec.rb +69 -0
- data/spec/models/calagator/source/parser_ical_non_standard_spec.rb +91 -0
- data/spec/models/calagator/source/parser_ical_spec.rb +322 -0
- data/spec/models/calagator/source/parser_meetup_spec.rb +69 -0
- data/spec/models/calagator/source/parser_plancast_spec.rb +53 -0
- data/spec/models/calagator/source/parser_spec.rb +238 -0
- data/spec/models/calagator/source_spec.rb +135 -0
- data/spec/models/calagator/venue/search_spec.rb +92 -0
- data/spec/models/calagator/venue_search_spec.rb +124 -0
- data/spec/models/calagator/venue_spec.rb +346 -0
- data/spec/models/tag_spec.rb +35 -0
- data/spec/rails_helper.rb +39 -0
- data/spec/spec_helper.rb +140 -0
- data/spec/support/disable_geocoding.rb +1 -0
- data/spec/support/http_samples.rb +5 -0
- data/spec/support/samples/facebook.json +23 -0
- data/spec/support/samples/hcal_basic.xml +6 -0
- data/spec/support/samples/hcal_dup_event_dup_venue.xml +13 -0
- data/spec/support/samples/hcal_event_duplicates_fixture.xml +13 -0
- data/spec/support/samples/hcal_event_wo_lat_and_long.xml +14 -0
- data/spec/support/samples/hcal_multiple.xml +16 -0
- data/spec/support/samples/hcal_same_event_twice_with_different_venues.xml +12 -0
- data/spec/support/samples/hcal_single.xml +8 -0
- data/spec/support/samples/hcal_two_identical_events.xml +14 -0
- data/spec/support/samples/hcal_upcoming_v1.html +412 -0
- data/spec/support/samples/hcal_upcoming_v2.html +749 -0
- data/spec/support/samples/hcal_upcoming_v3.html +685 -0
- data/spec/support/samples/hcal_upcoming_v4.html +761 -0
- data/spec/support/samples/ical_apple.ics +22 -0
- data/spec/support/samples/ical_apple_v3.ics +37 -0
- data/spec/support/samples/ical_basic.ics +15 -0
- data/spec/support/samples/ical_basic_with_duration.ics +16 -0
- data/spec/support/samples/ical_event_with_squashed_venue.ics +12 -0
- data/spec/support/samples/ical_eventful_many.ics +504 -0
- data/spec/support/samples/ical_gmt.ics +12 -0
- data/spec/support/samples/ical_google.ics +786 -0
- data/spec/support/samples/ical_multiple_calendars.ics +111 -0
- data/spec/support/samples/ical_upcoming.ics +36 -0
- data/spec/support/samples/ical_upcoming_many.ics +682 -0
- data/spec/support/samples/ical_upcoming_v2.ics +43 -0
- data/spec/support/samples/ical_z.ics +10 -0
- data/spec/support/samples/meetup.ics +16 -0
- data/spec/support/samples/meetup.json +31 -0
- data/spec/support/samples/plancast.ics +59 -0
- data/spec/support/samples/plancast.json +51 -0
- data/spec/support/samples/plancast_with_missing_venue.json +39 -0
- data/spec/support/samples/upcoming_v1.xml +8 -0
- data/spec/support/samples/upcoming_v2_with_invalid_utc_dates.xml +8 -0
- data/spec/support/time_convenience_methods.rb +8 -0
- data/spec/support/time_zones.rb +12 -0
- data/spec/support/url_helpers.rb +5 -0
- data/spec/support/wait_for_ajax.rb +15 -0
- data/spec/support/webmock.rb +8 -0
- data/spec/travis_spec.rb +7 -0
- metadata +1194 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Calagator
|
|
4
|
+
|
|
5
|
+
describe Source::Parser::Meetup, :type => :model do
|
|
6
|
+
describe "with a meetup.com API key in secrets.yml" do
|
|
7
|
+
before do
|
|
8
|
+
SECRETS.meetup_api_key = "foo"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
meetup_url = "http://www.meetup.com/pdxpython/events/ldhnqyplbnb/"
|
|
13
|
+
api_url = "https://api.meetup.com/2/event/ldhnqyplbnb?key=foo&sign=true"
|
|
14
|
+
|
|
15
|
+
stub_request(:get, api_url).to_return(body: read_sample('meetup.json'), headers: { content_type: "application/json" })
|
|
16
|
+
@events = Source::Parser::Meetup.to_events(url: meetup_url)
|
|
17
|
+
@event = @events.first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should find one event" do
|
|
21
|
+
expect(@events.size).to eq 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should set event details" do
|
|
25
|
+
expect(@event.title).to eq "eLearning Network Meetup"
|
|
26
|
+
expect(@event.start_time).to eq Time.zone.parse("Thu Aug 11 00:00:00 UTC 2011")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should tag Meetup events with automagic machine tags" do
|
|
30
|
+
expect(@event.tag_list).to eq ["meetup:event=ldhnqyplbnb", "meetup:group=eLearningNetwork"]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should populate a venue when structured data is provided" do
|
|
34
|
+
expect(@event.venue).to be_a Venue
|
|
35
|
+
expect(@event.venue.title).to eq "Green Dragon Bistro and Brewpub"
|
|
36
|
+
expect(@event.venue.street_address).to eq "928 SE 9th Ave"
|
|
37
|
+
expect(@event.venue.tag_list).to eq ["meetup:venue=774133"]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "without a meetup API key" do
|
|
42
|
+
before do
|
|
43
|
+
SECRETS.meetup_api_key = nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
before(:each) do
|
|
47
|
+
url = "http://www.meetup.com/pdxpython/events/ldhnqyplbnb/ical"
|
|
48
|
+
stub_request(:get, url).to_return(body: read_sample('meetup.ics'))
|
|
49
|
+
@events = Source::Parser::Meetup.to_events(url: url)
|
|
50
|
+
@event = @events.first
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should find one event" do
|
|
54
|
+
expect(@events.size).to eq 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should set event details" do
|
|
58
|
+
expect(@event.title).to eq "eLearning Network Meetup"
|
|
59
|
+
expect(@event.start_time.to_date).to eq Date.parse("3011-08-11")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should populate a venue when structured data is provided" do
|
|
63
|
+
expect(@event.venue).to be_a Venue
|
|
64
|
+
expect(@event.venue.title).to eq "Green Dragon Bistro and Brewpub"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Calagator
|
|
4
|
+
|
|
5
|
+
describe Source::Parser::Plancast, :type => :model do
|
|
6
|
+
|
|
7
|
+
context do
|
|
8
|
+
before(:each) do
|
|
9
|
+
plancast_url = 'http://plancast.com/p/3cos/indiewebcamp'
|
|
10
|
+
api_url = 'http://api.plancast.com/02/plans/show.json?extensions=place&plan_id=3cos'
|
|
11
|
+
stub_request(:get, api_url).to_return(body: read_sample('plancast.json'), headers: { content_type: "application/json" })
|
|
12
|
+
|
|
13
|
+
@events = Source::Parser::Plancast.to_events(url: plancast_url)
|
|
14
|
+
@event = @events.first
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should find one event" do
|
|
18
|
+
expect(@events.size).to eq 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should set event details" do
|
|
22
|
+
expect(@event.title).to eq "IndieWebCamp"
|
|
23
|
+
expect(@event.start_time).to eq Time.zone.parse("Sat, 25 Jun 2011 00:00:00")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should tag Plancast events with automagic machine tags" do
|
|
27
|
+
expect(@event.tag_list).to eq ["plancast:plan=3cos"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should populate a venue when structured data is provided" do
|
|
31
|
+
expect(@event.venue.title).to eq "Urban Airship"
|
|
32
|
+
expect(@event.venue.address).to eq "334 Northwest 11th Avenue, Portland, Oregon, United States"
|
|
33
|
+
expect(@event.venue.tag_list).to eq ["plancast:place=1520153"]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "with missing venue" do
|
|
38
|
+
before(:each) do
|
|
39
|
+
plancast_url = 'http://plancast.com/p/3cos/indiewebcamp'
|
|
40
|
+
api_url = 'http://api.plancast.com/02/plans/show.json?extensions=place&plan_id=3cos'
|
|
41
|
+
stub_request(:get, api_url).to_return(body: read_sample('plancast_with_missing_venue.json'), headers: { content_type: "application/json" })
|
|
42
|
+
@events = Source::Parser::Plancast.to_events(url: plancast_url)
|
|
43
|
+
@event = @events.first
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "uses fallback when no venue is detected" do
|
|
47
|
+
expect(@event.venue.title).to eq "The Center of the Earth"
|
|
48
|
+
expect(@event.venue.address).to be_blank
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Calagator
|
|
4
|
+
|
|
5
|
+
describe Source::Parser, "when reading content", :type => :model do
|
|
6
|
+
it "should read from a normal URL" do
|
|
7
|
+
stub_request(:get, "http://a.real/~url").to_return(body: "42")
|
|
8
|
+
expect(Source::Parser.read_url("http://a.real/~url")).to eq "42"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should raise an error when unauthorized" do
|
|
12
|
+
stub_request(:get, "http://a.private/~url").to_return(status: [401, "Forbidden"])
|
|
13
|
+
expect {
|
|
14
|
+
Source::Parser.read_url("http://a.private/~url")
|
|
15
|
+
}.to raise_error Source::Parser::HttpAuthenticationRequiredError
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe Source::Parser, "when subclassing", :type => :model do
|
|
20
|
+
it "should demand that #to_events is implemented" do
|
|
21
|
+
expect{ Source::Parser.new.to_events }.to raise_error NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe Source::Parser, "when parsing events", :type => :model do
|
|
26
|
+
it "should have site-specific parsers first, then generics" do
|
|
27
|
+
expect(Source::Parser.parsers.to_a).to eq [
|
|
28
|
+
Source::Parser::Facebook,
|
|
29
|
+
Source::Parser::Meetup,
|
|
30
|
+
Source::Parser::Plancast,
|
|
31
|
+
Source::Parser::Hcal,
|
|
32
|
+
Source::Parser::Ical,
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should use first successful parser's results" do
|
|
37
|
+
events = [double]
|
|
38
|
+
|
|
39
|
+
body = {
|
|
40
|
+
name: "event",
|
|
41
|
+
start_time: "2010-01-01 12:00:00 UTC",
|
|
42
|
+
end_time: "2010-01-01 13:00:00 UTC"
|
|
43
|
+
}.to_json
|
|
44
|
+
stub_request(:get, "http://graph.facebook.com/omg").to_return(body: body, headers: { content_type: "application/json" })
|
|
45
|
+
|
|
46
|
+
expect(Source::Parser.to_events(url: "http://www.facebook.com/events/omg")).to have(1).event
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe Source::Parser, "checking duplicates when importing", :type => :model do
|
|
51
|
+
describe "with two identical events" do
|
|
52
|
+
before :each do
|
|
53
|
+
@venue_size_before_import = Venue.count
|
|
54
|
+
url = "http://mysample.hcal/"
|
|
55
|
+
@cal_source = Source.new(title: "Calendar event feed", url: url)
|
|
56
|
+
@cal_content = (%{
|
|
57
|
+
<div class="vevent">
|
|
58
|
+
<abbr class="dtstart" title="20080714"></abbr>
|
|
59
|
+
<abbr class="summary" title="Bastille Day"></abbr>
|
|
60
|
+
<abbr class="location" title="Arc de Triomphe"></abbr>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="vevent">
|
|
63
|
+
<abbr class="dtstart" title="20080714"></abbr>
|
|
64
|
+
<abbr class="summary" title="Bastille Day"></abbr>
|
|
65
|
+
<abbr class="location" title="Arc de Triomphe"></abbr>
|
|
66
|
+
</div>})
|
|
67
|
+
stub_request(:get, url).to_return(body: @cal_content)
|
|
68
|
+
@events = @cal_source.to_events
|
|
69
|
+
@created_events = @cal_source.create_events!(:skip_old => false)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should only parse one event" do
|
|
73
|
+
expect(@events.size).to eq 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should create only one event" do
|
|
77
|
+
expect(@created_events.size).to eq 1
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should create only one venue" do
|
|
81
|
+
expect(Venue.count).to eq @venue_size_before_import + 1
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "with an event" do
|
|
86
|
+
it "should retrieve an existing event if it's an exact duplicate" do
|
|
87
|
+
url = "http://mysample.hcal/"
|
|
88
|
+
hcal_source = Source.new(title: "Calendar event feed", url: url)
|
|
89
|
+
stub_request(:get, url).to_return(body: read_sample('hcal_event_duplicates_fixture.xml'))
|
|
90
|
+
|
|
91
|
+
event = hcal_source.to_events.first
|
|
92
|
+
event.save!
|
|
93
|
+
|
|
94
|
+
event2 = hcal_source.to_events.first
|
|
95
|
+
expect(event2).not_to be_a_new_record
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "an event with a orphaned exact duplicate should should remove duplicate marking" do
|
|
99
|
+
orphan = Event.create!(:title => "orphan", :start_time => Time.parse("July 14 2008"), :duplicate_of_id => 7142008 )
|
|
100
|
+
cal_content = %(
|
|
101
|
+
<div class="vevent">
|
|
102
|
+
<abbr class="summary" title="orphan"></abbr>
|
|
103
|
+
<abbr class="dtstart" title="20080714"></abbr>
|
|
104
|
+
</div>
|
|
105
|
+
)
|
|
106
|
+
url = "http://mysample.hcal/"
|
|
107
|
+
stub_request(:get, url).to_return(body: cal_content)
|
|
108
|
+
|
|
109
|
+
cal_source = Source.new(title: "Calendar event feed", url: url)
|
|
110
|
+
imported_event = cal_source.create_events!(:skip_old => false).first
|
|
111
|
+
expect(imported_event).not_to be_marked_as_duplicate
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe "should create two events when importing two non-identical events" do
|
|
116
|
+
# This behavior is tested under
|
|
117
|
+
# describe Source::Parser::Hcal, "with hCalendar events" do
|
|
118
|
+
# 'it "should parse a page with multiple events" '
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe "two identical events with different venues" do
|
|
122
|
+
before(:each) do
|
|
123
|
+
cal_content = %(
|
|
124
|
+
<div class="vevent">
|
|
125
|
+
<abbr class="dtstart" title="20080714"></abbr>
|
|
126
|
+
<abbr class="summary" title="Bastille Day"></abbr>
|
|
127
|
+
<abbr class="location" title="Arc de Triomphe"></abbr>
|
|
128
|
+
</div>
|
|
129
|
+
<div class="vevent">
|
|
130
|
+
<abbr class="dtstart" title="20080714"></abbr>
|
|
131
|
+
<abbr class="summary" title="Bastille Day"></abbr>
|
|
132
|
+
<abbr class="location" title="Bastille"></abbr>
|
|
133
|
+
</div>
|
|
134
|
+
)
|
|
135
|
+
url = "http://mysample.hcal/"
|
|
136
|
+
stub_request(:get, url).to_return(body: cal_content)
|
|
137
|
+
|
|
138
|
+
cal_source = Source.new(title: "Calendar event feed", url: url)
|
|
139
|
+
@parsed_events = cal_source.to_events
|
|
140
|
+
@created_events = cal_source.create_events!(:skip_old => false)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should parse two events" do
|
|
144
|
+
expect(@parsed_events.size).to eq 2
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "should create two events" do
|
|
148
|
+
expect(@created_events.size).to eq 2
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should have different venues for the parsed events" do
|
|
152
|
+
expect(@parsed_events[0].venue).not_to eq @parsed_events[1].venue
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should have different venues for the created events" do
|
|
156
|
+
expect(@created_events[0].venue).not_to eq @created_events[1].venue
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should use an existing venue when importing an event whose venue matches a squashed duplicate" do
|
|
161
|
+
dummy_source = Source.create!(:title => "Dummy", :url => "http://IcalEventWithSquashedVenue.com/")
|
|
162
|
+
master_venue = Venue.create!(:title => "Master")
|
|
163
|
+
squashed_venue = Venue.create!(
|
|
164
|
+
:title => "Squashed Duplicate Venue",
|
|
165
|
+
:duplicate_of_id => master_venue.id)
|
|
166
|
+
|
|
167
|
+
cal_content = %(
|
|
168
|
+
<div class="vevent">
|
|
169
|
+
<abbr class="dtstart" title="20090117"></abbr>
|
|
170
|
+
<abbr class="summary" title="Event with cloned venue"></abbr>
|
|
171
|
+
<abbr class="location" title="Squashed Duplicate Venue"></abbr>
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
url = "http://mysample.hcal/"
|
|
176
|
+
stub_request(:get, url).to_return(body: cal_content)
|
|
177
|
+
|
|
178
|
+
source = Source.new(title: "Event with squashed venue", url: url)
|
|
179
|
+
|
|
180
|
+
event = source.to_events(:skip_old => false).first
|
|
181
|
+
expect(event.venue.title).to eq "Master"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should use an existing venue when importing an event with a matching machine tag that describes a venue" do
|
|
185
|
+
venue = Venue.create!(:title => "Custom Urban Airship", :tag_list => "plancast:place=1520153")
|
|
186
|
+
|
|
187
|
+
plancast_url = 'http://plancast.com/p/3cos/indiewebcamp'
|
|
188
|
+
api_url = 'http://api.plancast.com/02/plans/show.json?extensions=place&plan_id=3cos'
|
|
189
|
+
stub_request(:get, api_url).to_return(body: read_sample('plancast.json'), headers: { content_type: "application/json" })
|
|
190
|
+
|
|
191
|
+
source = Source.new(title: "Event with duplicate machine-tagged venue", url: plancast_url)
|
|
192
|
+
|
|
193
|
+
event = source.to_events(:skip_old => false).first
|
|
194
|
+
|
|
195
|
+
expect(event.venue).to eq venue
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe "choosing parsers by matching URLs" do
|
|
199
|
+
{ "Calagator::Source::Parser::Plancast" => "http://plancast.com/p/3cos/indiewebcamp",
|
|
200
|
+
"Calagator::Source::Parser::Meetup" => "http://www.meetup.com/pdxweb/events/23287271/" }.each do |parser_name, url|
|
|
201
|
+
|
|
202
|
+
it "should only invoke the #{parser_name} parser when given #{url}" do
|
|
203
|
+
parser = parser_name.constantize
|
|
204
|
+
expect_any_instance_of(parser).to receive(:to_events).and_return([Event.new])
|
|
205
|
+
Source::Parser.parsers.reject{|p| p == parser }.each do |other_parser|
|
|
206
|
+
expect_any_instance_of(other_parser).not_to receive :to_events
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
stub_request(:get, url)
|
|
210
|
+
Source.new(:title => parser_name, :url => url).to_events
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
describe Source::Parser, "labels", :type => :model do
|
|
217
|
+
it "should have labels" do
|
|
218
|
+
expect(Source::Parser.labels).not_to be_blank
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "should have labels for each parser" do
|
|
222
|
+
expect(Source::Parser.labels.size).to eq Source::Parser.parsers.size
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should use the label of the parser, as a string" do
|
|
226
|
+
label = Source::Parser.parsers.first.label.to_s
|
|
227
|
+
expect(Source::Parser.labels).to include label
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "should have sorted labels" do
|
|
231
|
+
labels = Source::Parser.labels
|
|
232
|
+
sorted = labels.sort_by(&:downcase)
|
|
233
|
+
|
|
234
|
+
expect(labels).to eq sorted
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Calagator
|
|
4
|
+
|
|
5
|
+
describe Source, "in general", :type => :model do
|
|
6
|
+
before(:each) do
|
|
7
|
+
@event = mock_model(Event,
|
|
8
|
+
:title => "Title",
|
|
9
|
+
:description => "Description",
|
|
10
|
+
:url => "http://my.url/",
|
|
11
|
+
:start_time => Time.now + 1.day,
|
|
12
|
+
:end_time => nil,
|
|
13
|
+
:venue => nil,
|
|
14
|
+
:duplicate_of_id => nil)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should create events for source from URL" do
|
|
18
|
+
expect(@event).to receive(:save!)
|
|
19
|
+
|
|
20
|
+
source = Source.new(:url => "http://my.url/")
|
|
21
|
+
expect(source).to receive(:to_events).and_return([@event])
|
|
22
|
+
expect(source.create_events!).to eq [@event]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should fail to create events for invalid sources" do
|
|
26
|
+
source = Source.new(:url => '\not valid/')
|
|
27
|
+
expect{ source.to_events }.to raise_error(ActiveRecord::RecordInvalid, /Url has invalid format/i)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe Source, "when reading name", :type => :model do
|
|
32
|
+
before(:each) do
|
|
33
|
+
@title = "title"
|
|
34
|
+
@url = "http://my.url/"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
before(:each) do
|
|
38
|
+
@source = Source.new
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should return nil if no title is available" do
|
|
42
|
+
expect(@source.name).to be_nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should use title if available" do
|
|
46
|
+
@source.title = @title
|
|
47
|
+
expect(@source.name).to eq @title
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should use URL if available" do
|
|
51
|
+
@source.url = @url
|
|
52
|
+
expect(@source.name).to eq @url
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should prefer to use title over URL if both are available" do
|
|
56
|
+
@source.title = @title
|
|
57
|
+
@source.url = @url
|
|
58
|
+
|
|
59
|
+
expect(@source.name).to eq @title
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe Source, "when parsing URLs", :type => :model do
|
|
64
|
+
before(:each) do
|
|
65
|
+
@http_url = 'http://upcoming.yahoo.com/event/390164/'
|
|
66
|
+
@ical_url = 'webcal://upcoming.yahoo.com/event/390164/'
|
|
67
|
+
@base_url = 'upcoming.yahoo.com/event/390164/'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
before(:each) do
|
|
71
|
+
@source = Source.new
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should not modify supported url schemes" do
|
|
75
|
+
@source.url = @http_url
|
|
76
|
+
|
|
77
|
+
expect(@source.url).to eq @http_url
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should substitute http for unsupported url schemes" do
|
|
81
|
+
@source.url = @ical_url
|
|
82
|
+
|
|
83
|
+
expect(@source.url).to eq @http_url
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "should add the http prefix to urls without one" do
|
|
87
|
+
@source.url = @base_url
|
|
88
|
+
|
|
89
|
+
expect(@source.url).to eq @http_url
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should strip leading and trailing whitespace from URL" do
|
|
93
|
+
source = Source.new
|
|
94
|
+
source.url = " #{@http_url} "
|
|
95
|
+
expect(source.url).to eq @http_url
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should be invalid if given invalid URL" do
|
|
99
|
+
source = Source.new
|
|
100
|
+
source.url = '\O.o/'
|
|
101
|
+
expect(source.url).to be_nil
|
|
102
|
+
expect(source).not_to be_valid
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe Source, "find_or_create_from", :type => :model do
|
|
107
|
+
before do
|
|
108
|
+
@url = "http://foo.bar"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "should return new, unsaved record if given no arguments" do
|
|
112
|
+
source = Source.find_or_create_from()
|
|
113
|
+
|
|
114
|
+
expect(source).to be_a_new_record
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "should return an existing or newly-created record" do
|
|
118
|
+
record = Source.new(:url => @url)
|
|
119
|
+
expect(Source).to receive(:find_or_create_by_url).and_return(record)
|
|
120
|
+
|
|
121
|
+
result = Source.find_or_create_from(:url => @url)
|
|
122
|
+
expect(record).to eq result
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should set re-import flag if given" do
|
|
126
|
+
record = Source.new(:url => @url)
|
|
127
|
+
expect(record).to receive(:save)
|
|
128
|
+
expect(Source).to receive(:find_or_create_by_url).and_return(record)
|
|
129
|
+
|
|
130
|
+
result = Source.find_or_create_from(:url => @url, :reimport => true)
|
|
131
|
+
expect(result.reimport).to be_truthy
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|