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.
Files changed (384) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +23 -0
  3. data/README.md +75 -0
  4. data/Rakefile +12 -0
  5. data/app/assets/images/confused-alligator-sm.png +0 -0
  6. data/app/assets/images/disk.png +0 -0
  7. data/app/assets/images/edit.png +0 -0
  8. data/app/assets/images/external_sites/epdx.png +0 -0
  9. data/app/assets/images/external_sites/external.gif +0 -0
  10. data/app/assets/images/external_sites/facebook.png +0 -0
  11. data/app/assets/images/external_sites/foursquare.png +0 -0
  12. data/app/assets/images/external_sites/gowalla.png +0 -0
  13. data/app/assets/images/external_sites/lanyrd.png +0 -0
  14. data/app/assets/images/external_sites/meetup.png +0 -0
  15. data/app/assets/images/external_sites/plancast.png +0 -0
  16. data/app/assets/images/external_sites/shizzow.png +0 -0
  17. data/app/assets/images/external_sites/upcoming.png +0 -0
  18. data/app/assets/images/external_sites/yelp.png +0 -0
  19. data/app/assets/images/feed.png +0 -0
  20. data/app/assets/images/heart.png +0 -0
  21. data/app/assets/images/icon_ical.gif +0 -0
  22. data/app/assets/images/information.png +0 -0
  23. data/app/assets/images/nav_marker.gif +0 -0
  24. data/app/assets/images/nav_marker.png +0 -0
  25. data/app/assets/images/plus.png +0 -0
  26. data/app/assets/images/redx.png +0 -0
  27. data/app/assets/images/site-icon.png +0 -0
  28. data/app/assets/images/spinner.gif +0 -0
  29. data/app/assets/images/star.png +0 -0
  30. data/app/assets/images/subnav_marker.gif +0 -0
  31. data/app/assets/images/subnav_marker.png +0 -0
  32. data/app/assets/images/tag_blue.png +0 -0
  33. data/app/assets/images/tag_icons/angular.png +0 -0
  34. data/app/assets/images/tag_icons/beer.png +0 -0
  35. data/app/assets/images/tag_icons/bitcoin.png +0 -0
  36. data/app/assets/images/tag_icons/free.png +0 -0
  37. data/app/assets/images/tag_icons/golang.png +0 -0
  38. data/app/assets/images/tag_icons/html.png +0 -0
  39. data/app/assets/images/tag_icons/javascript.png +0 -0
  40. data/app/assets/images/tag_icons/linux.png +0 -0
  41. data/app/assets/images/tag_icons/php.png +0 -0
  42. data/app/assets/images/tag_icons/pizza.png +0 -0
  43. data/app/assets/images/tag_icons/python.png +0 -0
  44. data/app/assets/images/tag_icons/rails.png +0 -0
  45. data/app/assets/images/tag_icons/ruby.png +0 -0
  46. data/app/assets/images/tag_icons/sass.png +0 -0
  47. data/app/assets/images/tag_icons/swift.png +0 -0
  48. data/app/assets/images/transmit_blue.png +0 -0
  49. data/app/assets/images/weekday_background.gif +0 -0
  50. data/app/assets/javascripts/calagator.js +18 -0
  51. data/app/assets/javascripts/calagator/forms.js +60 -0
  52. data/app/assets/stylesheets/calagator.scss +8 -0
  53. data/app/assets/stylesheets/calagator/common.scss +14 -0
  54. data/app/assets/stylesheets/calagator/datepicker.scss +177 -0
  55. data/app/assets/stylesheets/calagator/errors.css +110 -0
  56. data/app/assets/stylesheets/calagator/forms.scss +4 -0
  57. data/app/assets/stylesheets/calagator/reset.css +40 -0
  58. data/app/assets/stylesheets/calagator/theme.css +0 -0
  59. data/app/controllers/calagator/admin_controller.rb +27 -0
  60. data/app/controllers/calagator/application_controller.rb +82 -0
  61. data/app/controllers/calagator/events_controller.rb +171 -0
  62. data/app/controllers/calagator/site_controller.rb +35 -0
  63. data/app/controllers/calagator/sources_controller.rb +94 -0
  64. data/app/controllers/calagator/venues_controller.rb +133 -0
  65. data/app/controllers/calagator/versions_controller.rb +20 -0
  66. data/app/helpers/calagator/application_helper.rb +128 -0
  67. data/app/helpers/calagator/events_helper.rb +184 -0
  68. data/app/helpers/calagator/google_event_export_helper.rb +67 -0
  69. data/app/helpers/calagator/mapping_helper.rb +103 -0
  70. data/app/helpers/calagator/sources_helper.rb +10 -0
  71. data/app/helpers/calagator/tags_helper.rb +42 -0
  72. data/app/helpers/calagator/time_range_helper.rb +166 -0
  73. data/app/models/calagator/event.rb +246 -0
  74. data/app/models/calagator/event/cloner.rb +39 -0
  75. data/app/models/calagator/event/ical_renderer.rb +155 -0
  76. data/app/models/calagator/event/overview.rb +45 -0
  77. data/app/models/calagator/event/saver.rb +58 -0
  78. data/app/models/calagator/event/search.rb +72 -0
  79. data/app/models/calagator/event/search_engine.rb +28 -0
  80. data/app/models/calagator/event/search_engine/apache_sunspot.rb +106 -0
  81. data/app/models/calagator/event/search_engine/sql.rb +107 -0
  82. data/app/models/calagator/source.rb +115 -0
  83. data/app/models/calagator/source/importer.rb +46 -0
  84. data/app/models/calagator/source/parser.rb +128 -0
  85. data/app/models/calagator/source/parser/facebook.rb +67 -0
  86. data/app/models/calagator/source/parser/hcal.rb +108 -0
  87. data/app/models/calagator/source/parser/http_authentication_required_error.rb +6 -0
  88. data/app/models/calagator/source/parser/ical.rb +186 -0
  89. data/app/models/calagator/source/parser/meetup.rb +72 -0
  90. data/app/models/calagator/source/parser/not_found.rb +9 -0
  91. data/app/models/calagator/source/parser/plancast.rb +59 -0
  92. data/app/models/calagator/venue.rb +161 -0
  93. data/app/models/calagator/venue/geocoder.rb +51 -0
  94. data/app/models/calagator/venue/search.rb +63 -0
  95. data/app/models/calagator/venue/search_engine.rb +24 -0
  96. data/app/models/calagator/venue/search_engine/apache_sunspot.rb +85 -0
  97. data/app/models/calagator/venue/search_engine/sql.rb +68 -0
  98. data/app/models/event/search_engine/base.rb +0 -0
  99. data/app/observers/calagator/cache_observer.rb +37 -0
  100. data/app/views/calagator/admin/events.html.erb +28 -0
  101. data/app/views/calagator/admin/index.html.erb +8 -0
  102. data/app/views/calagator/events/_feed_item.html.erb +62 -0
  103. data/app/views/calagator/events/_form.html.erb +63 -0
  104. data/app/views/calagator/events/_gcal_reminder.html.erb +1 -0
  105. data/app/views/calagator/events/_hcal.html.erb +41 -0
  106. data/app/views/calagator/events/_item.html.erb +120 -0
  107. data/app/views/calagator/events/_list.html.erb +30 -0
  108. data/app/views/calagator/events/_list_item.html.erb +37 -0
  109. data/app/views/calagator/events/_search_section.html.erb +15 -0
  110. data/app/views/calagator/events/_subnav.html.erb +13 -0
  111. data/app/views/calagator/events/_table.html.erb +74 -0
  112. data/app/views/calagator/events/duplicates.html.erb +58 -0
  113. data/app/views/calagator/events/edit.html.erb +3 -0
  114. data/app/views/calagator/events/index.atom.builder +32 -0
  115. data/app/views/calagator/events/index.html.erb +51 -0
  116. data/app/views/calagator/events/index.kml.erb +20 -0
  117. data/app/views/calagator/events/new.html.erb +7 -0
  118. data/app/views/calagator/events/search.html.erb +25 -0
  119. data/app/views/calagator/events/show.html.erb +81 -0
  120. data/app/views/calagator/site/_appropriateness_message.html.erb +15 -0
  121. data/app/views/calagator/site/_description.html.erb +3 -0
  122. data/app/views/calagator/site/about.html.erb +7 -0
  123. data/app/views/calagator/site/defunct.html.erb +15 -0
  124. data/app/views/calagator/site/export.html.erb +4 -0
  125. data/app/views/calagator/site/index.html.erb +40 -0
  126. data/app/views/calagator/site/opensearch.xml.builder +8 -0
  127. data/app/views/calagator/sources/_subnav.html.erb +0 -0
  128. data/app/views/calagator/sources/edit.html.erb +12 -0
  129. data/app/views/calagator/sources/import.html.erb +10 -0
  130. data/app/views/calagator/sources/index.html.erb +22 -0
  131. data/app/views/calagator/sources/new.html.erb +32 -0
  132. data/app/views/calagator/sources/show.html.erb +16 -0
  133. data/app/views/calagator/venues/_form.html.erb +57 -0
  134. data/app/views/calagator/venues/_subnav.html.erb +10 -0
  135. data/app/views/calagator/venues/duplicates.html.erb +65 -0
  136. data/app/views/calagator/venues/edit.html.erb +3 -0
  137. data/app/views/calagator/venues/index.html.erb +93 -0
  138. data/app/views/calagator/venues/index.kml.erb +15 -0
  139. data/app/views/calagator/venues/map.html.erb +4 -0
  140. data/app/views/calagator/venues/new.html.erb +5 -0
  141. data/app/views/calagator/venues/show.html.erb +113 -0
  142. data/app/views/calagator/versions/_chooser.html.erb +28 -0
  143. data/app/views/calagator/versions/_edit_with_chooser.html.erb +16 -0
  144. data/app/views/layouts/calagator/application.html.erb +110 -0
  145. data/config/deploy/local.rb +37 -0
  146. data/config/deploy/lucca.rb +33 -0
  147. data/config/initializers/dates.rb +7 -0
  148. data/config/initializers/formtastic.rb +82 -0
  149. data/config/initializers/geokit.rb +74 -0
  150. data/config/initializers/ics_renderer.rb +6 -0
  151. data/config/initializers/load_tag_model_extensions.rb +3 -0
  152. data/config/initializers/mime_types.rb +9 -0
  153. data/config/initializers/observers.rb +1 -0
  154. data/config/initializers/search_engine.rb +4 -0
  155. data/config/initializers/set_default_url_host.rb +5 -0
  156. data/config/initializers/time_get_zone.rb +8 -0
  157. data/config/locales/en.yml +5 -0
  158. data/config/routes.rb +55 -0
  159. data/config/secrets.yml.blag +75 -0
  160. data/config/sunspot.yml +23 -0
  161. data/db/development.sqlite3 +0 -0
  162. data/db/development.sqlite3.bak +0 -0
  163. data/db/development.sqlite3.old +0 -0
  164. data/db/development~20111112@110950.sqlite3 +0 -0
  165. data/db/migrate/001_create_events.rb +17 -0
  166. data/db/migrate/002_create_venues.rb +17 -0
  167. data/db/migrate/003_create_sources.rb +16 -0
  168. data/db/migrate/004_add_detailed_fields_to_venue.rb +19 -0
  169. data/db/migrate/005_add_end_time_to_events.rb +9 -0
  170. data/db/migrate/006_add_source_id_to_events.rb +9 -0
  171. data/db/migrate/008_add_source_id_to_venues.rb +10 -0
  172. data/db/migrate/009_add_duplicate_of_column_to_venues.rb +9 -0
  173. data/db/migrate/010_add_duplicate_of_column_to_events.rb +9 -0
  174. data/db/migrate/011_change_lat_long_type.rb +12 -0
  175. data/db/migrate/012_add_source_reimport.rb +9 -0
  176. data/db/migrate/013_change_end_time_to_duration.rb +11 -0
  177. data/db/migrate/014_remove_format_type_from_source.rb +9 -0
  178. data/db/migrate/015_create_updates.rb +15 -0
  179. data/db/migrate/016_remove_next_update_from_source.rb +9 -0
  180. data/db/migrate/20080705163959_change_duration_to_end_time.rb +11 -0
  181. data/db/migrate/20080705164959_create_tags_and_taggings.rb +28 -0
  182. data/db/migrate/20081011181519_create_versioned_events.rb +25 -0
  183. data/db/migrate/20081011193124_create_versioned_venues.rb +32 -0
  184. data/db/migrate/20081115190515_add_rrule_to_events.rb +15 -0
  185. data/db/migrate/20090912082129_create_versions.rb +18 -0
  186. data/db/migrate/20110219205156_add_closed_flag_to_venues.rb +9 -0
  187. data/db/migrate/20110220001008_add_wifi_flag_to_venues.rb +9 -0
  188. data/db/migrate/20110220011427_add_access_notes_to_venues.rb +9 -0
  189. data/db/migrate/20110220031117_add_events_count_to_venues.rb +8 -0
  190. data/db/migrate/20110604174521_add_venue_details_to_events.rb +9 -0
  191. data/db/migrate/20110717231316_acts_as_taggable_on_migration.rb +50 -0
  192. data/db/migrate/20120709092821_cleanup.rb +14 -0
  193. data/db/migrate/20120831234448_specify_venues_latitude_and_longitude_precision.rb +11 -0
  194. data/db/migrate/20150206085809_remove_updates.rb +13 -0
  195. data/db/migrate/20150207231355_add_locked_status_to_events.rb +5 -0
  196. data/db/production.sqlite3 +0 -0
  197. data/db/schema.rb +102 -0
  198. data/db/seeds.rb +16 -0
  199. data/db/test.sqlite3 +0 -0
  200. data/db/test2.sqlite3 +0 -0
  201. data/lib/calagator.rb +30 -0
  202. data/lib/calagator/blacklist_validator.rb +69 -0
  203. data/lib/calagator/decode_html_entities_hack.rb +33 -0
  204. data/lib/calagator/duplicate_checking.rb +133 -0
  205. data/lib/calagator/duplicate_checking/controller_actions.rb +38 -0
  206. data/lib/calagator/duplicate_checking/duplicate_finder.rb +83 -0
  207. data/lib/calagator/duplicate_checking/duplicate_squasher.rb +74 -0
  208. data/lib/calagator/engine.rb +30 -0
  209. data/lib/calagator/strip_whitespace.rb +19 -0
  210. data/lib/calagator/tag_model_extensions.rb +104 -0
  211. data/lib/calagator/url_prefixer.rb +9 -0
  212. data/lib/calagator/version.rb +3 -0
  213. data/lib/generators/calagator/install_generator.rb +39 -0
  214. data/lib/generators/calagator/templates/config/calagator.rb +26 -0
  215. data/lib/generators/calagator/templates/config/secrets.yml.sample +83 -0
  216. data/lib/secrets_reader.rb +76 -0
  217. data/lib/tasks/spec_db.rake +53 -0
  218. data/lib/tasks/sunspot_reindex_calagator.rake +6 -0
  219. data/lib/tasks/sunspot_solr_restart_enhancements.rake +19 -0
  220. data/lib/tasks/update_counter_caches.rake +13 -0
  221. data/lib/templates/erb/scaffold/_form.html.erb +11 -0
  222. data/lib/theme_reader.rb +17 -0
  223. data/lib/wait_for_solr.rb +25 -0
  224. data/spec/controllers/calagator/application_controller_spec.rb +47 -0
  225. data/spec/controllers/calagator/events_controller_spec.rb +794 -0
  226. data/spec/controllers/calagator/site_controller_spec.rb +59 -0
  227. data/spec/controllers/calagator/sources_controller_spec.rb +439 -0
  228. data/spec/controllers/calagator/venues_controller_spec.rb +319 -0
  229. data/spec/controllers/calagator/versions_controller_spec.rb +82 -0
  230. data/spec/controllers/squash_many_duplicates_examples.rb +49 -0
  231. data/spec/dummy/Gemfile +39 -0
  232. data/spec/dummy/Gemfile.lock +195 -0
  233. data/spec/dummy/README.rdoc +261 -0
  234. data/spec/dummy/Rakefile +7 -0
  235. data/spec/dummy/app/assets/images/rails.png +0 -0
  236. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  237. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  238. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  239. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  240. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  241. data/spec/dummy/config.ru +4 -0
  242. data/spec/dummy/config/application.rb +62 -0
  243. data/spec/dummy/config/boot.rb +6 -0
  244. data/spec/dummy/config/database.yml +25 -0
  245. data/spec/dummy/config/environment.rb +5 -0
  246. data/spec/dummy/config/environments/development.rb +37 -0
  247. data/spec/dummy/config/environments/production.rb +67 -0
  248. data/spec/dummy/config/environments/test.rb +37 -0
  249. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  250. data/spec/dummy/config/initializers/calagator.rb +26 -0
  251. data/spec/dummy/config/initializers/inflections.rb +15 -0
  252. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  253. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  254. data/spec/dummy/config/initializers/session_store.rb +8 -0
  255. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  256. data/spec/dummy/config/locales/en.yml +5 -0
  257. data/spec/dummy/config/routes.rb +59 -0
  258. data/spec/dummy/config/secrets.yml +83 -0
  259. data/spec/dummy/db/development.sqlite3 +0 -0
  260. data/spec/dummy/db/migrate/20150309023304_create_events.calagator.rb +18 -0
  261. data/spec/dummy/db/migrate/20150309023305_create_venues.calagator.rb +18 -0
  262. data/spec/dummy/db/migrate/20150309023306_create_sources.calagator.rb +17 -0
  263. data/spec/dummy/db/migrate/20150309023307_add_detailed_fields_to_venue.calagator.rb +20 -0
  264. data/spec/dummy/db/migrate/20150309023308_add_end_time_to_events.calagator.rb +10 -0
  265. data/spec/dummy/db/migrate/20150309023309_add_source_id_to_events.calagator.rb +10 -0
  266. data/spec/dummy/db/migrate/20150309023310_add_source_id_to_venues.calagator.rb +11 -0
  267. data/spec/dummy/db/migrate/20150309023311_add_duplicate_of_column_to_venues.calagator.rb +10 -0
  268. data/spec/dummy/db/migrate/20150309023312_add_duplicate_of_column_to_events.calagator.rb +10 -0
  269. data/spec/dummy/db/migrate/20150309023313_change_lat_long_type.calagator.rb +13 -0
  270. data/spec/dummy/db/migrate/20150309023314_add_source_reimport.calagator.rb +10 -0
  271. data/spec/dummy/db/migrate/20150309023315_change_end_time_to_duration.calagator.rb +12 -0
  272. data/spec/dummy/db/migrate/20150309023316_remove_format_type_from_source.calagator.rb +10 -0
  273. data/spec/dummy/db/migrate/20150309023317_create_updates.calagator.rb +16 -0
  274. data/spec/dummy/db/migrate/20150309023318_remove_next_update_from_source.calagator.rb +10 -0
  275. data/spec/dummy/db/migrate/20150309023319_change_duration_to_end_time.calagator.rb +12 -0
  276. data/spec/dummy/db/migrate/20150309023320_create_tags_and_taggings.calagator.rb +29 -0
  277. data/spec/dummy/db/migrate/20150309023321_create_versioned_events.calagator.rb +26 -0
  278. data/spec/dummy/db/migrate/20150309023322_create_versioned_venues.calagator.rb +33 -0
  279. data/spec/dummy/db/migrate/20150309023323_add_rrule_to_events.calagator.rb +16 -0
  280. data/spec/dummy/db/migrate/20150309023324_create_versions.calagator.rb +19 -0
  281. data/spec/dummy/db/migrate/20150309023325_add_closed_flag_to_venues.calagator.rb +10 -0
  282. data/spec/dummy/db/migrate/20150309023326_add_wifi_flag_to_venues.calagator.rb +10 -0
  283. data/spec/dummy/db/migrate/20150309023327_add_access_notes_to_venues.calagator.rb +10 -0
  284. data/spec/dummy/db/migrate/20150309023328_add_events_count_to_venues.calagator.rb +9 -0
  285. data/spec/dummy/db/migrate/20150309023329_add_venue_details_to_events.calagator.rb +10 -0
  286. data/spec/dummy/db/migrate/20150309023330_acts_as_taggable_on_migration.calagator.rb +51 -0
  287. data/spec/dummy/db/migrate/20150309023331_cleanup.calagator.rb +15 -0
  288. data/spec/dummy/db/migrate/20150309023332_specify_venues_latitude_and_longitude_precision.calagator.rb +12 -0
  289. data/spec/dummy/db/migrate/20150309023333_remove_updates.calagator.rb +14 -0
  290. data/spec/dummy/db/migrate/20150309023334_add_locked_status_to_events.calagator.rb +6 -0
  291. data/spec/dummy/db/schema.rb +95 -0
  292. data/spec/dummy/db/seeds.rb +7 -0
  293. data/spec/dummy/db/test.sqlite3 +0 -0
  294. data/spec/dummy/doc/README_FOR_APP +2 -0
  295. data/spec/dummy/log/development.log +273 -0
  296. data/spec/dummy/public/404.html +26 -0
  297. data/spec/dummy/public/422.html +26 -0
  298. data/spec/dummy/public/500.html +25 -0
  299. data/spec/dummy/public/favicon.ico +0 -0
  300. data/spec/dummy/public/robots.txt +5 -0
  301. data/spec/dummy/script/rails +6 -0
  302. data/spec/dummy/test/performance/browsing_test.rb +12 -0
  303. data/spec/dummy/test/test_helper.rb +13 -0
  304. data/spec/factories.rb +93 -0
  305. data/spec/features/add_event_spec.rb +99 -0
  306. data/spec/features/add_venue_spec.rb +34 -0
  307. data/spec/features/admin_auth_spec.rb +22 -0
  308. data/spec/features/admin_lock_event_spec.rb +41 -0
  309. data/spec/features/import_events_from_feed_spec.rb +43 -0
  310. data/spec/features/managing_event_spec.rb +111 -0
  311. data/spec/features/managing_venue_spec.rb +71 -0
  312. data/spec/features/search_event_spec.rb +27 -0
  313. data/spec/helpers/calagator/application_helper_spec.rb +82 -0
  314. data/spec/helpers/calagator/events_helper_spec.rb +172 -0
  315. data/spec/helpers/calagator/google_event_export_helper_spec.rb +70 -0
  316. data/spec/helpers/calagator/sources_helper_spec.rb +12 -0
  317. data/spec/helpers/calagator/tags_helper_spec.rb +85 -0
  318. data/spec/helpers/calagator/time_range_helper_spec.rb +59 -0
  319. data/spec/lib/calagator/blacklist_validator_spec.rb +65 -0
  320. data/spec/lib/calagator/decode_html_entities_hack_spec.rb +54 -0
  321. data/spec/lib/calagator/settings_spec.rb +20 -0
  322. data/spec/lib/calagator/url_prefixer_spec.rb +33 -0
  323. data/spec/lib/secrets_reader_spec.rb +65 -0
  324. data/spec/models/calagator/event/cloner_spec.rb +43 -0
  325. data/spec/models/calagator/event/overview_spec.rb +79 -0
  326. data/spec/models/calagator/event/search_spec.rb +103 -0
  327. data/spec/models/calagator/event_search_spec.rb +149 -0
  328. data/spec/models/calagator/event_spec.rb +859 -0
  329. data/spec/models/calagator/source/parser_facebook_spec.rb +73 -0
  330. data/spec/models/calagator/source/parser_hcal_spec.rb +69 -0
  331. data/spec/models/calagator/source/parser_ical_non_standard_spec.rb +91 -0
  332. data/spec/models/calagator/source/parser_ical_spec.rb +322 -0
  333. data/spec/models/calagator/source/parser_meetup_spec.rb +69 -0
  334. data/spec/models/calagator/source/parser_plancast_spec.rb +53 -0
  335. data/spec/models/calagator/source/parser_spec.rb +238 -0
  336. data/spec/models/calagator/source_spec.rb +135 -0
  337. data/spec/models/calagator/venue/search_spec.rb +92 -0
  338. data/spec/models/calagator/venue_search_spec.rb +124 -0
  339. data/spec/models/calagator/venue_spec.rb +346 -0
  340. data/spec/models/tag_spec.rb +35 -0
  341. data/spec/rails_helper.rb +39 -0
  342. data/spec/spec_helper.rb +140 -0
  343. data/spec/support/disable_geocoding.rb +1 -0
  344. data/spec/support/http_samples.rb +5 -0
  345. data/spec/support/samples/facebook.json +23 -0
  346. data/spec/support/samples/hcal_basic.xml +6 -0
  347. data/spec/support/samples/hcal_dup_event_dup_venue.xml +13 -0
  348. data/spec/support/samples/hcal_event_duplicates_fixture.xml +13 -0
  349. data/spec/support/samples/hcal_event_wo_lat_and_long.xml +14 -0
  350. data/spec/support/samples/hcal_multiple.xml +16 -0
  351. data/spec/support/samples/hcal_same_event_twice_with_different_venues.xml +12 -0
  352. data/spec/support/samples/hcal_single.xml +8 -0
  353. data/spec/support/samples/hcal_two_identical_events.xml +14 -0
  354. data/spec/support/samples/hcal_upcoming_v1.html +412 -0
  355. data/spec/support/samples/hcal_upcoming_v2.html +749 -0
  356. data/spec/support/samples/hcal_upcoming_v3.html +685 -0
  357. data/spec/support/samples/hcal_upcoming_v4.html +761 -0
  358. data/spec/support/samples/ical_apple.ics +22 -0
  359. data/spec/support/samples/ical_apple_v3.ics +37 -0
  360. data/spec/support/samples/ical_basic.ics +15 -0
  361. data/spec/support/samples/ical_basic_with_duration.ics +16 -0
  362. data/spec/support/samples/ical_event_with_squashed_venue.ics +12 -0
  363. data/spec/support/samples/ical_eventful_many.ics +504 -0
  364. data/spec/support/samples/ical_gmt.ics +12 -0
  365. data/spec/support/samples/ical_google.ics +786 -0
  366. data/spec/support/samples/ical_multiple_calendars.ics +111 -0
  367. data/spec/support/samples/ical_upcoming.ics +36 -0
  368. data/spec/support/samples/ical_upcoming_many.ics +682 -0
  369. data/spec/support/samples/ical_upcoming_v2.ics +43 -0
  370. data/spec/support/samples/ical_z.ics +10 -0
  371. data/spec/support/samples/meetup.ics +16 -0
  372. data/spec/support/samples/meetup.json +31 -0
  373. data/spec/support/samples/plancast.ics +59 -0
  374. data/spec/support/samples/plancast.json +51 -0
  375. data/spec/support/samples/plancast_with_missing_venue.json +39 -0
  376. data/spec/support/samples/upcoming_v1.xml +8 -0
  377. data/spec/support/samples/upcoming_v2_with_invalid_utc_dates.xml +8 -0
  378. data/spec/support/time_convenience_methods.rb +8 -0
  379. data/spec/support/time_zones.rb +12 -0
  380. data/spec/support/url_helpers.rb +5 -0
  381. data/spec/support/wait_for_ajax.rb +15 -0
  382. data/spec/support/webmock.rb +8 -0
  383. data/spec/travis_spec.rb +7 -0
  384. metadata +1194 -0
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ module Calagator
4
+
5
+ describe GoogleEventExportHelper, :type => :helper do
6
+ describe "google_event_export_link" do
7
+ def escape(string)
8
+ return Regexp.escape(CGI.escape(string))
9
+ end
10
+
11
+ shared_context "exported event setup" do
12
+ before do
13
+ @venue = Venue.create!(:title => "My venue", :address => "1930 SW 4th Ave, Portland, Oregon 97201")
14
+ @event = Event.create!(:title => "My event", :start_time => "2010-01-01 12:00:00", :end_time => "2010-01-01 13:00:00", :venue => @venue, :description => event_description)
15
+ @export = helper.google_event_export_link(@event)
16
+ end
17
+ end
18
+
19
+ shared_examples_for "exported event" do
20
+ it "should have title" do
21
+ expect(@export).to match /\&text=#{escape(@event.title)}/
22
+ end
23
+
24
+ it "should have time range in utc" do
25
+ dates = Rack::Utils.parse_query(@export)["dates"]
26
+ format = "%Y%m%dT%H%M%SZ"
27
+ dates.should == [
28
+ @event.start_time.utc.strftime(format),
29
+ @event.end_time.utc.strftime(format),
30
+ ].join("/")
31
+ end
32
+
33
+ it "should have venue title" do
34
+ expect(@export).to match /\&location=#{escape(@event.venue.title)}/
35
+ end
36
+
37
+ it "should have venue address" do
38
+ expect(@export).to match /\&location=.+?#{escape(@event.venue.geocode_address)}/
39
+ end
40
+ end
41
+
42
+ describe "an event's text doesn't need truncation" do
43
+ let(:event_description) { "My event description." }
44
+ include_context "exported event setup"
45
+
46
+ it_should_behave_like "exported event"
47
+
48
+ it "should have a complete event description" do
49
+ expect(@export).to match /\&details=.*#{escape(event_description)}/
50
+ end
51
+ end
52
+
53
+ describe "an event's text needs truncation" do
54
+ let(:event_description) { "My event description. " * 100 }
55
+ include_context "exported event setup"
56
+
57
+ it_should_behave_like "exported event"
58
+
59
+ it "should have a truncated event description" do
60
+ expect(@export).to match /\&details=.*#{escape(event_description[0..100])}/
61
+ end
62
+
63
+ it "should have a truncated URL" do
64
+ expect(@export.size).to be < event_description.size
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe Calagator::SourcesHelper, :type => :helper do
4
+ describe "#source_url_link" do
5
+ it "returns an unspiderable link that opens in a new window" do
6
+ source = double(url: "http://google.com")
7
+ expect(helper.source_url_link(source)).to eq(
8
+ %(<a href="http://google.com" rel="nofollow" target="_BLANK">http://google.com</a>)
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ module Calagator
4
+
5
+ describe TagsHelper, type: :helper do
6
+ describe "#tag_links_for" do
7
+ it "renders tag links for the supplied model" do
8
+ event = FactoryGirl.create(:event, tag_list: %w(b a))
9
+ expect(tag_links_for(event)).to eq(
10
+ %(<a href="/events/tag/a" class="p-category">a</a>, ) +
11
+ %(<a href="/events/tag/b" class="p-category">b</a>)
12
+ )
13
+ end
14
+ end
15
+
16
+ describe "#icon_exists_for?" do
17
+ it "should return true if there is a PNG file in tag_icons with the name of the argument" do
18
+ expect(helper.icon_exists_for?("pizza")).to eq true
19
+ end
20
+
21
+ it "should return false if there is not a PNG file in tag_icons with the name of the argument" do
22
+ expect(helper.icon_exists_for?("no_image")).to eq false
23
+ end
24
+ end
25
+
26
+ shared_context "tag icons" do
27
+ before do
28
+ @event = FactoryGirl.create(:event, :tag_list => ['ruby', 'pizza'])
29
+ @event2 = FactoryGirl.create(:event, :tag_list => ['no_image', 'also_no_image'])
30
+ @untagged_event = Event.new
31
+ end
32
+ end
33
+
34
+ describe "#get_tag_icon_links" do
35
+ include_context "tag icons"
36
+
37
+ it "should generate an array of image tags" do
38
+ helper.get_tag_icon_links(@event).each do |item|
39
+ expect(item).to include "<img "
40
+ end
41
+ end
42
+
43
+ it "should generate an array of link tags" do
44
+ helper.get_tag_icon_links(@event).each do |item|
45
+ expect(item).to include "<a "
46
+ end
47
+ end
48
+
49
+ it "should generate items for each tag that has a corresponding image" do
50
+ expect(helper.get_tag_icon_links(@event)[0]).to include "Ruby"
51
+ expect(helper.get_tag_icon_links(@event)[0]).to include "ruby.png"
52
+ expect(helper.get_tag_icon_links(@event)[1]).to include "Pizza"
53
+ expect(helper.get_tag_icon_links(@event)[1]).to include "pizza.png"
54
+ end
55
+
56
+ it "should return nil values for tags that do not correspond to images" do
57
+ expect(helper.get_tag_icon_links(@event2)).to eq [nil, nil]
58
+ end
59
+
60
+ it "should return a blank array if event has no tags" do
61
+ expect(helper.get_tag_icon_links(@untagged_event)).to eq []
62
+ end
63
+ end
64
+
65
+ describe "#display_tag_icons" do
66
+ include_context "tag icons"
67
+
68
+ it "should render image tags inline and whitespace separated" do
69
+ expect(helper.display_tag_icons(@event)).to include "Ruby"
70
+ expect(helper.display_tag_icons(@event)).to include "ruby.png"
71
+ expect(helper.display_tag_icons(@event)).to include "Pizza"
72
+ expect(helper.display_tag_icons(@event)).to include "pizza.png"
73
+ end
74
+
75
+ it "should render nothing if no image tags" do
76
+ expect(helper.display_tag_icons(@event2)).to eq " "
77
+ end
78
+
79
+ it "should render nothing if event has no tags" do
80
+ expect(helper.display_tag_icons(@untagged_event)).to eq ""
81
+ end
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ module Calagator
4
+
5
+ describe TimeRangeHelper do
6
+ let(:start_time) { DateTime.new(2008, 4, 1, 9, 00) }
7
+
8
+ # Test all permutations of
9
+ # - context-date: with vs without
10
+ # - format: hcal vs html (tags stripped) vs text (tags stripped, '&ndash;' --> '-')
11
+ tests = [
12
+ # comment, end_time, results_without_context, results_with_context
13
+ [ "start time only", nil,
14
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">Tuesday, April 1, 2008 at 9am</time>",
15
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">9am</time>"],
16
+ [ "same day & am-pm", DateTime.new(2008, 4, 1, 11, 00),
17
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">Tuesday, April 1, 2008 from 9</time>&ndash;<time class=\"dtend dt-end\" title=\"2008-04-01T11:00:00\" datetime=\"2008-04-01T11:00:00\">11am</time>",
18
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">9</time>&ndash;<time class=\"dtend dt-end\" title=\"2008-04-01T11:00:00\" datetime=\"2008-04-01T11:00:00\">11am</time>" ],
19
+ [ "same day, different am-pm", DateTime.new(2008, 4, 1, 13, 30),
20
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">Tuesday, April 1, 2008 from 9am</time>&ndash;<time class=\"dtend dt-end\" title=\"2008-04-01T13:30:00\" datetime=\"2008-04-01T13:30:00\">1:30pm</time>",
21
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">9am</time>&ndash;<time class=\"dtend dt-end\" title=\"2008-04-01T13:30:00\" datetime=\"2008-04-01T13:30:00\">1:30pm</time>" ],
22
+ [ "different days", DateTime.new(2009, 4, 1, 13, 30),
23
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">Tuesday, April 1, 2008 at 9am</time> through <time class=\"dtend dt-end\" title=\"2009-04-01T13:30:00\" datetime=\"2009-04-01T13:30:00\">Wednesday, April 1, 2009 at 1:30pm</time>",
24
+ "<time class=\"dtstart dt-start\" title=\"2008-04-01T09:00:00\" datetime=\"2008-04-01T09:00:00\">9am</time> through <time class=\"dtend dt-end\" title=\"2009-04-01T13:30:00\" datetime=\"2009-04-01T13:30:00\">Wednesday, April 1, 2009 at 1:30pm</time>" ]
25
+ ]
26
+
27
+ [nil, Date.new(2008, 4, 1)].each do |context_date|
28
+ describe "with#{context_date.nil? ? "out" : ""} context date" do
29
+ [:text, :hcal, :html].each do |format|
30
+ tests.each do |label, end_time, expected_without_context, expected_with_context|
31
+ expected = context_date ? expected_with_context : expected_without_context
32
+ expected = expected.gsub(%r|\<[^\>]*\>|,'') if format != :hcal
33
+ expected = expected.gsub('&ndash;', '-') if format == :text
34
+ it "should format #{label} in #{format} format as '#{expected}'" do
35
+ actual = helper.normalize_time(start_time, end_time, format: format, context: context_date)
36
+ expect(actual).to eq expected
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "with objects" do
44
+ it "should format from objects that respond to just start_time" do
45
+ event = Event.new(:start_time => Time.zone.parse('2008-04-01 13:30'))
46
+ actual = helper.normalize_time(event, format: :text)
47
+ expect(actual).to eq "Tuesday, April 1, 2008 at 1:30pm"
48
+ end
49
+
50
+ it "should format from objects that respond to both start_time and end_time" do
51
+ event = Event.new(:start_time => Time.zone.parse('2008-04-01 13:30'),
52
+ :end_time => Time.zone.parse('2008-04-01 15:30'))
53
+ actual = helper.normalize_time(event, format: :text)
54
+ expect(actual).to eq "Tuesday, April 1, 2008 from 1:30-3:30pm"
55
+ end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,65 @@
1
+ require "active_model"
2
+ require "calagator/blacklist_validator"
3
+
4
+ module Calagator
5
+
6
+ describe BlacklistValidator do
7
+ let(:klass) do
8
+ Class.new do
9
+ include ActiveModel::Validations
10
+ validates :title, blacklist: true
11
+ attr_accessor :title
12
+ end
13
+ end
14
+
15
+ subject { klass.new }
16
+
17
+ describe "with default blacklist" do
18
+ it "should be valid when clean" do
19
+ subject.title = "Title"
20
+ expect(subject).to be_valid
21
+ end
22
+
23
+ it "should not be valid when it features blacklisted word" do
24
+ subject.title = "Foo bar cialis"
25
+ expect(subject).not_to be_valid
26
+ end
27
+ end
28
+
29
+ describe "with custom blacklist" do
30
+ before do
31
+ klass.validates :title, blacklist: { patterns: [/Kltpzyxm/i] }
32
+ end
33
+
34
+ it "should be valid when clean" do
35
+ subject.title = "Title"
36
+ expect(subject).to be_valid
37
+ end
38
+
39
+ it "should not be valid when it features custom blacklisted word" do
40
+ subject.title = "fooKLTPZYXMbar"
41
+ expect(subject).not_to be_valid
42
+ end
43
+ end
44
+
45
+ describe "created with custom blacklist file" do
46
+ let(:blacklist_file_path) { Rails.root.join("config/blacklist.txt") }
47
+
48
+ before do
49
+ allow(File).to receive(:exists?).with(blacklist_file_path).and_return(true)
50
+ expect(File).to receive(:readlines).with(blacklist_file_path).and_return(["Kltpzyxm"])
51
+ end
52
+
53
+ it "should be valid when clean" do
54
+ subject.title = "Title"
55
+ expect(subject).to be_valid
56
+ end
57
+
58
+ it "should not be valid when it features custom blacklisted word" do
59
+ subject.title = "fooKLTPZYXMbar"
60
+ expect(subject).not_to be_valid
61
+ end
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ # Non-database model derived from: http://railscasts.com/episodes/219-active-model
4
+ module Calagator
5
+
6
+ class ModelWithoutDecodeHack
7
+ include ActiveModel::Callbacks
8
+ include ActiveModel::Validations
9
+ include ActiveModel::Conversion
10
+ extend ActiveModel::Naming
11
+
12
+ define_callbacks :validate
13
+
14
+ attr_accessor :kitten
15
+
16
+ def initialize(attributes = {})
17
+ attributes.each do |name, value|
18
+ send("#{name}=", value)
19
+ end
20
+ end
21
+
22
+ def persisted?
23
+ false
24
+ end
25
+
26
+ def attributes
27
+ { :kitten => kitten }
28
+ end
29
+ end
30
+
31
+ # Same as above but with the mixin
32
+ class ModelWithDecodeHack < ModelWithoutDecodeHack
33
+ include DecodeHtmlEntitiesHack
34
+ end
35
+
36
+ describe DecodeHtmlEntitiesHack, :type => :model do
37
+ let(:encoded_string) { "cute &amp; furry" }
38
+ let(:decoded_string) { "cute & furry" }
39
+
40
+ it "should not modify attributes in models that don't include it" do
41
+ record = ModelWithoutDecodeHack.new(:kitten => encoded_string)
42
+ expect(record).to be_valid
43
+ expect(record.kitten).to eq encoded_string
44
+ end
45
+
46
+ it "should modify attributes in models that include it" do
47
+ record = ModelWithDecodeHack.new(:kitten => encoded_string)
48
+ expect(record).to be_valid
49
+ expect(record.kitten).to eq decoded_string
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Calagator
4
+ describe 'Calagator.title' do
5
+ it "should use default value" do
6
+ expect(Calagator.title).to eq('Calagator')
7
+ end
8
+
9
+ it "should be configurable" do
10
+ Calagator.setup { |config| config.title = 'Calagator Test' }
11
+ expect(Calagator.title).to eq('Calagator Test')
12
+ end
13
+
14
+ around do |example|
15
+ original = Calagator.title
16
+ example.run
17
+ Calagator.title = original
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "calagator/url_prefixer"
3
+
4
+ module Calagator
5
+
6
+ describe UrlPrefixer do
7
+ it "adds an http prefix to urls missing it" do
8
+ url = UrlPrefixer.prefix("google.com")
9
+ url.should == "http://google.com"
10
+ end
11
+
12
+ it "leaves urls with an existing scheme alone" do
13
+ url = UrlPrefixer.prefix("https://google.com")
14
+ url.should == "https://google.com"
15
+ end
16
+
17
+ it "leaves blank urls alone" do
18
+ url = UrlPrefixer.prefix(" ")
19
+ url.should == " "
20
+ end
21
+
22
+ it "leaves nil urls alone" do
23
+ url = UrlPrefixer.prefix(nil)
24
+ url.should == nil
25
+ end
26
+
27
+ it "avoids whitespace inside url" do
28
+ url = UrlPrefixer.prefix(" google.com ")
29
+ url.should == "http://google.com "
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,65 @@
1
+ describe SecretsReader do
2
+ describe ".read" do
3
+ let(:yml) { <<-YML }
4
+ administrator_email: 'your@email.addr'
5
+ mapping:
6
+ marker_color: green
7
+ google_maps_api_key: <your google maps v3 API key>
8
+ YML
9
+
10
+ it "returns an openstruct read from the given file path" do
11
+ path = "myfile.yml"
12
+ allow(File).to receive(:exist?).with(path).and_return(true)
13
+ allow(File).to receive(:read).with(path).and_return(yml)
14
+
15
+ expect(SecretsReader.read(path)).to eq OpenStruct.new({
16
+ "administrator_email" => "your@email.addr",
17
+ "mapping" => {
18
+ "marker_color" => "green",
19
+ "google_maps_api_key" => "<your google maps v3 API key>",
20
+ }
21
+ })
22
+ end
23
+
24
+ it "defaults to config/secrets.yml" do
25
+ path = Rails.root.join("config/secrets.yml").to_s
26
+ allow(File).to receive(:exist?).with(path).and_return(true)
27
+ allow(File).to receive(:read).with(path).and_return(yml)
28
+
29
+ expect(SecretsReader.read).to eq OpenStruct.new({
30
+ "administrator_email" => "your@email.addr",
31
+ "mapping" => {
32
+ "marker_color" => "green",
33
+ "google_maps_api_key" => "<your google maps v3 API key>",
34
+ }
35
+ })
36
+ end
37
+
38
+ it "will fall back to config/secrets.yml.sample" do
39
+ default_path = Rails.root.join("config/secrets.yml").to_s
40
+ allow(File).to receive(:exist?).with(default_path).and_return(false)
41
+
42
+ path = Rails.root.join("config/secrets.yml.sample").to_s
43
+ allow(File).to receive(:exist?).with(path).and_return(true)
44
+ allow(File).to receive(:read).with(path).and_return(yml)
45
+
46
+ expect(SecretsReader.read).to eq OpenStruct.new({
47
+ "administrator_email" => "your@email.addr",
48
+ "mapping" => {
49
+ "marker_color" => "green",
50
+ "google_maps_api_key" => "<your google maps v3 API key>",
51
+ }
52
+ })
53
+ end
54
+
55
+ it "returns an empty openstruct if all fails" do
56
+ default_path = Rails.root.join("config/secrets.yml").to_s
57
+ allow(File).to receive(:exist?).with(default_path).and_return(false)
58
+
59
+ path = Rails.root.join("config/secrets.yml.sample").to_s
60
+ allow(File).to receive(:exist?).with(path).and_return(false)
61
+
62
+ expect(SecretsReader.read).to eq OpenStruct.new
63
+ end
64
+ end
65
+ end