rspec-approvals 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +21 -16
- data/bin/approvals +10 -0
- data/lib/rspec/approvals.rb +9 -2
- data/lib/rspec/approvals/approval.rb +43 -76
- data/lib/rspec/approvals/cli.rb +30 -0
- data/lib/rspec/approvals/dotfile.rb +40 -0
- data/lib/rspec/approvals/dsl.rb +3 -2
- data/lib/rspec/approvals/empty_approval.rb +12 -0
- data/lib/rspec/approvals/executable.rb +16 -0
- data/lib/rspec/approvals/formatter.rb +58 -0
- data/lib/rspec/approvals/version.rb +1 -1
- data/rspec-approvals.gemspec +2 -1
- data/spec/approval_spec.rb +54 -119
- data/spec/approvals/fairy_dust_and_unicorns.approved.txt +1 -0
- data/spec/approvals/{rspec_approvals_a_complex_object.approved.txt → rspec_approvals_a_complex_object_with_implicit_inspect.approved.txt} +0 -0
- data/spec/approvals/rspec_approvals_an_executable.approved.txt +1 -0
- data/spec/approvals/rspec_approvals_formats_json_nicely.approved.txt +3 -0
- data/spec/approvals_spec.rb +21 -11
- data/spec/dotfile_spec.rb +22 -0
- data/spec/executable_spec.rb +15 -0
- metadata +64 -65
- data/lib/rspec/approvals/formatters/opendiff_formatter.rb +0 -22
- data/spec/spec_helper.rb +0 -2
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -31,7 +31,7 @@ You can change this using the configuration option
|
|
31
31
|
|
32
32
|
The basic format of the approval is modeled after RSpec's `it`:
|
33
33
|
|
34
|
-
|
34
|
+
verify "something" do
|
35
35
|
"this is the received contents"
|
36
36
|
end
|
37
37
|
|
@@ -56,14 +56,18 @@ The contents of the two files are compared, and the approval will fail at this p
|
|
56
56
|
### Formatting
|
57
57
|
|
58
58
|
You can pass options to format output before it gets written to the file.
|
59
|
-
At the moment, only xml and
|
59
|
+
At the moment, only xml, html, and json are supported.
|
60
60
|
|
61
|
-
Simply add a `:format => :xml
|
61
|
+
Simply add a `:format => :xml`, `:format => :html`, or `:format => :json` option to the example:
|
62
62
|
|
63
|
-
|
63
|
+
verify "some html", :format => :html do
|
64
64
|
"<html><head></head><body><h1>ZOMG</h1></body></html>"
|
65
65
|
end
|
66
66
|
|
67
|
+
verify "some json", :format => :json do
|
68
|
+
{"beverage" => "coffee"}.to_json
|
69
|
+
end
|
70
|
+
|
67
71
|
|
68
72
|
### Approving a spec
|
69
73
|
|
@@ -76,22 +80,23 @@ For an example who's full description is `My Spec`:
|
|
76
80
|
|
77
81
|
When you rerun the spec, it should now pass.
|
78
82
|
|
79
|
-
###
|
80
|
-
|
81
|
-
You can specify a custom formatter when you run the specs.
|
83
|
+
### Expensive computations
|
82
84
|
|
83
|
-
|
85
|
+
The Executable class allows you to perform expensive operations only when the command to execute it changes.
|
84
86
|
|
85
|
-
|
86
|
-
-f RSpec::Approvals::Formatters::OpendiffFormatter spec/
|
87
|
+
For example, if you have a SQL query that is very slow, you can create an executable with the actual SQL to be performed.
|
87
88
|
|
88
|
-
The
|
89
|
-
|
90
|
-
specs.
|
91
|
-
|
92
|
-
That's pretty unweildy, so I'm looking at options to add shortcuts for
|
93
|
-
this.
|
89
|
+
The first time the spec runs, it will fail, allowing you to inspect the results.
|
90
|
+
If this output looks right, approve the query. The next time the spec is run, it will compare only the actual SQL.
|
94
91
|
|
92
|
+
If someone changes the query, then the comparison will fail. Both the previously approved command and the received command will be executed so that you can inspect the difference between the results of the two.
|
95
93
|
|
94
|
+
verify "an executable" do
|
95
|
+
sql = subject.expensive_sql # the actual sql as a string
|
96
|
+
RSpec::Approvals::Executable.new(sql) do |command|
|
97
|
+
result = ActiveRecord::Base.connection.execute(command)
|
98
|
+
# do something to display the result
|
99
|
+
end
|
100
|
+
end
|
96
101
|
|
97
102
|
Copyright (c) 2011 Katrina Owen, released under the MIT license
|
data/bin/approvals
ADDED
data/lib/rspec/approvals.rb
CHANGED
@@ -3,13 +3,15 @@ require 'xml'
|
|
3
3
|
require "rspec/approvals/version"
|
4
4
|
require "rspec/approvals/approval"
|
5
5
|
require "rspec/approvals/dsl"
|
6
|
-
require 'rspec/approvals/
|
7
|
-
|
6
|
+
require 'rspec/approvals/dotfile'
|
7
|
+
require 'rspec/approvals/formatter'
|
8
|
+
require 'rspec/approvals/executable'
|
8
9
|
|
9
10
|
module RSpec
|
10
11
|
RSpec.configure do |c|
|
11
12
|
c.extend RSpec::Approvals::DSL
|
12
13
|
c.add_setting :approvals_path, :default => 'spec/approvals'
|
14
|
+
c.before(:suite) { RSpec::Approvals.reset }
|
13
15
|
end
|
14
16
|
|
15
17
|
module Approvals
|
@@ -22,6 +24,11 @@ module RSpec
|
|
22
24
|
def path
|
23
25
|
RSpec.configuration.approvals_path + "/"
|
24
26
|
end
|
27
|
+
|
28
|
+
def reset
|
29
|
+
Dotfile.reset
|
30
|
+
end
|
31
|
+
|
25
32
|
end
|
26
33
|
|
27
34
|
end
|
@@ -1,41 +1,37 @@
|
|
1
1
|
require 'rspec/expectations/errors'
|
2
|
+
require 'rspec/approvals/empty_approval'
|
2
3
|
|
3
4
|
module RSpec
|
4
5
|
module Approvals
|
5
6
|
|
6
7
|
class ReceivedDiffersError < RSpec::Expectations::ExpectationNotMetError; end
|
7
8
|
|
8
|
-
class EmptyApproval
|
9
|
-
def inspect
|
10
|
-
""
|
11
|
-
end
|
12
|
-
def strip; end
|
13
|
-
end
|
14
|
-
|
15
9
|
class Approval
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def self.base_path(s)
|
22
|
-
Approvals.path + normalize(s)
|
11
|
+
class << self
|
12
|
+
def normalize(s)
|
13
|
+
s.gsub(/[\W]/, ' ').strip.squeeze(" ").gsub(' ', '_').downcase
|
14
|
+
end
|
23
15
|
end
|
24
16
|
|
25
|
-
attr_reader :location
|
17
|
+
attr_reader :location, :name, :options, :path, :received
|
26
18
|
|
27
19
|
def initialize(example, received = '', options = {})
|
28
|
-
@
|
20
|
+
@name = Approval.normalize(example.full_description)
|
21
|
+
@path = Approvals.path + name
|
29
22
|
@options = options
|
23
|
+
@received = received
|
24
|
+
@formatter = Formatter.new(self)
|
30
25
|
|
31
26
|
example.options[:approval] = true
|
32
27
|
example.options[:approval_diff_paths] = {
|
33
28
|
:received => received_path,
|
34
29
|
:approved => approved_path,
|
35
30
|
}
|
31
|
+
end
|
36
32
|
|
37
|
-
|
38
|
-
|
33
|
+
def location=(backtrace)
|
34
|
+
@location = [backtrace.first.gsub(Dir.pwd, '.').gsub(/:in\ .*$/, '')]
|
39
35
|
end
|
40
36
|
|
41
37
|
def approved_path
|
@@ -46,82 +42,53 @@ module RSpec
|
|
46
42
|
"#{@path}.received.txt"
|
47
43
|
end
|
48
44
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
45
|
+
def diff_path
|
46
|
+
"#{received_path} #{approved_path}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def approved_text
|
50
|
+
if File.exists?(approved_path)
|
51
|
+
File.read(approved_path)
|
52
|
+
else
|
53
|
+
EmptyApproval.new.inspect
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def received_text
|
58
|
+
@received_text ||= Formatter.new(self).as_s(received)
|
59
|
+
end
|
60
|
+
|
61
|
+
def verify
|
62
|
+
unless received_text == approved_text
|
63
|
+
write(received_path, received_text)
|
64
|
+
Dotfile.append(diff_path)
|
65
|
+
if received.respond_to?(:on_failure)
|
66
|
+
received.on_failure.call(approved_text)
|
67
|
+
received.on_failure.call(received_text)
|
65
68
|
end
|
69
|
+
raise RSpec::Approvals::ReceivedDiffersError, failure_message, location
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
73
|
+
def write(path, contents)
|
74
|
+
File.open(path, 'w') do |f|
|
75
|
+
f.write contents
|
76
|
+
end
|
72
77
|
end
|
73
78
|
|
74
|
-
def
|
79
|
+
def failure_message
|
75
80
|
<<-FAILURE_MESSAGE
|
76
81
|
|
77
82
|
Approval Failure:
|
78
|
-
|
79
|
-
The received contents did not match the approved contents.
|
83
|
+
The received contents did not match the approved contents.
|
80
84
|
|
81
85
|
Inspect the differences in the following files:
|
82
86
|
#{received_path}
|
83
87
|
#{approved_path}
|
84
88
|
|
85
|
-
If you like what you see in the *.received.txt file, you can approve it
|
86
|
-
by renaming it with the .approved.txt suffix.
|
87
|
-
|
88
|
-
mv #{received_path} #{approved_path}
|
89
|
-
|
90
|
-
|
91
89
|
FAILURE_MESSAGE
|
92
90
|
end
|
93
91
|
|
94
|
-
def failure_message_exposing_received
|
95
|
-
default_failure_message << " received:\n " << received << "\n\n\n"
|
96
|
-
end
|
97
|
-
|
98
|
-
def location=(backtrace)
|
99
|
-
@location = [backtrace.first.gsub(Dir.pwd, '.')]
|
100
|
-
end
|
101
|
-
|
102
|
-
def verify
|
103
|
-
if FileUtils.cmp(received_path, approved_path)
|
104
|
-
File.unlink(received_path)
|
105
|
-
else
|
106
|
-
raise RSpec::Approvals::ReceivedDiffersError, failure_message, location
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def approved
|
111
|
-
File.read(approved_path)
|
112
|
-
end
|
113
|
-
|
114
|
-
def received
|
115
|
-
File.read(received_path)
|
116
|
-
end
|
117
|
-
|
118
|
-
def xml?
|
119
|
-
[:xml, :html].include? @options[:format]
|
120
|
-
end
|
121
|
-
|
122
|
-
def show_received?
|
123
|
-
@options[:show_received]
|
124
|
-
end
|
125
92
|
end
|
126
93
|
end
|
127
94
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Approvals
|
3
|
+
class CLI < Thor
|
4
|
+
|
5
|
+
desc "verify", "Go through all failing approvals with a diff tool"
|
6
|
+
method_option :diff, :type => :string, :default => 'vimdiff', :aliases => '-d', :desc => 'The difftool to use'
|
7
|
+
method_option :ask, :type => :boolean, :default => false, :aliases => "-a", :desc => 'Offer to approve the received file for you.'
|
8
|
+
def verify
|
9
|
+
|
10
|
+
approvals = File.read('.approvals').split("\n")
|
11
|
+
|
12
|
+
rejected = []
|
13
|
+
approvals.each do |approval|
|
14
|
+
system("#{options[:diff]} #{approval}")
|
15
|
+
|
16
|
+
if options[:ask] && yes?("Approve?")
|
17
|
+
system("mv #{approval}")
|
18
|
+
else
|
19
|
+
rejected << approval
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
File.open('.approvals', 'w') do |f|
|
24
|
+
f.write rejected.join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Approvals
|
3
|
+
|
4
|
+
class Dotfile
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def reset
|
8
|
+
File.delete(path) if File.exists?(path)
|
9
|
+
touch
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
'.approvals'
|
14
|
+
end
|
15
|
+
|
16
|
+
def touch
|
17
|
+
FileUtils.touch(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def append(text)
|
21
|
+
unless includes?(text)
|
22
|
+
write text
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def includes?(text)
|
27
|
+
system("cat #{path} | grep -q \"^#{text}$\"")
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(text)
|
31
|
+
File.open(path, 'a+') do |f|
|
32
|
+
f.write "#{text}\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
data/lib/rspec/approvals/dsl.rb
CHANGED
@@ -4,15 +4,16 @@ module RSpec
|
|
4
4
|
module Approvals
|
5
5
|
module DSL
|
6
6
|
|
7
|
-
def
|
7
|
+
def verify(description, options = {})
|
8
8
|
|
9
|
+
origin = caller
|
9
10
|
specify(description) do
|
10
11
|
approval = Approval.new(example, yield, options)
|
11
12
|
|
12
13
|
# We may be able to set file_path and
|
13
14
|
# line_number on example in the approval
|
14
15
|
# see RSpec::Core::Metadata::LocationKeys
|
15
|
-
approval.location =
|
16
|
+
approval.location = origin
|
16
17
|
|
17
18
|
approval.verify
|
18
19
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Approvals
|
3
|
+
class Formatter
|
4
|
+
attr_accessor :approval
|
5
|
+
def initialize(approval)
|
6
|
+
self.approval = approval
|
7
|
+
end
|
8
|
+
|
9
|
+
def as_s(contents)
|
10
|
+
if xml?
|
11
|
+
as_xml(contents)
|
12
|
+
elsif json?
|
13
|
+
as_json(contents)
|
14
|
+
elsif contents.respond_to?(:each_pair)
|
15
|
+
as_hash(contents)
|
16
|
+
elsif contents.respond_to?(:each_with_index)
|
17
|
+
as_array(contents)
|
18
|
+
else
|
19
|
+
contents.inspect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def xml?
|
24
|
+
[:xml, :html].include? approval.options[:format]
|
25
|
+
end
|
26
|
+
|
27
|
+
def json?
|
28
|
+
approval.options[:format] == :json
|
29
|
+
end
|
30
|
+
|
31
|
+
def as_json(contents)
|
32
|
+
JSON.pretty_generate(JSON.parse(contents))
|
33
|
+
end
|
34
|
+
|
35
|
+
def as_xml(contents)
|
36
|
+
parser = XML::Parser.string contents.strip
|
37
|
+
parser.parse.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def as_hash(contents)
|
41
|
+
s = ""
|
42
|
+
contents.each_pair do |k,v|
|
43
|
+
s << "#{k.inspect} => #{v.inspect}\n"
|
44
|
+
end
|
45
|
+
s
|
46
|
+
end
|
47
|
+
|
48
|
+
def as_array(contents)
|
49
|
+
s = ""
|
50
|
+
contents.each_with_index do |v,i|
|
51
|
+
s << "[#{i.inspect}] #{v.inspect}\n"
|
52
|
+
end
|
53
|
+
s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
data/rspec-approvals.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_dependency 'rspec', '~> 2.
|
21
|
+
s.add_dependency 'rspec', '~> 2.7'
|
22
|
+
s.add_dependency 'thor'
|
22
23
|
s.add_dependency 'libxml-ruby'
|
23
24
|
end
|
data/spec/approval_spec.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
|
-
require '
|
1
|
+
require 'rspec/approvals'
|
2
2
|
|
3
|
-
describe Approvals::Approval do
|
4
|
-
|
5
|
-
let(:example) { stub('example', :full_description => 'fairy dust and unicorns').as_null_object }
|
3
|
+
describe RSpec::Approvals::Approval do
|
4
|
+
include RSpec::Approvals
|
6
5
|
|
7
6
|
describe "#normalize" do
|
8
7
|
it "downcases" do
|
9
|
-
|
8
|
+
Approval.normalize("KTHXBYE").should eq("kthxbye")
|
10
9
|
end
|
11
10
|
|
12
11
|
it "replaces spaces with underscores" do
|
13
|
-
|
12
|
+
Approval.normalize("the spec").should eq("the_spec")
|
14
13
|
end
|
15
14
|
|
16
15
|
it "leaves numbers alone" do
|
17
|
-
|
16
|
+
Approval.normalize('a 2009 party').should eq("a_2009_party")
|
18
17
|
end
|
19
18
|
|
20
19
|
it "deletes funky characters" do
|
21
|
-
|
20
|
+
Approval.normalize('the !@\#$%^&*(){}+| name').should eq("the_name")
|
22
21
|
end
|
23
22
|
|
24
23
|
it "collapses spaces before replacing with underscores" do
|
25
|
-
|
24
|
+
Approval.normalize('omf g').should eq('omf_g')
|
26
25
|
end
|
27
26
|
|
28
27
|
it "deletes all sorts of spaces" do
|
@@ -30,152 +29,88 @@ describe Approvals::Approval do
|
|
30
29
|
|
31
30
|
The::Class \t \r\n \fname
|
32
31
|
FUNKY_NAME
|
33
|
-
|
32
|
+
Approval.normalize(name).should eq('the_class_name')
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
37
|
-
|
38
|
-
approval = Approvals::Approval.new(example)
|
39
|
-
approval.approved_path.should eq("#{description}.approved.txt")
|
40
|
-
end
|
41
|
-
|
42
|
-
it "knows the received path" do
|
43
|
-
approval = Approvals::Approval.new(example)
|
44
|
-
approval.received_path.should eq("#{description}.received.txt")
|
45
|
-
end
|
36
|
+
let(:example) { stub('example', :full_description => 'fairy dust and unicorns').as_null_object }
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
approval.location = ['the/path/to/my/heart:9372 <is through my stomach>', 'bla bla bla']
|
51
|
-
approval.location.should eq(['./to/my/heart:9372 <is through my stomach>'])
|
52
|
-
end
|
38
|
+
describe "an approval" do
|
39
|
+
let(:path) { 'spec/approvals/fairy_dust_and_unicorns' }
|
40
|
+
subject { Approval.new(example) }
|
53
41
|
|
54
|
-
|
55
|
-
|
56
|
-
@approved_file = "#{description}.approved.txt"
|
57
|
-
@received_file = "#{description}.received.txt"
|
58
|
-
end
|
42
|
+
its(:approved_path) { should eq("#{path}.approved.txt") }
|
43
|
+
its(:received_path) { should eq("#{path}.received.txt") }
|
59
44
|
|
60
|
-
|
61
|
-
|
62
|
-
|
45
|
+
it "can set a location" do
|
46
|
+
Dir.stub(:pwd => 'the/path')
|
47
|
+
subject.location = ['the/path/to/my/heart:9372:in <is through my stomach>', 'bla bla bla']
|
48
|
+
subject.location.should eq(['./to/my/heart:9372'])
|
63
49
|
end
|
50
|
+
end
|
64
51
|
|
65
|
-
|
66
|
-
|
67
|
-
it "writes the approved file if it doesn't exist" do
|
68
|
-
File.delete(@approved_file) if File.exists?(@approved_file)
|
69
|
-
|
70
|
-
Approvals::Approval.new(example)
|
52
|
+
describe "verification" do
|
53
|
+
let(:approval) { Approval.new(example, 'xyz') }
|
71
54
|
|
72
|
-
|
73
|
-
|
55
|
+
context "with a match" do
|
56
|
+
before :each do
|
57
|
+
approval.stub(:approved_text => 'xyz', :received_text => 'xyz')
|
74
58
|
end
|
75
59
|
|
76
|
-
it "
|
77
|
-
|
78
|
-
f.write "this doesn't get deleted"
|
79
|
-
end
|
80
|
-
|
81
|
-
Approvals::Approval.new(example)
|
82
|
-
|
83
|
-
File.exists?(@approved_file).should be_true
|
84
|
-
File.read(@approved_file).should eq("this doesn't get deleted")
|
60
|
+
it "does not raise an error" do
|
61
|
+
lambda { approval.verify }.should_not raise_error(RSpec::Approvals::ReceivedDiffersError)
|
85
62
|
end
|
86
63
|
|
87
|
-
it "
|
88
|
-
|
89
|
-
|
90
|
-
File.exists?(@received_file).should be_true
|
91
|
-
File.read(@received_file).should eq('"oooh, shiney!"')
|
64
|
+
it "does not leave a received file" do
|
65
|
+
lambda { approval.verify }.call
|
66
|
+
File.exists?(approval.received_path).should be_false
|
92
67
|
end
|
93
68
|
end
|
94
69
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
@approval = Approvals::Approval.new(example, 'xyz')
|
100
|
-
@approval.write(:approved, 'xyz')
|
101
|
-
end
|
70
|
+
context "with a mismatch" do
|
71
|
+
before :each do
|
72
|
+
approval.stub(:approved_text => 'xyz', :received_text => 'abc')
|
73
|
+
end
|
102
74
|
|
103
|
-
|
104
|
-
|
105
|
-
|
75
|
+
after :each do
|
76
|
+
File.delete(approval.received_path) if File.exists?(approval.received_path)
|
77
|
+
end
|
106
78
|
|
107
|
-
|
108
|
-
|
109
|
-
File.exists?(@approval.received_path).should be_false
|
110
|
-
end
|
79
|
+
it "raises an error" do
|
80
|
+
lambda { approval.verify }.should raise_error(RSpec::Approvals::ReceivedDiffersError)
|
111
81
|
end
|
112
82
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
83
|
+
it "leaves a received file" do
|
84
|
+
begin
|
85
|
+
approval.verify
|
86
|
+
rescue RSpec::Approvals::ReceivedDiffersError => e
|
87
|
+
# we want to land here and then move on
|
117
88
|
end
|
89
|
+
File.exists?(approval.received_path).should be_true
|
90
|
+
end
|
118
91
|
|
119
|
-
|
120
|
-
|
121
|
-
|
92
|
+
it "appends to the dotfile" do
|
93
|
+
approval.stub(:diff_path => 'the diff path')
|
94
|
+
Dotfile.should_receive(:append).with "the diff path"
|
122
95
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
# we want to land here and then move on
|
128
|
-
end
|
129
|
-
File.exists?(@approval.received_path).should be_true
|
96
|
+
begin
|
97
|
+
approval.verify
|
98
|
+
rescue RSpec::Approvals::ReceivedDiffersError => e
|
99
|
+
# moving on
|
130
100
|
end
|
131
101
|
end
|
132
102
|
end
|
133
103
|
|
134
104
|
it "fails magnificently" do
|
135
|
-
approval = Approvals::Approval.new(example, 'xyz')
|
136
105
|
message = <<-FAILURE_MESSAGE
|
137
106
|
|
138
107
|
Approval Failure:
|
139
|
-
|
140
|
-
The received contents did not match the approved contents.
|
108
|
+
The received contents did not match the approved contents.
|
141
109
|
|
142
110
|
Inspect the differences in the following files:
|
143
111
|
#{approval.received_path}
|
144
112
|
#{approval.approved_path}
|
145
113
|
|
146
|
-
If you like what you see in the *.received.txt file, you can approve it
|
147
|
-
by renaming it with the .approved.txt suffix.
|
148
|
-
|
149
|
-
mv #{approval.received_path} #{approval.approved_path}
|
150
|
-
|
151
|
-
|
152
|
-
FAILURE_MESSAGE
|
153
|
-
|
154
|
-
approval.failure_message.should eq(message)
|
155
|
-
end
|
156
|
-
|
157
|
-
it "fails with exposed 'received'" do
|
158
|
-
approval = Approvals::Approval.new(example, 'aoeu', :show_received => true)
|
159
|
-
message = <<-FAILURE_MESSAGE
|
160
|
-
|
161
|
-
Approval Failure:
|
162
|
-
|
163
|
-
The received contents did not match the approved contents.
|
164
|
-
|
165
|
-
Inspect the differences in the following files:
|
166
|
-
#{approval.received_path}
|
167
|
-
#{approval.approved_path}
|
168
|
-
|
169
|
-
If you like what you see in the *.received.txt file, you can approve it
|
170
|
-
by renaming it with the .approved.txt suffix.
|
171
|
-
|
172
|
-
mv #{approval.received_path} #{approval.approved_path}
|
173
|
-
|
174
|
-
|
175
|
-
received:
|
176
|
-
#{approval.received}
|
177
|
-
|
178
|
-
|
179
114
|
FAILURE_MESSAGE
|
180
115
|
|
181
116
|
approval.failure_message.should eq(message)
|
@@ -0,0 +1 @@
|
|
1
|
+
"abc"
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
SELECT 1
|
data/spec/approvals_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'rspec/approvals'
|
2
|
+
require 'json'
|
2
3
|
|
3
|
-
describe Approvals do
|
4
|
+
describe RSpec::Approvals do
|
5
|
+
include RSpec
|
4
6
|
|
5
7
|
it "defaults the output dir to spec/approvals" do
|
6
8
|
RSpec.configuration.approvals_path.should == 'spec/approvals'
|
@@ -24,13 +26,11 @@ describe Approvals do
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
approve "a string" do
|
29
|
+
verify "a string" do
|
30
30
|
"We have, I fear, confused power with greatness."
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
verify "a hash" do
|
34
34
|
{
|
35
35
|
:universe => {
|
36
36
|
:side => :dark,
|
@@ -41,7 +41,7 @@ describe Approvals do
|
|
41
41
|
}
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
verify "an array" do
|
45
45
|
[
|
46
46
|
"abc",
|
47
47
|
123,
|
@@ -50,7 +50,7 @@ describe Approvals do
|
|
50
50
|
]
|
51
51
|
end
|
52
52
|
|
53
|
-
|
53
|
+
verify "a complex object with implicit #inspect" do
|
54
54
|
hello = Object.new
|
55
55
|
def hello.to_s
|
56
56
|
"Hello, World!"
|
@@ -60,17 +60,27 @@ describe Approvals do
|
|
60
60
|
"#<The World Says: Hello!>"
|
61
61
|
end
|
62
62
|
|
63
|
-
hello
|
63
|
+
hello
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
verify "formats html nicely", :format => :html do
|
67
67
|
<<-XML
|
68
68
|
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>blog</title><script type="text/javascript" src="/blog/static/jquery-1.1.3.pack.js"></script><script type="text/javascript" src="/blog/static/blog.js"></script><link type="text/css" rel="stylesheet" href="/blog/styles.css" media="screen"/></head><body><h1 class="header"><a href="/blog/">blog</a></h1><div class="content"><h1 class="post_head"><a href="/blog/view/2">Hej</a><a class="edit_link" href="/blog/edit/2">edit</a></h1><p>ASDJlksdjfsld
|
69
69
|
</p><h2 class="comment_head"><a href="javascript:getComments(2)">See comments (2)</a></h2><div id="comments"><h3>tyysen</h3><p>miljoooner</p><h3>hej</h3><p>bulan</p></div><h2 class="add_comment_head"><a href="#comment_form">Add comment</a></h2><form method="post" name="comment_form" id="comment_form" action="/blog/comment"><label for="post_username">Name</label><br/><input type="text" name="post_username"/><br/><label for="post_body">Comment</label><br/><textarea name="post_body"></textarea><br/><input type="hidden" name="post_id" value="2"/><input type="submit" value="Add comment"/></form></div></body></html>
|
70
70
|
XML
|
71
71
|
end
|
72
72
|
|
73
|
-
|
73
|
+
verify "formats xml nicely", :format => :xml, do
|
74
74
|
"<xml testsdf=\"dsfsdf\"><test/><node><content attr='fgsd' /></node><node id='2'><content /></node></xml>"
|
75
75
|
end
|
76
|
+
|
77
|
+
verify "formats json nicely", :format => :json do
|
78
|
+
{"hello" => "world"}.to_json
|
79
|
+
end
|
80
|
+
|
81
|
+
verify "an executable" do
|
82
|
+
executable = RSpec::Approvals::Executable.new('SELECT 1') do |command|
|
83
|
+
puts "your slip is showing (#{command})"
|
84
|
+
end
|
85
|
+
end
|
76
86
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rspec/approvals/dotfile'
|
2
|
+
|
3
|
+
describe RSpec::Approvals::Dotfile do
|
4
|
+
include RSpec::Approvals
|
5
|
+
let(:dotfile) { '/tmp/.approvals' }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Dotfile.stub(:path => dotfile)
|
9
|
+
Dotfile.reset
|
10
|
+
end
|
11
|
+
|
12
|
+
it "appends the text" do
|
13
|
+
Dotfile.append('text')
|
14
|
+
File.readlines(dotfile).map(&:chomp).should eq(['text'])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "appends the text exactly once" do
|
18
|
+
Dotfile.append('text')
|
19
|
+
Dotfile.append('text')
|
20
|
+
File.readlines(dotfile).map(&:chomp).should eq(['text'])
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec/approvals/executable'
|
2
|
+
|
3
|
+
describe RSpec::Approvals::Executable do
|
4
|
+
include RSpec::Approvals
|
5
|
+
|
6
|
+
subject { Executable.new('SELECT 1') }
|
7
|
+
its(:inspect) { should eq('SELECT 1') }
|
8
|
+
|
9
|
+
it "takes a block" do
|
10
|
+
executable = Executable.new('SELECT 1') do |command|
|
11
|
+
"execute query: #{command}"
|
12
|
+
end
|
13
|
+
executable.on_failure.call('SELECT 1').should eq('execute query: SELECT 1')
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,111 +1,110 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-approvals
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 0
|
8
|
-
- 4
|
9
|
-
version: 0.0.4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Katrina Owen
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-02-12 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: rspec
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70165236704760 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
18
|
+
requirements:
|
26
19
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.7'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70165236704760
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
requirement: &70165236701340 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
32
33
|
type: :runtime
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: libxml-ruby
|
36
34
|
prerelease: false
|
37
|
-
|
35
|
+
version_requirements: *70165236701340
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: libxml-ruby
|
38
|
+
requirement: &70165236698420 !ruby/object:Gem::Requirement
|
38
39
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
- 0
|
44
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
45
44
|
type: :runtime
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70165236698420
|
47
|
+
description: An RSpec extension that adds support for approvals. Based on the idea
|
48
|
+
of the Golden Master.
|
49
|
+
email:
|
49
50
|
- katrina.owen@gmail.com
|
50
|
-
executables:
|
51
|
-
|
51
|
+
executables:
|
52
|
+
- approvals
|
52
53
|
extensions: []
|
53
|
-
|
54
54
|
extra_rdoc_files: []
|
55
|
-
|
56
|
-
files:
|
55
|
+
files:
|
57
56
|
- .gitignore
|
58
57
|
- Gemfile
|
59
58
|
- License.txt
|
60
59
|
- README.md
|
61
60
|
- Rakefile
|
61
|
+
- bin/approvals
|
62
62
|
- lib/rspec-approvals.rb
|
63
63
|
- lib/rspec/approvals.rb
|
64
64
|
- lib/rspec/approvals/approval.rb
|
65
|
+
- lib/rspec/approvals/cli.rb
|
66
|
+
- lib/rspec/approvals/dotfile.rb
|
65
67
|
- lib/rspec/approvals/dsl.rb
|
66
|
-
- lib/rspec/approvals/
|
68
|
+
- lib/rspec/approvals/empty_approval.rb
|
69
|
+
- lib/rspec/approvals/executable.rb
|
70
|
+
- lib/rspec/approvals/formatter.rb
|
67
71
|
- lib/rspec/approvals/version.rb
|
68
72
|
- rspec-approvals.gemspec
|
69
73
|
- spec/approval_spec.rb
|
70
|
-
- spec/approvals/
|
74
|
+
- spec/approvals/fairy_dust_and_unicorns.approved.txt
|
75
|
+
- spec/approvals/rspec_approvals_a_complex_object_with_implicit_inspect.approved.txt
|
71
76
|
- spec/approvals/rspec_approvals_a_hash.approved.txt
|
72
77
|
- spec/approvals/rspec_approvals_a_string.approved.txt
|
73
78
|
- spec/approvals/rspec_approvals_an_array.approved.txt
|
79
|
+
- spec/approvals/rspec_approvals_an_executable.approved.txt
|
74
80
|
- spec/approvals/rspec_approvals_formats_html_nicely.approved.txt
|
81
|
+
- spec/approvals/rspec_approvals_formats_json_nicely.approved.txt
|
75
82
|
- spec/approvals/rspec_approvals_formats_xml_nicely.approved.txt
|
76
83
|
- spec/approvals_spec.rb
|
77
|
-
- spec/
|
78
|
-
|
79
|
-
homepage:
|
84
|
+
- spec/dotfile_spec.rb
|
85
|
+
- spec/executable_spec.rb
|
86
|
+
homepage: ''
|
80
87
|
licenses: []
|
81
|
-
|
82
88
|
post_install_message:
|
83
89
|
rdoc_options: []
|
84
|
-
|
85
|
-
require_paths:
|
90
|
+
require_paths:
|
86
91
|
- lib
|
87
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
93
|
none: false
|
89
|
-
requirements:
|
90
|
-
- -
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
|
93
|
-
|
94
|
-
version: "0"
|
95
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
99
|
none: false
|
97
|
-
requirements:
|
98
|
-
- -
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
|
101
|
-
- 0
|
102
|
-
version: "0"
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
103
104
|
requirements: []
|
104
|
-
|
105
105
|
rubyforge_project: rspec-approvals
|
106
|
-
rubygems_version: 1.
|
106
|
+
rubygems_version: 1.8.10
|
107
107
|
signing_key:
|
108
108
|
specification_version: 3
|
109
109
|
summary: Approval Tests for Ruby
|
110
110
|
test_files: []
|
111
|
-
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'rspec/core/formatters/progress_formatter'
|
2
|
-
|
3
|
-
module RSpec
|
4
|
-
module Approvals
|
5
|
-
module Formatters
|
6
|
-
|
7
|
-
class OpendiffFormatter < RSpec::Core::Formatters::ProgressFormatter
|
8
|
-
def dump_failures
|
9
|
-
super
|
10
|
-
failed_examples.each do |example|
|
11
|
-
if example.options[:approval]
|
12
|
-
paths = example.options[:approval_diff_paths]
|
13
|
-
system("opendiff #{paths[:received]} #{paths[:approved]} &")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/spec/spec_helper.rb
DELETED