sum 0.1.1

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 (282) hide show
  1. data/Capfile +3 -0
  2. data/MIT-LICENSE +18 -0
  3. data/README.markdown +69 -0
  4. data/Rakefile +56 -0
  5. data/config.ru +3 -0
  6. data/config/database.example.yml +10 -0
  7. data/config/deploy.example.rb +36 -0
  8. data/config/externals.yml +18 -0
  9. data/config/mail.example.yml +32 -0
  10. data/config/schedule.rb +20 -0
  11. data/db/migrate/001_users.rb +22 -0
  12. data/db/migrate/002_user_emails.rb +15 -0
  13. data/features/front_page.feature +15 -0
  14. data/features/read_email.feature +445 -0
  15. data/features/receive_email.feature +59 -0
  16. data/features/step_definitions/email.rb +52 -0
  17. data/features/step_definitions/given.rb +60 -0
  18. data/features/step_definitions/then.rb +36 -0
  19. data/features/step_definitions/when.rb +46 -0
  20. data/features/support/env.rb +38 -0
  21. data/features/support/helpers.rb +50 -0
  22. data/features/support/rspec.rb +11 -0
  23. data/features/support/webrat.rb +3 -0
  24. data/features/update_user.feature +83 -0
  25. data/gemspec.rb +45 -0
  26. data/lib/sum.rb +30 -0
  27. data/lib/sum/boot.rb +29 -0
  28. data/lib/sum/controller/cron.rb +12 -0
  29. data/lib/sum/controller/front.rb +6 -0
  30. data/lib/sum/controller/new.rb +15 -0
  31. data/lib/sum/helper/application.rb +8 -0
  32. data/lib/sum/helper/cron.rb +12 -0
  33. data/lib/sum/helper/new.rb +27 -0
  34. data/lib/sum/model/incoming_mail.rb +89 -0
  35. data/lib/sum/model/user.rb +298 -0
  36. data/lib/sum/model/user_email.rb +31 -0
  37. data/lib/sum/view/email.haml +70 -0
  38. data/lib/sum/view/field.haml +23 -0
  39. data/lib/sum/view/form.haml +13 -0
  40. data/lib/sum/view/front.haml +29 -0
  41. data/lib/sum/view/layout.haml +26 -0
  42. data/lib/sum/view/new.haml +5 -0
  43. data/lib/sum/view/success.haml +14 -0
  44. data/lib/sum/view/tos.haml +3 -0
  45. data/public/image/1.png +0 -0
  46. data/public/image/2.png +0 -0
  47. data/public/image/3.png +0 -0
  48. data/public/image/bg.png +0 -0
  49. data/public/image/bot.png +0 -0
  50. data/public/image/facebox/b.png +0 -0
  51. data/public/image/facebox/bl.png +0 -0
  52. data/public/image/facebox/br.png +0 -0
  53. data/public/image/facebox/closelabel.gif +0 -0
  54. data/public/image/facebox/loading.gif +0 -0
  55. data/public/image/facebox/tl.png +0 -0
  56. data/public/image/facebox/tr.png +0 -0
  57. data/public/image/favicon.png +0 -0
  58. data/public/image/field_off.png +0 -0
  59. data/public/image/field_on.png +0 -0
  60. data/public/image/ribbon.png +0 -0
  61. data/public/image/screenshot_receive.png +0 -0
  62. data/public/image/screenshot_send.png +0 -0
  63. data/public/image/submit.png +0 -0
  64. data/public/image/top.png +0 -0
  65. data/public/javascript/facebox.js +319 -0
  66. data/public/javascript/jquery-1.3.2.js +19 -0
  67. data/public/javascript/sum.js +13 -0
  68. data/public/style/facebox.css +95 -0
  69. data/public/style/ie.css +35 -0
  70. data/public/style/print.css +30 -0
  71. data/public/style/screen.css +256 -0
  72. data/public/style/sum.css +119 -0
  73. data/public/style/sum.less +159 -0
  74. data/spec/spec.opts +1 -0
  75. data/spec/spec_helper.rb +59 -0
  76. data/spec/sum/model/incoming_mail_spec.rb +106 -0
  77. data/spec/sum/model/user_spec.rb +172 -0
  78. data/sum.gemspec +69 -0
  79. data/vendor/webrat/History.txt +358 -0
  80. data/vendor/webrat/MIT-LICENSE.txt +19 -0
  81. data/vendor/webrat/README.rdoc +85 -0
  82. data/vendor/webrat/Rakefile +200 -0
  83. data/vendor/webrat/install.rb +1 -0
  84. data/vendor/webrat/lib/webrat.rb +31 -0
  85. data/vendor/webrat/lib/webrat/core.rb +14 -0
  86. data/vendor/webrat/lib/webrat/core/configuration.rb +102 -0
  87. data/vendor/webrat/lib/webrat/core/elements/area.rb +31 -0
  88. data/vendor/webrat/lib/webrat/core/elements/element.rb +33 -0
  89. data/vendor/webrat/lib/webrat/core/elements/field.rb +409 -0
  90. data/vendor/webrat/lib/webrat/core/elements/form.rb +103 -0
  91. data/vendor/webrat/lib/webrat/core/elements/label.rb +31 -0
  92. data/vendor/webrat/lib/webrat/core/elements/link.rb +93 -0
  93. data/vendor/webrat/lib/webrat/core/elements/select_option.rb +35 -0
  94. data/vendor/webrat/lib/webrat/core/locators.rb +20 -0
  95. data/vendor/webrat/lib/webrat/core/locators/area_locator.rb +38 -0
  96. data/vendor/webrat/lib/webrat/core/locators/button_locator.rb +54 -0
  97. data/vendor/webrat/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  98. data/vendor/webrat/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  99. data/vendor/webrat/lib/webrat/core/locators/field_locator.rb +25 -0
  100. data/vendor/webrat/lib/webrat/core/locators/field_named_locator.rb +41 -0
  101. data/vendor/webrat/lib/webrat/core/locators/form_locator.rb +19 -0
  102. data/vendor/webrat/lib/webrat/core/locators/label_locator.rb +34 -0
  103. data/vendor/webrat/lib/webrat/core/locators/link_locator.rb +74 -0
  104. data/vendor/webrat/lib/webrat/core/locators/locator.rb +20 -0
  105. data/vendor/webrat/lib/webrat/core/locators/select_option_locator.rb +59 -0
  106. data/vendor/webrat/lib/webrat/core/logging.rb +24 -0
  107. data/vendor/webrat/lib/webrat/core/matchers.rb +4 -0
  108. data/vendor/webrat/lib/webrat/core/matchers/have_content.rb +73 -0
  109. data/vendor/webrat/lib/webrat/core/matchers/have_selector.rb +74 -0
  110. data/vendor/webrat/lib/webrat/core/matchers/have_tag.rb +21 -0
  111. data/vendor/webrat/lib/webrat/core/matchers/have_xpath.rb +147 -0
  112. data/vendor/webrat/lib/webrat/core/methods.rb +63 -0
  113. data/vendor/webrat/lib/webrat/core/mime.rb +29 -0
  114. data/vendor/webrat/lib/webrat/core/save_and_open_page.rb +48 -0
  115. data/vendor/webrat/lib/webrat/core/scope.rb +350 -0
  116. data/vendor/webrat/lib/webrat/core/session.rb +299 -0
  117. data/vendor/webrat/lib/webrat/core/xml.rb +115 -0
  118. data/vendor/webrat/lib/webrat/core/xml/hpricot.rb +19 -0
  119. data/vendor/webrat/lib/webrat/core/xml/nokogiri.rb +76 -0
  120. data/vendor/webrat/lib/webrat/core/xml/rexml.rb +24 -0
  121. data/vendor/webrat/lib/webrat/core_extensions/blank.rb +58 -0
  122. data/vendor/webrat/lib/webrat/core_extensions/deprecate.rb +8 -0
  123. data/vendor/webrat/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  124. data/vendor/webrat/lib/webrat/core_extensions/meta_class.rb +6 -0
  125. data/vendor/webrat/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  126. data/vendor/webrat/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  127. data/vendor/webrat/lib/webrat/mechanize.rb +74 -0
  128. data/vendor/webrat/lib/webrat/merb.rb +9 -0
  129. data/vendor/webrat/lib/webrat/merb_multipart_support.rb +27 -0
  130. data/vendor/webrat/lib/webrat/merb_session.rb +82 -0
  131. data/vendor/webrat/lib/webrat/rack.rb +25 -0
  132. data/vendor/webrat/lib/webrat/rails.rb +106 -0
  133. data/vendor/webrat/lib/webrat/rspec-rails.rb +10 -0
  134. data/vendor/webrat/lib/webrat/selenium.rb +81 -0
  135. data/vendor/webrat/lib/webrat/selenium/application_server_factory.rb +40 -0
  136. data/vendor/webrat/lib/webrat/selenium/application_servers.rb +5 -0
  137. data/vendor/webrat/lib/webrat/selenium/application_servers/base.rb +46 -0
  138. data/vendor/webrat/lib/webrat/selenium/application_servers/external.rb +26 -0
  139. data/vendor/webrat/lib/webrat/selenium/application_servers/merb.rb +50 -0
  140. data/vendor/webrat/lib/webrat/selenium/application_servers/rails.rb +44 -0
  141. data/vendor/webrat/lib/webrat/selenium/application_servers/sinatra.rb +37 -0
  142. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/button.js +19 -0
  143. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
  144. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  145. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratlink.js +12 -0
  146. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  147. data/vendor/webrat/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  148. data/vendor/webrat/lib/webrat/selenium/matchers.rb +4 -0
  149. data/vendor/webrat/lib/webrat/selenium/matchers/have_content.rb +66 -0
  150. data/vendor/webrat/lib/webrat/selenium/matchers/have_selector.rb +49 -0
  151. data/vendor/webrat/lib/webrat/selenium/matchers/have_tag.rb +72 -0
  152. data/vendor/webrat/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
  153. data/vendor/webrat/lib/webrat/selenium/selenium_extensions.js +6 -0
  154. data/vendor/webrat/lib/webrat/selenium/selenium_rc_server.rb +84 -0
  155. data/vendor/webrat/lib/webrat/selenium/selenium_session.rb +248 -0
  156. data/vendor/webrat/lib/webrat/selenium/silence_stream.rb +18 -0
  157. data/vendor/webrat/lib/webrat/sinatra.rb +11 -0
  158. data/vendor/webrat/spec/fakes/test_session.rb +34 -0
  159. data/vendor/webrat/spec/integration/merb/Rakefile +35 -0
  160. data/vendor/webrat/spec/integration/merb/app/controllers/application.rb +2 -0
  161. data/vendor/webrat/spec/integration/merb/app/controllers/exceptions.rb +13 -0
  162. data/vendor/webrat/spec/integration/merb/app/controllers/testing.rb +27 -0
  163. data/vendor/webrat/spec/integration/merb/app/views/exceptions/not_acceptable.html.erb +63 -0
  164. data/vendor/webrat/spec/integration/merb/app/views/exceptions/not_found.html.erb +47 -0
  165. data/vendor/webrat/spec/integration/merb/app/views/layout/application.html.erb +12 -0
  166. data/vendor/webrat/spec/integration/merb/app/views/testing/show_form.html.erb +27 -0
  167. data/vendor/webrat/spec/integration/merb/app/views/testing/upload.html.erb +9 -0
  168. data/vendor/webrat/spec/integration/merb/config/environments/development.rb +15 -0
  169. data/vendor/webrat/spec/integration/merb/config/environments/rake.rb +11 -0
  170. data/vendor/webrat/spec/integration/merb/config/environments/test.rb +14 -0
  171. data/vendor/webrat/spec/integration/merb/config/init.rb +25 -0
  172. data/vendor/webrat/spec/integration/merb/config/rack.rb +11 -0
  173. data/vendor/webrat/spec/integration/merb/config/router.rb +34 -0
  174. data/vendor/webrat/spec/integration/merb/spec/spec.opts +1 -0
  175. data/vendor/webrat/spec/integration/merb/spec/spec_helper.rb +24 -0
  176. data/vendor/webrat/spec/integration/merb/spec/webrat_spec.rb +39 -0
  177. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/app_script.rb +31 -0
  178. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/common.rb +64 -0
  179. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/gem_ext.rb +124 -0
  180. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/main.thor +150 -0
  181. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/ops.rb +93 -0
  182. data/vendor/webrat/spec/integration/merb/tasks/merb.thor/utils.rb +40 -0
  183. data/vendor/webrat/spec/integration/rack/Rakefile +5 -0
  184. data/vendor/webrat/spec/integration/rack/app.rb +73 -0
  185. data/vendor/webrat/spec/integration/rack/test/helper.rb +20 -0
  186. data/vendor/webrat/spec/integration/rack/test/webrat_rack_test.rb +62 -0
  187. data/vendor/webrat/spec/integration/rails/Rakefile +30 -0
  188. data/vendor/webrat/spec/integration/rails/app/controllers/application.rb +15 -0
  189. data/vendor/webrat/spec/integration/rails/app/controllers/buttons_controller.rb +7 -0
  190. data/vendor/webrat/spec/integration/rails/app/controllers/fields_controller.rb +4 -0
  191. data/vendor/webrat/spec/integration/rails/app/controllers/links_controller.rb +7 -0
  192. data/vendor/webrat/spec/integration/rails/app/controllers/webrat_controller.rb +43 -0
  193. data/vendor/webrat/spec/integration/rails/app/helpers/buttons_helper.rb +2 -0
  194. data/vendor/webrat/spec/integration/rails/app/helpers/fields_helper.rb +2 -0
  195. data/vendor/webrat/spec/integration/rails/app/helpers/links_helper.rb +2 -0
  196. data/vendor/webrat/spec/integration/rails/app/views/buttons/show.html.erb +11 -0
  197. data/vendor/webrat/spec/integration/rails/app/views/fields/show.html.erb +9 -0
  198. data/vendor/webrat/spec/integration/rails/app/views/links/show.html.erb +5 -0
  199. data/vendor/webrat/spec/integration/rails/app/views/webrat/before_redirect_form.html.erb +4 -0
  200. data/vendor/webrat/spec/integration/rails/app/views/webrat/buttons.html.erb +11 -0
  201. data/vendor/webrat/spec/integration/rails/app/views/webrat/form.html.erb +28 -0
  202. data/vendor/webrat/spec/integration/rails/config/boot.rb +109 -0
  203. data/vendor/webrat/spec/integration/rails/config/environment.rb +12 -0
  204. data/vendor/webrat/spec/integration/rails/config/environments/development.rb +17 -0
  205. data/vendor/webrat/spec/integration/rails/config/environments/selenium.rb +22 -0
  206. data/vendor/webrat/spec/integration/rails/config/environments/test.rb +22 -0
  207. data/vendor/webrat/spec/integration/rails/config/initializers/inflections.rb +10 -0
  208. data/vendor/webrat/spec/integration/rails/config/initializers/mime_types.rb +5 -0
  209. data/vendor/webrat/spec/integration/rails/config/initializers/new_rails_defaults.rb +17 -0
  210. data/vendor/webrat/spec/integration/rails/config/locales/en.yml +5 -0
  211. data/vendor/webrat/spec/integration/rails/config/routes.rb +18 -0
  212. data/vendor/webrat/spec/integration/rails/public/404.html +30 -0
  213. data/vendor/webrat/spec/integration/rails/public/422.html +30 -0
  214. data/vendor/webrat/spec/integration/rails/public/500.html +33 -0
  215. data/vendor/webrat/spec/integration/rails/script/about +4 -0
  216. data/vendor/webrat/spec/integration/rails/script/console +3 -0
  217. data/vendor/webrat/spec/integration/rails/script/dbconsole +3 -0
  218. data/vendor/webrat/spec/integration/rails/script/destroy +3 -0
  219. data/vendor/webrat/spec/integration/rails/script/generate +3 -0
  220. data/vendor/webrat/spec/integration/rails/script/performance/benchmarker +3 -0
  221. data/vendor/webrat/spec/integration/rails/script/performance/profiler +3 -0
  222. data/vendor/webrat/spec/integration/rails/script/performance/request +3 -0
  223. data/vendor/webrat/spec/integration/rails/script/plugin +3 -0
  224. data/vendor/webrat/spec/integration/rails/script/process/inspector +3 -0
  225. data/vendor/webrat/spec/integration/rails/script/process/reaper +3 -0
  226. data/vendor/webrat/spec/integration/rails/script/process/spawner +3 -0
  227. data/vendor/webrat/spec/integration/rails/script/runner +3 -0
  228. data/vendor/webrat/spec/integration/rails/script/server +3 -0
  229. data/vendor/webrat/spec/integration/rails/test/integration/button_click_test.rb +80 -0
  230. data/vendor/webrat/spec/integration/rails/test/integration/fill_in_test.rb +24 -0
  231. data/vendor/webrat/spec/integration/rails/test/integration/link_click_test.rb +27 -0
  232. data/vendor/webrat/spec/integration/rails/test/integration/webrat_test.rb +97 -0
  233. data/vendor/webrat/spec/integration/rails/test/test_helper.rb +25 -0
  234. data/vendor/webrat/spec/integration/sinatra/Rakefile +5 -0
  235. data/vendor/webrat/spec/integration/sinatra/classic_app.rb +64 -0
  236. data/vendor/webrat/spec/integration/sinatra/modular_app.rb +16 -0
  237. data/vendor/webrat/spec/integration/sinatra/test/classic_app_test.rb +37 -0
  238. data/vendor/webrat/spec/integration/sinatra/test/modular_app_test.rb +18 -0
  239. data/vendor/webrat/spec/integration/sinatra/test/test_helper.rb +16 -0
  240. data/vendor/webrat/spec/private/core/configuration_spec.rb +116 -0
  241. data/vendor/webrat/spec/private/core/field_spec.rb +85 -0
  242. data/vendor/webrat/spec/private/core/link_spec.rb +24 -0
  243. data/vendor/webrat/spec/private/core/logging_spec.rb +10 -0
  244. data/vendor/webrat/spec/private/core/session_spec.rb +195 -0
  245. data/vendor/webrat/spec/private/mechanize/mechanize_session_spec.rb +81 -0
  246. data/vendor/webrat/spec/private/merb/attaches_file_spec.rb +93 -0
  247. data/vendor/webrat/spec/private/merb/merb_session_spec.rb +61 -0
  248. data/vendor/webrat/spec/private/nokogiri_spec.rb +77 -0
  249. data/vendor/webrat/spec/private/rails/attaches_file_spec.rb +81 -0
  250. data/vendor/webrat/spec/private/rails/rails_session_spec.rb +112 -0
  251. data/vendor/webrat/spec/private/selenium/application_servers/rails_spec.rb +26 -0
  252. data/vendor/webrat/spec/public/basic_auth_spec.rb +24 -0
  253. data/vendor/webrat/spec/public/check_spec.rb +191 -0
  254. data/vendor/webrat/spec/public/choose_spec.rb +118 -0
  255. data/vendor/webrat/spec/public/click_area_spec.rb +106 -0
  256. data/vendor/webrat/spec/public/click_button_spec.rb +496 -0
  257. data/vendor/webrat/spec/public/click_link_spec.rb +511 -0
  258. data/vendor/webrat/spec/public/fill_in_spec.rb +209 -0
  259. data/vendor/webrat/spec/public/locators/field_by_xpath_spec.rb +19 -0
  260. data/vendor/webrat/spec/public/locators/field_labeled_spec.rb +172 -0
  261. data/vendor/webrat/spec/public/locators/field_with_id_spec.rb +16 -0
  262. data/vendor/webrat/spec/public/matchers/contain_spec.rb +114 -0
  263. data/vendor/webrat/spec/public/matchers/have_selector_spec.rb +142 -0
  264. data/vendor/webrat/spec/public/matchers/have_tag_spec.rb +39 -0
  265. data/vendor/webrat/spec/public/matchers/have_xpath_spec.rb +136 -0
  266. data/vendor/webrat/spec/public/reload_spec.rb +10 -0
  267. data/vendor/webrat/spec/public/save_and_open_spec.rb +70 -0
  268. data/vendor/webrat/spec/public/select_date_spec.rb +112 -0
  269. data/vendor/webrat/spec/public/select_datetime_spec.rb +137 -0
  270. data/vendor/webrat/spec/public/select_spec.rb +249 -0
  271. data/vendor/webrat/spec/public/select_time_spec.rb +100 -0
  272. data/vendor/webrat/spec/public/selenium/application_server_factory_spec.rb +49 -0
  273. data/vendor/webrat/spec/public/selenium/application_servers/external_spec.rb +12 -0
  274. data/vendor/webrat/spec/public/selenium/selenium_session_spec.rb +37 -0
  275. data/vendor/webrat/spec/public/set_hidden_field_spec.rb +5 -0
  276. data/vendor/webrat/spec/public/submit_form_spec.rb +5 -0
  277. data/vendor/webrat/spec/public/visit_spec.rb +58 -0
  278. data/vendor/webrat/spec/public/within_spec.rb +177 -0
  279. data/vendor/webrat/spec/rcov.opts +1 -0
  280. data/vendor/webrat/spec/spec.opts +2 -0
  281. data/vendor/webrat/spec/spec_helper.rb +50 -0
  282. metadata +474 -0
