|
96 | 96 | describe 'reset_password_url' do |
97 | 97 | it { expect(sofia_account.reset_password_url(sofia_account.user.activation_token)).to eq "http://testhost:1337/sofia_accounts/#{sofia_account.id}/reset_password?activation_token=#{sofia_account.user.activation_token}" } |
98 | 98 | end |
| 99 | + |
| 100 | + describe '.find_for_login' do |
| 101 | + let!(:account) { create(:sofia_account, username: 'testuser', password: 'password1234') } |
| 102 | + let!(:account_with_email) { create(:sofia_account, password: 'password1234') } |
| 103 | + |
| 104 | + context 'when searching by username' do |
| 105 | + it 'finds account by exact username match' do |
| 106 | + result = described_class.find_for_login('testuser') |
| 107 | + expect(result).to eq(account) |
| 108 | + end |
| 109 | + |
| 110 | + it 'finds account by username regardless of case' do |
| 111 | + result = described_class.find_for_login('TESTUSER') |
| 112 | + expect(result).to eq(account) |
| 113 | + end |
| 114 | + |
| 115 | + it 'finds account by username with whitespace trimmed' do |
| 116 | + result = described_class.find_for_login(' testuser ') |
| 117 | + expect(result).to eq(account) |
| 118 | + end |
| 119 | + end |
| 120 | + |
| 121 | + context 'when searching by email' do |
| 122 | + before do |
| 123 | + account_with_email.user.update!(email: 'user@example.com') |
| 124 | + end |
| 125 | + |
| 126 | + it 'finds account by exact email match' do |
| 127 | + result = described_class.find_for_login('user@example.com') |
| 128 | + expect(result).to eq(account_with_email) |
| 129 | + end |
| 130 | + |
| 131 | + it 'finds account by email regardless of case' do |
| 132 | + result = described_class.find_for_login('USER@EXAMPLE.COM') |
| 133 | + expect(result).to eq(account_with_email) |
| 134 | + end |
| 135 | + |
| 136 | + it 'finds account by email with whitespace trimmed' do |
| 137 | + result = described_class.find_for_login(' user@example.com ') |
| 138 | + expect(result).to eq(account_with_email) |
| 139 | + end |
| 140 | + |
| 141 | + it 'prefers username match over email match' do |
| 142 | + account_with_email.update!(username: 'user@example.com') |
| 143 | + result = described_class.find_for_login('user@example.com') |
| 144 | + expect(result).to eq(account_with_email) |
| 145 | + end |
| 146 | + end |
| 147 | + |
| 148 | + context 'when handling nil or blank input' do |
| 149 | + it 'returns nil for nil or blank identifier' do |
| 150 | + expect(described_class.find_for_login(nil)).to be_nil |
| 151 | + expect(described_class.find_for_login('')).to be_nil |
| 152 | + expect(described_class.find_for_login(' ')).to be_nil |
| 153 | + end |
| 154 | + end |
| 155 | + |
| 156 | + context 'when no account matches' do |
| 157 | + it 'returns nil for non-existent username' do |
| 158 | + result = described_class.find_for_login('nonexistent') |
| 159 | + expect(result).to be_nil |
| 160 | + end |
| 161 | + |
| 162 | + it 'returns nil for non-existent email' do |
| 163 | + result = described_class.find_for_login('nonexistent@example.com') |
| 164 | + expect(result).to be_nil |
| 165 | + end |
| 166 | + end |
| 167 | + end |
| 168 | + |
| 169 | + describe '.resolve_login_identifier' do |
| 170 | + context 'when identifier resolves to an account' do |
| 171 | + let(:email_resolve_account) { create(:sofia_account, username: 'emailuser', password: 'password1234') } |
| 172 | + |
| 173 | + before do |
| 174 | + create(:sofia_account, username: 'resolveuser', password: 'password1234') |
| 175 | + email_resolve_account.user.update!(email: 'resolve@example.com') |
| 176 | + end |
| 177 | + |
| 178 | + it 'returns username when searched by username' do |
| 179 | + result = described_class.resolve_login_identifier('resolveuser') |
| 180 | + expect(result).to eq('resolveuser') |
| 181 | + end |
| 182 | + |
| 183 | + it 'returns username when searched by email' do |
| 184 | + result = described_class.resolve_login_identifier('resolve@example.com') |
| 185 | + expect(result).to eq(email_resolve_account.username) |
| 186 | + end |
| 187 | + |
| 188 | + it 'normalizes case for username lookup' do |
| 189 | + result = described_class.resolve_login_identifier('RESOLVEUSER') |
| 190 | + expect(result).to eq('resolveuser') |
| 191 | + end |
| 192 | + |
| 193 | + it 'normalizes case for email lookup' do |
| 194 | + result = described_class.resolve_login_identifier('RESOLVE@EXAMPLE.COM') |
| 195 | + expect(result).to eq(email_resolve_account.username) |
| 196 | + end |
| 197 | + |
| 198 | + it 'trims whitespace for username lookup' do |
| 199 | + result = described_class.resolve_login_identifier(' resolveuser ') |
| 200 | + expect(result).to eq('resolveuser') |
| 201 | + end |
| 202 | + |
| 203 | + it 'trims whitespace for email lookup' do |
| 204 | + result = described_class.resolve_login_identifier(' resolve@example.com ') |
| 205 | + expect(result).to eq(email_resolve_account.username) |
| 206 | + end |
| 207 | + end |
| 208 | + |
| 209 | + context 'when identifier does not resolve to an account' do |
| 210 | + it 'returns nil for nil, empty or non-existent identifiers' do |
| 211 | + expect(described_class.resolve_login_identifier(nil)).to be_nil |
| 212 | + expect(described_class.resolve_login_identifier('')).to be_nil |
| 213 | + expect(described_class.resolve_login_identifier(' ')).to be_nil |
| 214 | + expect(described_class.resolve_login_identifier('nonexistentuser')).to be_nil |
| 215 | + expect(described_class.resolve_login_identifier('nonexistent@example.com')).to be_nil |
| 216 | + end |
| 217 | + end |
| 218 | + end |
99 | 219 | end |
0 commit comments