tricle 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0a773a86cbdcd4e1c093bd098e1a79d450e7e73
4
- data.tar.gz: 47963dbca244c39651964fd6516c5847d1e79e57
3
+ metadata.gz: 4372146161a539991112213326850b05350166b0
4
+ data.tar.gz: 44e745d968a91ab3e87175efc683c17b987428b7
5
5
  SHA512:
6
- metadata.gz: 5948b2159e96493cb19eeb3f0de03be23f941749a8ceb13ccb9c84169ce999de99ae5fe06a53db30ac3205cf1a090e6db1b5992a743bafd05c75046de8ef97ba
7
- data.tar.gz: 544c67eb18aa0beaad093f4f04dab5ee7a42f2bbef03824e8d8fec9090ec796c4579e1bb8f041d0283fd8264d73486e0c9693518f9c9848cb89d72574ebef85e
6
+ metadata.gz: 1e24e644085b382989dd3046a11fb8e5e3b835b08ee49513787ef4c40606ffb99772497db28ee8a3347ae97f5a71740db4bd372807f9a2f691fca4be679f79b6
7
+ data.tar.gz: 48bd0e13000ea8c0d8bb67c33f4bc32c56aa2bb340f362b5ffaff2ecba4667b2e640fda7157e73d72c85a46e72849fe5c5113d482eb68cafcdcc4affd43dbaca
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Tricle [![Build Status](https://travis-ci.org/afeld/tricle.png?branch=master)](https://travis-ci.org/afeld/tricle) [![Code Climate](https://codeclimate.com/github/afeld/tricle.png)](https://codeclimate.com/github/afeld/tricle)
1
+ # Tricle [![Build Status]](https://travis-ci.org/afeld/tricle) [![Code Climate]](https://codeclimate.com/github/afeld/tricle) [![Gem Version]](http://badge.fury.io/rb/tricle)
2
2
 
3
3
  Automated metrics reporting via email. It's datastore-agnostic, so you can query SQL, MongoDB, external APIs, etc. to generate the stats you need. See [here](https://github.com/afeld/tricle-afeld) for an example implementation ([live demo](http://tricle.afeld.me/weekly_metrics)). Uses [sparkle](https://github.com/afeld/sparkle) for generating sparklines.
4
4
 
@@ -141,6 +141,8 @@ class MyMailer < Tricle::Mailer
141
141
  # ...
142
142
  )
143
143
 
144
+ self.period = :day # options are :day, :week (default), and :month
145
+
144
146
  metric MyMetric1
145
147
  metric MyMetric2
146
148
  # ...
@@ -247,7 +249,13 @@ end
247
249
  To send all Tricle emails, run
248
250
 
249
251
  ```bash
250
- rake tricle:emails:send
252
+ rake tricle:emails:send # sends all emails
253
+ ```
254
+
255
+ or
256
+
257
+ ```bash
258
+ rake tricle:emails:daily # sends emails with period = :day
251
259
  ```
252
260
 
253
261
  To set a speficic time zone, use the `TZ` environment variable (see the list [here](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)).
@@ -274,3 +282,7 @@ TZ=UTC rake tricle:emails:send
274
282
  * Heroku Scheduler only supports a maximum of daily tasks, hence needing to use a special task.
275
283
 
276
284
  You can trigger the email(s) manually for testing with `heroku run rake tricle:emails:send`.
285
+
286
+ [Build Status]: http://img.shields.io/travis/afeld/tricle.svg?style=flat
287
+ [Gem Version]: http://img.shields.io/gem/v/tricle.svg?style=flat
288
+ [Code Climate]: http://img.shields.io/codeclimate/github/afeld/tricle.svg?style=flat
data/Rakefile CHANGED
@@ -7,6 +7,8 @@ reset_time
7
7
 
8
8
  # used for the preview
9
9
  require_relative 'lib/tricle'
10
+ require_relative 'spec/app/daily_test_mailer.rb'
11
+ require_relative 'spec/app/monthly_test_mailer.rb'
10
12
  require_relative 'spec/app/group_test_mailer.rb'
11
13
  require_relative 'spec/app/list_test_mailer.rb'
12
14
  require_relative 'spec/app/test_mailer.rb'
@@ -4,39 +4,33 @@ module Tricle
4
4
  module Aggregation
5
5
  extend ActiveSupport::Concern
6
6
 
7
- def days_ago(n)
8
- start_at = self.now.beginning_of_day.ago(n.days)
9
- end_at = start_at + 1.day
10
- self.size_for_range(start_at, end_at)
11
- end
12
-
13
- def yesterday
14
- self.days_ago(1)
15
- end
7
+ def periods_ago(period, n)
8
+ case period
9
+ when :day
10
+ start_at = self.now.beginning_of_day.ago(n.days)
11
+ end_at = start_at + 1.day
12
+ when :week
13
+ start_at = self.now.beginning_of_week.ago(n.weeks)
14
+ end_at = start_at + 7.days
15
+ when :month
16
+ start_at = self.now.beginning_of_month.advance(months: -n)
17
+ end_at = start_at.advance(months: 1)
18
+ end
16
19
 
17
- def weeks_ago(n)
18
- start_at = self.now.beginning_of_week.weeks_ago(n)
19
- end_at = start_at + 7.days
20
20
  self.size_for_range(start_at, end_at)
21
21
  end
22
22
 
23
- def last_week
24
- self.weeks_ago(1)
23
+ def range_values(period, num_durations)
24
+ range = num_durations.downto(1)
25
+ range.map do |n|
26
+ self.periods_ago(period, n)
27
+ end
25
28
  end
26
29
 
27
- def weekly_values(past_num_weeks)
28
- weeks_range = past_num_weeks.downto(1)
29
- weeks_range.map{|n| self.weeks_ago(n) }
30
- end
31
-
32
- def weeks_average(past_num_weeks)
33
- values = self.weekly_values(past_num_weeks)
30
+ def range_average(period, past_num_durations)
31
+ values = self.range_values(period, past_num_durations)
34
32
  total = values.reduce(0, :+)
35
- total.to_f / past_num_weeks
36
- end
37
-
38
- def week_average_this_quarter
39
- self.weeks_average(13)
33
+ total.to_f / past_num_durations
40
34
  end
41
35
  end
42
36
  end
@@ -5,8 +5,48 @@ module Tricle
5
5
  module EmailHelper
6
6
  include ActiveSupport::Inflector
7
7
 
8
- def weeks_ago(n)
9
- Date.today.beginning_of_week.ago(n.weeks)
8
+ def num_durations
9
+ case period
10
+ when :day
11
+ 7 # week
12
+ when :week
13
+ 13 # quarter
14
+ when :month
15
+ 12 # year
16
+ end
17
+ end
18
+
19
+ def periods_ago(n)
20
+ case period
21
+ when :day
22
+ Date.today.beginning_of_day.ago(n.days)
23
+ when :week
24
+ Date.today.beginning_of_week.ago(n.weeks)
25
+ when :month
26
+ Date.today.beginning_of_month.advance(months: -n) # for old ActiveSupport
27
+ end
28
+ end
29
+
30
+ def end_of_period(beginning)
31
+ case period
32
+ when :day
33
+ beginning.end_of_day
34
+ when :week
35
+ beginning.end_of_week
36
+ when :month
37
+ beginning.end_of_month
38
+ end
39
+ end
40
+
41
+ def add_periods(time, n)
42
+ case period
43
+ when :day
44
+ time.advance(days: n)
45
+ when :week
46
+ time.advance(weeks: n)
47
+ when :month
48
+ time.advance(months: n)
49
+ end
10
50
  end
11
51
 
12
52
  def format_date(date)
@@ -61,7 +101,11 @@ module Tricle
61
101
  end
62
102
 
63
103
  def dates_range_str(start_at, end_at)
64
- "#{ self.format_date(start_at) } - #{ self.format_date(end_at) }"
104
+ if end_at
105
+ "#{ self.format_date(start_at) } - #{ self.format_date(end_at) }"
106
+ else
107
+ self.format_date(start_at)
108
+ end
65
109
  end
66
110
 
67
111
  def dates_cell(start_at, end_at)
@@ -69,30 +113,100 @@ module Tricle
69
113
  %[<div class="date-range">(#{range})</div>].html_safe
70
114
  end
71
115
 
116
+ def single_day_dates_cell(start_at)
117
+ dates_cell(start_at, nil)
118
+ end
119
+
72
120
  def single_week_dates_cell(start_at)
73
121
  dates_cell(start_at, start_at.end_of_week)
74
122
  end
75
123
 
76
- def last_week_dates_cell
77
- single_week_dates_cell(weeks_ago(1))
124
+ def single_month_dates_cell(start_at)
125
+ dates_cell(start_at, start_at.end_of_month)
126
+ end
127
+
128
+ def period
129
+ self.mailer.period
130
+ end
131
+
132
+ def old_dates_cell
133
+ dates_cell periods_ago(num_durations), end_of_period(periods_ago(1))
134
+ end
135
+
136
+ def previous_dates_cell
137
+ dates_cell(
138
+ periods_ago(2),
139
+ if period == :day then nil else end_of_period(periods_ago(2)) end
140
+ )
141
+ end
142
+
143
+ def current_dates_cell
144
+ dates_cell(
145
+ periods_ago(1),
146
+ if period == :day then nil else end_of_period(periods_ago(1)) end
147
+ )
148
+ end
149
+
150
+ def old_dates_cell_header
151
+ case period
152
+ when :day
153
+ 'Weekly average'
154
+ when :week
155
+ 'Quarterly average'
156
+ when :month
157
+ 'Yearly average'
158
+ end
159
+ end
160
+
161
+ def previous_dates_cell_header
162
+ case period
163
+ when :day
164
+ '2 days ago'
165
+ when :week
166
+ 'Previous week'
167
+ when :month
168
+ 'Previous month'
169
+ end
170
+ end
171
+
172
+ def current_dates_cell_header
173
+ case period
174
+ when :day
175
+ 'Yesterday'
176
+ when :week
177
+ 'Last week'
178
+ when :month
179
+ 'Last month'
180
+ end
181
+ end
182
+
183
+ def old_data_cell(metric)
184
+ percent_change_cell metric.periods_ago(period, 1),
185
+ metric.range_average(period, num_durations),
186
+ metric.better,
187
+ metric.unit
78
188
  end
79
189
 
80
- def previous_week_dates_cell
81
- single_week_dates_cell(weeks_ago(2))
190
+ def previous_data_cell(metric)
191
+ percent_change_cell metric.periods_ago(period, 1),
192
+ metric.periods_ago(period, 2),
193
+ metric.better,
194
+ metric.unit
82
195
  end
83
196
 
84
- def quarter_dates_cell
85
- dates_cell(weeks_ago(13), weeks_ago(1).end_of_week)
197
+ def current_number(metric)
198
+ format_number metric.periods_ago(period, 1),
199
+ metric.unit
86
200
  end
87
201
 
88
202
  def list_markup(list)
89
- start_at = self.weeks_ago(1).to_time
90
- end_at = start_at + 7.days
203
+ start_at = self.periods_ago(1).to_time
204
+ end_at = add_periods(start_at, 1)
91
205
  list.items_markup(start_at, end_at).html_safe
92
206
  end
93
207
 
94
208
  def sparkline(metric)
95
- values = metric.weekly_values(13)
209
+ values = metric.range_values(period, num_durations)
96
210
  attachment_url = "https://sparklines.herokuapp.com/api/v1.png?values=#{values.join(',')}"
97
211
  image_tag(attachment_url, alt: 'sparkline').html_safe
98
212
  end
@@ -6,18 +6,18 @@ require_relative 'email_helper'
6
6
  require_relative 'presenters/report'
7
7
  require_relative 'time'
8
8
 
9
-
10
9
  module Tricle
11
10
  class Mailer < ActionMailer::Base
12
11
  include ActiveSupport::DescendantsTracker
13
12
 
14
13
  class_attribute :report
14
+ class_attribute :period
15
+ self.period = :week # or :day, :month
15
16
  helper Tricle::EmailHelper
16
17
  self.view_paths = File.dirname(__FILE__)
17
18
 
18
19
  CSS = File.read(File.join(File.dirname(__FILE__), 'templates', 'email.css')).freeze
19
20
 
20
-
21
21
  def subject
22
22
  "Your #{self.class.name.titleize}"
23
23
  end
@@ -62,8 +62,34 @@ module Tricle
62
62
  self.report.add_list(klass, opts, &block)
63
63
  end
64
64
 
65
- def send_all
66
- mailers = Tricle::Mailer.descendants
65
+ def send_today?
66
+ time = Tricle::Time.new
67
+
68
+ case self.period
69
+ when :day
70
+ true
71
+ when :week
72
+ time.beginning_of_week?
73
+ when :month
74
+ time.beginning_of_month?
75
+ end
76
+ end
77
+
78
+ def send_at_period
79
+ send_mailers(Tricle::Mailer.descendants.select(&:send_today?))
80
+ end
81
+
82
+ def send_all(with_period = nil)
83
+ klasses = Tricle::Mailer.descendants.select do |klass|
84
+ !with_period || (klass.period == with_period)
85
+ end
86
+
87
+ send_mailers(klasses)
88
+ end
89
+
90
+ private
91
+
92
+ def send_mailers(mailers)
67
93
  puts "Sending #{mailers.size} emails..."
68
94
  mailers.each do |klass|
69
95
  puts "Sending #{klass.name}..."
@@ -71,15 +97,6 @@ module Tricle
71
97
  end
72
98
  puts "Done."
73
99
  end
74
-
75
- def send_all_if_beginning_of_week
76
- time = Tricle::Time.new
77
- if time.beginning_of_week?
78
- self.send_all
79
- else
80
- puts "Skipping send, because it's not the beginning of the week."
81
- end
82
- end
83
100
  end
84
101
  end
85
102
  end
@@ -16,10 +16,24 @@ namespace :tricle do
16
16
  Tricle::Mailer.send_all
17
17
  end
18
18
 
19
+ task :daily do
20
+ Tricle::Mailer.send(:day)
21
+ end
22
+
23
+ task :weekly do
24
+ Tricle::Mailer.send(:week)
25
+ end
26
+
27
+ task :monthly do
28
+ Tricle::Mailer.send(:month)
29
+ end
30
+
19
31
  # needed for Heroku Scheduler, whose most infrequent option is daily
20
- desc "Send all emails, but only if it's the current day is the \"beginning of the week\". See http://api.rubyonrails.org/classes/Date.html#method-i-beginning_of_week-3D."
21
- task :send_after_beginning_of_week do
22
- Tricle::Mailer.send_all_if_beginning_of_week
32
+ task :send_at_period do
33
+ Tricle::Mailer.send_at_period
23
34
  end
35
+
36
+ # Backwards-compatibility
37
+ task send_after_beginning_of_week: [:send_at_period]
24
38
  end
25
39
  end
@@ -15,25 +15,25 @@
15
15
  <tr>
16
16
  <th><!--Title--></th>
17
17
  <th>
18
- <div>Quarterly average</div>
19
- <%= quarter_dates_cell %>
18
+ <div><%= old_dates_cell_header %></div>
19
+ <%= old_dates_cell %>
20
20
  </th>
21
21
  <th>
22
- <div>Previous week</div>
23
- <%= previous_week_dates_cell %>
22
+ <div><%= previous_dates_cell_header %></div>
23
+ <%= previous_dates_cell %>
24
24
  </th>
25
25
  <th>
26
- <div>Last week</div>
27
- <%= last_week_dates_cell %>
26
+ <div><%= current_dates_cell_header %></div>
27
+ <%= current_dates_cell %>
28
28
  </th>
29
29
  </tr>
30
30
  <% section.metrics.each do |metric| %>
31
31
  <tr>
32
32
  <th class="metric-title" rowspan="2"><%= metric.title %></th>
33
- <%= percent_change_cell(metric.last_week, metric.week_average_this_quarter, metric.better, metric.unit) %>
34
- <%= percent_change_cell(metric.last_week, metric.weeks_ago(2), metric.better, metric.unit) %>
33
+ <%= old_data_cell(metric) %>
34
+ <%= previous_data_cell(metric) %>
35
35
  <td>
36
- <div><%= format_number(metric.last_week, metric.unit) %></div>
36
+ <div><%= current_number(metric) %></div>
37
37
  <% if metric.total? %>
38
38
  <div><%= format_number(metric.total) %> (total)</div>
39
39
  <% end %>
@@ -10,10 +10,18 @@ module Tricle
10
10
  self.time.strftime('%A').downcase.to_sym
11
11
  end
12
12
 
13
+ def day_of_month
14
+ self.time.strftime('%-d').to_i
15
+ end
16
+
13
17
  def beginning_of_week?
14
18
  self.day_of_week == self.class.beginning_of_week
15
19
  end
16
20
 
21
+ def beginning_of_month?
22
+ self.day_of_month == 1
23
+ end
24
+
17
25
  ## delegate methods ##
18
26
 
19
27
  def beginning_of_day
@@ -24,6 +32,10 @@ module Tricle
24
32
  self.time.beginning_of_week
25
33
  end
26
34
 
35
+ def beginning_of_month
36
+ self.time.beginning_of_month
37
+ end
38
+
27
39
  ######################
28
40
 
29
41
  class << self
@@ -1,3 +1,3 @@
1
1
  module Tricle
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -0,0 +1,13 @@
1
+ require_relative '../../lib/tricle/mailer'
2
+ require_relative 'daily_test_metric'
3
+
4
+ class DailyTestMailer < Tricle::Mailer
5
+ default(
6
+ to: ['recipient1@test.com', 'recipient2@test.com'],
7
+ from: 'sender@test.com'
8
+ )
9
+
10
+ self.period = :day
11
+
12
+ metric DailyTestMetric
13
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'test_metric_with_no_total'
2
+
3
+ class DailyTestMetric < TestMetricWithNoTotal
4
+ def fixture_filename
5
+ 'days.csv'
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../../lib/tricle/mailer'
2
+ require_relative 'monthly_test_metric'
3
+
4
+ class MonthlyTestMailer < Tricle::Mailer
5
+ default(
6
+ to: ['recipient1@test.com', 'recipient2@test.com'],
7
+ from: 'sender@test.com'
8
+ )
9
+
10
+ self.period = :month
11
+
12
+ metric MonthlyTestMetric
13
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'test_metric_with_no_total'
2
+
3
+ class MonthlyTestMetric < TestMetricWithNoTotal
4
+ def fixture_filename
5
+ 'months.csv'
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../../lib/tricle/metric'
2
+
3
+ class RandomTestMetric < Tricle::Metric
4
+ def size_for_range(start_at, end_at)
5
+ @sizes ||= {}
6
+ @sizes["#{start_at}#{end_at}"] ||= rand(0..10)
7
+ end
8
+ end
@@ -10,8 +10,12 @@ class TestMetricWithNoTotal < Tricle::Metric
10
10
  self.load_data
11
11
  end
12
12
 
13
+ def fixture_filename
14
+ 'weeks.csv'
15
+ end
16
+
13
17
  def load_data
14
- filename = File.join(File.dirname(__FILE__), '..', 'fixtures', 'weeks.csv')
18
+ filename = File.join(File.dirname(__FILE__), '..', 'fixtures', fixture_filename)
15
19
  data = CSV.read(filename)
16
20
 
17
21
  self.data_by_start_on = Tricle::RangeData.new
@@ -0,0 +1,7 @@
1
+ 2013-07-25,whatever,12
2
+ 2013-07-26,whatever,14
3
+ 2013-07-27,whatever,13
4
+ 2013-07-28,whatever,15.6
5
+ 2013-07-29,whatever,14
6
+ 2013-07-30,whatever,20
7
+ 2013-07-31,whatever,11
@@ -0,0 +1,12 @@
1
+ 2012-08-01,whatever,149
2
+ 2012-09-01,whatever,112
3
+ 2012-10-01,whatever,92
4
+ 2012-11-01,whatever,1220
5
+ 2012-12-01,whatever,12
6
+ 2013-01-01,whatever,124
7
+ 2013-02-01,whatever,139
8
+ 2013-03-01,whatever,123
9
+ 2013-04-01,whatever,152.6
10
+ 2013-05-01,whatever,143
11
+ 2013-06-01,whatever,200
12
+ 2013-07-01,whatever,429
@@ -4,45 +4,37 @@ require_relative '../../lib/tricle/aggregation'
4
4
  describe Tricle::Aggregation do
5
5
  let(:metric) { TestMetric.new }
6
6
 
7
- describe '#days_ago' do
8
- it "should start and end at midnight" do
9
- expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 29), Time.new(2013, 7, 30))
10
- metric.days_ago(3)
7
+ describe '#periods_ago' do
8
+ context 'day' do
9
+ it "should start and end at midnight" do
10
+ expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 29), Time.new(2013, 7, 30))
11
+ metric.periods_ago(:day, 3)
12
+ end
11
13
  end
