From c3f6979314a1cac38812410bf18650adc05612d0 Mon Sep 17 00:00:00 2001 From: Samuel Cochran Date: Fri, 21 Mar 2014 14:36:54 +1100 Subject: [PATCH] Basic but ugly acceptance specs with selenium --- Gemfile.lock | 11 ++ examples/multipartmail | 2 +- examples/plainmail | 4 +- mailcatcher.gemspec | 1 + spec/acceptance_spec.rb | 228 +++++++++++++++++++++++++++++++++++++++ spec/mailcatcher_spec.rb | 67 ------------ 6 files changed, 243 insertions(+), 70 deletions(-) create mode 100644 spec/acceptance_spec.rb delete mode 100644 spec/mailcatcher_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index 56c722a..4300aeb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,6 +17,8 @@ GEM activesupport (3.2.17) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) + childprocess (0.5.1) + ffi (~> 1.0, >= 1.0.11) chunky_png (1.3.0) coffee-script (2.2.0) coffee-script-source @@ -29,6 +31,7 @@ GEM daemons (1.1.9) eventmachine (1.0.3) execjs (2.0.2) + ffi (1.9.3) fssm (0.2.10) haml (4.0.5) tilt @@ -48,7 +51,13 @@ GEM rake (10.1.1) rdoc (4.1.1) json (~> 1.4) + rubyzip (1.1.2) sass (3.2.17) + selenium-webdriver (2.40.0) + childprocess (>= 0.5.0) + multi_json (~> 1.0) + rubyzip (~> 1.0) + websocket (~> 1.0.4) sinatra (1.4.4) rack (~> 1.4) rack-protection (~> 1.4) @@ -76,6 +85,7 @@ GEM uglifier (2.5.0) execjs (>= 0.3.0) json (>= 1.8.0) + websocket (1.0.7) PLATFORMS ruby @@ -88,6 +98,7 @@ DEPENDENCIES rake rdoc sass + selenium-webdriver sprockets sprockets-sass uglifier diff --git a/examples/multipartmail b/examples/multipartmail index 2d9fe24..80b2309 100644 --- a/examples/multipartmail +++ b/examples/multipartmail @@ -16,4 +16,4 @@ Content-Type: text/html HTML mail ---BOUNDARY--198849662-- \ No newline at end of file +--BOUNDARY--198849662-- diff --git a/examples/plainmail b/examples/plainmail index 0eb9261..b799bdc 100644 --- a/examples/plainmail +++ b/examples/plainmail @@ -1,6 +1,6 @@ To: Blah From: Me -Subject: Whatever +Subject: Plain mail Content-Type: text/plain -Plain text mail +Here's some text diff --git a/mailcatcher.gemspec b/mailcatcher.gemspec index 3b639e4..2975e71 100644 --- a/mailcatcher.gemspec +++ b/mailcatcher.gemspec @@ -45,6 +45,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rake" s.add_development_dependency "rdoc" s.add_development_dependency "sass" + s.add_development_dependency "selenium-webdriver" s.add_development_dependency "sprockets" s.add_development_dependency "sprockets-sass" s.add_development_dependency "uglifier" diff --git a/spec/acceptance_spec.rb b/spec/acceptance_spec.rb new file mode 100644 index 0000000..cc09708 --- /dev/null +++ b/spec/acceptance_spec.rb @@ -0,0 +1,228 @@ +require "minitest/autorun" +require "mail_catcher" +require "socket" +require "net/smtp" +require "selenium-webdriver" + +SMTP_PORT = 10025 +HTTP_PORT = 10080 + +# Start MailCatcher +MAILCATCHER_PID = spawn "bundle", "exec", "mailcatcher", "--foreground", "--smtp-port", SMTP_PORT.to_s, "--http-port", HTTP_PORT.to_s + +# Make sure it will be stopped +MiniTest.after_run do + Process.kill("TERM", MAILCATCHER_PID) and Process.wait +end + +# Wait for it to boot +begin + TCPSocket.new("127.0.0.1", SMTP_PORT).close +rescue Errno::ECONNREFUSED + retry +end + +describe MailCatcher do + DEFAULT_FROM = "from@example.com" + DEFAULT_TO = "to@example.com" + + def deliver(message, options={}) + options = {:from => DEFAULT_FROM, :to => DEFAULT_TO}.merge(options) + Net::SMTP.start('127.0.0.1', SMTP_PORT) do |smtp| + smtp.send_message message, options[:from], options[:to] + end + end + + def read_example(name) + File.read(File.expand_path("../../examples/#{name}", __FILE__)) + end + + def deliver_example(name, options={}) + deliver(read_example(name), options) + end + + def selenium + @selenium ||= begin + Selenium::WebDriver.for(:phantomjs).tap do |selenium| + selenium.navigate.to("http://127.0.0.1:#{HTTP_PORT}") + end + end + end + + def messages_element + selenium.find_element(:id, "messages") + end + + def message_row_element + messages_element.find_element(:xpath, ".//table/tbody/tr[1]") + end + + def message_from_element + message_row_element.find_element(:xpath, ".//td[1]") + end + + def message_to_element + message_row_element.find_element(:xpath, ".//td[2]") + end + + def message_subject_element + message_row_element.find_element(:xpath, ".//td[3]") + end + + def message_received_element + message_row_element.find_element(:xpath, ".//td[4]") + end + + def html_tab_element + selenium.find_element(:css, "#message header .format.html a") + end + + def plain_tab_element + selenium.find_element(:css, "#message header .format.plain a") + end + + def source_tab_element + selenium.find_element(:css, "#message header .format.source a") + end + + def iframe_element + selenium.find_element(:css, "#message iframe") + end + + def body_element + selenium.find_element(:tag_name, "body") + end + + before { selenium.navigate.refresh } + + it "catches and displays a plain text message as plain text and source" do + deliver_example("plainmail") + + message_from_element.text.must_include DEFAULT_FROM + message_to_element.text.must_include DEFAULT_TO + message_subject_element.text.must_equal "Plain mail" + Time.parse(message_received_element.text).must_be_close_to Time.now, 5 + + message_row_element.click + + source_tab_element.displayed?.must_equal true + plain_tab_element.displayed?.must_equal true + html_tab_element.displayed?.must_equal false + + plain_tab_element.click + + iframe_element.displayed?.must_equal true + iframe_element.attribute(:src).must_match /\.plain\Z/ + + selenium.switch_to.frame(iframe_element) + + body_element.text.wont_include "Subject: Plain mail" + body_element.text.must_include "Here's some text" + + selenium.switch_to.default_content + source_tab_element.click + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "Subject: Plain mail" + body_element.text.must_include "Here's some text" + end + + it "catches and displays an html message as html and source" do + deliver_example("htmlmail") + + message_from_element.text.must_include DEFAULT_FROM + message_to_element.text.must_include DEFAULT_TO + message_subject_element.text.must_equal "Test HTML Mail" + Time.parse(message_received_element.text).must_be_close_to Time.now, 5 + + message_row_element.click + + source_tab_element.displayed?.must_equal true + plain_tab_element.displayed?.must_equal false + html_tab_element.displayed?.must_equal true + + html_tab_element.click + + iframe_element.displayed?.must_equal true + iframe_element.attribute(:src).must_match /\.html\Z/ + + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "Yo, you slimey scoundrel." + body_element.text.wont_include "Content-Type: text/html" + body_element.text.wont_include "Yo, you slimey scoundrel." + + selenium.switch_to.default_content + source_tab_element.click + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "Content-Type: text/html" + body_element.text.must_include "Yo, you slimey scoundrel." + body_element.text.wont_include "Yo, you slimey scoundrel." + end + + it "catches and displays a multipart message as text, html and source" do + deliver_example("multipartmail") + + message_from_element.text.must_include DEFAULT_FROM + message_to_element.text.must_include DEFAULT_TO + message_subject_element.text.must_equal "Test Multipart Mail" + Time.parse(message_received_element.text).must_be_close_to Time.now, 5 + + message_row_element.click + + source_tab_element.displayed?.must_equal true + plain_tab_element.displayed?.must_equal true + html_tab_element.displayed?.must_equal true + + plain_tab_element.click + + iframe_element.displayed?.must_equal true + iframe_element.attribute(:src).must_match /\.plain\Z/ + + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "Plain text mail" + body_element.text.wont_include "HTML mail" + body_element.text.wont_include "Content-Type: multipart/alternative; boundary=BOUNDARY--198849662" + + selenium.switch_to.default_content + html_tab_element.click + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "HTML mail" + body_element.text.wont_include "Content-Type: multipart/alternative; boundary=BOUNDARY--198849662" + + selenium.switch_to.default_content + source_tab_element.click + selenium.switch_to.frame(iframe_element) + + body_element.text.must_include "Content-Type: multipart/alternative; boundary=BOUNDARY--198849662" + body_element.text.must_include "Plain text mail" + body_element.text.must_include "HTML mail" + end + + it "catches and displays an unknown message as source" do + deliver_example("unknownmail") + + skip + end + + it "catches and displays a message with multipart attachments" do + deliver_example("attachmail") + + skip + end + + it "doesn't choke on messages containing dots" do + deliver_example("dotmail") + + skip + end + + it "doesn't choke on messages containing quoted printables" do + deliver_example("quoted_printable_htmlmail") + + skip + end +end diff --git a/spec/mailcatcher_spec.rb b/spec/mailcatcher_spec.rb deleted file mode 100644 index 52c7919..0000000 --- a/spec/mailcatcher_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require "minitest/autorun" -require "mail_catcher" -require "socket" -require "net/smtp" - -SMTP_PORT = 10025 -HTTP_PORT = 10080 - -# Start MailCatcher -MAILCATCHER_PID = spawn "bundle", "exec", "mailcatcher", "--foreground", "--smtp-port", SMTP_PORT.to_s, "--http-port", HTTP_PORT.to_s - -# Make sure it will be stopped -MiniTest.after_run do - Process.kill("TERM", MAILCATCHER_PID) and Process.wait -end - -# Wait for it to boot -begin - TCPSocket.new("127.0.0.1", SMTP_PORT).close -rescue Errno::ECONNREFUSED - retry -end - -describe MailCatcher do - def deliver(message, options={}) - options = {:from => "from@example.com", :to => "to@example.com"}.merge(options) - Net::SMTP.start('127.0.0.1', SMTP_PORT) do |smtp| - smtp.send_message message, options[:from], options[:to] - end - end - - def read_example(name) - File.read(File.expand_path("../../examples/#{name}", __FILE__)) - end - - def deliver_example(name, options={}) - deliver(read_example(name), options) - end - - it "catches and displays a plain text message as plain text and source" do - deliver_example("plainmail") - end - - it "catches and displays an html message as html and source" do - deliver_example("htmlmail") - end - - it "catches and displays a multipart message as text, html and source" do - deliver_example("multipartmail") - end - - it "catches and displays an unknown message as source" do - deliver_example("unknownmail") - end - - it "catches and displays a message with multipart attachments" do - deliver_example("attachmail") - end - - it "doesn't choke on messages containing dots" do - deliver_example("dotmail") - end - - it "doesn't choke on messages containing quoted printables" do - deliver_example("quoted_printable_htmlmail") - end -end