pendaxes 0.0.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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +148 -0
- data/Rakefile +5 -0
- data/bin/pendaxes +11 -0
- data/fixtures/repo.tar.gz +0 -0
- data/lib/pendaxes/command_line.rb +56 -0
- data/lib/pendaxes/config.rb +10 -0
- data/lib/pendaxes/defaults.rb +12 -0
- data/lib/pendaxes/detector.rb +23 -0
- data/lib/pendaxes/detectors/rspec.rb +78 -0
- data/lib/pendaxes/finder.rb +34 -0
- data/lib/pendaxes/notificator.rb +32 -0
- data/lib/pendaxes/notificators/mail.rb +72 -0
- data/lib/pendaxes/notificators/terminal.rb +19 -0
- data/lib/pendaxes/pending_manager.rb +30 -0
- data/lib/pendaxes/reporter.rb +27 -0
- data/lib/pendaxes/reporters/haml.rb +49 -0
- data/lib/pendaxes/reporters/template.haml +45 -0
- data/lib/pendaxes/reporters/text.rb +13 -0
- data/lib/pendaxes/version.rb +3 -0
- data/lib/pendaxes/workspace.rb +39 -0
- data/lib/pendaxes.rb +10 -0
- data/pendaxes.gemspec +32 -0
- data/spec/defaults_spec.rb +41 -0
- data/spec/detector_spec.rb +12 -0
- data/spec/detectors/rspec_spec.rb +75 -0
- data/spec/finder_spec.rb +62 -0
- data/spec/notificator_spec.rb +41 -0
- data/spec/notificators/mail_spec.rb +184 -0
- data/spec/notificators/terminal_spec.rb +67 -0
- data/spec/pendaxes_spec.rb +7 -0
- data/spec/pending_manager_spec.rb +97 -0
- data/spec/reporter_spec.rb +23 -0
- data/spec/reporters/text_spec.rb +34 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/workspace_spec.rb +115 -0
- metadata +203 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{charset: 'UTF-8'}
|
5
|
+
%title Pendaxes report - #{pendings.size} pendings are waiting to be fixed
|
6
|
+
%body
|
7
|
+
.container{style: 'font-family: sans-serif; color: #3C3C3C;'}
|
8
|
+
%h1 #{pendings.size} pendings are waiting to be fixed
|
9
|
+
- if config.report_url
|
10
|
+
%p
|
11
|
+
%strong Full Report:
|
12
|
+
%a{href: config.report_url}&= config.report_url
|
13
|
+
= config.message || ""
|
14
|
+
%h2 Pendings
|
15
|
+
- pendings.sort_by {|x| (Time.now - x[:commit][:at]) * (config.older_first ? -1 : 1) }.each do |pending|
|
16
|
+
%section
|
17
|
+
- if config.gravatar
|
18
|
+
.avatar{style: "float: left; width: 60px; margin-right: 12px;"}
|
19
|
+
%img{src: "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(pending[:commit][:email])}.png?s=120", width: 60, height: 60}
|
20
|
+
.right{style: "float: left; width: 80%;"}
|
21
|
+
%header{style: "width: 100%; background-color: #e9e7e6; border-radius: 5px; margin-top: 0px; margin-bottom: 10px; padding-top: 5px; padding-bottom: 5px; padding-left: 10px;"}
|
22
|
+
%h3{style: "font-size: 1.8em; margin-top: 0px; margin-bottom: 15px;"}&= pending[:example][:message]
|
23
|
+
.at
|
24
|
+
by #{pending[:commit][:name]},
|
25
|
+
%span.relative{style: pending[:allowed] ? '' : 'font-weight: bold;'}&= relative_time(pending[:commit][:at])
|
26
|
+
= " - "
|
27
|
+
%time&= pending[:commit][:at]
|
28
|
+
.parent
|
29
|
+
%strong In:
|
30
|
+
%span.monospace{style: "font-family: 'Inconsolata', 'Monaco', monospace;", style: "font-family: 'Inconsolata', 'Monaco', monospace;"}&= pending[:example][:parent]
|
31
|
+
.file
|
32
|
+
%strong File:
|
33
|
+
- if config.file_url
|
34
|
+
%a.monospace{href: config.file_url.gsub(/%file%/, pending[:example][:file]).gsub(/%line%/, pending[:example][:line].to_s), style: "font-family: 'Inconsolata', 'Monaco', monospace;"}&= "#{pending[:example][:file]}:#{pending[:example][:line]}"
|
35
|
+
- else
|
36
|
+
%span.monospace{style: "font-family: 'Inconsolata', 'Monaco', monospace;"}&= "#{pending[:example][:file]}:#{pending[:example][:line]}"
|
37
|
+
.commit
|
38
|
+
%strong Commit:
|
39
|
+
- if config.commit_url
|
40
|
+
%a.monospace{href: config.commit_url.gsub(/%commit%/, pending[:commit][:sha])}&= pending[:commit][:sha]
|
41
|
+
- else
|
42
|
+
%span.monospace{style: "font-family: 'Inconsolata', 'Monaco', monospace;"}&= pending[:commit][:sha]
|
43
|
+
&= " by #{pending[:commit][:name]}"
|
44
|
+
.clear{style: "clear: both; height: 28px;"}
|
45
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../reporter'
|
2
|
+
|
3
|
+
module Pendaxes
|
4
|
+
class Reporter
|
5
|
+
class Text < Reporter
|
6
|
+
def report
|
7
|
+
pendings.sort_by{|x| x[:commit][:at] - Time.now }.map {|pending|
|
8
|
+
"* #{pending[:example][:file]}:#{pending[:example][:line]} - #{pending[:example][:message]} (@ #{pending[:commit][:sha]} #{pending[:commit][:at]})"
|
9
|
+
}.join("\n")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'defaults'
|
2
|
+
require 'hashr'
|
3
|
+
|
4
|
+
module Pendaxes
|
5
|
+
class Workspace
|
6
|
+
extend Defaults
|
7
|
+
|
8
|
+
def initialize(config={})
|
9
|
+
@config = Hashr.new(self.class.defaults.merge(config))
|
10
|
+
end
|
11
|
+
|
12
|
+
def clone
|
13
|
+
FileUtils.remove_entry_secure(path) if File.exist?(path)
|
14
|
+
git "clone", @config.repository, path
|
15
|
+
end
|
16
|
+
|
17
|
+
def update
|
18
|
+
clone unless File.exist?(path)
|
19
|
+
|
20
|
+
dive do
|
21
|
+
git "fetch", "origin"
|
22
|
+
git "reset", "--hard", @config.branch || "FETCH_HEAD"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def path; @config.path; end
|
27
|
+
|
28
|
+
def dive
|
29
|
+
Dir.chdir(path) do
|
30
|
+
yield
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def git(*args)
|
35
|
+
str = IO.popen([@config.git || "git", *args], 'r', &:read)
|
36
|
+
$?.success? ? str : nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/pendaxes.rb
ADDED
data/pendaxes.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pendaxes/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "pendaxes"
|
8
|
+
gem.version = Pendaxes::VERSION
|
9
|
+
gem.authors = ["Shota Fukumori (sora_h)"]
|
10
|
+
gem.email = ["sorah@cookpad.com"]
|
11
|
+
gem.description = %q{Throw axes to pending makers!}
|
12
|
+
gem.summary = <<-EOS
|
13
|
+
Throw axes to pending makers! Leaving a pending long time is really bad,
|
14
|
+
shouldn't be happened.
|
15
|
+
So, this gem sends notification to committer that added pending after a while from the commit.
|
16
|
+
|
17
|
+
Avoid the trouble due to pending examples :D
|
18
|
+
EOS
|
19
|
+
gem.homepage = ""
|
20
|
+
|
21
|
+
gem.files = `git ls-files`.split($/)
|
22
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
23
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features|fixtures)/})
|
24
|
+
gem.require_paths = ["lib"]
|
25
|
+
|
26
|
+
gem.add_dependency 'hashr'
|
27
|
+
gem.add_dependency 'haml'
|
28
|
+
gem.add_dependency 'mail'
|
29
|
+
gem.add_development_dependency 'rspec'
|
30
|
+
gem.add_development_dependency 'rake'
|
31
|
+
gem.add_development_dependency 'simplecov'
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
require 'pendaxes/defaults'
|
3
|
+
|
4
|
+
describe Pendaxes::Defaults do
|
5
|
+
subject { Class.new { extend Pendaxes::Defaults } }
|
6
|
+
|
7
|
+
describe "#defaults" do
|
8
|
+
context "with no argument" do
|
9
|
+
it "returns current defaults" do
|
10
|
+
subject.defaults.should == {}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with argument" do
|
15
|
+
it "sets defaults" do
|
16
|
+
subject.defaults :a => :b
|
17
|
+
subject.defaults.should == {:a => :b}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with superclass" do
|
22
|
+
let(:superclass) { Class.new { extend Pendaxes::Defaults }.tap{|klass| klass.defaults :a => :b } }
|
23
|
+
subject { Class.new(superclass) { extend Pendaxes::Defaults } }
|
24
|
+
|
25
|
+
context "without argument (first time)" do
|
26
|
+
it "returns superclass' default" do
|
27
|
+
subject.defaults.should == {:a => :b}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with argument" do
|
32
|
+
it "merges into superclass' defaults" do
|
33
|
+
subject.defaults :b => :c
|
34
|
+
subject.defaults.should == {:a => :b, :b => :c}
|
35
|
+
subject.defaults :b => :d
|
36
|
+
subject.defaults.should == {:a => :b, :b => :d}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
require 'pendaxes/detector'
|
3
|
+
|
4
|
+
describe Pendaxes::Detector do
|
5
|
+
it "has included Defaults" do
|
6
|
+
described_class.singleton_class.included_modules.include?(Pendaxes::Defaults).should be_true
|
7
|
+
end
|
8
|
+
|
9
|
+
it "responds to #detect" do
|
10
|
+
described_class.new(Pendaxes::Workspace.new).should be_respond_to(:detect)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'pendaxes/detectors/rspec'
|
3
|
+
require 'pendaxes/workspace'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
describe Pendaxes::Detector::RSpec do
|
7
|
+
it "has Pendaxes::Detector as superclass" do
|
8
|
+
described_class.superclass.should == Pendaxes::Detector
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#detect" do
|
12
|
+
before do
|
13
|
+
Time.stub(now: Time.at(1348214400))
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:repository) { File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'repo')) }
|
17
|
+
let(:workspace) { Pendaxes::Workspace.new(repository: repository, path: repository) }
|
18
|
+
let(:config) { {} }
|
19
|
+
subject { described_class.new(workspace, config) }
|
20
|
+
|
21
|
+
it "detects pendings in all files" do
|
22
|
+
pendings = subject.detect
|
23
|
+
pendings.size.should == 3
|
24
|
+
|
25
|
+
xit = pendings.find {|pend| /xit/ === pend[:example][:message] }
|
26
|
+
it_a = pendings.find {|pend| /pending$/ === pend[:example][:message] && pend[:example][:file] == "spec/a_spec.rb" }
|
27
|
+
it_c = pendings.find {|pend| pend[:example][:file] == "spec/b/c_spec.rb" }
|
28
|
+
# require 'pp'; pp pendings
|
29
|
+
|
30
|
+
xit.should == {
|
31
|
+
example: {file: "spec/a_spec.rb", line: 9,
|
32
|
+
message: 'xit "d" do', parent: 'context "c" do'},
|
33
|
+
commit: {sha: '371955e233bf1ff42d0c7cca3510ec0f8d71ec8d',
|
34
|
+
name: 'Shota Fukumori', email: 'sorah@cookpad.com',
|
35
|
+
at: Time.parse('2012-09-21 16:44:13 +0900')},
|
36
|
+
allowed: true
|
37
|
+
}
|
38
|
+
it_a.should == {
|
39
|
+
example: {file: "spec/a_spec.rb", line: 4,
|
40
|
+
message: 'pending', parent: 'it "a" do'},
|
41
|
+
commit: {sha: '642caa033642700cd9d4c6f026fe73282985ed50',
|
42
|
+
name: 'Shota Fukumori', email: 'sorah@cookpad.com',
|
43
|
+
at: Time.parse('Thu, 7 Apr 2005 22:13:13 +0900')},
|
44
|
+
allowed: false
|
45
|
+
}
|
46
|
+
it_c.should == {
|
47
|
+
example: {file: "spec/b/c_spec.rb", line: 3,
|
48
|
+
message: 'pending', parent: 'it "d" do'},
|
49
|
+
commit: {sha: '49499865388dcbce14be3a8b7eca841538b29496',
|
50
|
+
name: 'Shota Fukumori', email: 'sorah@cookpad.com',
|
51
|
+
at: Time.parse('Fri, 21 Sep 2012 16:43:43 +0900')},
|
52
|
+
allowed: true
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with config.allowed_for" do
|
57
|
+
let(:config) { {allowed_for: 0} }
|
58
|
+
|
59
|
+
it "marks pending as not allowed if committed after than :allowed_for" do
|
60
|
+
subject.detect.all? {|pending| !pending[:allowed] }.should be_true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with :pattern" do
|
65
|
+
let(:config) { {pattern: '*_test.rb'} }
|
66
|
+
|
67
|
+
it "uses that as file pattern for git-grep" do
|
68
|
+
pendings = subject.detect
|
69
|
+
|
70
|
+
pendings.size.should == 1
|
71
|
+
pendings.first[:example][:file].should match(/d_test\.rb$/)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/finder_spec.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
require 'pendaxes/finder'
|
3
|
+
|
4
|
+
describe Pendaxes::Finder do
|
5
|
+
subject { Class.new { extend Pendaxes::Finder } }
|
6
|
+
|
7
|
+
describe ".find" do
|
8
|
+
let(:klass) { Class.new(subject) }
|
9
|
+
|
10
|
+
context "with String" do
|
11
|
+
it 'requires that' do
|
12
|
+
subject.should_receive(:require).with("foo/bar/baz")
|
13
|
+
|
14
|
+
subject.find('foo/bar/baz')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with Symbol" do
|
19
|
+
it 'requires that' do
|
20
|
+
subject.should_receive(:require).with("foo")
|
21
|
+
subject.find(:foo)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "requires file and return included ancestor" do
|
26
|
+
subject.should_receive(:require).with("foo") do
|
27
|
+
klass; true
|
28
|
+
end
|
29
|
+
subject.find(:foo).should == klass
|
30
|
+
end
|
31
|
+
|
32
|
+
context "on second time" do
|
33
|
+
it "requires once" do
|
34
|
+
subject.should_receive(:require).with("foo").once do
|
35
|
+
klass; true
|
36
|
+
end
|
37
|
+
subject.find(:foo).should == klass
|
38
|
+
subject.find(:foo).should == klass
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with not Symbol or String" do
|
43
|
+
it "raises ArgumentError" do
|
44
|
+
expect { subject.find(Object.new) }.to raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".find_in" do
|
50
|
+
subject do
|
51
|
+
Class.new do
|
52
|
+
extend Pendaxes::Finder
|
53
|
+
find_in "hoge"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'makes Finder.find(Symbol) to use as prefix for require' do
|
58
|
+
subject.should_receive(:require).with("hoge/foo")
|
59
|
+
subject.find(:foo)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
require 'pendaxes/notificator'
|
3
|
+
require 'pendaxes/reporter'
|
4
|
+
|
5
|
+
describe Pendaxes::Notificator do
|
6
|
+
it "has included Defaults" do
|
7
|
+
described_class.singleton_class.included_modules.include?(Pendaxes::Defaults).should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has included PendingManager" do
|
11
|
+
described_class.included_modules.include?(Pendaxes::PendingManager).should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "responds to #notify" do
|
15
|
+
described_class.new.should be_respond_to(:notify)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#report_for" do
|
19
|
+
let(:reporter) do
|
20
|
+
Class.new(Pendaxes::Reporter) do
|
21
|
+
def report
|
22
|
+
[@config, @pendings]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:fixture) do
|
28
|
+
[{commit: {:sha => 'a'}, example: {:file => 'a'}, allowed: true}, {commit: {:sha => 'b'}, example: {:file => 'b'}, allowed: false}]
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
Pendaxes::Reporter.announce(:report_for, reporter)
|
33
|
+
end
|
34
|
+
|
35
|
+
subject { described_class.new(reporter: {use: :report_for, foo: :bar}) }
|
36
|
+
|
37
|
+
it "returns report using reporter specified by config" do
|
38
|
+
subject.report_for(fixture).should == [{use: :report_for, foo: :bar, include_allowed: true}, fixture]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'pendaxes/notificators/mail'
|
3
|
+
require 'pendaxes/reporter'
|
4
|
+
require 'mail'
|
5
|
+
|
6
|
+
Mail.defaults do
|
7
|
+
delivery_method :test
|
8
|
+
end
|
9
|
+
|
10
|
+
class TestReporter < Pendaxes::Reporter
|
11
|
+
def report
|
12
|
+
"Test reporting: #{pendings.inspect}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestHtmlReporter < TestReporter
|
17
|
+
def self.html?; true; end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
describe Pendaxes::Notificator::Mail do
|
22
|
+
before(:all) do
|
23
|
+
Pendaxes::Reporter.announce :test_reporter, TestReporter
|
24
|
+
Pendaxes::Reporter.announce :test_html_reporter, TestHtmlReporter
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:pendings) do
|
28
|
+
[{
|
29
|
+
example: {file: "spec/a_spec.rb", line: 9,
|
30
|
+
message: 'xit "d" do', parent: 'context "c" do'},
|
31
|
+
commit: {sha: '371955e233bf1ff42d0c7cca3510ec0f8d71ec8d',
|
32
|
+
name: 'Shota Fukumori', email: 'sorah@cookpad.com',
|
33
|
+
at: Time.parse('2012-09-21 16:44:13 +0900')},
|
34
|
+
allowed: true
|
35
|
+
},
|
36
|
+
{
|
37
|
+
example: {file: "spec/a_spec.rb", line: 4,
|
38
|
+
message: 'pending', parent: 'it "a" do'},
|
39
|
+
commit: {sha: '642caa033642700cd9d4c6f026fe73282985ed50',
|
40
|
+
name: 'Shota Fukumori', email: 'sorah@cookpad.com',
|
41
|
+
at: Time.parse('Thu, 7 Apr 2005 22:13:13 +0900')},
|
42
|
+
allowed: false
|
43
|
+
},
|
44
|
+
{
|
45
|
+
example: {file: "spec/b/c_spec.rb", line: 3,
|
46
|
+
message: 'pending', parent: 'it "d" do'},
|
47
|
+
commit: {sha: '49499865388dcbce14be3a8b7eca841538b29496',
|
48
|
+
name: 'Shohta Fukumori', email: 'sorah+b@cookpad.com',
|
49
|
+
at: Time.parse('Fri, 21 Sep 2012 16:43:43 +0900')},
|
50
|
+
allowed: true
|
51
|
+
}]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has Pendaxes::Notificator as superclass" do
|
55
|
+
described_class.superclass.should == Pendaxes::Notificator
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#notify" do
|
59
|
+
include Mail::Matchers
|
60
|
+
let(:config_root) { {reporter: {use: :test_reporter}, from: "sorah+from@cookpad.com", include_allowed: true} }
|
61
|
+
let(:config) { config_root }
|
62
|
+
let(:deliveries) { Mail::TestMailer.deliveries }
|
63
|
+
subject { described_class.new(config) }
|
64
|
+
before { subject.add(pendings) }
|
65
|
+
after { Mail::TestMailer.deliveries.clear }
|
66
|
+
|
67
|
+
it "sends mails for each committers" do
|
68
|
+
subject.notify
|
69
|
+
|
70
|
+
deliveries.size.should == 2
|
71
|
+
should have_sent_email.from('sorah+from@cookpad.com')
|
72
|
+
should have_sent_email.to('sorah@cookpad.com')
|
73
|
+
should have_sent_email.to('sorah+b@cookpad.com')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "uses report as body of mail" do
|
77
|
+
subject.notify
|
78
|
+
|
79
|
+
%w(sorah@cookpad.com sorah+b@cookpad.com).each do |email|
|
80
|
+
delivery = deliveries.find {|deliver| deliver.to.include? email }
|
81
|
+
delivery.body.should == "Test reporting: #{pendings.select {|pending| pending[:commit][:email] == email}.inspect}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with :delivery_method" do
|
86
|
+
let(:config) { config_root.merge(delivery_method: :test, delivery_options: {foo: :bar}) }
|
87
|
+
|
88
|
+
it "uses that as delivery_method" do
|
89
|
+
method = Mail.new.delivery_method
|
90
|
+
Mail::Message.any_instance.should_receive(:delivery_method).with(:test, foo: :bar).at_least(:once)
|
91
|
+
exception = Exception.new
|
92
|
+
Mail::Message.any_instance.stub(:deliver) { raise exception }
|
93
|
+
|
94
|
+
expect { subject.notify }.to raise_error(exception)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "with :to" do
|
99
|
+
let(:config) { config_root.merge(to: 'sorah+c@cookpad.com') }
|
100
|
+
|
101
|
+
it "sends all mails to that" do
|
102
|
+
subject.notify
|
103
|
+
|
104
|
+
deliveries.size.should == 1
|
105
|
+
should have_sent_email.to('sorah+c@cookpad.com')
|
106
|
+
deliveries.first.body.should == "Test reporting: #{pendings.inspect}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "with :whitelist" do
|
111
|
+
let(:config) { config_root.merge(whitelist: ['sorah@cookpad.com']) }
|
112
|
+
|
113
|
+
it "won't send mail to addresses don't match" do
|
114
|
+
subject.notify
|
115
|
+
|
116
|
+
deliveries.size.should == 1
|
117
|
+
should_not have_sent_email.to('sorah+b@cookpad.com')
|
118
|
+
should have_sent_email.to('sorah@cookpad.com')
|
119
|
+
end
|
120
|
+
|
121
|
+
context "regex" do
|
122
|
+
let(:config) { config_root.merge(whitelist: ['/^sorah@/']) }
|
123
|
+
|
124
|
+
it "parses as Regexp" do
|
125
|
+
subject.notify
|
126
|
+
|
127
|
+
deliveries.size.should == 1
|
128
|
+
should_not have_sent_email.to('sorah+b@cookpad.com')
|
129
|
+
should have_sent_email.to('sorah@cookpad.com')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with :blacklist" do
|
135
|
+
let(:config) { config_root.merge(blacklist: ['sorah+b@cookpad.com']) }
|
136
|
+
|
137
|
+
it "won't send mail to addresses that match" do
|
138
|
+
subject.notify
|
139
|
+
|
140
|
+
deliveries.size.should == 1
|
141
|
+
should_not have_sent_email.to('sorah+b@cookpad.com')
|
142
|
+
should have_sent_email.to('sorah@cookpad.com')
|
143
|
+
end
|
144
|
+
|
145
|
+
context "regex" do
|
146
|
+
let(:config) { config_root.merge(blacklist: ['/^sorah\+/']) }
|
147
|
+
|
148
|
+
it "parses as Regexp" do
|
149
|
+
subject.notify
|
150
|
+
|
151
|
+
deliveries.size.should == 1
|
152
|
+
should_not have_sent_email.to('sorah+b@cookpad.com')
|
153
|
+
should have_sent_email.to('sorah@cookpad.com')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "with :whitelist & :blacklist" do
|
159
|
+
let(:config) { config_root.merge(whitelist: [/@cookpad\.com$/], blacklist: ['sorah+b@cookpad.com']) }
|
160
|
+
|
161
|
+
it "prefers blacklist first" do
|
162
|
+
subject.notify
|
163
|
+
|
164
|
+
deliveries.size.should == 1
|
165
|
+
should_not have_sent_email.to('sorah+b@cookpad.com')
|
166
|
+
should have_sent_email.to('sorah@cookpad.com')
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "when reporter's html is false" do
|
171
|
+
it "sends mail as plain text" do
|
172
|
+
deliveries.all? {|delivery| delivery.content_type == nil }.should be_true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when reporter's html is true" do
|
177
|
+
let(:config) { {reporter: {use: :test_html_reporter} } }
|
178
|
+
|
179
|
+
it "sends mail as text/html" do
|
180
|
+
deliveries.all? {|delivery| delivery.content_type == 'text/html; charset=utf-8' }.should be_true
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'pendaxes/notificators/terminal'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
describe Pendaxes::Notificator::Terminal do
|
6
|
+
it "has Pendaxes::Notificator as superclass" do
|
7
|
+
described_class.superclass.should == Pendaxes::Notificator
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#notify" do
|
11
|
+
let(:io) { StringIO.new }
|
12
|
+
let(:config) { {to: io} }
|
13
|
+
let(:now) { Time.now }
|
14
|
+
let(:fixture) do
|
15
|
+
[
|
16
|
+
{commit: {sha: 'a', name: 'foo', email: 'foo@example.com', at: (now-86400)},
|
17
|
+
example: {file: 'a_spec.rb', line: 10, message: "pending 'because it fails'"}, allowed: true},
|
18
|
+
{commit: {sha: 'b', name: 'foo', email: 'foo@example.com', at: (now-864000)},
|
19
|
+
example: {file: 'a_spec.rb', line: 15, message: "pending 'because it fails.'"}, allowed: false},
|
20
|
+
{commit: {sha: 'c', name: 'bar', email: 'bar@example.com', at: (now-86400)},
|
21
|
+
example: {file: 'a_spec.rb', line: 20, message: "pending 'because it fails..'"}, allowed: true},
|
22
|
+
{commit: {sha: 'd', name: 'bar', email: 'bar@example.com', at: (now-864000)},
|
23
|
+
example: {file: 'a_spec.rb', line: 25, message: "pending 'because it fails...'"}, allowed: false},
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
subject { described_class.new(config) }
|
28
|
+
|
29
|
+
before do
|
30
|
+
subject.add(fixture)
|
31
|
+
subject.notify
|
32
|
+
end
|
33
|
+
|
34
|
+
it "notifies into terminal" do
|
35
|
+
out = io.string
|
36
|
+
out.should == <<-EOF
|
37
|
+
foo <foo@example.com>:
|
38
|
+
|
39
|
+
* a_spec.rb:15 - pending 'because it fails.' (@ b #{now-864000})
|
40
|
+
|
41
|
+
bar <bar@example.com>:
|
42
|
+
|
43
|
+
* a_spec.rb:25 - pending 'because it fails...' (@ d #{now-864000})
|
44
|
+
|
45
|
+
EOF
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with :include_allowed" do
|
49
|
+
let(:config) { {to: io, include_allowed: true} }
|
50
|
+
it "notifies all into terminal" do
|
51
|
+
out = io.string
|
52
|
+
out.should == <<-EOF
|
53
|
+
foo <foo@example.com>:
|
54
|
+
|
55
|
+
* a_spec.rb:15 - pending 'because it fails.' (@ b #{now-864000})
|
56
|
+
* a_spec.rb:10 - pending 'because it fails' (@ a #{now-86400})
|
57
|
+
|
58
|
+
bar <bar@example.com>:
|
59
|
+
|
60
|
+
* a_spec.rb:25 - pending 'because it fails...' (@ d #{now-864000})
|
61
|
+
* a_spec.rb:20 - pending 'because it fails..' (@ c #{now-86400})
|
62
|
+
|
63
|
+
EOF
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|