12
- end
13
-
14
- describe '#yesterday' do
15
- it "should start and end at midnight" do
16
- expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 31), Time.new(2013, 8, 1))
17
- metric.yesterday
18
- end
19
- end
20
-
21
- describe '#weeks_ago' do
22
- it "should start and end on Monday" do
23
- expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 8), Time.new(2013, 7, 15))
24
- metric.weeks_ago(3)
25
- end
26
- end
27
14
 
28
- describe '#last_week' do
29
- it "should start and end on Monday" do
30
- expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 22), Time.new(2013, 7, 29))
31
- metric.last_week
15
+ context 'week' do
16
+ it "should start and end on Monday" do
17
+ expect(metric).to receive(:size_for_range).with(Time.new(2013, 7, 8), Time.new(2013, 7, 15))
18
+ metric.periods_ago(:week, 3)
19
+ end
32
20
  end
33
21
  end
34
22
 
35
- describe '#weekly_values' do
36
- it "should return the values by week ascending" do
37
- expect(metric).to receive(:weeks_ago) {|n| n }.exactly(5).times
38
- expect(metric.weekly_values(5)).to eq([5,4,3,2,1])
23
+ describe '#range_values' do
24
+ context 'week' do
25
+ it "should return the values by week ascending" do
26
+ expect(metric).to receive(:periods_ago) {|period, n| n }.exactly(5).times
27
+ expect(metric.range_values(:week, 5)).to eq([5,4,3,2,1])
28
+ end
39
29
  end
