campfire_logic 1.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/Capfile +4 -0
  2. data/Gemfile +29 -0
  3. data/Gemfile.local +27 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +43 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/application_controller.rb +5 -0
  8. data/app/controllers/directory_controller.rb +65 -0
  9. data/app/controllers/locations_controller.rb +65 -0
  10. data/app/controllers/services_controller.rb +46 -0
  11. data/app/helpers/application_helper.rb +27 -0
  12. data/app/models/google_maps_geocoder.rb +108 -0
  13. data/app/models/locale.rb +204 -0
  14. data/app/models/location.rb +216 -0
  15. data/app/models/location_import.rb +48 -0
  16. data/app/models/service.rb +27 -0
  17. data/app/models/zip_code.rb +48 -0
  18. data/app/models/zip_code_import.rb +19 -0
  19. data/app/views/directory/_search_form.html.erb +4 -0
  20. data/app/views/directory/_show_children.html.erb +29 -0
  21. data/app/views/directory/_show_location.html.erb +14 -0
  22. data/app/views/directory/search.html.erb +31 -0
  23. data/app/views/directory/show.html.erb +32 -0
  24. data/app/views/layouts/application.html.erb +49 -0
  25. data/app/views/locations/_form.html.erb +69 -0
  26. data/app/views/locations/edit.html.erb +3 -0
  27. data/app/views/locations/export.erb +4 -0
  28. data/app/views/locations/import.html.erb +13 -0
  29. data/app/views/locations/index.html.erb +37 -0
  30. data/app/views/locations/new.html.erb +3 -0
  31. data/app/views/locations/show.html.erb +70 -0
  32. data/app/views/services/_form.html.erb +29 -0
  33. data/app/views/services/edit.html.erb +3 -0
  34. data/app/views/services/index.html.erb +25 -0
  35. data/app/views/services/new.html.erb +3 -0
  36. data/app/views/services/show.html.erb +15 -0
  37. data/app/views/shared/_location.html.erb +18 -0
  38. data/app/views/shared/_map.html.erb +2 -0
  39. data/app/views/shared/_nav_tabs.html.erb +5 -0
  40. data/autotest/discover.rb +1 -0
  41. data/campfire_logic.gemspec +208 -0
  42. data/config/application.rb +44 -0
  43. data/config/boot.rb +13 -0
  44. data/config/cucumber.yml +10 -0
  45. data/config/deploy.rb +40 -0
  46. data/config/environment.rb +6 -0
  47. data/config/environments/development.rb +28 -0
  48. data/config/environments/production.rb +49 -0
  49. data/config/environments/test.rb +35 -0
  50. data/config/initializers/campfire_logic.rb +3 -0
  51. data/config/initializers/metric_fu.rb +9 -0
  52. data/config/initializers/secret_token.rb +7 -0
  53. data/config/initializers/session_store.rb +8 -0
  54. data/config/locales/en.yml +5 -0
  55. data/config/mongoid.yml +25 -0
  56. data/config/routes.rb +96 -0
  57. data/config.ru +4 -0
  58. data/db/seeds.rb +5 -0
  59. data/db/zip_codes.txt +42742 -0
  60. data/doc/google_maps_response.rb +56 -0
  61. data/features/admin_manages_locations.feature +10 -0
  62. data/features/customer_browses_directory.feature +25 -0
  63. data/features/customer_searches_directory.feature +29 -0
  64. data/features/step_definitions/directory_steps.rb +22 -0
  65. data/features/step_definitions/location_steps.rb +10 -0
  66. data/features/step_definitions/web_steps.rb +211 -0
  67. data/features/support/env.rb +31 -0
  68. data/features/support/paths.rb +33 -0
  69. data/features/support/selectors.rb +39 -0
  70. data/init.rb +1 -0
  71. data/lib/campfire_logic/engine.rb +7 -0
  72. data/lib/campfire_logic/railtie.rb +10 -0
  73. data/lib/campfire_logic.rb +31 -0
  74. data/lib/tasks/campfire_logic.rake +7 -0
  75. data/lib/tasks/cucumber.rake +71 -0
  76. data/public/404.html +26 -0
  77. data/public/422.html +26 -0
  78. data/public/500.html +26 -0
  79. data/public/favicon.ico +0 -0
  80. data/public/images/icons/collapsed.gif +0 -0
  81. data/public/images/icons/delete.png +0 -0
  82. data/public/images/icons/drag.png +0 -0
  83. data/public/images/icons/edit.png +0 -0
  84. data/public/images/icons/expanded.gif +0 -0
  85. data/public/images/icons/help_icon.png +0 -0
  86. data/public/images/icons/link_icon.png +0 -0
  87. data/public/images/icons/move.png +0 -0
  88. data/public/images/icons/move_white.png +0 -0
  89. data/public/images/icons/note.png +0 -0
  90. data/public/images/icons/note_white.png +0 -0
  91. data/public/images/icons/notification_icon_sprite.png +0 -0
  92. data/public/images/icons/spinner.gif +0 -0
  93. data/public/images/icons/view.png +0 -0
  94. data/public/images/icons/warning.png +0 -0
  95. data/public/images/icons/warning_2.png +0 -0
  96. data/public/images/icons/warning_box.png +0 -0
  97. data/public/images/icons/warning_icon.png +0 -0
  98. data/public/images/icons/warning_white.png +0 -0
  99. data/public/images/layout/arrow_asc.png +0 -0
  100. data/public/images/layout/arrow_desc.png +0 -0
  101. data/public/images/layout/black_bar.png +0 -0
  102. data/public/images/layout/branding.png +0 -0
  103. data/public/images/layout/button_bg.png +0 -0
  104. data/public/images/layout/content_left_bg.png +0 -0
  105. data/public/images/layout/content_right_bg.png +0 -0
  106. data/public/images/layout/footer_bg.png +0 -0
  107. data/public/images/layout/h2_bg.png +0 -0
  108. data/public/images/layout/h2_bg_for_table.png +0 -0
  109. data/public/images/layout/header_bg_grey.png +0 -0
  110. data/public/images/layout/header_bg_purple.png +0 -0
  111. data/public/images/layout/legend_bg.png +0 -0
  112. data/public/images/layout/text_field_bg.jpg +0 -0
  113. data/public/images/layout/text_field_error_bg.png +0 -0
  114. data/public/images/layout/th_bg.png +0 -0
  115. data/public/images/layout/th_bg_selected.png +0 -0
  116. data/public/images/rails.png +0 -0
  117. data/public/index.html +9 -0
  118. data/public/javascripts/application.js +2 -0
  119. data/public/javascripts/controls.js +965 -0
  120. data/public/javascripts/dragdrop.js +974 -0
  121. data/public/javascripts/effects.js +1123 -0
  122. data/public/javascripts/prototype.js +6001 -0
  123. data/public/javascripts/rails.js +175 -0
  124. data/public/robots.txt +6 -0
  125. data/public/sample-locations.xls +1 -0
  126. data/public/stylesheets/.gitkeep +0 -0
  127. data/public/stylesheets/application.css +682 -0
  128. data/public/stylesheets/core.css +1147 -0
  129. data/public/stylesheets/core_ie.css +52 -0
  130. data/public/stylesheets/csshover3.htc +14 -0
  131. data/script/cucumber +10 -0
  132. data/script/rails +6 -0
  133. data/spec/controllers/directory_controller_spec.rb +11 -0
  134. data/spec/controllers/services_controller_spec.rb +62 -0
  135. data/spec/models/google_maps_geocoder_spec.rb +62 -0
  136. data/spec/models/locale_spec.rb +64 -0
  137. data/spec/models/location_import_spec.rb +41 -0
  138. data/spec/models/location_spec.rb +195 -0
  139. data/spec/rcov.opts +2 -0
  140. data/spec/spec_helper.rb +12 -0
  141. data/spec/test-locations.xls +1 -0
  142. metadata +361 -0
