diff options
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/commit_spec.rb | 44 | ||||
-rw-r--r-- | spec/models/error_tracking/project_error_tracking_setting_spec.rb | 32 | ||||
-rw-r--r-- | spec/models/grafana_integration_spec.rb | 34 | ||||
-rw-r--r-- | spec/models/hooks/web_hook_log_spec.rb | 35 | ||||
-rw-r--r-- | spec/models/integrations/campfire_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/integrations/drone_ci_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/integrations/jira_spec.rb | 20 | ||||
-rw-r--r-- | spec/models/integrations/packagist_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/integrations/zentao_spec.rb | 25 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 1 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 58 | ||||
-rw-r--r-- | spec/models/snippet_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/todo_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 256 |
14 files changed, 464 insertions, 71 deletions
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 7c67b9a3d63..fe54b1574a2 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -226,27 +226,45 @@ RSpec.describe Commit do end describe '#committer' do - context 'with a confirmed e-mail' do - it 'returns the user' do - user = create(:user, email: commit.committer_email) + context "when committer_email is the user's primary email" do + context 'when the user email is confirmed' do + let!(:user) { create(:user, email: commit.committer_email) } - expect(commit.committer).to eq(user) + it 'returns the user' do + expect(commit.committer).to eq(user) + expect(commit.committer(confirmed: false)).to eq(user) + end end - end - context 'with an unconfirmed e-mail' do - let(:user) { create(:user) } + context 'when the user email is unconfirmed' do + let!(:user) { create(:user, :unconfirmed, email: commit.committer_email) } - before do - create(:email, user: user, email: commit.committer_email) + it 'returns the user according to confirmed argument' do + expect(commit.committer).to be_nil + expect(commit.committer(confirmed: false)).to eq(user) + end end + end - it 'returns no user' do - expect(commit.committer).to be_nil + context "when committer_email is the user's secondary email" do + let!(:user) { create(:user) } + + context 'when the user email is confirmed' do + let!(:email) { create(:email, :confirmed, user: user, email: commit.committer_email) } + + it 'returns the user' do + expect(commit.committer).to eq(user) + expect(commit.committer(confirmed: false)).to eq(user) + end end - it 'returns the user' do - expect(commit.committer(confirmed: false)).to eq(user) + context 'when the user email is unconfirmed' do + let!(:email) { create(:email, user: user, email: commit.committer_email) } + + it 'does not return the user' do + expect(commit.committer).to be_nil + expect(commit.committer(confirmed: false)).to be_nil + end end end end diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb index 15b6b45eaba..0685144dea6 100644 --- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb +++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb @@ -121,6 +121,38 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do end end end + + describe 'before_validation :reset_token' do + context 'when a token was previously set' do + subject { create(:project_error_tracking_setting, project: project) } + + it 'resets token if url changed' do + subject.api_url = 'http://sentry.com/api/0/projects/org-slug/proj-slug/' + + expect(subject).not_to be_valid + expect(subject.token).to be_nil + end + + it "does not reset token if new url is set together with the same token" do + subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/' + current_token = subject.token + subject.token = current_token + + expect(subject).to be_valid + expect(subject.token).to eq(current_token) + expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/') + end + + it 'does not reset token if new url is set together with a new token' do + subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/' + subject.token = 'token' + + expect(subject).to be_valid + expect(subject.token).to eq('token') + expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/') + end + end + end end describe '.extract_sentry_external_url' do diff --git a/spec/models/grafana_integration_spec.rb b/spec/models/grafana_integration_spec.rb index bb822187e0c..73ec2856c05 100644 --- a/spec/models/grafana_integration_spec.rb +++ b/spec/models/grafana_integration_spec.rb @@ -86,4 +86,38 @@ RSpec.describe GrafanaIntegration do end end end + + describe 'Callbacks' do + describe 'before_validation :reset_token' do + context 'when a token was previously set' do + subject(:grafana_integration) { create(:grafana_integration) } + + it 'resets token if url changed' do + grafana_integration.grafana_url = 'http://gitlab1.com' + + expect(grafana_integration).not_to be_valid + expect(grafana_integration.send(:token)).to be_nil + end + + it "does not reset token if new url is set together with the same token" do + grafana_integration.grafana_url = 'http://gitlab_edited.com' + current_token = grafana_integration.send(:token) + grafana_integration.token = current_token + + expect(grafana_integration).to be_valid + expect(grafana_integration.send(:token)).to eq(current_token) + expect(grafana_integration.grafana_url).to eq('http://gitlab_edited.com') + end + + it 'does not reset token if new url is set together with a new token' do + grafana_integration.grafana_url = 'http://gitlab_edited.com' + grafana_integration.token = 'token' + + expect(grafana_integration).to be_valid + expect(grafana_integration.send(:token)).to eq('token') + expect(grafana_integration.grafana_url).to eq('http://gitlab_edited.com') + end + end + end + end end diff --git a/spec/models/hooks/web_hook_log_spec.rb b/spec/models/hooks/web_hook_log_spec.rb index 9cfbb14e087..25df569c461 100644 --- a/spec/models/hooks/web_hook_log_spec.rb +++ b/spec/models/hooks/web_hook_log_spec.rb @@ -30,15 +30,12 @@ RSpec.describe WebHookLog do end describe '#save' do - let(:web_hook_log) { build(:web_hook_log, url: url) } - let(:url) { 'http://example.com' } - - subject { web_hook_log.save! } + context 'with basic auth credentials' do + let(:web_hook_log) { build(:web_hook_log, url: 'http://test:123@example.com') } - it { is_expected.to eq(true) } + subject { web_hook_log.save! } - context 'with basic auth credentials' do - let(:url) { 'http://test:123@example.com'} + it { is_expected.to eq(true) } it 'obfuscates the basic auth credentials' do subject @@ -46,6 +43,30 @@ RSpec.describe WebHookLog do expect(web_hook_log.url).to eq('http://*****:*****@example.com') end end + + context 'with author email' do + let(:author) { create(:user) } + let(:web_hook_log) { create(:web_hook_log, request_data: data) } + let(:data) do + { + commit: { + author: { + name: author.name, + email: author.email + } + } + }.deep_stringify_keys + end + + it "redacts author's email" do + expect(web_hook_log.request_data['commit']).to match a_hash_including( + 'author' => { + 'name' => author.name, + 'email' => _('[REDACTED]') + } + ) + end + end end describe '#success?' do diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb index 0044e6fae21..d249c8470ca 100644 --- a/spec/models/integrations/campfire_spec.rb +++ b/spec/models/integrations/campfire_spec.rb @@ -5,7 +5,17 @@ require 'spec_helper' RSpec.describe Integrations::Campfire do include StubRequests + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { described_class.new } + end + describe 'Validations' do + it { is_expected.to validate_numericality_of(:room).is_greater_than(0).only_integer } + it { is_expected.to validate_length_of(:subdomain).is_at_most(63) } + it { is_expected.to allow_value("foo").for(:subdomain) } + it { is_expected.not_to allow_value("foo.bar").for(:subdomain) } + it { is_expected.not_to allow_value("foo.bar/#").for(:subdomain) } + context 'when integration is active' do before do subject.active = true diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb index 78d55c49e7b..5ae4af1a665 100644 --- a/spec/models/integrations/drone_ci_spec.rb +++ b/spec/models/integrations/drone_ci_spec.rb @@ -7,6 +7,10 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do subject(:integration) { described_class.new } + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { subject } + end + describe 'validations' do context 'active' do before do diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb index 061c770a61a..84abcf69fc1 100644 --- a/spec/models/integrations/jira_spec.rb +++ b/spec/models/integrations/jira_spec.rb @@ -12,6 +12,7 @@ RSpec.describe Integrations::Jira do let(:api_url) { 'http://api-jira.example.com' } let(:username) { 'jira-username' } let(:password) { 'jira-password' } + let(:project_key) { nil } let(:transition_id) { 'test27' } let(:server_info_results) { { 'deploymentType' => 'Cloud' } } let(:jira_integration) do @@ -19,7 +20,8 @@ RSpec.describe Integrations::Jira do project: project, url: url, username: username, - password: password + password: password, + project_key: project_key ) end @@ -478,6 +480,22 @@ RSpec.describe Integrations::Jira do expect(WebMock).to have_requested(:get, issue_url) end end + + context 'with restricted restrict_project_key option' do + subject(:find_issue) { jira_integration.find_issue(issue_key, restrict_project_key: true) } + + it { is_expected.to eq(nil) } + + context 'and project_key matches' do + let(:project_key) { 'JIRA' } + + it 'calls the Jira API to get the issue' do + find_issue + + expect(WebMock).to have_requested(:get, issue_url) + end + end + end end describe '#close_issue' do diff --git a/spec/models/integrations/packagist_spec.rb b/spec/models/integrations/packagist_spec.rb index dce96890522..d1976e73e2e 100644 --- a/spec/models/integrations/packagist_spec.rb +++ b/spec/models/integrations/packagist_spec.rb @@ -29,6 +29,10 @@ RSpec.describe Integrations::Packagist do let(:hook_url) { "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}" } end + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { described_class.new(packagist_params) } + end + describe '#execute' do let(:user) { create(:user) } let(:project) { create(:project, :repository) } diff --git a/spec/models/integrations/zentao_spec.rb b/spec/models/integrations/zentao_spec.rb index 2b0532c7930..4ef977ba3d2 100644 --- a/spec/models/integrations/zentao_spec.rb +++ b/spec/models/integrations/zentao_spec.rb @@ -9,6 +9,31 @@ RSpec.describe Integrations::Zentao do let(:zentao_product_xid) { '3' } let(:zentao_integration) { create(:zentao_integration) } + it_behaves_like Integrations::ResetSecretFields do + let(:integration) { zentao_integration } + end + + describe 'set_default_data' do + let(:project) { create(:project, :repository) } + + context 'when gitlab.yml was initialized' do + it 'is prepopulated with the settings' do + settings = { + 'zentao' => { + 'url' => 'http://zentao.sample/projects/project_a', + 'api_url' => 'http://zentao.sample/api' + } + } + allow(Gitlab.config).to receive(:issues_tracker).and_return(settings) + + integration = project.create_zentao_integration(active: true) + + expect(integration.url).to eq('http://zentao.sample/projects/project_a') + expect(integration.api_url).to eq('http://zentao.sample/api') + end + end + end + describe '#create' do let(:project) { create(:project, :repository) } let(:params) do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index ed5b3d4e0be..990189a10a1 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -5623,6 +5623,7 @@ RSpec.describe Project, factory_default: :keep do let(:import_state) { create(:import_state, project: project) } it 'runs the correct hooks' do + expect(project.repository).to receive(:remove_prohibited_branches) expect(project.repository).to receive(:expire_content_cache) expect(project.wiki.repository).to receive(:expire_content_cache) expect(import_state).to receive(:finish) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 215f83adf5d..e24adc20143 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -3375,4 +3375,62 @@ RSpec.describe Repository do end end end + + describe '#remove_prohibited_branches' do + let(:branch_name) { '37fd3601be4c25497a39fa2e6a206e09e759d597' } + + before do + allow(repository.raw_repository).to receive(:branch_names).and_return([branch_name]) + end + + context 'when prohibited branch exists' do + it 'deletes prohibited branch' do + expect(repository.raw_repository).to receive(:delete_branch).with(branch_name) + + repository.remove_prohibited_branches + end + end + + shared_examples 'does not delete branch' do + it 'returns without removing the branch' do + expect(repository.raw_repository).not_to receive(:delete_branch) + + repository.remove_prohibited_branches + end + end + + context 'when branch name is 40-characters long but not hexadecimal' do + let(:branch_name) { '37fd3601be4c25497a39fa2e6a206e09e759d59s' } + + include_examples 'does not delete branch' + end + + context 'when branch name is hexadecimal' do + context 'when branch name is less than 40-characters long' do + let(:branch_name) { '37fd3601be4c25497a39fa2e6a206e09e759d' } + + include_examples 'does not delete branch' + end + + context 'when branch name is more than 40-characters long' do + let(:branch_name) { '37fd3601be4c25497a39fa2e6a206e09e759dfdfd' } + + include_examples 'does not delete branch' + end + end + + context 'when prohibited branch does not exist' do + let(:branch_name) { 'main' } + + include_examples 'does not delete branch' + end + + context 'when raw repository does not exist' do + before do + allow(repository).to receive(:exists?).and_return(false) + end + + include_examples 'does not delete branch' + end + end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 70afafce132..a54edc8510e 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -36,8 +36,6 @@ RSpec.describe Snippet do it { is_expected.to validate_presence_of(:content) } - it { is_expected.to validate_inclusion_of(:visibility_level).in_array(Gitlab::VisibilityLevel.values) } - it do allow(Gitlab::CurrentSettings).to receive(:snippet_size_limit).and_return(1) diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb index 651e2cf273f..7a312a13259 100644 --- a/spec/models/todo_spec.rb +++ b/spec/models/todo_spec.rb @@ -475,4 +475,14 @@ RSpec.describe Todo do it { is_expected.to contain_exactly(user1.id, user2.id) } end + + describe '.for_internal_notes' do + it 'returns todos created from internal notes' do + internal_note = create(:note, confidential: true ) + todo = create(:todo, note: internal_note) + create(:todo) + + expect(described_class.for_internal_notes).to contain_exactly(todo) + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6c887777dac..c9067833b63 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2634,6 +2634,14 @@ RSpec.describe User do expect(described_class.find_by_any_email(private_email, confirmed: true)).to eq(user) end + it 'finds user through private commit email when user is unconfirmed' do + user = create(:user, :unconfirmed) + private_email = user.private_commit_email + + expect(described_class.find_by_any_email(private_email)).to eq(user) + expect(described_class.find_by_any_email(private_email, confirmed: true)).to eq(user) + end + it 'finds by primary email' do user = create(:user, email: 'foo@example.com') @@ -2641,6 +2649,13 @@ RSpec.describe User do expect(described_class.find_by_any_email(user.email, confirmed: true)).to eq user end + it 'finds by primary email when user is unconfirmed according to confirmed argument' do + user = create(:user, :unconfirmed, email: 'foo@example.com') + + expect(described_class.find_by_any_email(user.email)).to eq user + expect(described_class.find_by_any_email(user.email, confirmed: true)).to be_nil + end + it 'finds by uppercased email' do user = create(:user, email: 'foo@example.com') @@ -2649,35 +2664,47 @@ RSpec.describe User do end context 'finds by secondary email' do - let(:user) { email.user } + context 'when primary email is confirmed' do + let(:user) { email.user } - context 'primary email confirmed' do - context 'secondary email confirmed' do + context 'when secondary email is confirmed' do let!(:email) { create(:email, :confirmed, email: 'foo@example.com') } - it 'finds user respecting the confirmed flag' do + it 'finds user' do expect(described_class.find_by_any_email(email.email)).to eq user expect(described_class.find_by_any_email(email.email, confirmed: true)).to eq user end end - context 'secondary email not confirmed' do + context 'when secondary email is unconfirmed' do let!(:email) { create(:email, email: 'foo@example.com') } - it 'finds user respecting the confirmed flag' do - expect(described_class.find_by_any_email(email.email)).to eq user + it 'does not find user' do + expect(described_class.find_by_any_email(email.email)).to be_nil expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil end end end - context 'primary email not confirmed' do + context 'when primary email is unconfirmed' do let(:user) { create(:user, :unconfirmed) } - let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') } - it 'finds user respecting the confirmed flag' do - expect(described_class.find_by_any_email(email.email)).to eq user - expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil + context 'when secondary email is confirmed' do + let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') } + + it 'finds user according to confirmed argument' do + expect(described_class.find_by_any_email(email.email)).to eq user + expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil + end + end + + context 'when secondary email is unconfirmed' do + let!(:email) { create(:email, user: user, email: 'foo@example.com') } + + it 'does not find user' do + expect(described_class.find_by_any_email(email.email)).to be_nil + expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil + end end end end @@ -2685,13 +2712,6 @@ RSpec.describe User do it 'returns nil when nothing found' do expect(described_class.find_by_any_email('')).to be_nil end - - it 'returns nil when user is not confirmed' do - user = create(:user, :unconfirmed, email: 'foo@example.com') - - expect(described_class.find_by_any_email(user.email, confirmed: false)).to eq(user) - expect(described_class.find_by_any_email(user.email, confirmed: true)).to be_nil - end end describe '.by_any_email' do @@ -2700,32 +2720,99 @@ RSpec.describe User do .to be_a_kind_of(ActiveRecord::Relation) end - it 'returns a relation of users' do + it 'returns empty relation of users when nothing found' do + expect(described_class.by_any_email('')).to be_empty + end + + it 'returns a relation of users for confirmed primary emails' do user = create(:user) - expect(described_class.by_any_email(user.email)).to eq([user]) + expect(described_class.by_any_email(user.email)).to match_array([user]) + expect(described_class.by_any_email(user.email, confirmed: true)).to match_array([user]) end - it 'returns a relation of users for confirmed users' do - user = create(:user) + it 'returns a relation of users for unconfirmed primary emails according to confirmed argument' do + user = create(:user, :unconfirmed) - expect(described_class.by_any_email(user.email, confirmed: true)).to eq([user]) + expect(described_class.by_any_email(user.email)).to match_array([user]) + expect(described_class.by_any_email(user.email, confirmed: true)).to be_empty end - it 'finds user through a private commit email' do + it 'finds users through private commit emails' do user = create(:user) private_email = user.private_commit_email - expect(described_class.by_any_email(private_email)).to eq([user]) - expect(described_class.by_any_email(private_email, confirmed: true)).to eq([user]) + expect(described_class.by_any_email(private_email)).to match_array([user]) + expect(described_class.by_any_email(private_email, confirmed: true)).to match_array([user]) + end + + it 'finds unconfirmed users through private commit emails' do + user = create(:user, :unconfirmed) + private_email = user.private_commit_email + + expect(described_class.by_any_email(private_email)).to match_array([user]) + expect(described_class.by_any_email(private_email, confirmed: true)).to match_array([user]) end it 'finds user through a private commit email in an array' do user = create(:user) private_email = user.private_commit_email - expect(described_class.by_any_email([private_email])).to eq([user]) - expect(described_class.by_any_email([private_email], confirmed: true)).to eq([user]) + expect(described_class.by_any_email([private_email])).to match_array([user]) + expect(described_class.by_any_email([private_email], confirmed: true)).to match_array([user]) + end + + it 'finds by uppercased email' do + user = create(:user, email: 'foo@example.com') + + expect(described_class.by_any_email(user.email.upcase)).to match_array([user]) + expect(described_class.by_any_email(user.email.upcase, confirmed: true)).to match_array([user]) + end + + context 'finds by secondary email' do + context 'when primary email is confirmed' do + let(:user) { email.user } + + context 'when secondary email is confirmed' do + let!(:email) { create(:email, :confirmed, email: 'foo@example.com') } + + it 'finds user' do + expect(described_class.by_any_email(email.email)).to match_array([user]) + expect(described_class.by_any_email(email.email, confirmed: true)).to match_array([user]) + end + end + + context 'when secondary email is unconfirmed' do + let!(:email) { create(:email, email: 'foo@example.com') } + + it 'does not find user' do + expect(described_class.by_any_email(email.email)).to be_empty + expect(described_class.by_any_email(email.email, confirmed: true)).to be_empty + end + end + end + + context 'when primary email is unconfirmed' do + let(:user) { create(:user, :unconfirmed) } + + context 'when secondary email is confirmed' do + let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') } + + it 'finds user according to confirmed argument' do + expect(described_class.by_any_email(email.email)).to match_array([user]) + expect(described_class.by_any_email(email.email, confirmed: true)).to be_empty + end + end + + context 'when secondary email is unconfirmed' do + let!(:email) { create(:email, user: user, email: 'foo@example.com') } + + it 'does not find user' do + expect(described_class.by_any_email(email.email)).to be_empty + expect(described_class.by_any_email(email.email, confirmed: true)).to be_empty + end + end + end end end @@ -2739,7 +2826,10 @@ RSpec.describe User do let_it_be(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@example.com') } let_it_be(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@example.com') } - let_it_be(:email) { create(:email, user: user, email: 'alias@example.com') } + let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, name: 'not verified', username: 'notverified') } + + let_it_be(:unconfirmed_secondary_email) { create(:email, user: user, email: 'alias@example.com') } + let_it_be(:confirmed_secondary_email) { create(:email, :confirmed, user: user, email: 'alias2@example.com') } describe 'name user and email relative ordering' do let_it_be(:named_alexander) { create(:user, name: 'Alexander Person', username: 'abcd', email: 'abcd@example.com') } @@ -2797,16 +2887,25 @@ RSpec.describe User do it 'does not return users with a matching private email' do expect(described_class.search(user.email)).to be_empty - expect(described_class.search(email.email)).to be_empty + expect(described_class.search(unconfirmed_secondary_email.email)).to be_empty + expect(described_class.search(confirmed_secondary_email.email)).to be_empty end context 'with private emails search' do - it 'returns users with matching private email' do + it 'returns users with matching private primary email' do expect(described_class.search(user.email, with_private_emails: true)).to match_array([user]) end - it 'returns users with matching private secondary email' do - expect(described_class.search(email.email, with_private_emails: true)).to match_array([user]) + it 'returns users with matching private unconfirmed primary email' do + expect(described_class.search(unconfirmed_user.email, with_private_emails: true)).to match_array([unconfirmed_user]) + end + + it 'returns users with matching private confirmed secondary email' do + expect(described_class.search(confirmed_secondary_email.email, with_private_emails: true)).to match_array([user]) + end + + it 'does not return users with matching private unconfirmed secondary email' do + expect(described_class.search(unconfirmed_secondary_email.email, with_private_emails: true)).to be_empty end end end @@ -3049,47 +3148,108 @@ RSpec.describe User do describe '#accept_pending_invitations!' do let(:user) { create(:user, email: 'user@email.com') } + + let(:confirmed_secondary_email) { create(:email, :confirmed, email: 'confirmedsecondary@example.com', user: user) } + let(:unconfirmed_secondary_email) { create(:email, email: 'unconfirmedsecondary@example.com', user: user) } + let!(:project_member_invite) { create(:project_member, :invited, invite_email: user.email) } let!(:group_member_invite) { create(:group_member, :invited, invite_email: user.email) } + let!(:external_project_member_invite) { create(:project_member, :invited, invite_email: 'external@email.com') } let!(:external_group_member_invite) { create(:group_member, :invited, invite_email: 'external@email.com') } + let!(:project_member_invite_via_confirmed_secondary_email) { create(:project_member, :invited, invite_email: confirmed_secondary_email.email) } + let!(:group_member_invite_via_confirmed_secondary_email) { create(:group_member, :invited, invite_email: confirmed_secondary_email.email) } + + let!(:project_member_invite_via_unconfirmed_secondary_email) { create(:project_member, :invited, invite_email: unconfirmed_secondary_email.email) } + let!(:group_member_invite_via_unconfirmed_secondary_email) { create(:group_member, :invited, invite_email: unconfirmed_secondary_email.email) } + it 'accepts all the user members pending invitations and returns the accepted_members' do accepted_members = user.accept_pending_invitations! - expect(accepted_members).to match_array([project_member_invite, group_member_invite]) + expect(accepted_members).to match_array( + [ + project_member_invite, + group_member_invite, + project_member_invite_via_confirmed_secondary_email, + group_member_invite_via_confirmed_secondary_email + ] + ) + expect(group_member_invite.reload).not_to be_invite expect(project_member_invite.reload).not_to be_invite + expect(external_project_member_invite.reload).to be_invite expect(external_group_member_invite.reload).to be_invite + + expect(project_member_invite_via_confirmed_secondary_email.reload).not_to be_invite + expect(group_member_invite_via_confirmed_secondary_email.reload).not_to be_invite + + expect(project_member_invite_via_unconfirmed_secondary_email.reload).to be_invite + expect(group_member_invite_via_unconfirmed_secondary_email.reload).to be_invite end end describe '#all_emails' do let(:user) { create(:user) } - let!(:email_confirmed) { create :email, user: user, confirmed_at: Time.current } - let!(:email_unconfirmed) { create :email, user: user } + let!(:unconfirmed_secondary_email) { create(:email, user: user) } + let!(:confirmed_secondary_email) { create(:email, :confirmed, user: user) } + + it 'returns all emails' do + expect(user.all_emails).to contain_exactly( + user.email, + user.private_commit_email, + confirmed_secondary_email.email + ) + end + + context 'when the primary email is confirmed' do + it 'includes the primary email' do + expect(user.all_emails).to include(user.email) + end + end + + context 'when the primary email is unconfirmed' do + let!(:user) { create(:user, :unconfirmed) } + + it 'includes the primary email' do + expect(user.all_emails).to include(user.email) + end + end + + context 'when the primary email is temp email for oauth' do + let!(:user) { create(:omniauth_user, :unconfirmed, email: 'temp-email-for-oauth-user@gitlab.localhost') } + + it 'does not include the primary email' do + expect(user.all_emails).not_to include(user.email) + end + end context 'when `include_private_email` is true' do - it 'returns all emails' do - expect(user.reload.all_emails).to contain_exactly( - user.email, - user.private_commit_email, - email_unconfirmed.email, - email_confirmed.email - ) + it 'includes the private commit email' do + expect(user.all_emails).to include(user.private_commit_email) end end context 'when `include_private_email` is false' do it 'does not include the private commit email' do - expect(user.reload.all_emails(include_private_email: false)).to contain_exactly( - user.email, - email_unconfirmed.email, - email_confirmed.email + expect(user.all_emails(include_private_email: false)).not_to include( + user.private_commit_email ) end end + + context 'when the secondary email is confirmed' do + it 'includes the secondary email' do + expect(user.all_emails).to include(confirmed_secondary_email.email) + end + end + + context 'when the secondary email is unconfirmed' do + it 'does not include the secondary email' do + expect(user.all_emails).not_to include(unconfirmed_secondary_email.email) + end + end end describe '#verified_emails' do |