diff --git a/app/components/tab_navigation_component.html.erb b/app/components/tab_navigation_component.html.erb new file mode 100644 index 00000000000..c9a89a8598a --- /dev/null +++ b/app/components/tab_navigation_component.html.erb @@ -0,0 +1,15 @@ +<%= content_tag(:nav, aria: { label: }, **tag_options) do %> + +<% end %> diff --git a/app/components/tab_navigation_component.rb b/app/components/tab_navigation_component.rb new file mode 100644 index 00000000000..c9b78092788 --- /dev/null +++ b/app/components/tab_navigation_component.rb @@ -0,0 +1,15 @@ +class TabNavigationComponent < BaseComponent + attr_reader :label, :routes, :tag_options + + def initialize(label:, routes:, **tag_options) + @label = label + @routes = routes + @tag_options = tag_options + end + + def is_current_path?(path) + request.path == URI.parse(path).path + rescue URI::InvalidURIError + false + end +end diff --git a/app/controllers/concerns/sign_in_a_b_test_concern.rb b/app/controllers/concerns/sign_in_a_b_test_concern.rb new file mode 100644 index 00000000000..01db563b03a --- /dev/null +++ b/app/controllers/concerns/sign_in_a_b_test_concern.rb @@ -0,0 +1,5 @@ +module SignInABTestConcern + def sign_in_a_b_test_bucket + AbTests::SIGN_IN.bucket(sp_session[:request_id] || session.id) + end +end diff --git a/app/controllers/sign_up/completions_controller.rb b/app/controllers/sign_up/completions_controller.rb index 5cb9cb4438f..d8d47742c5c 100644 --- a/app/controllers/sign_up/completions_controller.rb +++ b/app/controllers/sign_up/completions_controller.rb @@ -1,6 +1,7 @@ module SignUp class CompletionsController < ApplicationController include SecureHeadersConcern + include SignInABTestConcern before_action :confirm_two_factor_authenticated before_action :verify_confirmed, if: :ial2? @@ -84,7 +85,10 @@ def analytics_attributes(page_occurence) end def track_completion_event(last_page) - analytics.user_registration_complete(**analytics_attributes(last_page)) + analytics.user_registration_complete( + **analytics_attributes(last_page), + sign_in_a_b_test_bucket:, + ) end def pii diff --git a/app/controllers/sign_up/registrations_controller.rb b/app/controllers/sign_up/registrations_controller.rb index 0f26e3fb160..b56270d8e12 100644 --- a/app/controllers/sign_up/registrations_controller.rb +++ b/app/controllers/sign_up/registrations_controller.rb @@ -2,6 +2,7 @@ module SignUp class RegistrationsController < ApplicationController include PhoneConfirmation include ApplicationHelper # for ial2_requested? + include SignInABTestConcern before_action :confirm_two_factor_authenticated, only: [:destroy_confirm] before_action :require_no_authentication @@ -14,7 +15,11 @@ def new analytics: analytics, attempts_tracker: irs_attempts_api_tracker, ) - analytics.user_registration_enter_email_visit + @sign_in_a_b_test_bucket = sign_in_a_b_test_bucket + analytics.user_registration_enter_email_visit( + sign_in_a_b_test_bucket: @sign_in_a_b_test_bucket, + from_sign_in: params[:source] == 'sign_in', + ) render :new, locals: { request_id: nil }, formats: :html end diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 65f59aa7e7c..1cc09669b83 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -7,6 +7,7 @@ class SessionsController < Devise::SessionsController include RememberDeviceConcern include Ial2ProfileConcern include Api::CsrfTokenConcern + include SignInABTestConcern rescue_from ActionController::InvalidAuthenticityToken, with: :redirect_to_signin @@ -19,15 +20,17 @@ class SessionsController < Devise::SessionsController after_action :add_csrf_token_header_to_response, only: [:keepalive] def new - analytics.sign_in_page_visit( - flash: flash[:alert], - stored_location: session['user_return_to'], - ) override_csp_for_google_analytics @request_id = request_id_if_valid @ial = sp_session_ial @browser_is_ie11 = browser_is_ie11? + @sign_in_a_b_test_bucket = sign_in_a_b_test_bucket + analytics.sign_in_page_visit( + flash: flash[:alert], + stored_location: session['user_return_to'], + sign_in_a_b_test_bucket: @sign_in_a_b_test_bucket, + ) super end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 13c640ffb53..b9901011db7 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2701,12 +2701,14 @@ def session_total_duration_timeout # @param [String] flash # @param [String] stored_location + # @param [String] sign_in_a_b_test_bucket # tracks when a user visits the sign in page - def sign_in_page_visit(flash:, stored_location:, **extra) + def sign_in_page_visit(flash:, stored_location:, sign_in_a_b_test_bucket:, **extra) track_event( 'Sign in page visited', flash: flash, stored_location: stored_location, + sign_in_a_b_test_bucket:, **extra, ) end @@ -2952,8 +2954,15 @@ def webauthn_setup_visit(platform_authenticator:, errors:, enabled_mfa_methods_c end # Tracks when user visits enter email page - def user_registration_enter_email_visit - track_event('User Registration: enter email visited') + # @param [String] sign_in_a_b_test_bucket + # @param [Boolean] from_sign_in + def user_registration_enter_email_visit(sign_in_a_b_test_bucket:, from_sign_in:, **extra) + track_event( + 'User Registration: enter email visited', + sign_in_a_b_test_bucket:, + from_sign_in:, + **extra, + ) end # @param [Integer] enabled_mfa_methods_count @@ -2982,6 +2991,7 @@ def user_registration_cancellation(request_came_from:, **extra) # @param [String] service_provider_name # @param [String] page_occurence # @param [String] needs_completion_screen_reason + # @param [String] sign_in_a_b_test_bucket # @param [Array] sp_request_requested_attributes # @param [Array] sp_session_requested_attributes def user_registration_complete( @@ -2989,6 +2999,7 @@ def user_registration_complete( service_provider_name:, page_occurence:, needs_completion_screen_reason:, + sign_in_a_b_test_bucket:, sp_session_requested_attributes:, sp_request_requested_attributes: nil, ialmax: nil, @@ -3001,6 +3012,7 @@ def user_registration_complete( service_provider_name: service_provider_name, page_occurence: page_occurence, needs_completion_screen_reason: needs_completion_screen_reason, + sign_in_a_b_test_bucket:, sp_request_requested_attributes: sp_request_requested_attributes, sp_session_requested_attributes: sp_session_requested_attributes, **extra, diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index a719f4ba22f..00525d3702f 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -10,9 +10,23 @@ <% if decorated_session.sp_name %> <%= render 'sign_up/registrations/sp_registration_heading' %> -<% else %> +<% elsif @sign_in_a_b_test_bucket == :default %> <%= render PageHeadingComponent.new.with_content(decorated_session.new_session_heading) %> <% end %> + +<% if @sign_in_a_b_test_bucket == :tabbed %> + <%= render TabNavigationComponent.new( + label: t('account.login.tab_navigation'), + routes: [ + { text: t('links.next'), path: new_user_session_url(request_id: @request_id) }, + { text: t('links.create_account'), path: sign_up_email_url(request_id: @request_id, source: :sign_in) }, + ], + class: 'margin-bottom-4', + ) %> + + <%= render PageHeadingComponent.new.with_content(t('headings.sign_in_existing_users')) %> +<% end %> + <%= render 'shared/sp_alert', section: 'sign_in' %> <%= simple_form_for( @@ -35,20 +49,20 @@ field_options: { required: true }, ) %> <%= f.input :request_id, as: :hidden, input_html: { value: @request_id } %> -
- <%= f.submit t('links.next'), full_width: true, wide: false %> + <%= f.submit t('links.next'), full_width: true, wide: false %> + <% if @sign_in_a_b_test_bucket == :default %>