@@ -0,0 +1,59 @@
1
+ Feature: Receive email
2
+
3
+ As a user
4
+ I want to receive a budget email
5
+ In order to read a budget email
6
+
7
+ Background:
8
+ Given my email queue is empty
9
+
10
+ Scenario: I receive a budget email after creating an account
11
+ Given I have not created an account
12
+ When I visit the front page
13
+ And I submit a valid form
14
+ And the background job runs
15
+ Then I should receive an email
16
+
17
+ Scenario: I receive a budget email after updating an account
18
+ Given I have created an account
19
+ When I visit the front page
20
+ And I submit a valid form
21
+ And the background job runs
22
+ Then I should receive an email
23
+
24
+ Scenario: I receive a budget email at midnight
25
+ Given I have created an account
26
+ And it is midnight
27
+ When the background job runs
28
+ Then I should receive an email
29
+
30
+ Scenario: I receive a budget email at midnight having added a transaction today
31
+ Given I have created an account
32
+ And today I have spent $1.00
33
+ And the background job ran
34
+ And my email queue is empty
35
+ And it is midnight
36
+ When the background job runs
37
+ Then I should receive an email
38
+ And spent today should be zero
39
+
40
+ Scenario: I receive a budget email at the end of the month
41
+ Given today is June 1, 2009
42
+ And I have created an account
43
+ And today I have spent $1.00
44
+ And today is July 1, 2009
45
+ And it is midnight
46
+ When the background job runs
47
+ And I open the email
48
+ Then spent today should be zero
49
+ And I should see in the email:
50
+ """
51
+ You need to earn $0.03 today.
52
+ """
53
+ # tests User#temporary_spending_cut
54
+ And I should see in the email:
55
+ """
56
+ Fiscal month: 07/01/09 to 08/01/09
57
+ """
58
+ And output the email
59
+
@@ -0,0 +1,52 @@
1
+ Given /^(?:my email queue is empty|no emails have been sent)$/ do
2
+ reset_mailer
3
+ end
4
+
5
+ When /^I open the email$/ do
6
+ open_email(current_email_address)
7
+ end
8
+
9
+ When %r{^I follow "([^"]*?)" in the email$} do |link|
10
+ visit_in_email(link)
11
+ end
12
+
13
+ Then /^I should receive (an|\d+) emails?$/ do |amount|
14
+ amount = 1 if amount == "an"
15
+ unread_emails_for(current_email_address).size.should == amount.to_i
16
+ end
17
+
18
+ Then %r{^"([^"]*?)" should receive (\d+) emails?$} do |address, n|
19
+ unread_emails_for(address).size.should == n.to_i
20
+ end
21
+
22
+ Then %r{^"([^"]*?)" should have (\d+) emails?$} do |address, n|
23
+ mailbox_for(address).size.should == n.to_i
24
+ end
25
+
26
+ Then %r{^"([^"]*?)" should not receive an email$} do |address|
27
+ find_email(address).should be_nil
28
+ end
29
+
30
+ Then %r{^I should see "([^"]*?)" in the subject$} do |text|
31
+ current_email.should have_subject(Regexp.new(Regexp.escape(text).gsub("\\n", "\n")))
32
+ end
33
+
34
+ Then %r{^I should see in the email:$} do |text|
35
+ current_email.body.should =~ Regexp.new(Regexp.escape(text).gsub("\\n", "\n"))
36
+ end
37
+
38
+ Then %r{^I should see "([^"]*?)" in the email$} do |text|
39
+ current_email.body.should =~ Regexp.new(Regexp.escape(text).gsub("\\n", "\n"))
40
+ end
41
+
42
+ When %r{^"([^"]*?)" opens? the email with subject "([^"]*?)"$} do |address, subject|
43
+ open_email(address, :with_subject => subject)
44
+ end
45
+
46
+ When %r{^"([^"]*?)" opens? the email with text "([^"]*?)"$} do |address, text|
47
+ open_email(address, :with_text => text)
48
+ end
49
+
50
+ When /^I click the first link in the email$/ do
51
+ click_first_link_in_email
52
+ end
@@ -0,0 +1,60 @@
1
+ Given /^I have created an account$/ do
2
+ $db.migrate_reset
3
+ When "I visit the front page"
4
+ When "I submit a valid form"
5
+ end
6
+
7
+ Given /^I have not created an account$/ do
8
+ User.delete_all
9
+ UserEmail.delete_all
10
+ end
11
+
12
+ Given /^it is midnight$/ do
13
+ now = Time.now.utc
14
+ today_at_12 = DateTime.strptime(
15
+ now.strftime("%m/%d/%Y 12:00 AM %Z"),
16
+ "%m/%d/%Y %I:%M %p %Z"
17
+ ).to_time
18
+ Time.stub!(:now).and_return(today_at_12)
19
+ end
20
+
21
+ Given /^I have created an account with these attributes:$/ do |table|
22
+ $db.migrate_reset
23
+ When "I visit the front page"
24
+ fill_all_with_valid_data(table.hashes.first)
25
+ click_button
26
+ end
27
+
28
+ Given /^today is (.+)$/ do |date|
29
+ now = DateTime.strptime(
30
+ "#{date} #{Time.now.utc.strftime("%H:%M:%S %Z")}",
31
+ "%B %d, %Y %H:%M:%S %Z"
32
+ ).to_time
33
+ Time.stub!(:now).and_return(now)
34
+ end
35
+
36
+ Given /^it is day (.+)$/ do |day|
37
+ day = day.to_i
38
+ user = find_user
39
+ # Email already sent today
40
+ user.update_attribute(:send_at, user.send_at + day.days)
41
+ Time.stub!(:now).and_return(user.reset_at - 1.month + (day - 1).days)
42
+ end
43
+
44
+ Given /^today I have spent \$(.+)$/ do |amount|
45
+ IncomingMail.receive(generate_email(:subject => amount))
46
+ end
47
+
48
+ Given /^before today I spent \$(.+)$/ do |amount|
49
+ user = find_user
50
+ user.spent_this_month += amount.to_f
51
+ user.save
52
+ end
53
+
54
+ Given /^I have deposited \$(.+)$/ do |amount|
55
+ IncomingMail.receive(generate_email(:subject => "+#{amount}"))
56
+ end
57
+
58
+ Given /^the background job ran$/ do
59
+ When "the background job runs"
60
+ end
@@ -0,0 +1,36 @@
1
+ Then /^I should see a form$/ do
2
+ assert_have_selector "form[action='/new'][method='post']"
3
+ end
4
+
5
+ Then /^I should see a.? (.+) text field$/ do |field|
6
+ assert_have_selector "#user_#{field}"
7
+ end
8
+
9
+ Then /^I should see a.? (.+) checkbox$/ do |field|
10
+ assert_have_selector "#user_#{field}"
11
+ end
12
+
13
+ Then /^I should see a submit button$/ do
14
+ assert_have_selector "input[type=image]"
15
+ end
16
+
17
+ Then /^I should see a success page$/ do
18
+ within "h1" do
19
+ assert_contain "Success!"
20
+ end
21
+ end
22
+
23
+ Then /^the (.+) field should have an error$/ do |field|
24
+ assert_have_selector "#user_#{field}"
25
+ assert_have_selector ".validation"
26
+ end
27
+
28
+ Then /^the error should be "([^\"]*)"$/ do |error|
29
+ within ".validation" do
30
+ assert_contain error
31
+ end
32
+ end
33
+
34
+ Then /^spent today should be zero$/ do
35
+ find_user.spent_today.should == 0
36
+ end
@@ -0,0 +1,46 @@
1
+ When /^I visit the front page$/ do
2
+ visit '/'
3
+ end
4
+
5
+ When /^I submit a valid form$/ do
6
+ fill_all_with_valid_data
7
+ click_button
8
+ end
9
+
10
+ When /^I submit a valid form with (.+)$/ do |input|
11
+ fill_all_with_valid_data
12
+ values = case input
13
+ when "decimals": [ "1000.00", "5000.00", "2000.00" ]
14
+ when "numbers only": [ "1000", "5000", "2000" ]
15
+ when "dollar signs": [ "$1000.00", "$5000.00", "$2000.00" ]
16
+ end
17
+ fill_in "user[savings]", :with => values.pop
18
+ fill_in "user[income]", :with => values.pop
19
+ fill_in "user[bills]", :with => values.pop
20
+ click_button
21
+ end
22
+
23
+ When /^submit an invalid (.+)$/ do |field|
24
+ fill_all_with_valid_data
25
+ fill_in "user[#{field.split.first}]", :with => "invalid"
26
+ click_button
27
+ end
28
+
29
+ When /^submit an empty (.+)$/ do |field|
30
+ fill_all_with_valid_data
31
+ case field
32
+ when 'tos'
33
+ uncheck "user[#{field}]"
34
+ else
35
+ fill_in "user[#{field.split.first}]", :with => ""
36
+ end
37
+ click_button
38
+ end
39
+
40
+ When /^the background job runs$/ do
41
+ visit '/cron'
42
+ end
43
+
44
+ When /^output the email$/ do
45
+ puts current_email.body
46
+ end
@@ -0,0 +1,38 @@
1
+ $testing = true
2
+ $root = File.expand_path(File.dirname(__FILE__) + "/../../")
3
+ $:.unshift "#{$root}/lib"
4
+
5
+ require 'sum'
6
+
7
+ gems = [
8
+ [ 'bmabey-email_spec', '=0.2.0' ],
9
+ [ 'rack-test', '=0.4.0' ],
10
+ [ 'rspec', '=1.2.7' ]
11
+ ]
12
+
13
+ gems.each do |name, version|
14
+ begin
15
+ gem name, version
16
+ rescue Exception
17
+ $:.unshift "#{File.dirname(__FILE__)}/../../vendor/#{name}/lib"
18
+ end
19
+ end
20
+
21
+ require 'email_spec'
22
+ require 'rack/test'
23
+ require 'spec/mocks'
24
+ require 'test/unit'
25
+ require "#{$root}/vendor/webrat/lib/webrat"
26
+
27
+ World do
28
+ def app
29
+ Application
30
+ end
31
+
32
+ include EmailSpec::Helpers
33
+ include EmailSpec::Matchers
34
+ include Rack::Test::Methods
35
+ include Test::Unit::Assertions
36
+ include Webrat::Matchers
37
+ include Webrat::Methods
38
+ end
@@ -0,0 +1,50 @@
1
+ def current_email_address
2
+ "cucumber@sumapp.com"
3
+ end
4
+
5
+ def fill_all_with_valid_data(hash={})
6
+ valid = {
7
+ 'savings' => '0',
8
+ 'income' => '0',
9
+ 'bills' => '0',
10
+ 'email' => current_email_address,
11
+ 'tos' => '1'
12
+ }.merge(hash)
13
+ valid.each do |key, value|
14
+ case key
15
+ when 'tos'
16
+ check "user[#{key}]"
17
+ else
18
+ fill_in "user[#{key}]", :with => value
19
+ end
20
+ end
21
+ end
22
+
23
+ def find_user
24
+ UserEmail.find_by_email(current_email_address).user
25
+ end
26
+
27
+ def generate_email(options={})
28
+ <<EMAIL
29
+ Delivered-To: test@sumapp.com
30
+ Return-Path: <#{options[:from] || current_email_address}>
31
+ From: Winton Welsh <#{options[:from] || current_email_address}>
32
+ To: test@sumapp.com
33
+ Subject: #{options[:subject] || ''}
34
+ Content-Type: multipart/alternative; boundary=000325574d2a5057e1046eae4ba5
35
+
36
+ --000325574d2a5057e1046eae4ba5
37
+ Content-Type: text/plain; charset=ISO-8859-1
38
+ Content-Transfer-Encoding: 7bit
39
+
40
+ #{options[:body] || ''}
41
+
42
+ --000325574d2a5057e1046eae4ba5
43
+ Content-Type: text/html; charset=ISO-8859-1
44
+ Content-Transfer-Encoding: 7bit
45
+
46
+ #{options[:body] || ''}<br>
47
+
48
+ --000325574d2a5057e1046eae4ba5--
49
+ EMAIL
50
+ end
@@ -0,0 +1,11 @@
1
+ Before do
2
+ $rspec_mocks ||= Spec::Mocks::Space.new
3
+ end
4
+
5
+ After do
6
+ begin
7
+ $rspec_mocks.verify_all
8
+ ensure
9
+ $rspec_mocks.reset_all
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ Webrat.configure do |config|
2
+ config.mode = :rack
3
+ end
@@ -0,0 +1,83 @@
1
+ Feature: Update user
2
+
3
+ As a user
4
+ I want to submit my information
5
+ In order to see a success page
6
+
7
+ Scenario: I submit a valid form with decimals
8
+ When I visit the front page
9
+ And I submit a valid form with decimals
10
+ Then I should see a success page
11
+
12
+ Scenario: I submit a valid form with numbers only
13
+ When I visit the front page
14
+ And I submit a valid form with numbers only
15
+ Then I should see a success page
16
+
17
+ Scenario: I submit a valid form with dollar signs
18
+ When I visit the front page
19
+ And I submit a valid form with dollar signs
20
+ Then I should see a success page
21
+
22
+ Scenario: I submit an invalid savings amount
23
+ When I visit the front page
24
+ And submit an invalid savings amount
25
+ Then I should see a form
26
+ And the savings field should have an error
27
+ And the error should be "is not a number"
28
+
29
+ Scenario: I submit an empty savings amount
30
+ When I visit the front page
31
+ And submit an empty savings amount
32
+ Then I should see a form
33
+ And the savings field should have an error
34
+ And the error should be "is not a number"
35
+
36
+ Scenario: I submit an invalid income amount
37
+ When I visit the front page
38
+ And submit an invalid income amount
39
+ Then I should see a form
40
+ And the income field should have an error
41
+ And the error should be "is not a number"
42
+
43
+ Scenario: I submit an empty income amount
44
+ When I visit the front page
45
+ And submit an empty income amount
46
+ Then I should see a form
47
+ And the income field should have an error
48
+ And the error should be "is not a number"
49
+
50
+ Scenario: I submit an invalid bills amount
51
+ When I visit the front page
52
+ And submit an invalid bills amount
53
+ Then I should see a form
54
+ And the bills field should have an error
55
+ And the error should be "is not a number"
56
+
57
+ Scenario: I submit an empty bills amount
58
+ When I visit the front page
59
+ And submit an empty bills amount
60
+ Then I should see a form
61
+ And the bills field should have an error
62
+ And the error should be "is not a number"
63
+
64
+ Scenario: I submit an invalid email
65
+ When I visit the front page
66
+ And submit an invalid email
67
+ Then I should see a form
68
+ And the email field should have an error
69
+ And the error should be "is invalid"
70
+
71
+ Scenario: I submit an empty email
72
+ When I visit the front page
73
+ And submit an empty email
74
+ Then I should see a form
75
+ And the email field should have an error
76
+ And the error should be "can't be blank"
77
+
78
+ Scenario: I don't check the terms of service
79
+ When I visit the front page
80
+ And submit an empty tos
81
+ Then I should see a form
82
+ And the tos field should have an error
83
+ And the error should be "must be accepted"