newman 0.2.1 → 0.3.0

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.
@@ -1,9 +1,40 @@
1
+ ### 0.3.0 (2012-03-08)
2
+
3
+ **Improvements:**
4
+
5
+ - Added documentation of all settings that can be modified via Newman configuration files.
6
+
7
+ - Added `Newman::Server#simple!`, which combines some of the flexibility of
8
+ manually building a server object with sensible defaults. This method is
9
+ useful for building simple tick-based servers, or for tweaking small details
10
+ such as which logger you want to use.
11
+
12
+ - Allow a locals hash to be passed to tilt via `Newman::Controller#template`,
13
+ and added some integration tests for template support.
14
+
15
+ **Behavior Changes:**
16
+
17
+ - Caching of logger object is less aggressive now, allowing
18
+ `Newman::Server#logger=` to be called at any time to change the
19
+ logger object used by the server.
20
+
21
+ - `Newman::Server.new` no longer accepts a custom logger argument.
22
+ Use `Newman::Server#logger=` instead.
23
+
24
+ - Locked explicitly to mail v2.3.0, because we're being bit by an upstream
25
+ bug. We will try to lock more optimistically in a future release of
26
+ Newman.
27
+
28
+ [Diff of all changes since 0.2.1](https://github.com/mendicant-university/newman/compare/v0.2.1...v0.3.0#diff-43)
29
+
1
30
  ### 0.2.1 (2012-02-11)
2
31
 
3
32
  - Fixed a bug with `Newman::Application#match`. It now normalizes keys to
4
33
  strings for easy use with `Newman::Application#compile_regex`, which
5
34
  fixes our substitution logic in patterns.
6
35
 
36
+ [Diff of all changes since 0.2.0](https://github.com/mendicant-university/newman/compare/v0.2.0...v0.2.1#diff-43)
37
+
7
38
  ### 0.2.0 (2012-02-08)
8
39
 
9
40
  - Internals mostly rewritten, changes too numerous to outline meaningfully.
@@ -25,6 +56,8 @@
25
56
  - Add a generic callback method to Newman::Application which allows for arbitrary
26
57
  callbacks to be run based on filters against the Mail::Message object.
27
58
 
59
+ [Diff of all changes since 0.1.1](https://github.com/mendicant-university/newman/compare/v0.1.1...v0.2.0#diff-43)
60
+
28
61
  ### 0.1.1 (2012-02-03)
29
62
 
30
63
  - First official release.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![Newman](http://i.imgur.com/92bZB.jpg)
1
+ ![Newman](http://i.imgur.com/GCqaT.png)
2
2
 
3
3
  Newman is a microframework which aims to do for email-based
4
4
  applications what Rack and Sinatra have done for web programming. **While our
@@ -45,6 +45,9 @@ simple examples in this repository.
45
45
 
46
46
  Check out [Newman's Rocco-based API documentation](http://mendicant-university.github.com/newman/lib/newman.html).
47
47
 
48
+ We update this documentation on each gem release of newman, but to generate this documentation yourself,
49
+ you'll need to install the rocco gem.
50
+
48
51
  ### For general discussion, questions, and ideas about Newman:
49
52
 
50
53
  Find seacreature or ericgj in the #newman channel on Freenode or send an email to newman@librelist.org
@@ -1,8 +1,13 @@
1
- # This is a cheap and possibly buggy clone of librelist.org's automatic
2
- # mailing list creation
3
-
4
1
  require_relative "example_helper"
5
2
 
3
+ # This is a cheap and possibly buggy clone of librelist.org's automatic
4
+ # mailing list creation
5
+ #
6
+ # Settings:
7
+ #
8
+ # - `application.librelist_db`<br>
9
+ # path to mailing list pstore file, relative to application root
10
+ #
6
11
  module Newman
7
12
  module Examples
8
13
  LibreList = Newman::Application.new do
@@ -1,11 +1,9 @@
1
1
  require_relative "ping_pong"
2
2
 
3
-
4
- settings = Newman::Settings.from_file("config/environment.rb")
5
- mailer = Newman::Mailer.new(settings)
6
-
7
- server = Newman::Server.new(settings, mailer)
8
- server.apps << Newman::Examples::PingPong
3
+ server = Newman::Server.simple!(Newman::Examples::PingPong,
4
+ "config/environment.rb")
5
+ mailer = server.mailer
6
+ settings = server.settings
9
7
 
10
8
  mailer.deliver_message(:to => settings.application.ping_email,
11
9
  :from => settings.service.default_sender)
@@ -1,5 +1,12 @@
1
1
  require_relative "example_helper"
2
2
 
3
+ # The simplest possible mailing list app
4
+ #
5
+ # Settings:
6
+ #
7
+ # - `application.simplelist_db`<br>
8
+ # path to mailing list pstore file, relative to application root
9
+ #
3
10
  module Newman
4
11
  module Examples
5
12
 
@@ -0,0 +1,3 @@
1
+ The body of the request follows:
2
+
3
+ <%= request.decoded %>
@@ -0,0 +1 @@
1
+ It was sent <%= request.date %>.
@@ -0,0 +1 @@
1
+ The list it was routed to was <%= params[:list_id] %>.
@@ -0,0 +1 @@
1
+ The sender of this email was <%= sender %>.
@@ -0,0 +1,6 @@
1
+ The sender of this email was <%= sender %>.
2
+ It was sent <%= request.date %>.
3
+ The list it was routed to was <%= params[:list_id] %>.
4
+ The body of the request follows:
5
+
6
+ <%= request.decoded %>
@@ -0,0 +1,4 @@
1
+ <%= template('test/_echo_sender') %>
2
+ <%= template('test/_echo_date') %>
3
+ <%= template('test/_echo_list') %>
4
+ <%= template('test/_echo_body') %>
@@ -0,0 +1,3 @@
1
+ Pick 4: <%= pick_4.map(&:to_s).join("") %>
2
+
3
+ Your magic code is: <%= magic_code %>
@@ -226,16 +226,13 @@ module Newman
226
226
  # 2) If the selection of `matched_callbacks` is empty, it executes the default
227
227
  # callback in the context of a controller object. Otherwise, it runs each
228
228
  # callback in sequence, in the context of a controller object.
229
- #
230
- # This method may have some weird side effects because it relies on
231
- # awkward state mutations that could be either done in a better way or
232
- # replaced with a mostly stateless approach. We will look at fixing
233
- # this in a future Newman release.
234
229
 
235
230
  def trigger_callbacks(controller)
231
+ match_data = {}
232
+
236
233
  matched_callbacks = callbacks.select do |e|
237
234
  filter = e[:filter]
238
- e[:match_data] = filter.call(controller)
235
+ match_data[e] = filter.call(controller)
239
236
  end
240
237
 
241
238
  if matched_callbacks.empty?
@@ -243,7 +240,7 @@ module Newman
243
240
  else
244
241
  matched_callbacks.each do |e|
245
242
  action = e[:action]
246
- controller.params = e[:match_data] || {}
243
+ controller.params = match_data[e]
247
244
  controller.instance_exec(&action)
248
245
  end
249
246
  end
@@ -54,16 +54,18 @@ module Newman
54
54
  # ---
55
55
 
56
56
  # `Newman::Controller#template` is used to invoke a template file within the
57
- # context of the current controller object using Tilt. A name for the template is
57
+ # context of the current controller object using Tilt. A `name` for the template is
58
58
  # provided and then looked up in the directory referenced by
59
- # `settings.service.templates_dir`. While an example of using templates is
60
- # included in Newman's source, this feature hasn't really been tested
61
- # adequately. Please report any problems with this method in our
62
- # [issue tracker](https://github.com/mendicant-university/newman/issues).
63
-
64
- def template(name)
59
+ # `settings.service.templates_dir`. If a `locals` hash is provided, these
60
+ # local variables will be made available in templates.
61
+ #
62
+ # **NOTE: This is feature is one we haven't adequately used in Newman,
63
+ # if you have trouble with it, please let us know via our [issue
64
+ # tracker](http://github.com/mendicant-university/newman/issues).**
65
+ #
66
+ def template(name,locals={})
65
67
  Tilt.new(Dir.glob("#{settings.service.templates_dir}/#{name}.*").first)
66
- .render(self)
68
+ .render(self,locals)
67
69
  end
68
70
 
69
71
  # ---
@@ -2,34 +2,34 @@
2
2
  # to applications as a request, and then delivers a response email after the
3
3
  # applications have modified it.
4
4
  #
5
- # A `Newman::Server` object can be used in three distinct ways:
5
+ # A `Newman::Server` object can be used in four distinct ways:
6
6
  #
7
7
  # 1) Instantiated via `Newman::Server.test_mode` and then run tick by tick
8
8
  # in integration tests.
9
9
  #
10
10
  # 2) Instantiated via `Newman::Server.simple` which immediately executes
11
11
  # an infinite polling loop.
12
- #
13
- # 3) Instantiated explicitly and manually configured, for maximum control.
12
+ #
13
+ # 3) Instantiated via `Newman::Server.simple!`, and then run manually (either
14
+ # in a loop or by tick), using the same defaults used by `Newman::Server.simple`
15
+ #
16
+ # 4) Instantiated explicitly and manually configured, for maximum control.
14
17
  #
15
18
  # All of these different workflows are supported, but if you are simply looking
16
19
  # to build applications with `Newman`, you are most likely going to end up using
17
- # `Newman::Server.simple` because it takes care of most of the setup work for
18
- # you and is the easiest way to run a single Newman application.
20
+ # either `simple()` or `simple!()` because they care of most of the setup work
21
+ # for you.
19
22
  #
20
23
  # `Newman::Server` is part of Newman's **external interface**.
21
24
 
22
25
  module Newman
23
26
  class Server
24
27
  # ---
25
-
26
- # `Newman::Server.simple` automatically generates a `Newman::Mailer` object
27
- # and `Newman::Settings` object from the privded `settings_file`. These
28
+
29
+ # `Newman::Server.simple!` automatically generates a `Newman::Mailer` object
30
+ # and `Newman::Settings` object from the provided `settings_file`. These
28
31
  # objects are then passed on to `Newman::Server.new` and a server instance
29
- # is created. The server object is set up to run the specified `app`, with
30
- # request and response logging support enabled. Calling this method puts
31
- # the server in an infinite polling loop, because its final action is to
32
- # call `Newman::Server.run`.
32
+ # is created.
33
33
  #
34
34
  # The following example demonstrates how to use this method:
35
35
  #
@@ -42,18 +42,29 @@ module Newman
42
42
  # respond(:subject => "You missed the ball!")
43
43
  # end
44
44
  # end
45
- #
46
- # Newman::Server.simple(ping_pong, "config/environment.rb")
47
- #
48
- # Given a properly configured settings file, this code will launch a polling
49
- # server and run the simple `ping_pong` application.
50
-
51
- def self.simple(app, settings_file)
45
+ #
46
+ # s = Newman::Server.simple!(ping_pong, "config/environment.rb")
47
+ # # call s.tick or s.run at some later point.
48
+ #
49
+ # Given a proper configuration file, this will make it possible to easily
50
+ # get your applications up and running with simple request and response
51
+ # logging enabled.
52
+ def self.simple!(app, settings_file)
52
53
  settings = Settings.from_file(settings_file)
53
54
  mailer = Mailer.new(settings)
54
55
  server = new(settings, mailer)
55
- server.apps = [RequestLogger, app, ResponseLogger]
56
+ server.apps = [RequestLogger, app, ResponseLogger]
56
57
 
58
+ server
59
+ end
60
+
61
+ # ---
62
+
63
+ # `Newman::Server#simple` is the same as `Newman::Server#simple!`, but
64
+ # automatically starts an infinite polling loop.
65
+
66
+ def self.simple(app, settings_file)
67
+ server = simple!(app, settings_file)
57
68
  server.run
58
69
  end
59
70
 
@@ -64,7 +75,7 @@ module Newman
64
75
  # objects are then passed on to `Newman::Server.new` and a server instance
65
76
  # which is preconfigured for use in integration testing is returned.
66
77
  #
67
- # Using the application from the `Newman::Server.simple` documentation
78
+ # Using the application from the `Newman::Server.simple!` documentation
68
79
  # above, it'd be possible to write a simple integration test using this
69
80
  # method in the following way:
70
81
  #
@@ -96,19 +107,17 @@ module Newman
96
107
  # ---
97
108
 
98
109
  # To initialize a `Newman::Server` object, a settings object and mailer object must
99
- # be provided, and a logger object may also be provided. If a logger object
100
- # is not provided, `Newman::Server#default_logger` is called to create one.
101
- #
110
+ # be provided.
111
+ #
102
112
  # Instantiating a server object directly can be useful for building live
103
113
  # integration tests, or for building cron jobs which process email
104
114
  # periodically rather than in a busy-wait loop. See one of Newman's [live
105
115
  # tests](https://github.com/mendicant-university/newman/blob/master/examples/live_test.rb)
106
116
  # for an example of how this approach works.
107
117
 
108
- def initialize(settings, mailer, logger=nil)
118
+ def initialize(settings, mailer)
109
119
  self.settings = settings
110
120
  self.mailer = mailer
111
- self.logger = logger || default_logger
112
121
  self.apps = []
113
122
  end
114
123
 
@@ -120,7 +129,17 @@ module Newman
120
129
  # as an implementation detail; all important data will get passed down
121
130
  # into your apps on each `tick`.
122
131
 
123
- attr_accessor :settings, :mailer, :apps, :logger
132
+ attr_accessor :settings, :mailer, :apps
133
+ attr_writer :logger
134
+
135
+ # ---
136
+
137
+ # Returns the logger object that was set via `Newman::Server#logger=`,
138
+ # or delegates to `default_logger` if no custom logger was provided.
139
+ #
140
+ def logger
141
+ @logger || default_logger
142
+ end
124
143
 
125
144
  # ---
126
145
 
@@ -160,6 +179,12 @@ module Newman
160
179
  # exception is re-raised, typically taking the server down with it. This
161
180
  # setting is off by default.
162
181
  #
182
+ # 2b) If there are any server errors (such as an error retrieving messages
183
+ # via IMAP), those errors are logged and re-raised, taking the server
184
+ # down. Currently, you should use a process watcher to restart
185
+ # Newman to protect against such failures, but be careful about restarting
186
+ # without knowing what went wrong!
187
+ #
163
188
  # 3) Assuming an exception is not encountered, the response is delivered.
164
189
 
165
190
  def tick
@@ -187,6 +212,9 @@ module Newman
187
212
 
188
213
  response.deliver
189
214
  end
215
+ rescue Exception => e
216
+ logger.fatal("Caught exception: #{e}\n\n#{e.backtrace.join("\n")}")
217
+ raise
190
218
  end
191
219
 
192
220
  # ---
@@ -13,6 +13,38 @@
13
13
  # `Newman::Settings`is part of Newman's **internal API**, but
14
14
  # the setting file format and various settings that Newman depends
15
15
  # on should be considered part of the **external API**.
16
+ #
17
+ # The following settings are currently supported:
18
+ #
19
+ # imap.address
20
+ # imap.user
21
+ # imap.password
22
+ # imap.ssl_enabled (default false)
23
+ # imap.port
24
+ #
25
+ # smtp.address
26
+ # smtp.user
27
+ # smtp.password
28
+ # smtp.starttls_enabled (default false)
29
+ # smtp.port
30
+ #
31
+ # service.debug_mode
32
+ # log error backtraces and full request and response emails
33
+ #
34
+ # service.default_sender
35
+ # default FROM field for responses
36
+ #
37
+ # service.domain
38
+ # mail domain, used by filters and in building email addresses
39
+ #
40
+ # service.polling_interval
41
+ # idle seconds between server ticks
42
+ #
43
+ # service.raise_exceptions
44
+ # raise exceptions during server ticks, killing the server
45
+ #
46
+ # service.templates_dir
47
+ # directory of template files, relative to application root
16
48
 
17
49
  module Newman
18
50
  class Settings
@@ -4,8 +4,8 @@
4
4
  module Newman
5
5
  module Version
6
6
  MAJOR = 0
7
- MINOR = 2
8
- TINY = 1
7
+ MINOR = 3
8
+ TINY = 0
9
9
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
10
10
  end
11
11
  end
@@ -7,12 +7,17 @@ require_relative "../lib/newman"
7
7
  module Newman
8
8
  TEST_DIR = File.dirname(__FILE__)
9
9
 
10
- def self.new_test_server(app)
10
+ def self.new_test_server(apps)
11
+ apps = Array(apps)
11
12
  server = Newman::Server.test_mode(TEST_DIR + "/settings.rb")
12
- server.apps << app
13
+ apps.each {|app| server.apps << app }
13
14
  server.settings.application.simplelist_db = TEST_DIR + "/test.store"
14
15
  server.settings.service.templates_dir = TEST_DIR + "/../examples/views"
15
16
 
17
+ logger = ::Logger.new( TEST_DIR + "/log/test.log" )
18
+ logger.level = ::Logger::DEBUG
19
+ server.logger = logger
20
+
16
21
  server
17
22
  end
18
23
  end
@@ -0,0 +1,93 @@
1
+ require 'digest/md5'
2
+ require_relative "../helper"
3
+
4
+ describe "template" do
5
+ let(:app) do
6
+ Newman::Application.new do
7
+ match :list_id, /[^\.]+/
8
+
9
+ to :tag, "{list_id}.echo" do
10
+ respond(:subject => "RE: #{request.subject}",
11
+ :body => template('test/echo')
12
+ )
13
+ end
14
+
15
+ to :tag, "{list_id}.moneyball" do
16
+ pick_4 = [ rand(9), rand(9), rand(9), rand(9) ]
17
+ magic_code = Digest::MD5.hexdigest(
18
+ "#{sender}#{params[:list_id]}"
19
+ )
20
+ respond(:subject => "Today's Jackpots",
21
+ :body => template('test/moneyball', :pick_4 => pick_4,
22
+ :magic_code => magic_code)
23
+ )
24
+ end
25
+
26
+ to :tag, "{list_id}.partials" do
27
+ respond(:subject => "RE: #{request.subject}",
28
+ :body => template('test/echo_with_partials')
29
+ )
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ let(:server) {
36
+ Newman.new_test_server([Newman::RequestLogger, app, Newman::ResponseLogger])
37
+ }
38
+
39
+ let(:mailer) { server.mailer }
40
+
41
+ # -----
42
+
43
+ it "renders simple template without passed locals hash" do
44
+ mailer.deliver_message(:from => "me@example.com",
45
+ :to => "test+fizbiz.echo@test.com",
46
+ :body => "Could you call me about fizbiz please?")
47
+ server.tick
48
+
49
+ msgs = mailer.messages
50
+ assert_equal 1, msgs.count
51
+
52
+ actual = msgs.first.decoded
53
+
54
+ # assert that list_id, sender, and body is rendered in view
55
+ assert_match /\bme\@example\.com\b/, actual
56
+ assert_match /\bfizbiz\b/, actual
57
+ assert_match /Could you call me about fizbiz please\?/, actual
58
+ end
59
+
60
+ it "renders template with passed locals hash" do
61
+ mailer.deliver_message(:from => "me@example.com",
62
+ :to => "test+fizbiz.moneyball@test.com")
63
+ server.tick
64
+
65
+ msgs = mailer.messages
66
+ assert_equal 1, msgs.count
67
+
68
+ actual = msgs.first.decoded
69
+ expected_code = Digest::MD5.hexdigest("me@example.comfizbiz")
70
+
71
+ # assert that pick_4 and magic_code locals are rendered in view
72
+ assert_match(/Pick 4\: \d\d\d\d/, actual)
73
+ assert_match(/Your magic code is\: #{expected_code}/, actual)
74
+ end
75
+
76
+ it "renders template with partials" do
77
+ mailer.deliver_message(:from => "me@example.com",
78
+ :to => "test+fizbiz.partials@test.com",
79
+ :body => "Could you call me about fizbiz please?")
80
+ server.tick
81
+
82
+ msgs = mailer.messages
83
+ assert_equal 1, msgs.count
84
+
85
+ actual = msgs.first.decoded
86
+
87
+ # assert that list_id, sender, and body is rendered in view
88
+ assert_match /\bme\@example\.com\b/, actual
89
+ assert_match /\bfizbiz\b/, actual
90
+ assert_match /Could you call me about fizbiz please\?/, actual
91
+ end
92
+
93
+ end
@@ -4,4 +4,5 @@ SimpleCov.start
4
4
  require_relative "integration/acid_tests"
5
5
  require_relative "integration/skip_response_test"
6
6
  require_relative "integration/subject_filter_test"
7
+ require_relative "integration/template_test"
7
8
  require_relative "integration/to_filter_test"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-12 00:00:00.000000000 Z
12
+ date: 2012-03-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mail
16
- requirement: &2153405740 !ruby/object:Gem::Requirement
16
+ requirement: &2164929320 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - =
20
20
  - !ruby/object:Gem::Version
21
21
  version: 2.3.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2153405740
24
+ version_requirements: *2164929320
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: tilt
27
- requirement: &2153405240 !ruby/object:Gem::Requirement
27
+ requirement: &2164924480 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.3.3
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2153405240
35
+ version_requirements: *2164924480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: minitest
38
- requirement: &2153404780 !ruby/object:Gem::Requirement
38
+ requirement: &2164923220 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.11.1
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2153404780
46
+ version_requirements: *2164923220
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: simplecov
49
- requirement: &2153404380 !ruby/object:Gem::Requirement
49
+ requirement: &2164956100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,21 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2153404380
57
+ version_requirements: *2164956100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: purdytest
60
- requirement: &2153403880 !ruby/object:Gem::Requirement
61
- none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
66
- type: :development
67
- prerelease: false
68
- version_requirements: *2153403880
69
- - !ruby/object:Gem::Dependency
70
- name: rocco
71
- requirement: &2153403360 !ruby/object:Gem::Requirement
60
+ requirement: &2164954780 !ruby/object:Gem::Requirement
72
61
  none: false
73
62
  requirements:
74
63
  - - ! '>='
@@ -76,10 +65,10 @@ dependencies:
76
65
  version: '0'
77
66
  type: :development
78
67
  prerelease: false
79
- version_requirements: *2153403360
68
+ version_requirements: *2164954780
80
69
  - !ruby/object:Gem::Dependency
81
70
  name: rake
82
- requirement: &2153402880 !ruby/object:Gem::Requirement
71
+ requirement: &2164953080 !ruby/object:Gem::Requirement
83
72
  none: false
84
73
  requirements:
85
74
  - - ! '>='
@@ -87,7 +76,7 @@ dependencies:
87
76
  version: '0'
88
77
  type: :development
89
78
  prerelease: false
90
- version_requirements: *2153402880
79
+ version_requirements: *2164953080
91
80
  description: A microframework for mail-centric applications
92
81
  email:
93
82
  - gregory.t.brown@gmail.com
@@ -121,12 +110,20 @@ files:
121
110
  - examples/views/non-subscriber-error.erb
122
111
  - examples/views/subscribe-error.erb
123
112
  - examples/views/subscribe-success.erb
113
+ - examples/views/test/_echo_body.erb
114
+ - examples/views/test/_echo_date.erb
115
+ - examples/views/test/_echo_list.erb
116
+ - examples/views/test/_echo_sender.erb
117
+ - examples/views/test/echo.erb
118
+ - examples/views/test/echo_with_partials.erb
119
+ - examples/views/test/moneyball.erb
124
120
  - examples/views/unsubscribe-error.erb
125
121
  - examples/views/unsubscribe-success.erb
126
122
  - test/helper.rb
127
123
  - test/integration/acid_tests.rb
128
124
  - test/integration/skip_response_test.rb
129
125
  - test/integration/subject_filter_test.rb
126
+ - test/integration/template_test.rb
130
127
  - test/integration/to_filter_test.rb
131
128
  - test/settings.rb
132
129
  - test/suite.rb