40
30
  end
41
31
 
42
- describe '#week_average_this_quarter' do
43
- it "should average the values provided by #size_for_range" do
44
- expect(metric).to receive(:size_for_range).exactly(13).times.and_return(1)
45
- expect(metric.week_average_this_quarter).to eq(1)
32
+ describe '#range_average' do
33
+ context 'week' do
34
+ it "should average the values provided by #size_for_range" do
35
+ expect(metric).to receive(:size_for_range).exactly(13).times.and_return(1)
36
+ expect(metric.range_average(:week, 13)).to eq(1)
37
+ end
46
38
  end
47
39
  end
48
40
  end
@@ -5,6 +5,8 @@ require_relative '../app/list_test_mailer'
5
5
  require_relative '../app/list_test_mailer_with_options'
6
6
  require_relative '../app/no_total_test_mailer'
7
7
  require_relative '../app/test_mailer'
8
+ require_relative '../app/daily_test_mailer'
9
+ require_relative '../app/monthly_test_mailer'
8
10
 
9
11
  describe Tricle::Mailer do
10
12
  def deliver(klass)
@@ -45,6 +47,50 @@ describe Tricle::Mailer do
45
47
  end
46
48
  end
47
49
 
50
+ describe 'daily email' do
51
+ before do
52
+ deliver(DailyTestMailer)
53
+ end
54
+
55
+ it 'includes the correct cell headers' do
56
+ expect(markup).to include('2 days ago')
57
+ expect(markup).to include('Yesterday')
58
+ end
59
+
60
+ it 'includes the correct data' do
61
+ expect(markup).to include('14.1')
62
+ expect(markup).to include('20.0')
63
+ expect(markup).to include('11.0')
64
+ end
65
+
66
+ it 'includes the correct averages' do
67
+ expect(markup).to include('-22.2')
68
+ expect(markup).to include('-45.0')
69
+ end
70
+ end
71
+
72
+ describe 'monthly email' do
73
+ before do
74
+ deliver(MonthlyTestMailer)
75
+ end
76
+
77
+ it 'includes the correct cell headers' do
78
+ expect(markup).to include('Previous month')
79
+ expect(markup).to include('Last month')
80
+ end
81
+
82
+ it 'includes the correct data' do
83
+ expect(markup).to include('241')
84
+ expect(markup).to include('200')
85
+ expect(markup).to include('429')
86
+ end
87
+
88
+ it 'includes the correct averages' do
89
+ expect(markup).to include('77.8')
90
+ expect(markup).to include('114.0')
91
+ end
92
+ end
93
+
48
94
  it "should exclude the total if not defined" do
