Files
ubicloud/spec/routes/web/spec_helper.rb
Jeremy Evans 7acbf5cd5a Switch to multi phase login
Multi phase login is the practice where you first ask for the login
(email) and not the password, and after you know the related account,
you show the options available for login to that account.

Multi phase login allows social login and OIDC login to be part of the
normal login flow. Once we know the related account, we can show the
authentication options for the account, and not include options that
are not available. If the account does not have a password and is only
connected to one social login provider, then the password field does
not display, and the only button is the button login to the social
login provider.

For accounts that only allow password authentication, multi phase login
results in an extra step during login. However, I think it's better to
support non-password authentication as part of the normal login flow.

A minor improvement I made during this process is if the user enters
their login, but cannot remember their password, if they click the
"Forgot your password?" link, their email address is already filled in.

Ideally, the login field would be have the readonly attribute during
the second login phase.  However, I found that this negatively affects
password managers such as 1password.  So I didn't mark the field as
readonly.  I left the handling of the readonly attribute as boolean,
in case we want to use readonly attributes elsewhere.

This required relatively few spec changes outside of the auth tests,
since almost all tests that test for logged in accounts use the login
helper method.
2025-07-09 04:32:44 +09:00

94 lines
2.6 KiB
Ruby

# frozen_string_literal: true
require_relative "../spec_helper"
Warning.ignore(:mismatched_indentations, File.expand_path("coverage/views")) if defined?(SimpleCov)
css_file = File.expand_path("../../../assets/css/app.css", __dir__)
File.write(css_file, "") unless File.file?(css_file)
require "capybara"
require "capybara/rspec"
if ENV["CLOVER_FREEZE"] == "1"
require "capybara/validate_html5"
Capybara.custom_html_validation do |doc, &block|
css = "*[required=true], *[required=false], input[checked=true], input[checked=false]"
doc.css(css).map(&block)
end
end
Gem.suffix_pattern
Capybara.app = Clover.app
Capybara.exact = true
module RackTestPlus
include Rack::Test::Methods
def app
Capybara.app
end
end
# Work around Middleware should not call #each error.
# Fix bugs with cookies, because the default behavior
# reuses the rack env of the last request, which is not valid.
class Capybara::RackTest::Browser
remove_method :refresh
def refresh
visit last_request.fullpath
end
end
RSpec.configure do |config|
config.include RackTestPlus
config.include Capybara::DSL
config.after do
Capybara.reset_sessions!
Capybara.use_default_driver
end
class RSpec::Matchers::DSL::Matcher
def self.flash_message_matcher(expected_type, expected_message)
match do |page|
next false unless page.has_css?("#flash-#{expected_type}")
actual_message = page.find_by_id("flash-#{expected_type}").text
if expected_message.is_a?(String)
actual_message == expected_message
else
actual_message =~ expected_message
end
end
failure_message do |page|
<<~MESSAGE
#{"expected: ".rjust(16)}#{expected_type} - #{expected_message}
#{"actual error: ".rjust(16)}#{page.has_css?("#flash-error") ? page.find_by_id("flash-error").text : "(no error message)"}
#{"actual notice: ".rjust(16)}#{page.has_css?("#flash-notice") ? page.find_by_id("flash-notice").text : "(no notice message)"}
MESSAGE
end
end
end
RSpec::Matchers.define :have_flash_notice do |expected_message|
flash_message_matcher(:notice, expected_message)
end
RSpec::Matchers.define :have_flash_error do |expected_message|
flash_message_matcher(:error, expected_message)
end
config.include(Module.new do
def login(email = TEST_USER_EMAIL, password = TEST_USER_PASSWORD)
visit "/login"
fill_in "Email Address", with: email
click_button "Sign in"
fill_in "Password", with: password
click_button "Sign in"
expect(page.title).to end_with("Dashboard")
end
end)
end