@@ -0,0 +1,56 @@
1
+ '837 Union St Brooklyn NY'=>{
2
+ "results"=>[
3
+ {
4
+ "address_components"=>[
5
+ {"long_name"=>"837", "types"=>["street_number"], "short_name"=>"837"},
6
+ {"long_name"=>"Union St", "types"=>["route"], "short_name"=>"Union St"},
7
+ {"long_name"=>"Brooklyn", "types"=>["sublocality", "political"], "short_name"=>"Brooklyn"},
8
+ {"long_name"=>"New York", "types"=>["locality", "political"], "short_name"=>"New York"},
9
+ {"long_name"=>"Kings", "types"=>["administrative_area_level_2", "political"], "short_name"=>"Kings"},
10
+ {"long_name"=>"New York", "types"=>["administrative_area_level_1", "political"], "short_name"=>"NY"},
11
+ {"long_name"=>"United States", "types"=>["country", "political"], "short_name"=>"US"},
12
+ {"long_name"=>"11217", "types"=>["postal_code"], "short_name"=>"11217"}
13
+ ],
14
+ "geometry"=>{
15
+ "location"=>{
16
+ "lng"=>-73.9760302, "lat"=>40.6748151
17
+ },
18
+ "location_type"=>"ROOFTOP",
19
+ "viewport"=>{
20
+ "northeast"=>{"lng"=>-73.9728826, "lat"=>40.6779627},
21
+ "southwest"=>{"lng"=>-73.9791778, "lat"=>40.6716675}
22
+ }
23
+ },
24
+ "types"=>["street_address"],
25
+ "formatted_address"=>"837 Union St, Brooklyn, NY 11217, USA"
26
+ }
27
+ ],
28
+ "status"=>"OK"
29
+ }
30
+ '1600 Pennsylvania Washington'=>{
31
+ "results"=>[
32
+ {
33
+ "address_components"=>[
34
+ {"long_name"=>"1600", "types"=>["street_number"], "short_name"=>"1600"},
35
+ {"long_name"=>"Pennsylvania Ave NW", "types"=>["route"], "short_name"=>"Pennsylvania Ave NW"},
36
+ {"long_name"=>"Washington", "types"=>["locality", "political"], "short_name"=>"Washington"},
37
+ {"long_name"=>"Washington", "types"=>["administrative_area_level_3", "political"], "short_name"=>"Washington"},
38
+ {"long_name"=>"District of Columbia", "types"=>["administrative_area_level_2", "political"], "short_name"=>"District of Columbia"},
39
+ {"long_name"=>"District of Columbia", "types"=>["administrative_area_level_1", "political"], "short_name"=>"DC"},
40
+ {"long_name"=>"United States", "types"=>["country", "political"], "short_name"=>"US"},
41
+ {"long_name"=>"20500", "types"=>["postal_code"], "short_name"=>"20500"}
42
+ ],
43
+ "partial_match"=>true,
44
+ "geometry"=>{
45
+ "location"=>{"lng"=>-77.0365191, "lat"=>38.8976964},
46
+ "location_type"=>"ROOFTOP",
47
+ "viewport"=>{
48
+ "northeast"=>{"lng"=>-77.0333715, "lat"=>38.900844},
49
+ "southwest"=>{"lng"=>-77.0396667, "lat"=>38.8945488}}
50
+ },
51
+ "types"=>["street_address"],
52
+ "formatted_address"=>"1600 Pennsylvania Ave NW, Washington, DC 20500, USA"
53
+ }
54
+ ],
55
+ "status"=>"OK"
56
+ }
@@ -0,0 +1,10 @@
1
+ Feature: Admin manages locations
2
+
3
+ As an administrator
4
+ I want to manage locations
5
+ So that the directory is kept current
6
+
7
+ @wip
8
+ Scenario: Admin uploads locations
9
+ When I upload a locations file
10
+ Then the site shows the locations
@@ -0,0 +1,25 @@
1
+ Feature: Customer browses directory
2
+
3
+ As a customer
4
+ I want to browse the directory
5
+ So that I can find locations near me
6
+
7
+ Background:
8
+ Given locales
9
+
10
+ Scenario: Browse
11
+ When I visit "/directory/united-states"
12
+ Then I should see "Select a State"
13
+ When I follow "New York"
14
+ Then I should see "Select a City"
15
+
16
+ Scenario: Browse a city
17
+ When I visit "/directory/united-states/new-york"
18
+ And I follow "Commack"
19
+ Then I should see "Select a Location"
20
+
21
+ Scenario: Browse a location
22
+ Given zip-coded locations
23
+ When I visit "/directory/united-states/new-york/commack"
24
+ And I follow "Mobile Mini Jericho"
25
+ Then the directory shows an address vcard
@@ -0,0 +1,29 @@
1
+ Feature: Customer searches directory
2
+
3
+ As a customer
4
+ I want to search the directory
5
+ So that I can find matching locations
6
+
7
+ Background:
8
+ Given locales
9
+
10
+ Scenario: Location matching a string
11
+ When I go to the directory page
12
+ And I fill in "search-input" with "Jericho"
13
+ And I press "Search"
14
+ Then I should see "Mobile Mini Jericho"
15
+
16
+ Scenario: Locales matching a string
17
+ When I go to the directory page
18
+ And I fill in "search-input" with "New York"
19
+ And I press "Search"
20
+ Then I should see "Mobile Mini Jericho"
21
+ Then I should see "Mobile Mini Utica"
22
+
23
+ Scenario: Locations near a ZIP
24
+ Given zip-coded locations
25
+ When I go to the directory page
26
+ And I fill in "search-input" with "10279"
27
+ And I press "Search"
28
+ Then I should see "Mobile Mini Jericho"
29
+ And I should see "Mobile Mini Utica"
@@ -0,0 +1,22 @@
1
+ Given /^locales$/ do
2
+ create_locale_tree
3
+ end
4
+
5
+ When /^I visit "([^"]*)"$/ do |url|
6
+ visit url
7
+ end
8
+
9
+ Then /^the directory shows an address vcard$/ do
10
+ page.should have_selector('div.vcard')
11
+ end
12
+
13
+ Given /^zip-coded locations$/ do
14
+ ZipCode.expects(:first).returns(ZipCode.new :lat_lng => [0, 0])
15
+ Location.expects(:near).returns(Location.all)
16
+ end
17
+
18
+ private
19
+
20
+ def create_locale_tree
21
+ LocationImport.test 'spec/test-locations.xls'
22
+ end
@@ -0,0 +1,10 @@
1
+ When /^I upload a locations file$/ do
2
+ visit import_locations_path
3
+ attach_file 'upload_datafile', "#{Rails.root}/spec/test-locations.xls"
4
+ click_button
5
+ end
6
+
7
+ Then /^the site shows the locations$/ do
8
+ response.should be_redirect
9
+ response.should have_selector('table.standard')
10
+ end
@@ -0,0 +1,211 @@
1
+ # TL;DR: YOU SHOULD DELETE THIS FILE
2
+ #
3
+ # This file iwas generated by Cucumber-Rails and is only here to get you a head start
4
+ # These step definitions are thin wrappers around the Capybara/Webrat API that lets you
5
+ # visit pages, interact with widgets and make assertions about page content.
6
+ #
7
+ # If you use these step definitions as basis for your features you will quickly end up
8
+ # with features that are:
9
+ #
10
+ # * Hard to maintain
11
+ # * Verbose to read
12
+ #
13
+ # A much better approach is to write your own higher level step definitions, following
14
+ # the advice in the following blog posts:
15
+ #
16
+ # * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
17
+ # * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
18
+ # * http://elabs.se/blog/15-you-re-cuking-it-wrong
19
+ #
20
+
21
+
22
+ require 'uri'
23
+ require 'cgi'
24
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "paths"))
25
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "support", "selectors"))
26
+
27
+ module WithinHelpers
28
+ def with_scope(locator)
29
+ locator ? within(*selector_for(locator)) { yield } : yield
30
+ end
31
+ end
32
+ World(WithinHelpers)
33
+
34
+ # Single-line step scoper
35
+ When /^(.*) within ([^:]+)$/ do |step, parent|
36
+ with_scope(parent) { When step }
37
+ end
38
+
39
+ # Multi-line step scoper
40
+ When /^(.*) within ([^:]+):$/ do |step, parent, table_or_string|
41
+ with_scope(parent) { When "#{step}:", table_or_string }
42
+ end
43
+
44
+ Given /^(?:|I )am on (.+)$/ do |page_name|
45
+ visit path_to(page_name)
46
+ end
47
+
48
+ When /^(?:|I )go to (.+)$/ do |page_name|
49
+ visit path_to(page_name)
50
+ end
51
+
52
+ When /^(?:|I )press "([^"]*)"$/ do |button|
53
+ click_button(button)
54
+ end
55
+
56
+ When /^(?:|I )follow "([^"]*)"$/ do |link|
57
+ click_link(link)
58
+ end
59
+
60
+ When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
61
+ fill_in(field, :with => value)
62
+ end
63
+
64
+ When /^(?:|I )fill in "([^"]*)" for "([^"]*)"$/ do |value, field|
65
+ fill_in(field, :with => value)
66
+ end
67
+
68
+ # Use this to fill in an entire form with data from a table. Example:
69
+ #
70
+ # When I fill in the following:
71
+ # | Account Number | 5002 |
72
+ # | Expiry date | 2009-11-01 |
73
+ # | Note | Nice guy |
74
+ # | Wants Email? | |
75
+ #
76
+ # TODO: Add support for checkbox, select og option
77
+ # based on naming conventions.
78
+ #
79
+ When /^(?:|I )fill in the following:$/ do |fields|
80
+ fields.rows_hash.each do |name, value|
81
+ When %{I fill in "#{name}" with "#{value}"}
82
+ end
83
+ end
84
+
85
+ When /^(?:|I )select "([^"]*)" from "([^"]*)"$/ do |value, field|
86
+ select(value, :from => field)
87
+ end
88
+
89
+ When /^(?:|I )check "([^"]*)"$/ do |field|
90
+ check(field)
91
+ end
92
+
93
+ When /^(?:|I )uncheck "([^"]*)"$/ do |field|
94
+ uncheck(field)
95
+ end
96
+
97
+ When /^(?:|I )choose "([^"]*)"$/ do |field|
98
+ choose(field)
99
+ end
100
+
101
+ When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"$/ do |path, field|
102
+ attach_file(field, File.expand_path(path))
103
+ end
104
+
105
+ Then /^(?:|I )should see "([^"]*)"$/ do |text|
106
+ if page.respond_to? :should
107
+ page.should have_content(text)
108
+ else
109
+ assert page.has_content?(text)
110
+ end
111
+ end
112
+
113
+ Then /^(?:|I )should see \/([^\/]*)\/$/ do |regexp|
114
+ regexp = Regexp.new(regexp)
115
+
116
+ if page.respond_to? :should
117
+ page.should have_xpath('//*', :text => regexp)
118
+ else
119
+ assert page.has_xpath?('//*', :text => regexp)
120
+ end
121
+ end
122
+
123
+ Then /^(?:|I )should not see "([^"]*)"$/ do |text|
124
+ if page.respond_to? :should
125
+ page.should have_no_content(text)
126
+ else
127
+ assert page.has_no_content?(text)
128
+ end
129
+ end
130
+
131
+ Then /^(?:|I )should not see \/([^\/]*)\/$/ do |regexp|
132
+ regexp = Regexp.new(regexp)
133
+
134
+ if page.respond_to? :should
135
+ page.should have_no_xpath('//*', :text => regexp)
136
+ else
137
+ assert page.has_no_xpath?('//*', :text => regexp)
138
+ end
139
+ end
140
+
141
+ Then /^the "([^"]*)" field(?: within (.*))? should contain "([^"]*)"$/ do |field, parent, value|
142
+ with_scope(parent) do
143
+ field = find_field(field)
144
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
145
+ if field_value.respond_to? :should
146
+ field_value.should =~ /#{value}/
147
+ else
148
+ assert_match(/#{value}/, field_value)
149
+ end
150
+ end
151
+ end
152
+
153
+ Then /^the "([^"]*)" field(?: within (.*))? should not contain "([^"]*)"$/ do |field, parent, value|
154
+ with_scope(parent) do
155
+ field = find_field(field)
156
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
157
+ if field_value.respond_to? :should_not
158
+ field_value.should_not =~ /#{value}/
159
+ else
160
+ assert_no_match(/#{value}/, field_value)
161
+ end
162
+ end
163
+ end
164
+
165
+ Then /^the "([^"]*)" checkbox(?: within (.*))? should be checked$/ do |label, parent|
166
+ with_scope(parent) do
167
+ field_checked = find_field(label)['checked']
168
+ if field_checked.respond_to? :should
169
+ field_checked.should be_true
170
+ else
171
+ assert field_checked
172
+ end
173
+ end
174
+ end
175
+
176
+ Then /^the "([^"]*)" checkbox(?: within (.*))? should not be checked$/ do |label, parent|
177
+ with_scope(parent) do
178
+ field_checked = find_field(label)['checked']
179
+ if field_checked.respond_to? :should
180
+ field_checked.should be_false
181
+ else
182
+ assert !field_checked
183
+ end
184
+ end
185
+ end
186
+
187
+ Then /^(?:|I )should be on (.+)$/ do |page_name|
188
+ current_path = URI.parse(current_url).path
189
+ if current_path.respond_to? :should
190
+ current_path.should == path_to(page_name)
191
+ else
192
+ assert_equal path_to(page_name), current_path
193
+ end
194
+ end
195
+
196
+ Then /^(?:|I )should have the following query string:$/ do |expected_pairs|
197
+ query = URI.parse(current_url).query
198
+ actual_params = query ? CGI.parse(query) : {}
199
+ expected_params = {}
200
+ expected_pairs.rows_hash.each_pair{|k,v| expected_params[k] = v.split(',')}
201
+
202
+ if actual_params.respond_to? :should
203
+ actual_params.should == expected_params
204
+ else
205
+ assert_equal expected_params, actual_params
206
+ end
207
+ end
208
+
209
+ Then /^show me the page$/ do
210
+ save_and_open_page
211
+ end
@@ -0,0 +1,31 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+
7
+ ENV["RAILS_ENV"] = "test"
8
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
9
+
10
+ require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support
11
+ require 'cucumber/rails/rspec'
12
+ require 'cucumber/rails/world'
13
+ require 'cucumber/web/tableish'
14
+ require 'capybara/rails'
15
+ require 'capybara/cucumber'
16
+ require 'capybara/session'
17
+ require 'be_valid_asset'
18
+ require 'mongoid'
19
+ require 'database_cleaner'
20
+ require 'database_cleaner/cucumber'
21
+
22
+ # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
23
+ # order to ease the transition to Capybara we set the default here. If you'd
24
+ # prefer to use XPath just remove this line and adjust any selectors in your
25
+ # steps to use the XPath syntax.
26
+ Capybara.default_selector = :css
27
+ Capybara.save_and_open_page_path = Rails.root + 'tmp'
28
+
29
+ # How to clean your database when transactions are turned off. See
30
+ # http://github.com/bmabey/database_cleaner for more info.
31
+ DatabaseCleaner.strategy = :truncation
@@ -0,0 +1,33 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when /the home\s?page/
12
+ '/'
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /^(.*)'s profile page$/i
18
+ # user_profile_path(User.find_by_login($1))
19
+
20
+ else
21
+ begin
22
+ page_name =~ /the (.*) page/
23
+ path_components = $1.split(/\s+/)
24
+ self.send(path_components.push('path').join('_').to_sym)
25
+ rescue Object => e
26
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
27
+ "Now, go and add a mapping in #{__FILE__}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ World(NavigationHelpers)
@@ -0,0 +1,39 @@
1
+ module HtmlSelectorsHelpers
2
+ # Maps a name to a selector. Used primarily by the
3
+ #
4
+ # When /^(.+) within (.+)$/ do |step, scope|
5
+ #
6
+ # step definitions in web_steps.rb
7
+ #
8
+ def selector_for(locator)
9
+ case locator
10
+
11
+ when /the page/
12
+ "html > body"
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /the (notice|error|info) flash/
18
+ # ".flash.#{$1}"
19
+
20
+ # You can also return an array to use a different selector
21
+ # type, like:
22
+ #
23
+ # when /the header/
24
+ # [:xpath, "//header"]
25
+
26
+ # This allows you to provide a quoted selector as the scope
27
+ # for "within" steps as was previously the default for the
28
+ # web steps:
29
+ when /"(.+)"/
30
+ $1
31
+
32
+ else
33
+ raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
34
+ "Now, go and add a mapping in #{__FILE__}"
35
+ end
36
+ end
37
+ end
38
+
39
+ World(HtmlSelectorsHelpers)
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'campfire_logic'
@@ -0,0 +1,7 @@
1
+ require 'campfire_logic'
2
+ require 'rails'
3
+
4
+ module CampfireLogic
5
+ class Engine < Rails::Engine
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'campfire_logic'
2
+ require 'rails'
3
+
4
+ module CampfireLogic
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ # load "#{Gem.searcher.find('campfire_logic').full_gem_path}/tasks/campfire_logic.rake"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ module CampfireLogic
2
+ require 'campfire_logic/engine.rb' if defined?(Rails)
3
+ require 'campfire_logic/railtie.rb' if defined?(Rails)
4
+ require 'mongoid'
5
+
6
+ mattr_accessor :directory_slug
7
+
8
+ def self.setup
9
+ yield self
10
+ end
11
+
12
+ module Base
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ module ClassMethods
18
+ # Register a before-validation handler for the given fields to trim leading and trailing
19
+ # spaces.
20
+ #
21
+ # Adapted from http://scottmoonen.com/2009/05/08/rails-pattern-trim-spaces-on-input/
22
+ def trimmed_fields *field_list
23
+ before_validation do |model|
24
+ field_list.each do |n|
25
+ model[n] = model[n].strip if model[n].respond_to?(:strip)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ namespace :campfire_logic do
2
+ desc 'Install required CampfireLogic files.'
3
+ task :install do
4
+ dir = Gem.searcher.find('campfire_logic').full_gem_path
5
+ system "rsync -rv --append #{dir}/db ."
6
+ end
7
+ end
@@ -0,0 +1,71 @@
1
+ # TL;DR: YOU SHOULD DELETE THIS FILE
2
+ #
3
+ # This file iwas generated by Cucumber-Rails and is only here to get you a head start
4
+ # These step definitions are thin wrappers around the Capybara/Webrat API that lets you
5
+ # visit pages, interact with widgets and make assertions about page content.
6
+ #
7
+ # If you use these step definitions as basis for your features you will quickly end up
8
+ # with features that are:
9
+ #
10
+ # * Hard to maintain
11
+ # * Verbose to read
12
+ #
13
+ # A much better approach is to write your own higher level step definitions, following
14
+ # the advice in the following blog posts:
15
+ #
16
+ # * http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html
17
+ # * http://dannorth.net/2011/01/31/whose-domain-is-it-anyway/
18
+ # * http://elabs.se/blog/15-you-re-cuking-it-wrong
19
+ #
20
+
21
+
22
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
23
+
24
+ vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
25
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
26
+
27
+ begin
28
+ require 'cucumber/rake/task'
29
+
30
+ namespace :cucumber do
31
+ Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
32
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
33
+ t.fork = true # You may get faster startup if you set this to false
34
+ t.profile = 'default'
35
+ end
36
+
37
+ Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
38
+ t.binary = vendored_cucumber_bin
39
+ t.fork = true # You may get faster startup if you set this to false
40
+ t.profile = 'wip'
41
+ end
42
+
43
+ Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
44
+ t.binary = vendored_cucumber_bin
45
+ t.fork = true # You may get faster startup if you set this to false
46
+ t.profile = 'rerun'
47
+ end
48
+
49
+ desc 'Run all features'
50
+ task :all => [:ok, :wip]
51
+ end
52
+ desc 'Alias for cucumber:ok'
53
+ task :cucumber => 'cucumber:ok'
54
+
55
+ task :default => :cucumber
56
+
57
+ task :features => :cucumber do
58
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
59
+ end
60
+
61
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
62
+ task 'db:test:prepare' do
63
+ end
64
+ rescue LoadError
65
+ desc 'cucumber rake task not available (cucumber not installed)'
66
+ task :cucumber do
67
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
68
+ end
69
+ end
70
+
71
+ end
data/public/404.html ADDED
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
data/public/422.html ADDED
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>