msg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +9 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/images/msg/message.png +0 -0
  5. data/app/assets/images/msg/ping.png +0 -0
  6. data/app/assets/images/msg/sending.png +0 -0
  7. data/app/assets/javascripts/lib/jquery.peity.js +261 -0
  8. data/app/assets/javascripts/msg.js.coffee +6 -0
  9. data/app/assets/stylesheets/msg.css.sass +218 -0
  10. data/app/controllers/msg/bounces_controller.rb +67 -0
  11. data/app/controllers/msg/engine_controller.rb +23 -0
  12. data/app/controllers/msg/envelopes_controller.rb +22 -0
  13. data/app/controllers/msg/messages_controller.rb +85 -0
  14. data/app/controllers/msg/sendings_controller.rb +58 -0
  15. data/app/helpers/msg/msg_helper.rb +40 -0
  16. data/app/mailers/msg/devise_mailer.rb +20 -0
  17. data/app/mailers/msg/msg_mailer.rb +23 -0
  18. data/app/models/msg/bounce.rb +19 -0
  19. data/app/models/msg/envelope.rb +56 -0
  20. data/app/models/msg/message.rb +26 -0
  21. data/app/models/msg/sending.rb +54 -0
  22. data/app/views/layouts/msg/default.html.haml +30 -0
  23. data/app/views/layouts/msg/email.html.haml +10 -0
  24. data/app/views/msg/bounces/_listing.html.haml +5 -0
  25. data/app/views/msg/bounces/_report.html.haml +10 -0
  26. data/app/views/msg/bounces/index.html.haml +5 -0
  27. data/app/views/msg/devise_mailer/confirmation_instructions.en.html.haml +1 -0
  28. data/app/views/msg/devise_mailer/reset_password_instructions.en.html.haml +1 -0
  29. data/app/views/msg/envelopes/_listing.html.haml +5 -0
  30. data/app/views/msg/messages/_action_menu.html.haml +10 -0
  31. data/app/views/msg/messages/_form.html.haml +38 -0
  32. data/app/views/msg/messages/_instructions.html.haml +28 -0
  33. data/app/views/msg/messages/_message.html.haml +11 -0
  34. data/app/views/msg/messages/_saved_messages.html.haml +2 -0
  35. data/app/views/msg/messages/_transactional_messages.html.haml +3 -0
  36. data/app/views/msg/messages/edit.html.haml +7 -0
  37. data/app/views/msg/messages/index.html.haml +23 -0
  38. data/app/views/msg/messages/new.html.haml +7 -0
  39. data/app/views/msg/messages/preview.html.haml +4 -0
  40. data/app/views/msg/messages/show.html.haml +25 -0
  41. data/app/views/msg/msg_mailer/message_in_envelope.html.haml +2 -0
  42. data/app/views/msg/sendings/_form.html.haml +45 -0
  43. data/app/views/msg/sendings/_listing.html.haml +17 -0
  44. data/app/views/msg/sendings/_report.html.haml +8 -0
  45. data/app/views/msg/sendings/_sending.html.haml +22 -0
  46. data/app/views/msg/sendings/_sendings.html.haml +2 -0
  47. data/app/views/msg/sendings/index.html.haml +8 -0
  48. data/app/views/msg/sendings/new.html.haml +9 -0
  49. data/app/views/msg/sendings/review.html.haml +2 -0
  50. data/app/views/msg/sendings/show.html.haml +50 -0
  51. data/app/views/msg/shared/_toolbar.html.haml +17 -0
  52. data/config/cucumber.yml +8 -0
  53. data/config/locales/en.yml +76 -0
  54. data/config/routes.rb +26 -0
  55. data/db/migrate/20130320141926_msg_data.rb +54 -0
  56. data/db/migrate/20130327134754_sending_circumstances.rb +6 -0
  57. data/lib/msg.rb +88 -0
  58. data/lib/msg/engine.rb +23 -0
  59. data/lib/msg/receivers.rb +64 -0
  60. data/lib/msg/version.rb +3 -0
  61. data/lib/tasks/cucumber.rake +65 -0
  62. data/lib/tasks/msg_tasks.rake +4 -0
  63. data/spec/controllers/msg/bounces_controller_spec.rb +48 -0
  64. data/spec/controllers/msg/envelopes_controller_spec.rb +22 -0
  65. data/spec/controllers/msg/messages_controller_spec.rb +9 -0
  66. data/spec/controllers/msg/sendings_controller_spec.rb +47 -0
  67. data/spec/dummy/README.rdoc +261 -0
  68. data/spec/dummy/Rakefile +7 -0
  69. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  70. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  71. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  72. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  73. data/spec/dummy/app/models/user.rb +14 -0
  74. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  75. data/spec/dummy/config.ru +4 -0
  76. data/spec/dummy/config/application.rb +59 -0
  77. data/spec/dummy/config/boot.rb +10 -0
  78. data/spec/dummy/config/database.yml +25 -0
  79. data/spec/dummy/config/environment.rb +5 -0
  80. data/spec/dummy/config/environments/development.rb +37 -0
  81. data/spec/dummy/config/environments/production.rb +67 -0
  82. data/spec/dummy/config/environments/test.rb +41 -0
  83. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/spec/dummy/config/initializers/devise.rb +285 -0
  85. data/spec/dummy/config/initializers/inflections.rb +15 -0
  86. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  87. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  88. data/spec/dummy/config/initializers/session_store.rb +8 -0
  89. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  90. data/spec/dummy/config/locales/en.yml +5 -0
  91. data/spec/dummy/config/routes.rb +9 -0
  92. data/spec/dummy/db/development.sqlite3 +0 -0
  93. data/spec/dummy/db/migrate/2013032210540_users.rb +49 -0
  94. data/spec/dummy/db/migrate/20130326093048_msg_data.msg.rb +55 -0
  95. data/spec/dummy/db/schema.rb +96 -0
  96. data/spec/dummy/db/test.sqlite3 +0 -0
  97. data/spec/dummy/log/development.log +143 -0
  98. data/spec/dummy/log/test.log +1022 -0
  99. data/spec/dummy/public/404.html +26 -0
  100. data/spec/dummy/public/422.html +26 -0
  101. data/spec/dummy/public/500.html +25 -0
  102. data/spec/dummy/public/favicon.ico +0 -0
  103. data/spec/dummy/script/rails +6 -0
  104. data/spec/factories/msg/bounces.rb +9 -0
  105. data/spec/factories/msg/envelopes.rb +10 -0
  106. data/spec/factories/msg/messages.rb +10 -0
  107. data/spec/factories/msg/sendings.rb +7 -0
  108. data/spec/factories/users.rb +11 -0
  109. data/spec/helpers/msg/msg_helper_spec.rb +17 -0
  110. data/spec/lib/msg_spec.rb +15 -0
  111. data/spec/mailers/msg/devise_mailer_spec.rb +21 -0
  112. data/spec/mailers/msg/msg_mailer_spec.rb +36 -0
  113. data/spec/models/msg/bounce_spec.rb +19 -0
  114. data/spec/models/msg/envelope_spec.rb +62 -0
  115. data/spec/models/msg/message_spec.rb +19 -0
  116. data/spec/models/msg/sending_spec.rb +10 -0
  117. data/spec/routing/sendings_routing_spec.rb +31 -0
  118. data/spec/spec_helper.rb +70 -0
  119. metadata +446 -0
