Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dpc-portal-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ make portal
# Prepare the environment
docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml up db --wait
docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint "bundle exec rails db:create db:migrate RAILS_ENV=test" dpc_portal
docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint "bundle exec rails assets:clobber" dpc_portal

# Run the tests
echo "┌─────────────────────────------─┐"
Expand All @@ -28,6 +29,7 @@ echo "│ │"
echo "└────────────────────────-----───┘"

docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint "bundle exec rubocop" dpc_portal
docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint "rails assets:clobber tmp:clear" dpc_portal
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because the asset cache isn't getting rebuilt between CI runs on our code builders, and it causes tests to fail whenever we need to add an image somewhere. This forces it in CI.

docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint "bundle exec rspec" dpc_portal
docker compose -p start-v1-portals -f docker-compose.yml -f docker-compose.portals.yml run --entrypoint docker/system-tests.sh dpc_portal
echo "┌────────────────────────────────┐"
Expand Down
26 changes: 26 additions & 0 deletions dpc-portal/app/assets/stylesheets/login.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,29 @@
line-height: 1.8;
}
}

.last-used-login-wrapper {
display: block;
text-align: center;
padding: 0.5rem;
background-color: #e1f3f8;
border: 1px solid #a8ddec;
border-radius: 4px;
box-sizing: border-box;
width: 100%;

// Make the button stretch across the full with.
.usa-button {
width: 100%;
margin-bottom: 0.5rem;
}

.last-used-login-wrapper__badge {
font-size: 0.875rem;
font-weight: bold;
color: #005ea2;
letter-spacing: 0.5px;
margin: 0;
line-height: 1;
}
}
26 changes: 18 additions & 8 deletions dpc-portal/app/components/page/session/login_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@
<div class="bg-white padding-y-3 padding-x-5 border border-base-lighter">
<h1 class="margin-bottom-0">DPC Portal sign in</h1>
<p>Sign in with your DPC Portal Login.gov account</p>
<%= button_to @login_path, class: 'usa-button width-full margin-bottom-1', data: { turbo: false } do %>
<span class="clear-login-button__logo">CLEAR</span>
<% end %>
<%= button_to @login_path, class: 'usa-button width-full margin-bottom-1', data: { turbo: false } do %>
<span class="idme-login-button__logo">ID.me</span>
<% end %>
<%= button_to @login_path, class: 'usa-button width-full margin-bottom-1', data: { turbo: false } do %>
<span class="lg-login-button__logo">Login.gov</span>

<%# Build a login button for each CSP %>
<%
csps = [
{ id: :clear, logo_class: 'clear-login-button__logo', text: 'CLEAR' },
{ id: :id_me, logo_class: 'idme-login-button__logo', text: 'ID.me' },
{ id: :login_dot_gov, logo_class: 'lg-login-button__logo', text: 'Login.gov' }
]
%>
<% csps.each do |csp| %>
<% is_last_used = (@last_used_csp == csp[:id]) %>
<div class="<%= class_names('last-used-login-wrapper margin-bottom-1': is_last_used) %>">
<%= button_to @login_path, class: 'usa-button width-full margin-bottom-1', data: { turbo: false } do %>
<span class="<%= csp[:logo_class] %>"><%= csp[:text] %></span>
<% end %>
<%= content_tag(:span, 'LAST USED', class: 'last-used-login-wrapper__badge') if is_last_used %>
</div>
<% end %>

<%= render(Core::Navigation::SystemUseAgreementLinkComponent.new) %>
<div class="line-separator"></div>
<p>
Expand Down
3 changes: 2 additions & 1 deletion dpc-portal/app/components/page/session/login_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ module Page
module Session
# Renders the log in page
class LoginComponent < ViewComponent::Base
def initialize(login_path)
def initialize(login_path, last_used_csp: nil)
super()
@login_path = login_path
@last_used_csp = last_used_csp
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ module Page
module Session
# Previews the log in page
class LoginComponentPreview < ViewComponent::Preview
def default
render(Page::Session::LoginComponent.new(root_path))
# The really long @param line fails a Rubocop check, but most of the alternatives I tried
# broke LookBook so I turned the check off.
# rubocop:disable Layout/LineLength
# @param last_used_csp select { choices: { "None": "", "CLEAR": "clear", "ID.me": "id_me", "Login.gov": "login_dot_gov" } }
# rubocop:enable Layout/LineLength
def default(last_used_csp: nil)
# Make sure if the user selects "None" that the value passed is actually nil and not "".
csp_value = last_used_csp.presence

