I use mail
, nokogiri
, and reverse_markdown
gems to read an email and process the body, stripping out external tags and a unicode zero width character (u200b
) to get an instance variable @body
that refers to a string. Here's the relevant code:
@body = email.html_part.decoded.delete("\u200b")
@body = Nokogiri::HTML.parse(@body).at("div")
@body.css("br").each { |node| node.replace('<br />') }
@body.css("div").each { |node| node.replace(node.inner_html)}
@body = @body.inner_html
@body = ReverseMarkdown.convert(@body)
if @body.gsub(/\s+/, "").length == 0
unless email.attachments.length > 0
raise StandardError, "Empty email"
end
end
puts @body.class # => "String"
After ReverseMarkdown.convert
, the empty email is still three characters long, likely due to whitespace from stripping out tags, or because the Markdown converter forces it to have a whitespace with two spaces. That's why I do gsub
length check to strip out white spaces.
When I run my rspec test:
context 'with no body' do
it 'outputs the body to markdown' do
puts instance_variable_get(:@body).class # => 'NilClass'
expect(instance_variable_get(:@body)).to eq("")
end
end
when the email is empty and has no attachments, it shows:
expected: ""
got: nil
I can't imagine why the class of the variable changes.
You haven't specified a receiver for
instance_variable_get
, so it will default toself
which here is an RSpec example group.You would need
email.instance_variable_get(:@body)
(assuming yoursubject
isemail
).However: using methods such as
instance_variable_get
in a test is a danger signal. You should aim to test a class by its public interface, not by examining its internals.