diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 0ff5442f..04959e9a 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,4 +1,17 @@ module ApplicationCable class Connection < ActionCable::Connection::Base + identified_by :current_user + + def connect + set_current_user || reject_unauthorized_connection + end + + private + + def set_current_user + if session ||= Session.find_by(id: cookies.signed[:session_id]) + self.current_user = session.user + end + end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b9811248..8c4c5e2d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,28 +1,12 @@ class ApplicationController < ActionController::Base + include Authentication # Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has. allow_browser versions: :modern include Pagy::Backend add_flash_types :success, :notice - helper_method :current_user rescue_from CanCan::AccessDenied do - flash[:alert] = t("flash.un_authorize") - - if current_user.nil? - redirect_to login_path - else - redirect_to request.referer || thaalis_all_path(CURR_YR) - end - end - - private - - def current_user - @current_user ||= User.select(:id, :slug).find(session[:user_id]) if session[:user_id] - end - - def logged_in? - redirect_to thaalis_all_path(CURR_YR), notice: t("flash.active_session") if session[:user_id] + return_to_default_path(type: :alert, msg: "flash.un_authorize") end end diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb new file mode 100644 index 00000000..181379f2 --- /dev/null +++ b/app/controllers/concerns/authentication.rb @@ -0,0 +1,64 @@ +module Authentication + extend ActiveSupport::Concern + + included do + before_action :require_authentication + helper_method :authenticated?, :current_user + end + + class_methods do + def allow_unauthenticated_access(**options) + skip_before_action :require_authentication, **options + end + end + + private + + def authenticated? + resume_session + end + + def require_authentication + resume_session || request_authentication + end + + def resume_session + Current.session ||= find_session_by_cookie + end + + def find_session_by_cookie + Session.find_by(id: cookies.signed[:session_id]) if cookies.signed[:session_id] + end + + def request_authentication + session[:return_to_after_authenticating] = request.url + redirect_to login_path, alert: t("flash.un_authorize") + end + + def after_authentication_url + return_to_url = session.delete(:return_to_after_authenticating) + return_to_url.present? ? "#{return_to_url}.html" : thaalis_all_path(CURR_YR, format: :html) + end + + def start_new_session_for(user) + user.sessions.create!(user_agent: request.user_agent, ip_address: request.remote_ip).tap do |session| + Current.session = session + cookies.signed.permanent[:session_id] = {value: session.id, httponly: true, same_site: :lax} + end + end + + def terminate_session + Rails.cache.delete("user_#{current_user.id}_role") + Current.session.destroy + cookies.delete(:session_id) + end + + def return_to_default_path(type: :notice, msg: "flash.active_session") + flash[type] = t(msg) + redirect_to thaalis_all_path(CURR_YR) + end + + def current_user + @current_user ||= Current.user + end +end diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 21ab591e..c32536fd 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -1,5 +1,6 @@ class PagesController < ApplicationController - before_action :logged_in? + allow_unauthenticated_access + before_action :return_to_default_path, if: -> { authenticated? } def home end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 4cb354f8..4506568f 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,26 +1,25 @@ class SessionsController < ApplicationController - before_action :logged_in?, only: :new + allow_unauthenticated_access only: %i[new create] + before_action :return_to_default_path, only: %i[new create], if: -> { authenticated? } + # rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_url, alert: "Try again later." } def new end def create - user = User.authenticate_by(user_params) - if user - session[:user_id] = user.id + if user ||= User.authenticate_by(user_params) + start_new_session_for user respond_to do |format| - format.all { redirect_to thaalis_all_path(CURR_YR, format: :html), success: t(".success") } + format.all { redirect_to after_authentication_url, success: t(".success") } end else - flash.now.alert = t(".error") - render :new, status: :not_found + redirect_to login_path, alert: t(".error") end end def destroy - Rails.cache.delete("user_#{current_user.id}_role") - session[:user_id] = nil + terminate_session redirect_to login_path, success: t(".success") end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a25faee1..8493ca3e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -38,7 +38,7 @@ def destroy if current_user.is?("admin") && current_user.id != @user&.id redirect_to users_path, success: t(".success") else - session[:user_id] = nil + terminate_session redirect_to login_path, success: t(".success") end end diff --git a/app/models/current.rb b/app/models/current.rb new file mode 100644 index 00000000..2bef56da --- /dev/null +++ b/app/models/current.rb @@ -0,0 +1,4 @@ +class Current < ActiveSupport::CurrentAttributes + attribute :session + delegate :user, to: :session, allow_nil: true +end diff --git a/app/models/session.rb b/app/models/session.rb new file mode 100644 index 00000000..cf376fb2 --- /dev/null +++ b/app/models/session.rb @@ -0,0 +1,3 @@ +class Session < ApplicationRecord + belongs_to :user +end diff --git a/app/models/user.rb b/app/models/user.rb index 1d65f77e..1f649297 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ class User < ApplicationRecord rolify has_secure_password + has_many :sessions, dependent: :destroy # * Callbacks include NameCallback diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 01541f98..4311e7f8 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -27,7 +27,7 @@ <%= render "shared/flash_messages" if flash.present? %> - <% if current_user.present? %> + <% if authenticated? %>
<%= render "shared/navbar/navbar" %> @@ -39,6 +39,6 @@ <%= yield %> - <%= render "shared/footer" if current_user.blank? %> + <%= render "shared/footer" unless authenticated? %> diff --git a/db/migrate/20241220050110_create_sessions.rb b/db/migrate/20241220050110_create_sessions.rb new file mode 100644 index 00000000..8102f13a --- /dev/null +++ b/db/migrate/20241220050110_create_sessions.rb @@ -0,0 +1,11 @@ +class CreateSessions < ActiveRecord::Migration[8.0] + def change + create_table :sessions do |t| + t.references :user, null: false, foreign_key: true + t.string :ip_address + t.string :user_agent + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 7fec87da..cc913a32 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2024_02_09_122254) do +ActiveRecord::Schema[8.0].define(version: 2024_12_20_050110) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -55,6 +55,15 @@ t.index ["slug"], name: "index_sabeels_on_slug", unique: true end + create_table "sessions", force: :cascade do |t| + t.bigint "user_id", null: false + t.string "ip_address" + t.string "user_agent" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["user_id"], name: "index_sessions_on_user_id" + end + create_table "thaalis", force: :cascade do |t| t.bigint "sabeel_id", null: false t.integer "year", null: false @@ -102,6 +111,7 @@ t.index ["user_id"], name: "index_users_roles_on_user_id" end + add_foreign_key "sessions", "users" add_foreign_key "thaalis", "sabeels" add_foreign_key "transactions", "thaalis" end diff --git a/spec/factories/sessions.rb b/spec/factories/sessions.rb new file mode 100644 index 00000000..98bc0166 --- /dev/null +++ b/spec/factories/sessions.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :session do + user + ip_address { Faker::Internet.public_ip_v4_address } + user_agent { Faker::Internet.user_agent } + end +end diff --git a/spec/features/layout/navbar_spec.rb b/spec/features/layout/navbar_spec.rb index 5939535b..7ca1c35b 100644 --- a/spec/features/layout/navbar_spec.rb +++ b/spec/features/layout/navbar_spec.rb @@ -3,10 +3,10 @@ require "rails_helper" RSpec.describe "Navbar" do - # * Accessibile by logged-in user + # * Accessible by logged-in user describe "logged in" do before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit thaalis_all_path(CURR_YR) end diff --git a/spec/features/sabeels/active_spec.rb b/spec/features/sabeels/active_spec.rb index 0bb57ff4..49bc5060 100644 --- a/spec/features/sabeels/active_spec.rb +++ b/spec/features/sabeels/active_spec.rb @@ -9,7 +9,7 @@ let!(:sabeels) { create_list(:burhani_sabeel_taking_thaali, 2) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit sabeels_active_path(apt.downcase) end diff --git a/spec/features/sabeels/destroy_spec.rb b/spec/features/sabeels/destroy_spec.rb index df21d21b..f58ef9a5 100644 --- a/spec/features/sabeels/destroy_spec.rb +++ b/spec/features/sabeels/destroy_spec.rb @@ -7,7 +7,7 @@ let(:sabeel) { create(:sabeel) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit sabeel_path(sabeel) click_on "Delete" end diff --git a/spec/features/sabeels/edit_spec.rb b/spec/features/sabeels/edit_spec.rb index 6d8aa739..be2ddf6a 100644 --- a/spec/features/sabeels/edit_spec.rb +++ b/spec/features/sabeels/edit_spec.rb @@ -7,7 +7,7 @@ let(:sabeel) { create(:sabeel) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit edit_sabeel_path(sabeel) end diff --git a/spec/features/sabeels/inactive_spec.rb b/spec/features/sabeels/inactive_spec.rb index 8182fb29..52bcc8b1 100644 --- a/spec/features/sabeels/inactive_spec.rb +++ b/spec/features/sabeels/inactive_spec.rb @@ -11,7 +11,7 @@ # rubocop:enable RSpec/LetSetup before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit sabeels_inactive_path(apt.downcase) end diff --git a/spec/features/sabeels/index_spec.rb b/spec/features/sabeels/index_spec.rb index e8c52800..25123560 100644 --- a/spec/features/sabeels/index_spec.rb +++ b/spec/features/sabeels/index_spec.rb @@ -7,7 +7,7 @@ let(:user) { create(:user) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:sabeel, 2) visit sabeels_path end diff --git a/spec/features/sabeels/new_spec.rb b/spec/features/sabeels/new_spec.rb index 8c94e15e..2d1f72e1 100644 --- a/spec/features/sabeels/new_spec.rb +++ b/spec/features/sabeels/new_spec.rb @@ -4,7 +4,7 @@ RSpec.describe "Sabeel New template" do before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit new_sabeel_path end diff --git a/spec/features/sabeels/show_spec.rb b/spec/features/sabeels/show_spec.rb index 5afee10f..2791ce64 100644 --- a/spec/features/sabeels/show_spec.rb +++ b/spec/features/sabeels/show_spec.rb @@ -9,7 +9,7 @@ let(:thaali) { sabeel.thaalis.first } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit sabeel_path(sabeel) end diff --git a/spec/features/sessions/destroy_spec.rb b/spec/features/sessions/destroy_spec.rb index e1f66294..708d2d71 100644 --- a/spec/features/sessions/destroy_spec.rb +++ b/spec/features/sessions/destroy_spec.rb @@ -6,7 +6,7 @@ let(:user) { create(:user) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit thaalis_all_path(CURR_YR) click_on "Log out" end diff --git a/spec/features/statistics/sabeels_spec.rb b/spec/features/statistics/sabeels_spec.rb index 2b46c433..9e939153 100644 --- a/spec/features/statistics/sabeels_spec.rb +++ b/spec/features/statistics/sabeels_spec.rb @@ -6,7 +6,7 @@ let(:user) { create(:user) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:burhani_sabeel_taking_thaali, 2) create_list(:burhani_sabeel_took_thaali, 2) visit statistics_sabeels_path diff --git a/spec/features/statistics/thaalis_spec.rb b/spec/features/statistics/thaalis_spec.rb index e6535546..418b5c0d 100644 --- a/spec/features/statistics/thaalis_spec.rb +++ b/spec/features/statistics/thaalis_spec.rb @@ -7,7 +7,7 @@ let(:thaalis) { Thaali.for_year(CURR_YR) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:taking_thaali, 2) create_list(:taking_thaali_dues_cleared, 2) visit statistics_thaalis_path diff --git a/spec/features/thaalis/all_spec.rb b/spec/features/thaalis/all_spec.rb index 5ca565d6..35550f8b 100644 --- a/spec/features/thaalis/all_spec.rb +++ b/spec/features/thaalis/all_spec.rb @@ -9,7 +9,7 @@ let(:thaalis) { Thaali.first(2) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:thaali, 2, year:) visit thaalis_all_path(year) diff --git a/spec/features/thaalis/complete_spec.rb b/spec/features/thaalis/complete_spec.rb index ebc1b524..05a834fa 100644 --- a/spec/features/thaalis/complete_spec.rb +++ b/spec/features/thaalis/complete_spec.rb @@ -8,7 +8,7 @@ let(:thaalis) { Thaali.dues_cleared_in(CURR_YR) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:taking_thaali_dues_cleared, 2) visit thaalis_complete_path(CURR_YR) diff --git a/spec/features/thaalis/destroy_spec.rb b/spec/features/thaalis/destroy_spec.rb index fdb05960..c2c91814 100644 --- a/spec/features/thaalis/destroy_spec.rb +++ b/spec/features/thaalis/destroy_spec.rb @@ -7,7 +7,7 @@ let(:thaali) { create(:thaali) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit thaali_path(thaali) click_on "Delete" end diff --git a/spec/features/thaalis/edit_spec.rb b/spec/features/thaalis/edit_spec.rb index 05761f4f..cc94f46d 100644 --- a/spec/features/thaalis/edit_spec.rb +++ b/spec/features/thaalis/edit_spec.rb @@ -7,7 +7,7 @@ let(:thaali) { create(:thaali) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit edit_thaali_path(thaali) end diff --git a/spec/features/thaalis/new_spec.rb b/spec/features/thaalis/new_spec.rb index 027642f6..ea720f47 100644 --- a/spec/features/thaalis/new_spec.rb +++ b/spec/features/thaalis/new_spec.rb @@ -6,7 +6,7 @@ let(:sabeel) { create(:sabeel) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit new_sabeel_thaali_path(sabeel) end diff --git a/spec/features/thaalis/pending_spec.rb b/spec/features/thaalis/pending_spec.rb index 905e777e..ad2db0ad 100644 --- a/spec/features/thaalis/pending_spec.rb +++ b/spec/features/thaalis/pending_spec.rb @@ -8,7 +8,7 @@ let(:thaalis) { Thaali.first(2) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) create_list(:taking_thaali, 2) visit thaalis_pending_path(CURR_YR) diff --git a/spec/features/thaalis/show_spec.rb b/spec/features/thaalis/show_spec.rb index ff42f9e4..8138b10d 100644 --- a/spec/features/thaalis/show_spec.rb +++ b/spec/features/thaalis/show_spec.rb @@ -8,7 +8,7 @@ let(:thaali) { create(:taking_thaali_partial_amount_paid) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit thaali_path(thaali) end diff --git a/spec/features/transactions/all_spec.rb b/spec/features/transactions/all_spec.rb index 0a754031..ef153e02 100644 --- a/spec/features/transactions/all_spec.rb +++ b/spec/features/transactions/all_spec.rb @@ -8,14 +8,14 @@ let!(:transactions) { create_list(:transaction, 2) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit transactions_all_path end # * ALL user types - describe "visited by any user type can", :js do - it { expect(page).to have_title "Transactions" } + it { expect(page).to have_title "Transactions" } + describe "visited by any user type can", :js do it_behaves_like "view transaction records" describe "search" do diff --git a/spec/features/transactions/destroy_spec.rb b/spec/features/transactions/destroy_spec.rb index b66a889a..a2b794f7 100644 --- a/spec/features/transactions/destroy_spec.rb +++ b/spec/features/transactions/destroy_spec.rb @@ -7,7 +7,7 @@ let(:transaction) { create(:transaction) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit transaction_path(transaction) click_on "Delete" end diff --git a/spec/features/transactions/edit_spec.rb b/spec/features/transactions/edit_spec.rb index 3e992733..5a3cab1e 100644 --- a/spec/features/transactions/edit_spec.rb +++ b/spec/features/transactions/edit_spec.rb @@ -7,7 +7,7 @@ let(:total) { transaction.thaali.total } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit edit_transaction_path(transaction) end diff --git a/spec/features/transactions/new_spec.rb b/spec/features/transactions/new_spec.rb index 6034a119..fe8f2d3d 100644 --- a/spec/features/transactions/new_spec.rb +++ b/spec/features/transactions/new_spec.rb @@ -3,9 +3,10 @@ require "rails_helper" RSpec.describe "Transaction new template" do + let(:thaali) { create(:thaali) } + before do - page.set_rack_session(user_id: user.id) - thaali = create(:thaali) + sign_in(user) visit new_thaali_transaction_path(thaali) end diff --git a/spec/features/transactions/show_spec.rb b/spec/features/transactions/show_spec.rb index 5001fa3f..2d96ac75 100644 --- a/spec/features/transactions/show_spec.rb +++ b/spec/features/transactions/show_spec.rb @@ -7,7 +7,7 @@ let(:transaction) { create(:transaction) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit transaction_path(transaction) end diff --git a/spec/features/users/destroy_spec.rb b/spec/features/users/destroy_spec.rb index 832ce866..6871b1ea 100644 --- a/spec/features/users/destroy_spec.rb +++ b/spec/features/users/destroy_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe "User destroy" do - before { page.set_rack_session(user_id: user.id) } + before { sign_in(user) } # * Admins & Members # * ITSELF diff --git a/spec/features/users/edit_spec.rb b/spec/features/users/edit_spec.rb index 9c5e3071..d1e56b7f 100644 --- a/spec/features/users/edit_spec.rb +++ b/spec/features/users/edit_spec.rb @@ -6,7 +6,7 @@ let(:user) { create(:user_admin_or_member) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit edit_user_path(user) end diff --git a/spec/features/users/index_spec.rb b/spec/features/users/index_spec.rb index 5561f53c..e46d992b 100644 --- a/spec/features/users/index_spec.rb +++ b/spec/features/users/index_spec.rb @@ -6,7 +6,7 @@ let!(:other_user) { create(:user) } before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit users_path end diff --git a/spec/features/users/new_spec.rb b/spec/features/users/new_spec.rb index 2c8d3778..85ac140e 100644 --- a/spec/features/users/new_spec.rb +++ b/spec/features/users/new_spec.rb @@ -9,7 +9,7 @@ # rubocop:disable Rails/SkipsModelValidations Role.insert_all([{name: "member"}, {name: "viewer"}]) # rubocop:enable Rails/SkipsModelValidations - page.set_rack_session(user_id: user.id) + sign_in(user) visit thaalis_all_path(CURR_YR) end diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb index deb9c6e6..a9a3c8aa 100644 --- a/spec/features/users/show_spec.rb +++ b/spec/features/users/show_spec.rb @@ -5,7 +5,7 @@ RSpec.describe "User show template" do before do - page.set_rack_session(user_id: user.id) + sign_in(user) visit user_path(user) end diff --git a/spec/models/session_spec.rb b/spec/models/session_spec.rb new file mode 100644 index 00000000..bfb1ed34 --- /dev/null +++ b/spec/models/session_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe Session do + subject(:session) { build(:session) } + + context "with associations" do + it { is_expected.to belong_to(:user) } + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 86e76803..280dac0f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -5,6 +5,10 @@ RSpec.describe User do subject(:user) { build(:user) } + context "with associations" do + it { is_expected.to have_many(:sessions).dependent(:destroy) } + end + context "when validating" do context "with password" do it { is_expected.to validate_length_of(:password).is_at_least(6).with_short_message("must be more than 6 characters") } diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 9da9ad11..a4b063ba 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -9,8 +9,6 @@ # Add additional requires below this line. Rails is not loaded until this point! require "rspec/rails" require "capybara/rspec" -require "rack_session_access/capybara" -require "action_view" # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are @@ -67,11 +65,7 @@ config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") -end -Shoulda::Matchers.configure do |config| - config.integrate do |with| - with.test_framework :rspec - with.library :rails - end + # Add custom sign in helper + config.include SignInHelper, type: :feature end diff --git a/spec/support/selenium_setup.rb b/spec/support/capybara.rb similarity index 100% rename from spec/support/selenium_setup.rb rename to spec/support/capybara.rb diff --git a/spec/support/shoulda_matchers.rb b/spec/support/shoulda_matchers.rb new file mode 100644 index 00000000..7d045f35 --- /dev/null +++ b/spec/support/shoulda_matchers.rb @@ -0,0 +1,6 @@ +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end +end diff --git a/spec/support/sign_in_helper.rb b/spec/support/sign_in_helper.rb new file mode 100644 index 00000000..6e19e3c4 --- /dev/null +++ b/spec/support/sign_in_helper.rb @@ -0,0 +1,16 @@ +module SignInHelper + def sign_in(user) + visit login_path + fill_in "sessions_its", with: user.its + fill_in "sessions_password", with: user.password + # Check if JS is enabled or disabled in test + if Capybara.current_driver == Capybara.javascript_driver + # Use JavaScript to click on login + page.execute_script("arguments[0].click();", find('input[name="commit"]')) + sleep 0.03 + else + # W/O JavaScript + click_on "Login" + end + end +end