<%= t('headings.create_account_with_sp.cta', app_name: APP_NAME) %>

<%= link_to( t('links.create_account'), - sign_up_email_url(request_id: @request_id), - class: 'usa-button usa-button--big usa-button--outline usa-button--full-width margin-top-1', + sign_up_email_url(request_id: @request_id, source: :sign_in), + class: 'usa-button usa-button--big usa-button--outline usa-button--full-width margin-bottom-105', ) %> -
+ <% end %> <% end %> <% if @ial && desktop_device? %> -
+
<%= link_to( t('account.login.piv_cac'), login_piv_cac_url, diff --git a/app/views/sign_up/registrations/new.html.erb b/app/views/sign_up/registrations/new.html.erb index c18bca98ebf..279bd9d3712 100644 --- a/app/views/sign_up/registrations/new.html.erb +++ b/app/views/sign_up/registrations/new.html.erb @@ -2,7 +2,24 @@ <%= render 'shared/sp_alert', section: 'sign_up' %> -<%= render PageHeadingComponent.new.with_content(t('titles.registrations.new')) %> +<% if @sign_in_a_b_test_bucket == :tabbed %> + <% if decorated_session.sp_name %> + <%= render 'sign_up/registrations/sp_registration_heading' %> + <% end %> + + <%= render TabNavigationComponent.new( + label: t('account.login.tab_navigation'), + routes: [ + { text: t('links.next'), path: new_user_session_url(request_id: sp_session[:request_id]) }, + { text: t('links.create_account'), path: sign_up_email_path(request_id: sp_session[:request_id]) }, + ], + class: 'margin-bottom-4', + ) %> + + <%= render PageHeadingComponent.new.with_content(t('headings.create_account_new_users')) %> +<% else %> + <%= render PageHeadingComponent.new.with_content(t('titles.registrations.new')) %> +<% end %> <%= simple_form_for( @register_user_email_form, diff --git a/config/application.yml.default b/config/application.yml.default index dc0d86c0267..25a606864d5 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -306,6 +306,7 @@ session_timeout_warning_seconds: 150 session_total_duration_timeout_in_minutes: 720 ses_configuration_set_name: '' set_remember_device_session_expiration: false +sign_in_a_b_testing: '{"default":100,"tabbed":0}' sp_handoff_bounce_max_seconds: 2 show_user_attribute_deprecation_warnings: false otp_min_attempts_remaining_warning_count: 3 diff --git a/config/initializers/ab_tests.rb b/config/initializers/ab_tests.rb index 361813ce4f3..58279e248c4 100644 --- a/config/initializers/ab_tests.rb +++ b/config/initializers/ab_tests.rb @@ -19,6 +19,11 @@ module AbTests }, ) + SIGN_IN = AbTestBucket.new( + experiment_name: 'Sign In Experience', + buckets: IdentityConfig.store.sign_in_a_b_testing, + ) + def self.in_person_cta_variant_testing_buckets buckets = Hash.new percents = IdentityConfig.store.in_person_cta_variant_testing_percents diff --git a/config/locales/account/en.yml b/config/locales/account/en.yml index db5af6e59b9..14757b71586 100644 --- a/config/locales/account/en.yml +++ b/config/locales/account/en.yml @@ -73,6 +73,7 @@ en: login: ie_not_supported: Internet Explorer 11 is no longer supported as of %{date} piv_cac: Sign in with your government employee ID + tab_navigation: Account creation tabs navigation: access_services: Access your government benefits and services from your %{app_name} account. diff --git a/config/locales/account/es.yml b/config/locales/account/es.yml index 6fe8b55f70a..15da56e0a52 100644 --- a/config/locales/account/es.yml +++ b/config/locales/account/es.yml @@ -74,6 +74,7 @@ es: login: ie_not_supported: Internet Explorer 11 dejó de ser compatible a partir del %{date} piv_cac: Inicie sesión con su identificación de empleado del gobierno + tab_navigation: Pestañas de creación de cuenta navigation: access_services: Acceda a los beneficios y servicios de su gobierno desde su cuenta %{app_name}. diff --git a/config/locales/account/fr.yml b/config/locales/account/fr.yml index efa01267c15..7d00e071849 100644 --- a/config/locales/account/fr.yml +++ b/config/locales/account/fr.yml @@ -79,6 +79,7 @@ fr: login: ie_not_supported: Internet Explorer 11 n’est plus pris en charge à partir du %{date} piv_cac: Connectez-vous avec votre ID d’employé du gouvernement + tab_navigation: Onglets de création de compte navigation: access_services: Accédez à vos avantages et services gouvernementaux depuis votre compte %{app_name}. diff --git a/config/locales/headings/en.yml b/config/locales/headings/en.yml index e5a43d89591..767d44b2d05 100644 --- a/config/locales/headings/en.yml +++ b/config/locales/headings/en.yml @@ -22,6 +22,7 @@ en: prompt: Are you sure you want to cancel? confirmations: new: Send another confirmation email + create_account_new_users: Create an account for new users create_account_with_sp: cta: First time using %{app_name}? sp_text: is using %{app_name} to allow you to sign in to your account safely and @@ -60,6 +61,7 @@ en: new: Use your PIV/CAC card to secure your account residential_address: Current residential address session_timeout_warning: Need more time? + sign_in_existing_users: Sign in for existing users sign_in_with_sp: Sign in to continue to %{sp} sign_in_without_sp: Sign in sp_handoff_bounced: There was a problem connecting to %{sp_name} diff --git a/config/locales/headings/es.yml b/config/locales/headings/es.yml index 01e8ebd575c..e46608025c5 100644 --- a/config/locales/headings/es.yml +++ b/config/locales/headings/es.yml @@ -22,6 +22,7 @@ es: prompt: '¿Estas seguro que quieres cancelar?' confirmations: new: Enviar otro email de confirmación + create_account_new_users: Crear una cuenta para usuarios nuevos create_account_with_sp: cta: '¿Es la primera vez que utiliza %{app_name}?' sp_text: está utilizando %{app_name} para permitirle iniciar sesión en su cuenta @@ -60,6 +61,7 @@ es: new: Use su tarjeta PIV/CAC para asegurar su cuenta residential_address: Dirección residencial actual session_timeout_warning: '¿Necesita más tiempo?' + sign_in_existing_users: Iniciar sesión para usuarios existentes sign_in_with_sp: Iniciar sesión para continuar con %{sp} sign_in_without_sp: Iniciar sesión sp_handoff_bounced: Hubo un problema al conectarse a %{sp_name} diff --git a/config/locales/headings/fr.yml b/config/locales/headings/fr.yml index 491d5073c65..bbb66734b05 100644 --- a/config/locales/headings/fr.yml +++ b/config/locales/headings/fr.yml @@ -22,6 +22,7 @@ fr: prompt: Es-tu sûre de vouloir annuler? confirmations: new: Envoyer un autre courriel de confirmation + create_account_new_users: Créer un compte pour les nouveaux utilisateurs create_account_with_sp: cta: Première fois que vous utilisez %{app_name}? sp_text: utilise %{app_name} pour vous permettre de vous connecter à votre @@ -63,6 +64,7 @@ fr: new: Utilisez votre carte PIV/CAC pour sécuriser votre compte residential_address: Adresse de résidence actuelle session_timeout_warning: Vous avez besoin de plus de temps? + sign_in_existing_users: S’identifier pour les utilisateurs existants sign_in_with_sp: Connectez-vous pour continuer à %{sp} sign_in_without_sp: Connexion sp_handoff_bounced: Un problème est survenu lors de la connexion à %{sp_name} diff --git a/lib/identity_config.rb b/lib/identity_config.rb index c25562d9e9d..8b6cbfa4aec 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -410,6 +410,7 @@ def self.build_store(config_map) config.add(:ses_configuration_set_name, type: :string) config.add(:set_remember_device_session_expiration, type: :boolean) config.add(:show_user_attribute_deprecation_warnings, type: :boolean) + config.add(:sign_in_a_b_testing, type: :json, options: { symbolize_names: true }) config.add(:skip_encryption_allowed_list, type: :json) config.add(:sp_handoff_bounce_max_seconds, type: :integer) config.add(:state_tracking_enabled, type: :boolean) diff --git a/spec/components/previews/tab_navigation_component_preview.rb b/spec/components/previews/tab_navigation_component_preview.rb new file mode 100644 index 00000000000..218be364117 --- /dev/null +++ b/spec/components/previews/tab_navigation_component_preview.rb @@ -0,0 +1,30 @@ +class TabNavigationComponentPreview < BaseComponentPreview + # @!group Preview + def default + render TabNavigationComponent.new( + label: 'Navigation', + routes: [ + { path: lookbook_path('preview'), text: 'Preview' }, + { path: lookbook_path('workbench'), text: 'Workbench' }, + ], + ) + end + # @!endgroup + + # @param label text + def workbench(label: 'Navigation') + render TabNavigationComponent.new( + label:, + routes: [ + { path: lookbook_path('preview'), text: 'Preview' }, + { path: lookbook_path('workbench'), text: 'Workbench' }, + ], + ) + end + + private + + def lookbook_path(example) + Lookbook::Engine.routes.url_helpers.lookbook_preview_path("tab_navigation/#{example}") + end +end diff --git a/spec/components/tab_navigation_component_spec.rb b/spec/components/tab_navigation_component_spec.rb new file mode 100644 index 00000000000..46225b53aa5 --- /dev/null +++ b/spec/components/tab_navigation_component_spec.rb @@ -0,0 +1,82 @@ +require 'rails_helper' + +RSpec.describe TabNavigationComponent, type: :component do + let(:label) { 'Navigation' } + let(:routes) { [{ path: '/first', text: 'First' }, { path: '/second', text: 'Second' }] } + let(:tag_options) { { label:, routes: } } + + subject(:rendered) do + render_inline TabNavigationComponent.new(**tag_options) + end + + it 'renders labelled navigation' do + expect(rendered).to have_css('nav[aria-label="Navigation"]') + expect(rendered).to have_link('First') { |link| !is_current_link?(link) } + expect(rendered).to have_link('Second') { |link| !is_current_link?(link) } + end + + context 'with tag options' do + let(:tag_options) { super().merge(data: { foo: 'bar' }) } + + it 'renders with tag options forwarded to navigation' do + expect(rendered).to have_css('nav[data-foo="bar"]') + end + end + + context 'with link for current request' do + before do + allow(request).to receive(:path).and_return('/first') + end + + it 'renders current link as highlighted' do + expect(rendered).to have_link('First') { |link| is_current_link?(link) } + expect(rendered).to have_link('Second') { |link| !is_current_link?(link) } + end + + context 'with routes defining full URL' do + let(:routes) do + [ + { path: 'https://example.com/first', text: 'First' }, + { path: 'https://example.com/second', text: 'Second' }, + ] + end + + it 'renders current link as highlighted' do + expect(rendered).to have_link('First') { |link| is_current_link?(link) } + expect(rendered).to have_link('Second') { |link| !is_current_link?(link) } + end + end + + context 'with routes including query parameters' do + let(:routes) do + [ + { path: '/first?foo=bar', text: 'First' }, + { path: '/second?foo=bar', text: 'Second' }, + ] + end + + it 'renders current link as highlighted' do + expect(rendered).to have_link('First') { |link| is_current_link?(link) } + expect(rendered).to have_link('Second') { |link| !is_current_link?(link) } + end + end + + context 'unparseable route' do + let(:routes) do + [ + { path: '😬', text: 'First' }, + { path: '😬', text: 'Second' }, + ] + end + + it 'renders gracefully without highlighted link' do + expect(rendered).to have_link('First') { |link| !is_current_link?(link) } + expect(rendered).to have_link('Second') { |link| !is_current_link?(link) } + end + end + end + + def is_current_link?(link) + link.matches_css?('[aria-current="page"]:not(.usa-button--outline)') + end +end diff --git a/spec/controllers/concerns/sign_in_a_b_test_concern_spec.rb b/spec/controllers/concerns/sign_in_a_b_test_concern_spec.rb new file mode 100644 index 00000000000..61acd114b21 --- /dev/null +++ b/spec/controllers/concerns/sign_in_a_b_test_concern_spec.rb @@ -0,0 +1,38 @@ +require 'rails_helper' + +RSpec.describe SignInABTestConcern, type: :controller do + controller ApplicationController do + include SignInABTestConcern + end + + describe '#sign_in_a_b_test_bucket' do + subject(:sign_in_a_b_test_bucket) { controller.sign_in_a_b_test_bucket } + + let(:sp_session) { {} } + + before do + allow(session).to receive(:id).and_return('session-id') + allow(controller).to receive(:sp_session).and_return(sp_session) + allow(AbTests::SIGN_IN).to receive(:bucket) do |discriminator| + case discriminator + when 'session-id' + :default + when 'request-id' + :tabbed + end + end + end + + it 'returns the bucket based on session id' do + expect(sign_in_a_b_test_bucket).to eq(:default) + end + + context 'with associated sp session request id' do + let(:sp_session) { { request_id: 'request-id' } } + + it 'returns the bucket based on request id' do + expect(sign_in_a_b_test_bucket).to eq(:tabbed) + end + end + end +end diff --git a/spec/controllers/sign_up/completions_controller_spec.rb b/spec/controllers/sign_up/completions_controller_spec.rb index d4bc5ca2325..a3525044fde 100644 --- a/spec/controllers/sign_up/completions_controller_spec.rb +++ b/spec/controllers/sign_up/completions_controller_spec.rb @@ -135,6 +135,7 @@ before do stub_analytics allow(@analytics).to receive(:track_event) + allow(controller).to receive(:sign_in_a_b_test_bucket).and_return(:default) @linker = instance_double(IdentityLinker) allow(@linker).to receive(:link_identity).and_return(true) allow(IdentityLinker).to receive(:new).and_return(@linker) @@ -158,6 +159,7 @@ service_provider_name: subject.decorated_session.sp_name, page_occurence: 'agency-page', needs_completion_screen_reason: :new_sp, + sign_in_a_b_test_bucket: :default, sp_request_requested_attributes: nil, sp_session_requested_attributes: nil, ) @@ -217,6 +219,7 @@ service_provider_name: subject.decorated_session.sp_name, page_occurence: 'agency-page', needs_completion_screen_reason: :new_sp, + sign_in_a_b_test_bucket: :default, sp_request_requested_attributes: nil, sp_session_requested_attributes: ['email'], ) diff --git a/spec/controllers/sign_up/registrations_controller_spec.rb b/spec/controllers/sign_up/registrations_controller_spec.rb index 6f3511ad465..8a28af1c2d5 100644 --- a/spec/controllers/sign_up/registrations_controller_spec.rb +++ b/spec/controllers/sign_up/registrations_controller_spec.rb @@ -26,6 +26,34 @@ to raise_error(Mime::Type::InvalidMimeType) end + it 'tracks visit event' do + stub_analytics + allow(controller).to receive(:sign_in_a_b_test_bucket).and_return(:default) + + expect(@analytics).to receive(:track_event).with( + 'User Registration: enter email visited', + sign_in_a_b_test_bucket: :default, + from_sign_in: false, + ) + + get :new + end + + context 'with source parameter' do + it 'tracks visit event' do + stub_analytics + allow(controller).to receive(:sign_in_a_b_test_bucket).and_return(:default) + + expect(@analytics).to receive(:track_event).with( + 'User Registration: enter email visited', + sign_in_a_b_test_bucket: :default, + from_sign_in: true, + ) + + get :new, params: { source: :sign_in } + end + end + context 'IdV unavailable' do before do allow(IdentityConfig.store).to receive(:idv_available).and_return(false) diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 6bcf286f36e..ff494bf471d 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -590,10 +590,15 @@ it 'tracks page visit, any alert flashes, and the Devise stored location' do stub_analytics allow(controller).to receive(:flash).and_return(alert: 'hello') + allow(controller).to receive(:sign_in_a_b_test_bucket).and_return(:default) subject.session['user_return_to'] = mock_valid_site - properties = { flash: 'hello', stored_location: mock_valid_site } - expect(@analytics).to receive(:track_event).with('Sign in page visited', properties) + expect(@analytics).to receive(:track_event).with( + 'Sign in page visited', + flash: 'hello', + stored_location: mock_valid_site, + sign_in_a_b_test_bucket: :default, + ) get :new end diff --git a/spec/support/features/session_helper.rb b/spec/support/features/session_helper.rb index b1e4d6e8b47..2db90c3916d 100644 --- a/spec/support/features/session_helper.rb +++ b/spec/support/features/session_helper.rb @@ -390,11 +390,11 @@ def sign_up_user_from_sp_without_confirming_email(email) click_sign_in_from_landing_page_then_click_create_account - expect(current_url).to eq sign_up_email_url(request_id: sp_request_id) + expect(current_url).to eq sign_up_email_url(request_id: sp_request_id, source: :sign_in) visit_landing_page_and_click_create_account_with_request_id(sp_request_id) - expect(current_url).to eq sign_up_email_url(request_id: sp_request_id) + expect(current_url).to eq sign_up_email_url(request_id: sp_request_id, source: :sign_in) expect_branded_experience submit_form_with_invalid_email diff --git a/spec/views/devise/sessions/new.html.erb_spec.rb b/spec/views/devise/sessions/new.html.erb_spec.rb index c67741e89df..e9f5c5c3854 100644 --- a/spec/views/devise/sessions/new.html.erb_spec.rb +++ b/spec/views/devise/sessions/new.html.erb_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe 'devise/sessions/new.html.erb' do + let(:sign_in_a_b_test_bucket) { :default } + before do allow(view).to receive(:resource).and_return(build_stubbed(:user)) allow(view).to receive(:resource_name).and_return(:user) @@ -9,6 +11,7 @@ allow(view).to receive(:decorated_session).and_return(SessionDecorator.new) allow_any_instance_of(ActionController::TestRequest).to receive(:path). and_return('/') + @sign_in_a_b_test_bucket = sign_in_a_b_test_bucket assign(:ial, 1) end @@ -30,10 +33,10 @@ render end - it 'includes a link to log in' do + it 'has a localized page heading' do render - expect(rendered).to have_content(t('headings.sign_in_without_sp')) + expect(rendered).to have_selector('h1', text: t('headings.sign_in_without_sp')) end it 'includes a link to create a new account' do @@ -41,7 +44,7 @@ expect(rendered). to have_link( - t('links.create_account'), href: sign_up_email_url(request_id: nil) + t('links.create_account'), href: sign_up_email_url(request_id: nil, source: :sign_in) ) end @@ -170,4 +173,23 @@ expect(rendered).to have_selector('input.email') end end + + context 'with tabbed layout A/B test' do + let(:sign_in_a_b_test_bucket) { :tabbed } + + it 'has a localized page heading' do + render + + expect(rendered).to have_selector('h1', text: t('headings.sign_in_existing_users')) + end + + it 'includes a link to create a new account' do + render + + expect(rendered).to have_link( + t('links.create_account'), + href: sign_up_email_url(request_id: nil, source: :sign_in), + ) + end + end end diff --git a/spec/views/sign_up/registrations/new.html.erb_spec.rb b/spec/views/sign_up/registrations/new.html.erb_spec.rb index de563bc00a1..b86a300aebd 100644 --- a/spec/views/sign_up/registrations/new.html.erb_spec.rb +++ b/spec/views/sign_up/registrations/new.html.erb_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' describe 'sign_up/registrations/new.html.erb' do + let(:sign_in_a_b_test_bucket) { :default } + let(:sp) do build_stubbed( :service_provider, @@ -8,12 +10,14 @@ return_to_sp_url: 'www.awesomeness.com', ) end + before do allow(view).to receive(:current_user).and_return(nil) @register_user_email_form = RegisterUserEmailForm.new( analytics: FakeAnalytics.new, attempts_tracker: IrsAttemptsApiTrackingHelper::FakeAttemptsTracker.new, ) + @sign_in_a_b_test_bucket = sign_in_a_b_test_bucket view_context = ActionController::Base.new.view_context allow(view_context).to receive(:new_user_session_url). and_return('https://www.example.com/') @@ -37,7 +41,7 @@ render end - it 'has a localized header' do + it 'has a localized page heading' do render expect(rendered).to have_selector('h1', text: t('titles.registrations.new')) @@ -75,4 +79,23 @@ [target='_blank'][rel='noopener noreferrer']", ) end + + context 'with tabbed layout A/B test' do + let(:sign_in_a_b_test_bucket) { :tabbed } + + it 'has a localized page heading' do + render + + expect(rendered).to have_selector('h1', text: t('headings.create_account_new_users')) + end + + it 'includes a link to sign in' do + render + + expect(rendered).to have_link( + t('links.next'), + href: new_user_session_url(request_id: nil), + ) + end + end end