49
95
  deliver(NoTotalTestMailer)
50
96
  expect(markup).to_not include('total')
@@ -74,23 +120,31 @@ describe Tricle::Mailer do
74
120
  end
75
121
  end
76
122
 
77
- describe '.send_all' do
78
- it "should .deliver all defined mailers" do
79
- Tricle::Mailer.send_all
80
- expect(ActionMailer::Base.deliveries.length).to eq(5)
123
+ describe '.send_at_period' do
124
+ it "should .deliver only mailers for the correct period" do
125
+ allow_any_instance_of(Tricle::Time).to receive(:beginning_of_week?).
126
+ and_return(false)
127
+
128
+ allow_any_instance_of(Tricle::Time).to receive(:beginning_of_month?).
129
+ and_return(false)
130
+
131
+ expect {
132
+ Tricle::Mailer.send_at_period
133
+ }.to change { ActionMailer::Base.deliveries.length }.by(1)
81
134
  end
82
135
  end
83
136
 
84
- describe '.send_all_if_beginning_of_week' do
85
- it "shouldn't do anything if not the beginning of the week" do
86
- expect(Tricle::Mailer).to_not receive(:send_all)
87
- Tricle::Mailer.send_all_if_beginning_of_week
137
+ describe '.send_all' do
138
+ it 'sends all mailers' do
139
+ expect {
140
+ Tricle::Mailer.send_all
141
+ }.to change { ActionMailer::Base.deliveries.length }.by(7)
88
142
  end