render(Page::Session::LoginComponent.new(root_path, last_used_csp: csp_value&.to_sym))
end
end
end
Expand Down
1 change: 1 addition & 0 deletions dpc-portal/app/controllers/login_dot_gov_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def sign_in_and_log(user)

sign_in(user)
session[:logged_in_at] = Time.now
cookies.permanent[:last_used_csp] = :login_dot_gov
Rails.logger.info(['User logged in',
{ actionContext: LoggingConstants::ActionContext::Authentication,
actionType: LoggingConstants::ActionType::UserLoggedIn }])
Expand Down
2 changes: 1 addition & 1 deletion dpc-portal/app/views/users/sessions/new.html.erb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<%= render(Page::Session::LoginComponent.new(omniauth_authorize_path(:login_dot_gov))) %>
<%= render(Page::Session::LoginComponent.new(omniauth_authorize_path(:login_dot_gov), last_used_csp: cookies[:last_used_csp]&.to_sym)) %>
57 changes: 57 additions & 0 deletions dpc-portal/spec/components/page/session/login_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,61 @@
expect(page.find_all('.grid-col-12').size).to eq 2
end
end

describe 'last used csp was CLEAR' do
let(:url) { '/' }
let(:component) { described_class.new(url, last_used_csp: :clear) }
before { render_inline(component) }

it 'wraps only the CLEAR button' do
# Check that the right button has the "last used" wrapper.
expect(page).to have_css('.last-used-login-wrapper .clear-login-button__logo')

# Make sure the other two don't.
expect(page).not_to have_css('.last-used-login-wrapper .idme-login-button__logo')
expect(page).not_to have_css('.last-used-login-wrapper .lg-login-button__logo')
end
end

describe 'last used csp was ID.me' do
let(:url) { '/' }
let(:component) { described_class.new(url, last_used_csp: :id_me) }
before { render_inline(component) }

it 'wraps only the ID.me button' do
# Check that the right button has the "last used" wrapper.
expect(page).to have_css('.last-used-login-wrapper .idme-login-button__logo')

# Make sure the other two don't.
expect(page).not_to have_css('.last-used-login-wrapper .clear-login-button__logo')
expect(page).not_to have_css('.last-used-login-wrapper .lg-login-button__logo')
end
end

describe 'last used csp was Login.gov' do
let(:url) { '/' }
let(:component) { described_class.new(url, last_used_csp: :login_dot_gov) }
before { render_inline(component) }

it 'wraps only the Login.gov button' do
# Check that the right button has the "last used" wrapper.
expect(page).to have_css('.last-used-login-wrapper .lg-login-button__logo')

# Make sure the other two don't.
expect(page).not_to have_css('.last-used-login-wrapper .clear-login-button__logo')
expect(page).not_to have_css('.last-used-login-wrapper .idme-login-button__logo')
end

describe 'no last used csp' do
let(:url) { '/' }
let(:component) { described_class.new(url, last_used_csp: nil) }
before { render_inline(component) }

it "doesn't wrap any buttons" do
expect(page).not_to have_css('.last-used-login-wrapper .clear-login-button__logo')
expect(page).not_to have_css('.last-used-login-wrapper .idme-login-button__logo')
expect(page).not_to have_css('.last-used-login-wrapper .lg-login-button__logo')
end
end
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

end
5 changes: 5 additions & 0 deletions dpc-portal/spec/requests/login_dot_gov_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
post '/auth/login_dot_gov'
follow_redirect!
end
it 'should write a cookie with the last used csp' do
post '/auth/login_dot_gov'
follow_redirect!
expect(cookies[:last_used_csp]).to eq 'login_dot_gov'
end
it 'should not add another user credential' do
expect(CspUser.where(uuid:, csp:).count).to eq 1
expect do
Expand Down
21 changes: 21 additions & 0 deletions dpc-portal/spec/requests/users/sessions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,25 @@
end
end
end

describe 'loads last_used_csp from cookies' do
let(:last_used_csp) { :login_dot_gov }
before do
cookies[:last_used_csp] = last_used_csp.to_s
get sign_in_path
end

# The functionality of which button is wrapped is handled in spec/components/page/session/login_component_spec.rb.
# Here I just wanted to make sure the cookie is read and the value is passed.
it 'should set last_used_csp' do
expect(response.body).to include('last-used-login-wrapper')
end
end

describe 'handles no last_used_csp cookie set' do
it 'should not wrap a csp button' do
get sign_in_path
expect(response.body).not_to include('last-used-login-wrapper')
end
end
end
Loading