From ebc3af90eba4e87413e7d686056effed90f57f27 Mon Sep 17 00:00:00 2001 From: Jan Cernik <66427541+jancernik@users.noreply.github.com> Date: Thu, 23 May 2024 10:01:05 -0300 Subject: [PATCH] DEV: More system specs for signup/login (#27150) --- spec/support/omniauth_helpers.rb | 13 +- spec/system/login_spec.rb | 14 +- spec/system/page_objects/modals/login.rb | 54 ++-- spec/system/page_objects/modals/signup.rb | 52 ++-- spec/system/signup_spec.rb | 12 +- spec/system/social_authentication_spec.rb | 360 ++++++++++++++++------ 6 files changed, 340 insertions(+), 165 deletions(-) diff --git a/spec/support/omniauth_helpers.rb b/spec/support/omniauth_helpers.rb index d78383a7b55..b8c4d2e242d 100644 --- a/spec/support/omniauth_helpers.rb +++ b/spec/support/omniauth_helpers.rb @@ -6,11 +6,12 @@ module OmniauthHelpers FULL_NAME = "John Doe" USERNAME = "john" EMAIL = "johndoe@example.com" + UID = "12345" def mock_facebook_auth(email: EMAIL, name: FULL_NAME) OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new( provider: "facebook", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new(email: email, name: name), ) @@ -20,7 +21,7 @@ module OmniauthHelpers def mock_google_auth(email: EMAIL, name: FULL_NAME, verified: true) OmniAuth.config.mock_auth[:google_oauth2] = OmniAuth::AuthHash.new( provider: "google_oauth2", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new(email: email, name: name), extra: { raw_info: { @@ -35,7 +36,7 @@ module OmniauthHelpers def mock_github_auth(email: EMAIL, nickname: USERNAME, name: FULL_NAME, verified: true) OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new( provider: "github", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new(email: email, nickname: nickname, name: name), extra: { all_emails: [{ email: email, primary: true, verified: verified, visibility: "private" }], @@ -48,7 +49,7 @@ module OmniauthHelpers def mock_twitter_auth(nickname: USERNAME, name: FULL_NAME, verified: true) OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new( provider: "twitter", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new(nickname: nickname, name: name), ) @@ -58,7 +59,7 @@ module OmniauthHelpers def mock_discord_auth(email: EMAIL, username: USERNAME, name: FULL_NAME) OmniAuth.config.mock_auth[:discord] = OmniAuth::AuthHash.new( provider: "discord", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new(email: email, name: name), ) @@ -68,7 +69,7 @@ module OmniauthHelpers def mock_linkedin_auth(email: EMAIL, first_name: FIRST_NAME, last_name: LAST_NAME) OmniAuth.config.mock_auth[:linkedin_oidc] = OmniAuth::AuthHash.new( provider: "linkedin_oidc", - uid: "12345", + uid: UID, info: OmniAuth::AuthHash::InfoHash.new( email: email, diff --git a/spec/system/login_spec.rb b/spec/system/login_spec.rb index 1ba11d2ec31..d8b1b4f497f 100644 --- a/spec/system/login_spec.rb +++ b/spec/system/login_spec.rb @@ -2,7 +2,7 @@ require "rotp" -describe "Login", type: :system do +shared_examples "login scenarios" do let(:login_modal) { PageObjects::Modals::Login.new } fab!(:user) { Fabricate(:user, username: "john", password: "supersecurepassword") } @@ -22,7 +22,7 @@ describe "Login", type: :system do login_modal.open login_modal.fill(username: "john", password: "supersecurepassword") login_modal.click_login - find(".activation-controls button.resend").click + login_modal.click(".activation-controls button.resend") wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 } @@ -157,3 +157,13 @@ describe "Login", type: :system do end end end + +describe "Login", type: :system do + context "when desktop" do + include_examples "login scenarios" + end + + context "when mobile", mobile: true do + include_examples "login scenarios" + end +end diff --git a/spec/system/page_objects/modals/login.rb b/spec/system/page_objects/modals/login.rb index 96a6b0a53c8..0d89b22579e 100644 --- a/spec/system/page_objects/modals/login.rb +++ b/spec/system/page_objects/modals/login.rb @@ -19,28 +19,42 @@ module PageObjects find(".login-button").click end + def click(selector) + if page.has_css?("html.mobile-view", wait: 0) + expect(page).to have_css(".d-modal:not(.is-animating)") + end + find(selector).click + end + def open_signup - find("#new-account-link").click + click("#new-account-link") end def click_login - find("#login-button").click + click("#login-button") end def email_login_link - find("#email-login-link").click + click("#email-login-link") end def forgot_password - find("#forgot-password-link").click + click("#forgot-password-link") + end + + def fill_input(selector, text) + if page.has_css?("html.mobile-view", wait: 0) + expect(page).to have_css(".d-modal:not(.is-animating)") + end + find(selector).fill_in(with: text) end def fill_username(username) - find("#login-account-name").fill_in(with: username) + fill_input("#login-account-name", username) end def fill_password(password) - find("#login-account-password").fill_in(with: password) + fill_input("#login-account-password", password) end def fill(username: nil, password: nil) @@ -48,32 +62,8 @@ module PageObjects fill_password(password) if password end - def select_facebook - find(".btn-social.facebook").click - end - - def select_google - find(".btn-social.google_oauth2").click - end - - def select_github - find(".btn-social.github").click - end - - def select_twitter - find(".btn-social.twitter").click - end - - def select_discord - find(".btn-social.discord").click - end - - def select_linkedin - find(".btn-social.linkedin_oidc").click - end - - def select_passkey - find(".btn-social.passkey-login-button").click + def click_social_button(provider) + click(".btn-social.#{provider}") end end end diff --git a/spec/system/page_objects/modals/signup.rb b/spec/system/page_objects/modals/signup.rb index b0aace02f11..92ee0fb66af 100644 --- a/spec/system/page_objects/modals/signup.rb +++ b/spec/system/page_objects/modals/signup.rb @@ -19,12 +19,19 @@ module PageObjects find(".sign-up-button").click end + def click(selector) + if page.has_css?("html.mobile-view", wait: 0) + expect(page).to have_css(".d-modal:not(.is-animating)") + end + find(selector).click + end + def open_login - find("#login-link").click + click("#login-link") end def click_create_account - find(".modal.create-account .btn-primary").click + click(".modal.create-account .btn-primary") end def has_password_input? @@ -35,24 +42,31 @@ module PageObjects has_no_css?("#new-account-password") end + def fill_input(selector, text) + if page.has_css?("html.mobile-view", wait: 0) + expect(page).to have_css(".d-modal:not(.is-animating)") + end + find(selector).fill_in(with: text) + end + def fill_email(email) - find("#new-account-email").fill_in(with: email) + fill_input("#new-account-email", email) end def fill_username(username) - find("#new-account-username").fill_in(with: username) + fill_input("#new-account-username", username) end def fill_name(name) - find("#new-account-name").fill_in(with: name) + fill_input("#new-account-name", name) end def fill_password(password) - find("#new-account-password").fill_in(with: password) + fill_input("#new-account-password", password) end def fill_code(code) - find("#inviteCode").fill_in(with: code) + fill_input("#inviteCode", code) end def fill_custom_field(name, value) @@ -77,28 +91,8 @@ module PageObjects has_valid_password? end - def select_facebook - find(".btn-social.facebook").click - end - - def select_google - find(".btn-social.google_oauth2").click - end - - def select_github - find(".btn-social.github").click - end - - def select_twitter - find(".btn-social.twitter").click - end - - def select_discord - find(".btn-social.discord").click - end - - def select_linkedin - find(".btn-social.linkedin_oidc").click + def click_social_button(provider) + click(".btn-social.#{provider}") end end end diff --git a/spec/system/signup_spec.rb b/spec/system/signup_spec.rb index 85e9cdbe304..92e789b7079 100644 --- a/spec/system/signup_spec.rb +++ b/spec/system/signup_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -describe "Signup", type: :system do +shared_examples "signup scenarios" do let(:login_modal) { PageObjects::Modals::Login.new } let(:signup_modal) { PageObjects::Modals::Signup.new } @@ -171,3 +171,13 @@ describe "Signup", type: :system do end end end + +describe "Signup", type: :system do + context "when desktop" do + include_examples "signup scenarios" + end + + context "when mobile", mobile: true do + include_examples "signup scenarios" + end +end diff --git a/spec/system/social_authentication_spec.rb b/spec/system/social_authentication_spec.rb index f1f364498d9..42a49283d44 100644 --- a/spec/system/social_authentication_spec.rb +++ b/spec/system/social_authentication_spec.rb @@ -1,129 +1,299 @@ # frozen_string_literal: true -describe "Social authentication", type: :system do +shared_context "with omniauth setup" do include OmniauthHelpers let(:login_modal) { PageObjects::Modals::Login.new } let(:signup_modal) { PageObjects::Modals::Signup.new } before { OmniAuth.config.test_mode = true } +end - context "for Facebook" do - before { SiteSetting.enable_facebook_logins = true } - after { reset_omniauth_config(:facebook) } +shared_examples "social authentication scenarios" do + include_context "with omniauth setup" - it "works" do - mock_facebook_auth - visit("/") + context "when user does not exist" do + context "with Facebook" do + before { SiteSetting.enable_facebook_logins = true } + after { reset_omniauth_config(:facebook) } - login_modal.open - login_modal.select_facebook - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".header-dropdown-toggle.current-user") + it "fills the signup form" do + mock_facebook_auth + visit("/") + + login_modal.open + login_modal.click_social_button("facebook") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".header-dropdown-toggle.current-user") + end + end + + context "with Google" do + before { SiteSetting.enable_google_oauth2_logins = true } + after { reset_omniauth_config(:google_oauth2) } + + it "fills the signup form" do + mock_google_auth + visit("/") + + login_modal.open + login_modal.click_social_button("google_oauth2") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".header-dropdown-toggle.current-user") + end + + context "when the email is not verified" do + it "needs to verify email" do + mock_google_auth(verified: false) + visit("/") + + login_modal.open + login_modal.click_social_button("google_oauth2") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".account-created") + end + end + end + + context "with Github" do + before { SiteSetting.enable_github_logins = true } + after { reset_omniauth_config(:github) } + + it "fills the signup form" do + mock_github_auth + visit("/") + + login_modal.open + login_modal.click_social_button("github") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".header-dropdown-toggle.current-user") + end + + context "when the email is not verified" do + it "needs to verify email" do + mock_github_auth(verified: false) + visit("/") + + login_modal.open + login_modal.click_social_button("github") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".account-created") + end + end + end + + context "with Twitter" do + before { SiteSetting.enable_twitter_logins = true } + after { reset_omniauth_config(:twitter) } + + it "fills the signup form" do + mock_twitter_auth + visit("/") + + login_modal.open + login_modal.click_social_button("twitter") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + signup_modal.fill_email(OmniauthHelpers::EMAIL) + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".account-created") + end + + context "when the email is not verified" do + it "needs to verify email" do + mock_twitter_auth(verified: false) + visit("/") + + login_modal.open + login_modal.click_social_button("twitter") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + signup_modal.fill_email(OmniauthHelpers::EMAIL) + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".account-created") + end + end + end + + context "with Discord" do + before { SiteSetting.enable_discord_logins = true } + after { reset_omniauth_config(:discord) } + + it "fills the signup form" do + mock_discord_auth + visit("/") + + login_modal.open + login_modal.click_social_button("discord") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".header-dropdown-toggle.current-user") + end + end + + context "with Linkedin" do + before do + SiteSetting.linkedin_oidc_client_id = "12345" + SiteSetting.linkedin_oidc_client_secret = "abcde" + SiteSetting.enable_linkedin_oidc_logins = true + end + after { reset_omniauth_config(:linkedin_oidc) } + + it "fills the signup form" do + mock_linkedin_auth + visit("/") + + login_modal.open + login_modal.click_social_button("linkedin_oidc") + expect(signup_modal).to be_open + expect(signup_modal).to have_no_password_input + expect(signup_modal).to have_valid_username + expect(signup_modal).to have_valid_email + signup_modal.click_create_account + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end end - context "for Google" do - before { SiteSetting.enable_google_oauth2_logins = true } - after { reset_omniauth_config(:google_oauth2) } - - it "works" do - mock_google_auth - visit("/") - - login_modal.open_from_header - login_modal.select_google - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".header-dropdown-toggle.current-user") + context "when user exists" do + fab!(:user) do + Fabricate( + :user, + email: OmniauthHelpers::EMAIL, + username: OmniauthHelpers::USERNAME, + password: "supersecurepassword", + ) end - end - context "for Github" do - before { SiteSetting.enable_github_logins = true } - after { reset_omniauth_config(:github) } + context "with Facebook" do + before { SiteSetting.enable_facebook_logins = true } + after { reset_omniauth_config(:facebook) } - it "works" do - mock_github_auth - visit("/") + it "logs in user" do + mock_facebook_auth + visit("/") - login_modal.open - login_modal.select_github - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".header-dropdown-toggle.current-user") + login_modal.open + login_modal.click_social_button("facebook") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end - end - context "for Twitter" do - before { SiteSetting.enable_twitter_logins = true } - after { reset_omniauth_config(:twitter) } + context "with Google" do + before { SiteSetting.enable_google_oauth2_logins = true } + after { reset_omniauth_config(:google_oauth2) } - it "works" do - mock_twitter_auth - visit("/") + it "logs in user" do + mock_google_auth + visit("/") - login_modal.open - login_modal.select_twitter - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - signup_modal.fill_email(OmniauthHelpers::EMAIL) - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".account-created") + login_modal.open + login_modal.click_social_button("google_oauth2") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end - end - context "for Discord" do - before { SiteSetting.enable_discord_logins = true } - after { reset_omniauth_config(:discord) } + context "with Github" do + before { SiteSetting.enable_github_logins = true } + after { reset_omniauth_config(:github) } - it "works" do - mock_discord_auth - visit("/") + it "logs in user" do + mock_github_auth + visit("/") - login_modal.open - login_modal.select_discord - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".header-dropdown-toggle.current-user") + login_modal.open + login_modal.click_social_button("github") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end - end - context "for Linkedin" do - before do - SiteSetting.linkedin_oidc_client_id = "12345" - SiteSetting.linkedin_oidc_client_secret = "abcde" - SiteSetting.enable_linkedin_oidc_logins = true + context "with Twitter" do + before { SiteSetting.enable_twitter_logins = true } + after { reset_omniauth_config(:twitter) } + + it "logs in user" do + UserAssociatedAccount.create!( + provider_name: "twitter", + user_id: user.id, + provider_uid: OmniauthHelpers::UID, + ) + + mock_twitter_auth + visit("/") + + login_modal.open + login_modal.click_social_button("twitter") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end - after { reset_omniauth_config(:linkedin_oidc) } - it "works" do - mock_linkedin_auth - visit("/") + context "with Discord" do + before { SiteSetting.enable_discord_logins = true } + after { reset_omniauth_config(:discord) } - login_modal.open - login_modal.select_linkedin - expect(signup_modal).to be_open - expect(signup_modal).to have_no_password_input - expect(signup_modal).to have_valid_username - expect(signup_modal).to have_valid_email - signup_modal.click_create_account - expect(page).to have_css(".header-dropdown-toggle.current-user") + it "logs in user" do + mock_discord_auth + visit("/") + + login_modal.open + login_modal.click_social_button("discord") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end + end + + context "with Linkedin" do + before do + SiteSetting.linkedin_oidc_client_id = "12345" + SiteSetting.linkedin_oidc_client_secret = "abcde" + SiteSetting.enable_linkedin_oidc_logins = true + end + after { reset_omniauth_config(:linkedin_oidc) } + + it "logs in user" do + mock_linkedin_auth + visit("/") + + login_modal.open + login_modal.click_social_button("linkedin_oidc") + expect(page).to have_css(".header-dropdown-toggle.current-user") + end end end end + +describe "Social authentication", type: :system do + context "when desktop" do + include_examples "social authentication scenarios" + end + + context "when mobile", mobile: true do + include_examples "social authentication scenarios" + end +end