make sure the form action will be valid even if the page is viewed from a mounting point other than /

did committed Mar 18, 2016
commit 5cb88117023e5d3dee8eee2f38286036693c48b3
Showing 4 changed files with 66 additions and 14 deletions
locomotive/steam/liquid/tags/model_form.rb b/lib/locomotive/steam/liquid/tags/model_form.rb +21 -6
@@ @@ -65,19 +65,34 @@ module Locomotive
end
def prepare_form_attributes(options)
- action = options[:action]
+ url = action_url(options)
attributes = options.slice(:id, :class, :name, :novalidate)
- if action.blank? && options[:json]
- action = current_context['path']
- action = (action.blank? ? 'index' : action) + '.json'
+ { method: 'POST', enctype: 'multipart/form-data' }.merge(attributes).tap do |_attributes|
+ _attributes[:action] = url if url
end
+ end
- { method: 'POST', enctype: 'multipart/form-data' }.merge(attributes).tap do |_attributes|
- _attributes[:action] = action if action
+ def action_url(options)
+ url = options[:action]
+
+ if url.blank?
+ if options[:json]
+ url = current_context['path'].blank? ? '/' : current_context['path']
+ url + 'index.json'
+ else
+ nil
+ end
+ else
+ url = '/' + url unless url.starts_with?('/')
+ url_builder.prefix(url)
end
end
+ def url_builder
+ current_context.registers[:services].url_builder
+ end
+
end
end
locomotive/steam/services/url_builder_service.rb b/lib/locomotive/steam/services/url_builder_service.rb +2 -2
@@ @@ -30,12 +30,12 @@ module Locomotive
"/entry_submissions/#{content_type.slug}"
end
- private
-
def prefix(url)
mounted_on ? "#{mounted_on}#{url}" : url
end
+ private
+
def mounted_on
return if request.nil?
request.env['steam.mounted_on']
spec/integration/server/contact_form_spec.rb +16 -3
@@ @@ -96,7 +96,9 @@ describe 'ContactForm' do
context 'when valid' do
- let(:response) { post_contact_form(url, params, false, true) }
+ let(:env) { {} }
+ let(:follow_redirect) { true }
+ let(:response) { post_contact_form(url, params, false, follow_redirect, env) }
it 'returns a success status' do
expect(response.status).to eq 200
@@ @@ -106,6 +108,17 @@ describe 'ContactForm' do
expect(response.body.to_s).to include 'Thank you John'
end
+ context 'mounted on a different path than /' do
+
+ let(:env) { { 'steam.mounted_on' => '/foo/bar/' } }
+ let(:follow_redirect) { false }
+
+ it 'redirects to the location prefixed by the mounted_on path' do
+ expect(response.location).to match(/\A\/foo\/bar\/\/events\?submitted_type_slug=messages\&submitted_entry_slug=john/)
+ end
+
+ end
+
end
end
@@ @@ -162,13 +175,13 @@ describe 'ContactForm' do
end
- def post_contact_form(url, params, json = false, follow_redirect = false)
+ def post_contact_form(url, params, json = false, follow_redirect = false, env = {})
if json
url += '.json'
params = params.symbolize_keys
end
- post url, params
+ post url, params, env
follow_redirect! if follow_redirect
spec/unit/liquid/tags/model_form_spec.rb +27 -3
@@ @@ -8,10 +8,12 @@ describe Locomotive::Steam::Liquid::Tags::ModelForm do
allow(Rack::Csrf).to receive(:token).and_return(42)
end
- let(:request) { instance_double('Request', env: {}) }
+ let(:path) { '' }
+ let(:env) { {} }
+ let(:request) { instance_double('Request', env: env) }
let(:source) { "{% model_form 'newsletter_addresses' %}Newsletter Form{% endmodel_form %}" }
let(:services) { Locomotive::Steam::Services.build_instance(request) }
- let(:context) { ::Liquid::Context.new({ path: '' }, {}, { services: services }) }
+ let(:context) { ::Liquid::Context.new({ 'path' => path }, {}, { services: services }) }
subject { render_template(source, context) }
@@ @@ -35,7 +37,29 @@ describe Locomotive::Steam::Liquid::Tags::ModelForm do
describe 'json enabled' do
let(:source) { "{% model_form 'newsletter_addresses', json: true %}Newsletter Form{% endmodel_form %}" }
- it { is_expected.to eq %(<form method="POST" enctype="multipart/form-data" action="index.json"><input type="hidden" name="content_type_slug" value="newsletter_addresses" /><input type="hidden" name="token" value="42" />Newsletter Form</form>) }
+ it { is_expected.to eq %(<form method="POST" enctype="multipart/form-data" action="/index.json"><input type="hidden" name="content_type_slug" value="newsletter_addresses" /><input type="hidden" name="token" value="42" />Newsletter Form</form>) }
+
+ context 'rendered at /_app/foo/preview' do
+
+ let(:path) { '/_app/foo/preview/' }
+ let(:env) { { 'steam.mounted_on' => '/_app/foo/preview/' } }
+ it { is_expected.to eq %(<form method="POST" enctype="multipart/form-data" action="/_app/foo/preview/index.json"><input type="hidden" name="content_type_slug" value="newsletter_addresses" /><input type="hidden" name="token" value="42" />Newsletter Form</form>) }
+
+ end
+
+ end
+
+ describe 'specifying an action' do
+
+ let(:source) { "{% model_form 'newsletter_addresses', action: 'foo/bar' %}Newsletter Form{% endmodel_form %}" }
+ it { is_expected.to eq %(<form method="POST" enctype="multipart/form-data" action="/foo/bar"><input type="hidden" name="content_type_slug" value="newsletter_addresses" /><input type="hidden" name="token" value="42" />Newsletter Form</form>) }
+
+ context 'mounted_on is not empty' do
+
+ let(:env) { { 'steam.mounted_on' => '/_app/foo/preview' } }
+ it { is_expected.to eq %(<form method="POST" enctype="multipart/form-data" action="/_app/foo/preview/foo/bar"><input type="hidden" name="content_type_slug" value="newsletter_addresses" /><input type="hidden" name="token" value="42" />Newsletter Form</form>) }
+
+ end
end