Skip to content

Commit

Permalink
Fix contact form not sending e-mails.
Browse files Browse the repository at this point in the history
There were a couple issues with the contact form on the example static
site that was preventing it from sending messages:

- In the example static site, the form was missing a couple of new
  fields that the API now requires (a subject and the name of the API):
  NREL/api-umbrella-static-site@c02b886
- Since the Rails 4 upgrade in API Umbrella v0.14, the serialization of
  the e-mail messages into delayed job was broken (since ActiveJob won't
  serialize arbitrary models). This is fixed by serializing the data as
  a plain hash instead.

This adds missing tests for this whole contact API, and also adds
integration tests to make sure the example static site form works in the
browser.

18F/api.data.gov#390
  • Loading branch information
GUI committed Jun 16, 2017
1 parent e7c870c commit 96862e0
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 9 deletions.
4 changes: 2 additions & 2 deletions build/cmake/versions.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Define the versions of the various dependencies to build.
set(API_UMBRELLA_STATIC_SITE_VERSION e54283244890e3d5ffeb7ec00dde2f5eaa778d28)
set(API_UMBRELLA_STATIC_SITE_HASH 037b9317f6b08eb2073060c1beed16e2)
set(API_UMBRELLA_STATIC_SITE_VERSION c02b8869cafb063deb7f9436d0137b0ea6e652aa)
set(API_UMBRELLA_STATIC_SITE_HASH 8998cd6cab3708257e4d47e169802d2f)
set(BUNDLER_VERSION 1.15.1)
set(BUNDLER_HASH fa6ec48f94faffe4987f89b4b85409fd6a4ddce8d46f779acdc26d041eb200d7)
set(ELASTICSEARCH_VERSION 2.4.5)
Expand Down
3 changes: 3 additions & 0 deletions src/api-umbrella/web-app/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ gem "sass-rails", "~> 5.0"
gem "bootstrap-sass", "~> 3.3.7"
gem "font-awesome-rails", "~> 4.7.0"

# Table-less models
gem "active_attr", "~> 0.10.1"

# Bundle gems for the local environment. Make sure to
# put test-only gems in this group so their generators
# and rake tasks are available in development mode:
Expand Down
4 changes: 4 additions & 0 deletions src/api-umbrella/web-app/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ GEM
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_attr (0.10.1)
activemodel (>= 3.0.2, < 5.2)
activesupport (>= 3.0.2, < 5.2)
activejob (4.2.8)
activesupport (= 4.2.8)
globalid (>= 0.3.0)
Expand Down Expand Up @@ -295,6 +298,7 @@ PLATFORMS
ruby

DEPENDENCIES
active_attr (~> 0.10.1)
awesome_print (~> 1.7.0)
bootstrap-sass (~> 3.3.7)
brakeman
Expand Down
9 changes: 5 additions & 4 deletions src/api-umbrella/web-app/app/mailers/contact_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
class ContactMailer < ActionMailer::Base
default :from => "noreply@#{ApiUmbrellaConfig[:web][:default_host]}"

def contact_email(contact)
@contact = contact
def contact_email(contact_params)
Rails.logger.info("CONTACT PARAMS: #{contact_params.inspect}")
@contact = Contact.new(contact_params)

mail :reply_to => contact.email,
:subject => "#{ApiUmbrellaConfig[:site_name]} Contact Message from #{contact.email}",
mail :reply_to => @contact.email,
:subject => "#{ApiUmbrellaConfig[:site_name]} Contact Message from #{@contact.email}",
:to => ApiUmbrellaConfig[:web][:contact_form_email]
end
end
10 changes: 7 additions & 3 deletions src/api-umbrella/web-app/app/models/contact.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
class Contact
include ActiveModel::Model
include ActiveAttr::Model

attr_accessor :name, :email, :api, :subject, :message
attribute :name, :type => String
attribute :email, :type => String
attribute :api, :type => String
attribute :subject, :type => String
attribute :message, :type => String

validates :name,
:presence => { :message => "Provide your first name." }
Expand All @@ -21,7 +25,7 @@ class Contact

def deliver
if self.valid?
ContactMailer.contact_email(self).deliver_later
ContactMailer.contact_email(self.as_json).deliver_later
else
false
end
Expand Down
50 changes: 50 additions & 0 deletions test/apis/v1/contact/test_email.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require_relative "../../../test_helper"

class Test::Apis::V1::Contact::TestEmail < Minitest::Test
include ApiUmbrellaTestHelpers::Setup
include ApiUmbrellaTestHelpers::DelayedJob

def setup
super
setup_server

response = Typhoeus.delete("http://127.0.0.1:#{$config["mailhog"]["api_port"]}/api/v1/messages")
assert_response_code(200, response)
end

def test_sends_email
user = FactoryGirl.create(:api_user, {
:roles => ["api-umbrella-contact-form"],
})

response = Typhoeus.post("https://127.0.0.1:9081/api-umbrella/v1/contact.json", http_options.deep_merge({
:headers => {
"X-Api-Key" => user["api_key"],
"Content-Type" => "application/x-www-form-urlencoded",
},
:body => {
:contact => {
:name => "Foo",
:email => "[email protected]",
:api => "Example API",
:subject => "Support",
:message => "Message body",
},
},
}))
assert_response_code(200, response)
data = MultiJson.load(response.body)
assert_equal(["submitted"], data.keys)

messages = delayed_job_sent_messages
assert_equal(1, messages.length)
message = messages.first

