Prueba de correos electrónicos multiparte de ActionMailer con RSpec


Actualmente estoy probando mis correos con RSpec, pero he empezado a configurar correos electrónicos multiparte como se describe en las Guías Rails aquí: http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

Tengo ambas plantillas de correo en formato texto y html, pero parece que mis pruebas solo están comprobando la parte HTML. ¿Hay alguna forma de revisar la plantilla de texto por separado?

Es solo comprobar la vista HTML porque es la primera en el valor predeterminado ¿orden?

Author: cmhobbs, 2011-06-27

4 answers

Para complementar la excelente respuesta de nilmethod, puede limpiar sus especificaciones probando versiones de texto y html utilizando un grupo de ejemplo compartido:

Spec_helper.rb

def get_message_part (mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }.body.raw_source
end

shared_examples_for "multipart email" do
  it "generates a multipart message (plain text and html)" do
    mail.body.parts.length.should eq(2)
    mail.body.parts.collect(&:content_type).should == ["text/plain; charset=UTF-8", "text/html; charset=UTF-8"]
  end
end

Su_email_spec.rb

let(:mail) { YourMailer.action }

shared_examples_for "your email content" do
  it "has some content" do
    part.should include("the content")
  end
end

it_behaves_like "multipart email"

describe "text version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /plain/) }
  end
end

describe "html version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /html/) }
  end
end
 32
Author: Lachlan Cotter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-03 22:48:00

Esto se puede probar con expresiones regulares.

Encontrar cosas en la parte HTML (use #should después de esto para coincidir):

mail.body.parts.find {|p| p.content_type.match /html/}.body.raw_source

Encontrar cosas en la porción de texto sin formato (use #should después de esto para coincidir):

mail.body.parts.find {|p| p.content_type.match /plain/}.body.raw_source

Comprobando que está, de hecho, generando un mensaje multiparte:

it "generates a multipart message (plain text and html)" do
  mail.body.parts.length.should == 2
  mail.body.parts.collect(&:content_type).should == ["text/html; charset=UTF-8", "text/plain; charset=UTF-8"]
end 
 26
Author: cmhobbs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-05 20:43:41

Para hacer las cosas aún más simples, puede usar

message.text_part    and
message.html_part

Para encontrar las partes respectivas. Esto funciona incluso para mensajes estructurados de varias partes / alternativos con archivos adjuntos. (Probado en Ruby 1.9.3 con Rails 3.0.14.)

Estos métodos emplean algún tipo de heurística para encontrar las partes del mensaje respectivas, por lo que si su mensaje tiene varias partes de texto (por ejemplo, como Apple Mail las crea) podría no hacer lo "correcto".

Esto cambiaría el método anterior a

def body_should_match_regex(mail, regex)
 if mail.multipart?
  ["text", "html"].each do |part|
   mail.send("#{part}_part").body.raw_source.should match(regex)
  end
 else
  mail.body.raw_source.should match(regex)
 end
end

Que funciona tanto para mensajes de texto plano (no multiparte) como para mensajes multiparte y prueba todos los cuerpos de mensajes contra una expresión regular específica.

Ahora, ¿algún voluntario para hacer un "verdadero" RSpec matcher de esto? :) Algo como

@mail.bodies_should_match /foobar/

Sería mucho mejor ...

 23
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-28 11:23:26

Si su correo electrónico tiene archivos adjuntos, las partes de texto y html se colocarán en una parte multipart/alternative. Esto se indica en Enviar correos electrónicos con Archivos adjuntos en la Guía Rails 3.

Para manejar esto, primero simplifiqué el método get_message_part anterior a:

def get_message_part(mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }
end

Entonces en mi prueba:

multipart = get_message_part(email, /multipart/)

html = get_message_part(multipart, /html/)
html_body = html.body.raw_source

assert_match 'some string', html_body
 1
Author: mikeycgto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-27 16:38:21