@@ -0,0 +1,50 @@
1
+ #sending
2
+
3
+
4
+ - if envelope = @sending.envelopes.first
5
+ .envelope
6
+ .headers
7
+ %p
8
+ %span.field
9
+ = t(:subject).titlecase + ":"
10
+ %strong
11
+ = envelope.subject
12
+ %p
13
+ %span.field
14
+ = t(:to).titlecase + ":"
15
+ %strong
16
+ = envelope.to_address
17
+ %p
18
+ %span.field
19
+ = t(:from).titlecase + ":"
20
+ %strong
21
+ = envelope.from_address
22
+ %p
23
+ %span.field
24
+ = t(:sent_at).titlecase + ":"
25
+ %strong
26
+ = l(@sending.created_at, :format => :natural_with_date)
27
+ %iframe.body{:src => msg.review_sending_url(@sending)}
28
+
29
+
30
+
31
+ -content_for :title do
32
+ = t :sent_message
33
+
34
+ -content_for :margin do
35
+ #receivers
36
+ %p
37
+ - if @sending.receiving_group
38
+ = t(:sent_to)
39
+ = t("msg.groups.#{@sending.receiving_group}")
40
+ = t(:receiver_count, :count => @sending.envelopes.count)
41
+ - else
42
+ = t(:sent)
43
+ = t(:at)
44
+ = l(@sending.created_at, :format => :natural_with_date)
45
+
46
+ %span.pie{:data => {:diameter => 50}}<
47
+ = @sending.statistics.join(',')
48
+
49
+ %ul.envelopes
50
+ = render :partial => "msg/envelopes/listing", :collection => @sending.envelopes
@@ -0,0 +1,17 @@
1
+ %header
2
+ %ul.commands
3
+ %li.command{:"data-wysihtml5-command" => "bold"}
4
+ %li.command{:"data-wysihtml5-command" => "italic"}
5
+ %li.command{:"data-wysihtml5-command" => "insertUnorderedList"}
6
+ %li.command{:"data-wysihtml5-command" => "insertOrderedList"}
7
+ %li.command{:"data-wysihtml5-command" => "createLink"}
8
+ %li.command{:"data-wysihtml5-command" => "formatBlock", :"data-wysihtml5-command-value" => "h1"}
9
+ %li.command{:"data-wysihtml5-command" => "formatBlock", :"data-wysihtml5-command-value" => "h2"}
10
+ %li.command{:"data-wysihtml5-action" => "change_view"}
11
+
12
+ %div{:"data-wysihtml5-dialog" => "createLink", :style => "display: none"}
13
+ %label
14
+ Link:
15
+ %input{:type => "text", :"data-wysihtml5-dialog-field" => "href", :value => "http://"}
16
+ %a{:"data-wysihtml5-dialog-action" => "save"} OK
17
+ %a{:"data-wysihtml5-dialog-action" => "cancel"} cancel
@@ -0,0 +1,8 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
5
+ %>
6
+ default: <%= std_opts %> features
7
+ wip: --tags @wip:3 --wip features
8
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
@@ -0,0 +1,76 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ msg:
5
+ message:
6
+ saved: "Save this message for reuse"
7
+ errors:
8
+ msg:
9
+ from: "From"
10
+ bounce_report: "Bounces"
11
+ close: "close"
12
+ create_message: "send or save a new message"
13
+ sent_report: "Sent messages"
14
+ messages: "Messages"
15
+ please_set_layout: "You probably want to set Msg.layout (in an initializer) so that msg uses your application layout and not this default file."
16
+ confirm_delete_message: "Are you sure you want to delete the message '%{subject}? This cannot be undone."
17
+ edit_message: "edit message"
18
+ from: "From"
19
+ message_subject: "Subject"
20
+ message_body: "Body"
21
+ message_description: "Description (for your reference: does not appear in message)"
22
+ message_subject: "Subject"
23
+ message_function: "Function"
24
+ message_from_address: "Sender email address"
25
+ message_from_name: "Sender name"
26
+ message_from_note: "Leave both address fields blank to use the default"
27
+ receiver_count:
28
+ zero: "(nobody)"
29
+ one: "(one person)"
30
+ other: "(%{count} people)"
31
+ save_message: "Save message"
32
+ save_and_preview: "Save and preview"
33
+ send_message: "send message"
34
+ send_the_message: "Send the message"
35
+ preview_message: "preview message"
36
+ preview_and_send: "preview and send"
37
+ delete_message: "delete message"
38
+ transactional_messages: "Administrative messages"
39
+ saved_messages: "Saved messages"
40
+ send_this_message: "Send this message"
41
+ sent_at: "Sent at"
42
+ sent_messages: "Sent box"
43
+ sent_message: "Sent message"
44
+ subject: "Subject"
45
+ more_detail: "More detail"
46
+ to: "To"
47
+ save_for_reuse: "Save this message for reuse"
48
+ saved_note: "'Saving' the message adds it to the main message list, making it easier to send again. Unsaved messages can still be found in the sent box and resent from there."
49
+ sender: "Sender's name and address"
50
+ send_to: "Send to"
51
+ sent_to: "Sent to"
52
+ sent_to_count:
53
+ zero: "Sent to nobody"
54
+ one: "Sent to one person"
55
+ other: "Sent to %{count} people"
56
+ sent_count: "Sent: %{count}"
57
+ opened_count: "Opened: %{count}"
58
+ bounced_count: "Bounced: %{count}"
59
+ transactional_message: "Transactional message"
60
+ transactional_message_note: "You probably don't want to change this."
61
+ date:
62
+ formats:
63
+ dashed_short_date_format: "%d-%m-%Y"
64
+ month_header: "%B %Y"
65
+ natural: "%d %B"
66
+ natural_full: "%l:%M%P, %d %B %Y"
67
+ natural_with_year: "%d %B %Y"
68
+ minimal_with_year: "%d %b %Y"
69
+ year: "%Y"
70
+ month: "%B %Y"
71
+ time:
72
+ formats:
73
+ natural: "%l:%M%P"
74
+ natural_with_date: "%l:%M%P, %d %B %Y"
75
+ precise: "%H:%M:%S"
76
+ month_and_year: "%b %Y"
@@ -0,0 +1,26 @@
1
+ Msg::Engine.routes.draw do
2
+
3
+ resources :messages do
4
+ resources :sendings, :only => [:new, :create]
5
+ member do
6
+ get :preview
7
+ end
8
+ collection do
9
+ get :transactional
10
+ get :saved
11
+ end
12
+ end
13
+
14
+ resources :sendings do
15
+ member do
16
+ get :review
17
+ end
18
+ end
19
+
20
+ # envelopes#show is pinged when a message is opened
21
+ resources :envelopes, :only => [:show]
22
+
23
+ # bounces#create is called from the email receiver
24
+ resources :bounces, :only => [:create]
25
+
26
+ end
@@ -0,0 +1,54 @@
1
+ class MsgData < ActiveRecord::Migration
2
+ def change
3
+ create_table :msg_messages do |t|
4
+ t.string :subject
5
+ t.string :from_address
6
+ t.string :from_name
7
+ t.text :body
8
+ t.string :function
9
+ t.text :description
10
+ t.boolean :transactional, :default => false
11
+ t.boolean :saved, :default => false
12
+ t.integer :created_by_id
13
+ t.timestamps
14
+ end
15
+
16
+ create_table :msg_sendings do |t|
17
+ t.integer :message_id
18
+ t.integer :created_by_id
19
+ t.datetime :sent_at
20
+ t.timestamps
21
+ end
22
+ add_index :msg_sendings, :message_id
23
+ add_index :msg_sendings, :created_by_id
24
+
25
+ create_table :msg_envelopes do |t|
26
+ t.integer :sending_id
27
+ t.integer :receiver_id
28
+ t.integer :email_id
29
+ t.string :receiver_type
30
+ t.string :to_address
31
+ t.string :from_address
32
+ t.string :subject
33
+ t.text :contents
34
+ t.datetime :sent_at
35
+ t.datetime :opened_at
36
+ t.timestamps
37
+ end
38
+ add_index :msg_envelopes, :sending_id
39
+ add_index :msg_envelopes, :email_id
40
+ add_index :msg_envelopes, :receiver_id
41
+ add_index :msg_envelopes, [:receiver_id, :receiver_type]
42
+
43
+ create_table :msg_bounces do |t|
44
+ t.integer :envelope_id
45
+ t.string :bounce_type
46
+ t.string :bounce_subtype
47
+ t.string :reporter
48
+ t.text :raw_message
49
+ t.timestamps
50
+ end
51
+ add_index :msg_bounces, :envelope_id
52
+
53
+ end
54
+ end
@@ -0,0 +1,6 @@
1
+ class SendingCircumstances < ActiveRecord::Migration
2
+ def change
3
+ add_column :msg_sendings, :receiving_class, :string
4
+ add_column :msg_sendings, :receiving_group, :string
5
+ end
6
+ end
@@ -0,0 +1,88 @@
1
+ require "msg/receivers"
2
+ require "msg/engine"
3
+
4
+ module Msg
5
+ mattr_accessor :user_class,
6
+ :layout,
7
+ :email_layout,
8
+ :default_from_address,
9
+ :default_from_name,
10
+ :email_bcc,
11
+ :email_values,
12
+ :messaging_groups,
13
+ :receiving_classes,
14
+ :sanitized_allowed_tags,
15
+ :sanitized_allowed_attributes,
16
+ :sending_domain,
17
+ :ses_access_key_id,
18
+ :ses_secret_access_key
19
+
20
+ class MsgError < StandardError; end
21
+ class EmailInvalid < MsgError; end
22
+
23
+
24
+ class << self
25
+
26
+ def setup
27
+ yield self
28
+ end
29
+
30
+ def layout
31
+ @@user_class ||= "User"
32
+ end
33
+
34
+ def layout
35
+ @@layout ||= "msg/default"
36
+ end
37
+
38
+ def email_layout
39
+ @@email_layout ||= "msg/email"
40
+ end
41
+
42
+ def default_from_address
43
+ @@default_from_address ||= "please_configure_email_in_msg_initializer@example.com"
44
+ end
45
+
46
+ def default_from_name
47
+ @@default_from_name ||= "Someone Unknown"
48
+ end
49
+
50
+ def default_from
51
+ "#{default_from_name} <#{default_from_address}>"
52
+ end
53
+
54
+ def email_values
55
+ @@email_values ||= {}
56
+ end
57
+
58
+ def receiving_classes
59
+ @@receiving_classes ||= []
60
+ end
61
+
62
+ def tags_allowed_in_email
63
+ @@permitted_tags ||= ActionView::Base.sanitized_allowed_tags
64
+ end
65
+
66
+ def attributes_allowed_in_email
67
+ @@permitted_attributes ||= ActionView::Base.sanitized_allowed_attributes
68
+ end
69
+
70
+ def sending_domain
71
+ @@sending_domain ||= ActionMailer::Base.default_url_options[:host]
72
+ end
73
+
74
+
75
+
76
+
77
+
78
+ def add_receiving_class(klass, options)
79
+ Rails.logger.warn ">>> Msg.add_receiving_class #{klass}"
80
+
81
+ k = klass.to_s
82
+ receiving_classes << k unless receiving_classes.include?(k)
83
+ klass.messaging_groups = options[:groups] || []
84
+ Msg::Sending.add_receiver_hooks(klass, options)
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,23 @@
1
+ module Msg
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Msg
4
+
5
+ initializer "msg.integration" do |app|
6
+ ActiveSupport.on_load :action_controller do
7
+ helper Msg::MsgHelper
8
+ end
9
+ end
10
+
11
+ config.generators do |g|
12
+ g.test_framework :rspec, :view_specs => false
13
+ g.fixture_replacement :factory_girl
14
+ g.assets false
15
+ g.helper false
16
+ end
17
+
18
+ config.to_prepare do
19
+ ActiveRecord::Base.send :include, Msg::Receivers
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,64 @@
1
+ # Msg::Receivers is for inclusion into ActiveRecord::Base...
2
+
3
+ module Msg
4
+ module Receivers
5
+ def self.included(base)
6
+ base.extend ActiveRecordClassMethods
7
+ end
8
+ end
9
+
10
+ module ActiveRecordClassMethods
11
+ # +receives_messages+ ...
12
+
13
+ def receives_messages(options={})
14
+ include ReceiverInstanceMethods
15
+ has_many :envelopes, :as => :receiver, :class_name => "Msg::Envelope"
16
+ Msg.add_receiving_class(self, options)
17
+ end
18
+
19
+ # Messaging groups are usually defined by passing a :groups parameter to `receives_messages`,
20
+ # but you can also override the messaging_groups methods if that's easier.
21
+ #
22
+ def messaging_groups
23
+ Thread.current["messaging_groups_#{self.to_s.underscore}"] ||= []
24
+ # @messaging_groups ||= []
25
+ end
26
+
27
+ # Messaging groups are always held as a hash of name => lambda { retrieval action }, and in a complex
28
+ # case they can be passed in that form. If all the groups correspond to scopes on the receiving class,
29
+ # you can alternatively supply a list of scope names. It will be expanded to simple lambdas here.
30
+ #
31
+ # receives_messages :groups => [:scope_name, :other_scope_name]
32
+ #
33
+
34
+ def messaging_groups=(groups)
35
+ if groups.is_a?(Array)
36
+ groups = groups.each_with_object({}) do |grp, hash|
37
+ hash[grp] = lambda { self.send grp }
38
+ end
39
+ end
40
+ Thread.current["messaging_groups_#{self.to_s.underscore}"] = groups
41
+ end
42
+
43
+ def messaging_group(name)
44
+ if definition = messaging_groups(name)
45
+ definition.call()
46
+ else
47
+ self.send name
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ module ReceiverInstanceMethods
54
+
55
+
56
+
57
+ end
58
+ end
59
+
60
+
61
+
62
+
63
+
64
+
@@ -0,0 +1,3 @@
1
+ module Msg
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,65 @@
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
+
8
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
9
+
10
+ vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
11
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
12
+
13
+ begin
14
+ require 'cucumber/rake/task'
15
+
16
+ namespace :cucumber do
17
+ Cucumber::Rake::Task.new({:ok => 'test:prepare'}, 'Run features that should pass') do |t|
18
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
19
+ t.fork = true # You may get faster startup if you set this to false
20
+ t.profile = 'default'
21
+ end
22
+
23
+ Cucumber::Rake::Task.new({:wip => 'test:prepare'}, 'Run features that are being worked on') do |t|
24
+ t.binary = vendored_cucumber_bin
25
+ t.fork = true # You may get faster startup if you set this to false
26
+ t.profile = 'wip'
27
+ end
28
+
29
+ Cucumber::Rake::Task.new({:rerun => 'test:prepare'}, 'Record failing features and run only them if any exist') do |t|
30
+ t.binary = vendored_cucumber_bin
31
+ t.fork = true # You may get faster startup if you set this to false
32
+ t.profile = 'rerun'
33
+ end
34
+
35
+ desc 'Run all features'
36
+ task :all => [:ok, :wip]
37
+
38
+ task :statsetup do
39
+ require 'rails/code_statistics'
40
+ ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
41
+ ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
42
+ end
43
+ end
44
+ desc 'Alias for cucumber:ok'
45
+ task :cucumber => 'cucumber:ok'
46
+
47
+ task :default => :cucumber
48
+
49
+ task :features => :cucumber do
50
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
51
+ end
52
+
53
+ # In case we don't have the generic Rails test:prepare hook, append a no-op task that we can depend upon.
54
+ task 'test:prepare' do
55
+ end
56
+
57
+ task :stats => 'cucumber:statsetup'
58
+ rescue LoadError
59
+ desc 'cucumber rake task not available (cucumber not installed)'
60
+ task :cucumber do
61
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
62
+ end
63
+ end
64
+
65
+ end