89
143
 
90
- it "should send if it's the beginning of the week" do
91
- Timecop.freeze(Time.now - 3.days) # Monday
92
- expect(Tricle::Mailer).to receive(:send_all)
93
- Tricle::Mailer.send_all_if_beginning_of_week
144
+ it 'sends a filtered segment of mailers' do
145
+ expect {
146
+ Tricle::Mailer.send_all(:week)
147
+ }.to change { ActionMailer::Base.deliveries.length }.by(5)
94
148
  end
95
149
  end
96
150
  end
@@ -5,15 +5,15 @@ require_relative '../app/test_metric'
5
5
  describe TestMetric do
6
6
  let(:metric) { TestMetric.new }
7
7
 
8
- describe '#weeks_ago' do
8
+ describe '#periods_ago' do
9
9
  it "should start and end on Monday" do
10
- expect(metric.weeks_ago(3)).to eq(51)
10
+ expect(metric.periods_ago(:week, 3)).to eq(51)
11
11
  end
12
12
  end
13
13
 
14
14
  describe '#last_week' do
15
15
  it "should start and end on Monday" do
16
- expect(metric.last_week).to eq(62)
16
+ expect(metric.range_values(:week, 1)).to eq([62])
17
17
  end
18
18
  end
19
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tricle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aidan Feldman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-07 00:00:00.000000000 Z
11
+ date: 2014-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -135,10 +135,15 @@ files:
135
135
  - lib/tricle/version.rb
