Class: Approvals::Approval

Inherits:
Object
  • Object
show all
Defined in:
lib/approvals/approval.rb

Constant Summary collapse

IDENTITIES =

Add a Proc that tests if subject is a kind of format

{
  hash: Proc.new(){|subject|subject.respond_to? :each_pair},
  array: Proc.new(){|subject|subject.respond_to? :each_with_index},
}
BINARY_FORMATS =
[:binary]

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subject, options = {}) ⇒ Approval

Returns a new instance of Approval.



9
10
11
12
13
# File 'lib/approvals/approval.rb', line 9

def initialize(subject, options = {})
  @subject = subject
  @namer = options[:namer] || default_namer(options[:name])
  @format = options[:format] || identify_format
end

Class Attribute Details

.namerObject

Returns the value of attribute namer.



5
6
7
# File 'lib/approvals/approval.rb', line 5

def namer
  @namer
end

Instance Attribute Details

#failureObject (readonly)

Returns the value of attribute failure.



8
9
10
# File 'lib/approvals/approval.rb', line 8

def failure
  @failure
end

#namerObject (readonly)

Returns the value of attribute namer.



8
9
10
# File 'lib/approvals/approval.rb', line 8

def namer
  @namer
end

#subjectObject (readonly)

Returns the value of attribute subject.



8
9
10
# File 'lib/approvals/approval.rb', line 8

def subject
  @subject
end

Instance Method Details

#approved?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/approvals/approval.rb', line 81

def approved?
  File.exist? approved_path
end

#approved_pathObject



128
129
130
# File 'lib/approvals/approval.rb', line 128

def approved_path
  full_path('approved')
end

#approved_textObject



136
137
138
# File 'lib/approvals/approval.rb', line 136

def approved_text
  File.read(approved_path).chomp
end

#default_namer(name) ⇒ Object



15
16
17
# File 'lib/approvals/approval.rb', line 15

def default_namer(name)
  Approvals::Approval.namer || Namers::DefaultNamer.new(name)
end

#diff_linesObject



69
70
71
72
73
74
75
# File 'lib/approvals/approval.rb', line 69

def diff_lines
  approved = @approved_content.split("\n")
  received = @received_content.split("\n")
  approved.each_with_index do |line, i|
    return line, received[i] unless line == received[i]
  end
end

#diff_pathObject



116
117
118
# File 'lib/approvals/approval.rb', line 116

def diff_path
  "#{approved_path} #{received_path}"
end

#diff_previewObject



58
59
60
61
62
63
64
65
66
67
# File 'lib/approvals/approval.rb', line 58

def diff_preview
  approved, received = diff_lines
  return unless approved and received
  diff_index =
      approved.each_char.with_index.find_index do |approved_char, i|
        approved_char != received[i]
      end
  "approved fragment: #{approved[diff_index - 10 .. diff_index + 30]}\n"+
  "received fragment: #{received[diff_index - 10 .. diff_index + 30]}"
end

#fail_with(message) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/approvals/approval.rb', line 101

def fail_with(message)
  Dotfile.append(diff_path)

  if subject.respond_to?(:on_failure)
    subject.on_failure.call(approved_text) if approved?
    subject.on_failure.call(received_text)
  end

  error = ApprovalError.new("Approval Error: #{message}")
  error.approved_path = approved_path
  error.received_path = received_path

  raise error
end

#full_path(state) ⇒ Object



120
121
122
# File 'lib/approvals/approval.rb', line 120

def full_path(state)
  "#{namer.output_dir}#{namer.name}.#{state}.#{writer.extension}"
end

#identify_formatObject



25
26
27
28
29
30
31
# File 'lib/approvals/approval.rb', line 25

def identify_format
  IDENTITIES.each_pair do |format, id_test|
    return format if id_test.call(subject)
  end
  # otherwise
  return :txt
end

#nameObject



124
125
126
# File 'lib/approvals/approval.rb', line 124

def name
  namer.name
end

#read_contentObject



87
88
89
90
91
92
93
94
95
# File 'lib/approvals/approval.rb', line 87

def read_content
  if BINARY_FORMATS.include?(@format) # Read without ERB
    [IO.read(approved_path).chomp,
     IO.read(received_path).chomp]
  else
    [ERB.new(IO.read(approved_path).chomp).result,
     ERB.new(IO.read(received_path).chomp).result]
  end
end

#received_matches?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/approvals/approval.rb', line 97

def received_matches?
  @approved_content == @received_content
end

#received_pathObject



132
133
134
# File 'lib/approvals/approval.rb', line 132

def received_path
  full_path('received')
end

#received_textObject



140
141
142
# File 'lib/approvals/approval.rb', line 140

def received_text
  File.read(received_path).chomp
end

#success!Object



77
78
79
# File 'lib/approvals/approval.rb', line 77

def success!
  File.delete received_path
end

#verifyObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/approvals/approval.rb', line 37

def verify
  unless File.exist?(namer.output_dir)
    FileUtils.mkdir_p(namer.output_dir)
  end

  writer.write(subject, received_path)

  unless approved?
    fail_with "Approval file \"#{approved_path}\" not found."
  end

  @approved_content, @received_content = read_content

  unless received_matches?
    fail_with "Received file does not match approved:\n"+
      "#{received_path}\n#{approved_path}\n#{diff_preview}"
  end

  success!
end

#writerObject



33
34
35
# File 'lib/approvals/approval.rb', line 33

def writer
  @writer ||= Writer.for(@format)
end