assert_equal(["[email protected]"], message["Content"]["Headers"]["To"])
assert_equal(["API Umbrella Contact Message from [email protected]"], message["Content"]["Headers"]["Subject"])
assert_equal(["noreply@localhost"], message["Content"]["Headers"]["From"])
assert_equal(["[email protected]"], message["Content"]["Headers"]["Reply-To"])
assert_equal(["text/plain; charset=UTF-8"], message["Content"]["Headers"]["Content-Type"])
assert_equal("Name: Foo\r\nEmail: [email protected]\r\nAPI: Example API\r\nSubject: Support\r\n\r\n-------------------------------------\r\n\r\nMessage body\r\n\r\n-------------------------------------", message["Content"]["Body"])
end
end
49 changes: 49 additions & 0 deletions test/apis/v1/contact/test_permissions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require_relative "../../../test_helper"

class Test::Apis::V1::Contact::TestPermissions < Minitest::Test
include ApiUmbrellaTestHelpers::Setup
parallelize_me!

def setup
super
setup_server
end

def test_forbids_api_key_without_role
user = FactoryGirl.create(:api_user, {
:roles => ["xapi-umbrella-contact-form", "api-umbrella-contact-formx"],
})

response = make_request(user)
assert_response_code(401, response)
end

def test_allows_api_key_with_role
user = FactoryGirl.create(:api_user, {
:roles => ["api-umbrella-contact-form"],
})

response = make_request(user)
assert_response_code(200, response)
end

private

def make_request(user)
Typhoeus.post("https://127.0.0.1:9081/api-umbrella/v1/contact.json", http_options.deep_merge({
:headers => {
"X-Api-Key" => user["api_key"],
"Content-Type" => "application/x-www-form-urlencoded",
},
:body => {
:contact => {
:name => "Foo",
:email => "[email protected]",
:api => "Example API",
:subject => "Support",
:message => "Message body",
},
},
}))
end
end
89 changes: 89 additions & 0 deletions test/apis/v1/contact/test_validations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require_relative "../../../test_helper"

class Test::Apis::V1::Contact::TestValidations < Minitest::Test
include ApiUmbrellaTestHelpers::Setup
parallelize_me!

def setup
super
setup_server
end

def test_required
response = make_request({})
assert_response_code(422, response)
data = MultiJson.load(response.body)
assert_equal(["errors"], data.keys)
assert_equal([
{
"code" => "INVALID_INPUT",
"message" => "Provide your first name.",
"field" => "name",
"full_message" => "Name: Provide your first name.",
},
{
"code" => "INVALID_INPUT",
"message" => "Provide your email address.",
"field" => "email",
"full_message" => "Email: Provide your email address.",
},
{
"code" => "INVALID_INPUT",
"message" => "Provide the API.",
"field" => "api",
"full_message" => "Api: Provide the API.",
},
{
"code" => "INVALID_INPUT",
"message" => "Provide a subject.",
"field" => "subject",
"full_message" => "Subject: Provide a subject.",
},
{
"code" => "INVALID_INPUT",
"message" => "Provide a message.",
"field" => "message",
"full_message" => "Message: Provide a message.",
},
].sort_by { |e| e["full_message"] }, data["errors"].sort_by { |e| e["full_message"] })
end

def test_email_format
response = make_request({
:name => "Foo",
:email => "foo@example",
:api => "Example API",
:subject => "Support",
:message => "Message body",
})
assert_response_code(422, response)
data = MultiJson.load(response.body)
assert_equal(["errors"], data.keys)
assert_equal([
{
"code" => "INVALID_INPUT",
"message" => "Provide a valid email address.",
"field" => "email",
"full_message" => "Email: Provide a valid email address.",
},
], data["errors"])
end

private

def make_request(attributes)
user = FactoryGirl.create(:api_user, {
:roles => ["api-umbrella-contact-form"],
})

Typhoeus.post("https://127.0.0.1:9081/api-umbrella/v1/contact.json", http_options.deep_merge({
:headers => {
"X-Api-Key" => user["api_key"],
"Content-Type" => "application/x-www-form-urlencoded",
},
:body => {
:contact => attributes,
},
}))
end
end
32 changes: 32 additions & 0 deletions test/static_site/test_contact.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require_relative "../test_helper"

class Test::StaticSite::TestContact < Minitest::Capybara::Test
include Capybara::Screenshot::MiniTestPlugin
include ApiUmbrellaTestHelpers::Setup
include ApiUmbrellaTestHelpers::DelayedJob

def setup
super
setup_server

response = Typhoeus.delete("http://127.0.0.1:#{$config["mailhog"]["api_port"]}/api/v1/messages")
assert_response_code(200, response)
end

def test_submission
visit "/contact/"
assert_text("Contact us directly")

fill_in "Name", :with => "Foo"
fill_in "Email", :with => "[email protected]"
fill_in "Which API are you inquiring about?", :with => "My API"
select "Other", :from => "What can we help you with?"
fill_in "Message", :with => "Test message"
click_button "Send"

assert_text("Thanks for sending your message. We'll be in touch.")

messages = delayed_job_sent_messages
assert_equal(1, messages.length)
end
end
3 changes: 3 additions & 0 deletions test/support/test_namespaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Analytics; end
module ApiScopes; end
module Apis; end
module Config; end
module Contact; end
module Users; end
module WebsiteBackends; end
end
Expand All @@ -44,5 +45,7 @@ module ResponseRewriting; end
module Routing; end
end

module StaticSite; end

module TestingSanityChecks; end
end

0 comments on commit 96862e0

Please sign in to comment.