136
136
  - screenshot.png
137
137
  - script/release
138
+ - spec/app/daily_test_mailer.rb
139
+ - spec/app/daily_test_metric.rb
138
140
  - spec/app/group_test_mailer.rb
139
141
  - spec/app/list_test_mailer.rb
140
142
  - spec/app/list_test_mailer_with_options.rb
143
+ - spec/app/monthly_test_mailer.rb
144
+ - spec/app/monthly_test_metric.rb
141
145
  - spec/app/no_total_test_mailer.rb
146
+ - spec/app/random_test_metric.rb
142
147
  - spec/app/test_active_record_metric.rb
143
148
  - spec/app/test_mailer.rb
144
149
  - spec/app/test_metric.rb
@@ -147,6 +152,8 @@ files:
147
152
  - spec/app/uber_test_mailer.rb
148
153
  - spec/config/timecop.rb
149
154
  - spec/fixture_generator
155
+ - spec/fixtures/days.csv
156
+ - spec/fixtures/months.csv
150
157
  - spec/fixtures/weeks.csv
151
158
  - spec/presenters/group_spec.rb
152
159
  - spec/presenters/report_spec.rb
@@ -188,10 +195,15 @@ summary: A datastore-agnostic mailer where you can define custom metrics, where
188
195
  can query SQL, MongoDB, external APIs, etc. to generate the stats you need. It
189
196
  can be used within a larger project (e.g. Rails), or standalone.
190
197
  test_files:
198
+ - spec/app/daily_test_mailer.rb
199
+ - spec/app/daily_test_metric.rb
191
200
  - spec/app/group_test_mailer.rb
192
201
  - spec/app/list_test_mailer.rb
193
202
  - spec/app/list_test_mailer_with_options.rb
203
+ - spec/app/monthly_test_mailer.rb
204
+ - spec/app/monthly_test_metric.rb
194
205
  - spec/app/no_total_test_mailer.rb
206
+ - spec/app/random_test_metric.rb
195
207
  - spec/app/test_active_record_metric.rb
196
208
  - spec/app/test_mailer.rb
197
209
  - spec/app/test_metric.rb
@@ -200,6 +212,8 @@ test_files:
200
212
  - spec/app/uber_test_mailer.rb
201
213
  - spec/config/timecop.rb
202
214
  - spec/fixture_generator
215
+ - spec/fixtures/days.csv
216
+ - spec/fixtures/months.csv
203
217
  - spec/fixtures/weeks.csv
204
218
  - spec/presenters/group_spec.rb
205
219
  - spec/presenters/report_spec.rb