Skip to content

Commit 4d913ad

Browse files
committed
Preserve the url hash when changing locales.
To implement this, I had to write a custom javascript handler to handle switching locales. Previously, this was handled for us via Rails's unobtrusive javascript, but I could not find any way to add in additional url parameters to the PATCH request the unobtrusive javascript was generating for us. There's actually an open PR from 2013 to implement support for this here: rails/jquery-ujs#307. I also rewrote the set_locale_spec to enable javascript and be more like what I believe a feature spec should be. I actually don't understand how the spec was even passing before, I would expect it to fail because it was sending a GET request, and we don't have a handler for GET request to update the locale. Maybe rspec/capybara/poltergiest has baked in support for unobtrusive javascript so that the right thing will happen even if you don't have javascript enabled?? That sounds crazy, but it's the only thing I can think of. Regardless of how this was working before, I do believe that the new specs are better. This fixes thewca#2962.
1 parent f216e7a commit 4d913ad

File tree

7 files changed

+68
-21
lines changed

7 files changed

+68
-21
lines changed

WcaOnRails/app/assets/javascripts/application.js

+20
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,23 @@ $(function() {
379379
$(this).text(formatted);
380380
});
381381
});
382+
383+
// Handler for locale changes.
384+
$(function() {
385+
$('#locale-selector').on('click', 'a', function(e) {
386+
e.preventDefault();
387+
e.stopPropagation();
388+
389+
// More or less copied from
390+
// https://github.com/rails/jquery-ujs/blob/9e805c90c8cfc57b39967052e1e9013ccb318cf8/src/rails.js#L215.
391+
var csrfToken = $('meta[name=csrf-token]').attr('content');
392+
var csrfParam = $('meta[name=csrf-param]').attr('content');
393+
var form = $('<form method="post" action="' + this.href + '"></form>');
394+
var metadataInput = '<input name="_method" value="patch" type="hidden" />';
395+
metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
396+
metadataInput += '<input name="current_url" value="' + window.location.toString() + '" type="hidden" />';
397+
398+
form.hide().append(metadataInput).appendTo('body');
399+
form.submit();
400+
});
401+
});

WcaOnRails/app/assets/stylesheets/navbar-static-top.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
margin-right: 10px;
1111
}
1212

13-
.dropdown-menu.countries {
13+
#locale-selector {
1414
min-width: 0;
1515
li {
1616
text-align: left;

WcaOnRails/app/controllers/application_controller.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def update_locale
4343
else
4444
flash[:danger] = I18n.t('users.update_locale.unavailable')
4545
end
46-
redirect_to request.referer || root_path
46+
redirect_to params[:current_url] || root_path
4747
end
4848

4949
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-the-response-body-when-unauthorized

WcaOnRails/app/views/layouts/_navigation.html.erb

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@
9090
<%= flag_icon active_locale_info[:flag_id] %> <span class="hidden-sm"><%= active_locale_info[:name] %></span>
9191
<span class="caret"></span>
9292
</a>
93-
<ul class="dropdown-menu countries" role="menu">
93+
<ul class="dropdown-menu" id="locale-selector" role="menu">
9494
<% Locales::AVAILABLE.each do |l, data| %>
9595
<li class="<%= l == I18n.locale ? "active" : "" %>">
96-
<%= link_to update_locale_path(l), method: :patch do %>
96+
<%= link_to update_locale_path(l) do %>
9797
<%= flag_icon data[:flag_id] %> <%= data[:name] %>
9898
<% end %>
9999
</li>

WcaOnRails/spec/controllers/application_controller_spec.rb

+12
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,17 @@
1515
expect(user.preferred_locale).to eq "fr"
1616
expect(session[:locale]).to eq "fr"
1717
end
18+
19+
it "redirects to given current_url" do
20+
sign_in user
21+
patch :update_locale, params: { locale: :fr, current_url: "http://foo.com#bar" }
22+
expect(response).to redirect_to "http://foo.com#bar"
23+
end
24+
25+
it "redirects to root if not given current_url" do
26+
sign_in user
27+
patch :update_locale, params: { locale: :fr }
28+
expect(response).to redirect_to root_url
29+
end
1830
end
1931
end

WcaOnRails/spec/features/set_locale_spec.rb

+26-17
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,31 @@
33
require "rails_helper"
44

55
RSpec.feature "Set the locale" do
6-
context "As a visitor" do
7-
let(:user) { FactoryBot.create :user }
8-
9-
scenario "visiting the home page and changing the locale" do
10-
visit "/"
11-
expect(I18n.locale).to eq I18n.default_locale
12-
click_on "Français"
13-
visit "/"
14-
expect(I18n.locale).to eq :fr
15-
end
16-
17-
scenario "signing in updates to the preferred_locale" do
18-
user.update!(preferred_locale: "fr")
19-
sign_in user
20-
visit "/"
21-
expect(I18n.locale).to eq :fr
22-
end
6+
scenario "visiting the home page while not signed in and changing the locale", js: true do
7+
visit "/#foo"
8+
expect(page).to have_content "English"
9+
expect(page).not_to have_content "Français"
10+
11+
click_on "English" # Activate the locale selection dropdown.
12+
click_on "Français"
13+
14+
expect(page.current_path).to eq "/"
15+
expect(URI.parse(page.current_url).fragment).to eq "foo"
16+
17+
expect(page).not_to have_content "English"
18+
expect(page).to have_content "Français"
19+
end
20+
21+
scenario "signing in updates to the preferred_locale", js: true do
22+
visit "/"
23+
expect(page).to have_content "English"
24+
expect(page).not_to have_content "Français"
25+
26+
user = FactoryBot.create :user, preferred_locale: "fr"
27+
sign_in user
28+
visit "/"
29+
30+
expect(page).not_to have_content "English"
31+
expect(page).to have_content "Français"
2332
end
2433
end

WcaOnRails/spec/rails_helper.rb

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
# If you are not using ActiveRecord, you can remove this line.
3232
ActiveRecord::Migration.maintain_test_schema!
3333

34+
# To debug feature specs using phantomjs, set `Capybara.javascript_driver = :poltergeist_debug`
35+
# and then call `page.driver.debug` in your feature spec.
36+
Capybara.register_driver :poltergeist_debug do |app|
37+
Capybara::Poltergeist::Driver.new(app, inspector: true, phantomjs: Phantomjs.path, debug: true)
38+
end
39+
3440
Capybara.javascript_driver = :poltergeist
3541
Capybara.server = :webrick
3642

0 commit comments

Comments
 (0)