From 5b8e34aa1d441e11ca313f73c1386dc4ba40c660 Mon Sep 17 00:00:00 2001 From: Georg Gadinger Date: Fri, 6 Jan 2023 13:37:22 +0100 Subject: [PATCH] add integration specs for changing locales --- app/controllers/application_controller.rb | 4 +- spec/integration/locale_switch_spec.rb | 85 +++++++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 spec/integration/locale_switch_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 718f760e..05b7ad28 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,9 +11,7 @@ class ApplicationController < ActionController::Base before_action :find_active_announcements # check if user wants to read - def switch_locale(&) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - return I18n.with_locale("en", &) if Rails.env.test? - + def switch_locale(&) locale = params[:lang] || current_user&.locale || cookies[:lang] || "en" if params[:lang] && current_user.present? current_user.locale = locale diff --git a/spec/integration/locale_switch_spec.rb b/spec/integration/locale_switch_spec.rb new file mode 100644 index 00000000..47ea9dfa --- /dev/null +++ b/spec/integration/locale_switch_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require "rails_helper" +require "nokogiri" + +describe "locale switching", type: :request do + matcher :have_html_lang do |expected_lang| + description { %(have the HTML "lang" attribute set to #{expected_lang.inspect}) } + + match do |result| + Nokogiri::HTML.parse(result).css("html[lang=#{expected_lang}]").size == 1 + end + end + + context "when user not signed in" do + it "uses the default :en locale" do + get "/" + expect(response.body).to have_html_lang "en" + expect(response.cookies["lang"]).to eq "en" + end + + context "when ?lang param is given" do + it "changes the locale" do + # 1. ensure we start with the default :en locale + get "/" + expect(response.body).to have_html_lang "en" + expect(response.cookies["lang"]).to eq "en" + + # 2. switch the language to en-xx + get "/?lang=en-xx" + expect(response.body).to have_html_lang "en-xx" + expect(response.cookies["lang"]).to eq "en-xx" + + # 3. remove the language parameter again + get "/" + expect(response.body).to have_html_lang "en-xx" + expect(response.cookies["lang"]).to be_nil # no new cookie here, it's already en-xx + end + end + end + + context "when user is signed in" do + let(:user) { FactoryBot.create(:user, password: "test1234", locale:) } + let(:locale) { "en" } + + before do + post "/sign_in", params: { user: { login: user.email, password: user.password } } + end + + it "uses the en locale" do + get "/" + expect(response.body).to have_html_lang "en" + expect(response.cookies["lang"]).to be_nil # no new cookie here, already set by the sign in + end + + context "when ?lang param is given" do + it "changes the locale" do + # 1. ensure we start with the :en locale + get "/" + expect(response.body).to have_html_lang "en" + expect(response.cookies["lang"]).to be_nil # no new cookie here, already set by the sign in + + # 2. switch the language to en-xx + expect { get "/?lang=en-xx" }.to change { user.reload.locale }.from("en").to("en-xx") + expect(response.body).to have_html_lang "en-xx" + expect(response.cookies["lang"]).to eq "en-xx" + + # 3. remove the language parameter again + get "/" + expect(response.body).to have_html_lang "en-xx" + expect(response.cookies["lang"]).to be_nil # no new cookie here, it's already en-xx + end + end + + context "when user has a different locale set" do + let(:locale) { "fi" } + + it "uses the different locale" do + get "/" + expect(response.body).to have_html_lang "fi" + expect(response.cookies["lang"]).to be_nil # no new cookie here, already set by the sign in + end + end + end +end