Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/build_spec.rb128
-rw-r--r--spec/models/chat_name_spec.rb16
-rw-r--r--spec/models/ci/build_spec.rb6
-rw-r--r--spec/models/concerns/access_requestable_spec.rb8
-rw-r--r--spec/models/concerns/issuable_spec.rb22
-rw-r--r--spec/models/concerns/subscribable_spec.rb117
-rw-r--r--spec/models/environment_spec.rb21
-rw-r--r--spec/models/event_spec.rb27
-rw-r--r--spec/models/group_spec.rb2
-rw-r--r--spec/models/key_spec.rb2
-rw-r--r--spec/models/member_spec.rb26
-rw-r--r--spec/models/project_group_link_spec.rb16
-rw-r--r--spec/models/project_services/chat_service_spec.rb15
-rw-r--r--spec/models/project_services/gitlab_issue_tracker_service_spec.rb6
-rw-r--r--spec/models/project_services/jira_service_spec.rb49
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb99
-rw-r--r--spec/models/project_services/slack_service/note_message_spec.rb16
-rw-r--r--spec/models/project_spec.rb85
-rw-r--r--spec/models/project_team_spec.rb8
-rw-r--r--spec/models/repository_spec.rb66
-rw-r--r--spec/models/service_spec.rb10
-rw-r--r--spec/models/subscription_spec.rb20
-rw-r--r--spec/models/user_spec.rb103
23 files changed, 763 insertions, 105 deletions
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index ae185de9ca3..ef07f2275b1 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -1052,4 +1052,132 @@ describe Ci::Build, models: true do
end
end
end
+
+ describe '#has_environment?' do
+ subject { build.has_environment? }
+
+ context 'when environment is defined' do
+ before do
+ build.update(environment: 'review')
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when environment is not defined' do
+ before do
+ build.update(environment: nil)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#starts_environment?' do
+ subject { build.starts_environment? }
+
+ context 'when environment is defined' do
+ before do
+ build.update(environment: 'review')
+ end
+
+ context 'no action is defined' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'and start action is defined' do
+ before do
+ build.update(options: { environment: { action: 'start' } } )
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'when environment is not defined' do
+ before do
+ build.update(environment: nil)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#stops_environment?' do
+ subject { build.stops_environment? }
+
+ context 'when environment is defined' do
+ before do
+ build.update(environment: 'review')
+ end
+
+ context 'no action is defined' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'and stop action is defined' do
+ before do
+ build.update(options: { environment: { action: 'stop' } } )
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'when environment is not defined' do
+ before do
+ build.update(environment: nil)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#last_deployment' do
+ subject { build.last_deployment }
+
+ context 'when multiple deployments are created' do
+ let!(:deployment1) { create(:deployment, deployable: build) }
+ let!(:deployment2) { create(:deployment, deployable: build) }
+
+ it 'returns the latest one' do
+ is_expected.to eq(deployment2)
+ end
+ end
+ end
+
+ describe '#outdated_deployment?' do
+ subject { build.outdated_deployment? }
+
+ context 'when build succeeded' do
+ let(:build) { create(:ci_build, :success) }
+ let!(:deployment) { create(:deployment, deployable: build) }
+
+ context 'current deployment is latest' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'current deployment is not latest on environment' do
+ let!(:deployment2) { create(:deployment, environment: deployment.environment) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'when build failed' do
+ let(:build) { create(:ci_build, :failed) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#expanded_environment_name' do
+ subject { build.expanded_environment_name }
+
+ context 'when environment uses variables' do
+ let(:build) { create(:ci_build, ref: 'master', environment: 'review/$CI_BUILD_REF_NAME') }
+
+ it { is_expected.to eq('review/master') }
+ end
+ end
end
diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb
new file mode 100644
index 00000000000..b02971cab82
--- /dev/null
+++ b/spec/models/chat_name_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe ChatName, models: true do
+ subject { create(:chat_name) }
+
+ it { is_expected.to belong_to(:service) }
+ it { is_expected.to belong_to(:user) }
+
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:service) }
+ it { is_expected.to validate_presence_of(:team_id) }
+ it { is_expected.to validate_presence_of(:chat_id) }
+
+ it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:service_id) }
+ it { is_expected.to validate_uniqueness_of(:chat_id).scoped_to(:service_id, :team_id) }
+end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index a37a00f461a..a7e90c8a381 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -4,6 +4,12 @@ describe Ci::Build, models: true do
let(:build) { create(:ci_build) }
let(:test_trace) { 'This is a test' }
+ it { is_expected.to belong_to(:runner) }
+ it { is_expected.to belong_to(:trigger_request) }
+ it { is_expected.to belong_to(:erased_by) }
+
+ it { is_expected.to have_many(:deployments) }
+
describe '#trace' do
it 'obfuscates project runners token' do
allow(build).to receive(:raw_trace).and_return("Test: #{build.project.runners_token}")
diff --git a/spec/models/concerns/access_requestable_spec.rb b/spec/models/concerns/access_requestable_spec.rb
index 96eee0e8bdd..4829ef17a20 100644
--- a/spec/models/concerns/access_requestable_spec.rb
+++ b/spec/models/concerns/access_requestable_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe AccessRequestable do
describe 'Group' do
describe '#request_access' do
- let(:group) { create(:group, :public) }
+ let(:group) { create(:group, :public, :access_requestable) }
let(:user) { create(:user) }
it { expect(group.request_access(user)).to be_a(GroupMember) }
@@ -11,7 +11,7 @@ describe AccessRequestable do
end
describe '#access_requested?' do
- let(:group) { create(:group, :public) }
+ let(:group) { create(:group, :public, :access_requestable) }
let(:user) { create(:user) }
before { group.request_access(user) }
@@ -22,14 +22,14 @@ describe AccessRequestable do
describe 'Project' do
describe '#request_access' do
- let(:project) { create(:empty_project, :public) }
+ let(:project) { create(:empty_project, :public, :access_requestable) }
let(:user) { create(:user) }
it { expect(project.request_access(user)).to be_a(ProjectMember) }
end
describe '#access_requested?' do
- let(:project) { create(:empty_project, :public) }
+ let(:project) { create(:empty_project, :public, :access_requestable) }
let(:user) { create(:user) }
before { project.request_access(user) }
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 6e987967ca5..6f84bffe046 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -176,23 +176,25 @@ describe Issue, "Issuable" do
end
describe '#subscribed?' do
+ let(:project) { issue.project }
+
context 'user is not a participant in the issue' do
before { allow(issue).to receive(:participants).with(user).and_return([]) }
it 'returns false when no subcription exists' do
- expect(issue.subscribed?(user)).to be_falsey
+ expect(issue.subscribed?(user, project)).to be_falsey
end
it 'returns true when a subcription exists and subscribed is true' do
- issue.subscriptions.create(user: user, subscribed: true)
+ issue.subscriptions.create(user: user, project: project, subscribed: true)
- expect(issue.subscribed?(user)).to be_truthy
+ expect(issue.subscribed?(user, project)).to be_truthy
end
it 'returns false when a subcription exists and subscribed is false' do
- issue.subscriptions.create(user: user, subscribed: false)
+ issue.subscriptions.create(user: user, project: project, subscribed: false)
- expect(issue.subscribed?(user)).to be_falsey
+ expect(issue.subscribed?(user, project)).to be_falsey
end
end
@@ -200,19 +202,19 @@ describe Issue, "Issuable" do
before { allow(issue).to receive(:participants).with(user).and_return([user]) }
it 'returns false when no subcription exists' do
- expect(issue.subscribed?(user)).to be_truthy
+ expect(issue.subscribed?(user, project)).to be_truthy
end
it 'returns true when a subcription exists and subscribed is true' do
- issue.subscriptions.create(user: user, subscribed: true)
+ issue.subscriptions.create(user: user, project: project, subscribed: true)
- expect(issue.subscribed?(user)).to be_truthy
+ expect(issue.subscribed?(user, project)).to be_truthy
end
it 'returns false when a subcription exists and subscribed is false' do
- issue.subscriptions.create(user: user, subscribed: false)
+ issue.subscriptions.create(user: user, project: project, subscribed: false)
- expect(issue.subscribed?(user)).to be_falsey
+ expect(issue.subscribed?(user, project)).to be_falsey
end
end
end
diff --git a/spec/models/concerns/subscribable_spec.rb b/spec/models/concerns/subscribable_spec.rb
index b7fc5a92497..58f5c164116 100644
--- a/spec/models/concerns/subscribable_spec.rb
+++ b/spec/models/concerns/subscribable_spec.rb
@@ -1,67 +1,128 @@
require 'spec_helper'
describe Subscribable, 'Subscribable' do
- let(:resource) { create(:issue) }
- let(:user) { create(:user) }
+ let(:project) { create(:empty_project) }
+ let(:resource) { create(:issue, project: project) }
+ let(:user_1) { create(:user) }
describe '#subscribed?' do
- it 'returns false when no subcription exists' do
- expect(resource.subscribed?(user)).to be_falsey
- end
+ context 'without project' do
+ it 'returns false when no subscription exists' do
+ expect(resource.subscribed?(user_1)).to be_falsey
+ end
+
+ it 'returns true when a subcription exists and subscribed is true' do
+ resource.subscriptions.create(user: user_1, subscribed: true)
+
+ expect(resource.subscribed?(user_1)).to be_truthy
+ end
- it 'returns true when a subcription exists and subscribed is true' do
- resource.subscriptions.create(user: user, subscribed: true)
+ it 'returns false when a subcription exists and subscribed is false' do
+ resource.subscriptions.create(user: user_1, subscribed: false)
- expect(resource.subscribed?(user)).to be_truthy
+ expect(resource.subscribed?(user_1)).to be_falsey
+ end
end
- it 'returns false when a subcription exists and subscribed is false' do
- resource.subscriptions.create(user: user, subscribed: false)
+ context 'with project' do
+ it 'returns false when no subscription exists' do
+ expect(resource.subscribed?(user_1, project)).to be_falsey
+ end
+
+ it 'returns true when a subcription exists and subscribed is true' do
+ resource.subscriptions.create(user: user_1, project: project, subscribed: true)
+
+ expect(resource.subscribed?(user_1, project)).to be_truthy
+ end
- expect(resource.subscribed?(user)).to be_falsey
+ it 'returns false when a subcription exists and subscribed is false' do
+ resource.subscriptions.create(user: user_1, project: project, subscribed: false)
+
+ expect(resource.subscribed?(user_1, project)).to be_falsey
+ end
end
end
+
describe '#subscribers' do
it 'returns [] when no subcribers exists' do
- expect(resource.subscribers).to be_empty
+ expect(resource.subscribers(project)).to be_empty
end
it 'returns the subscribed users' do
- resource.subscriptions.create(user: user, subscribed: true)
- resource.subscriptions.create(user: create(:user), subscribed: false)
+ user_2 = create(:user)
+ resource.subscriptions.create(user: user_1, subscribed: true)
+ resource.subscriptions.create(user: user_2, project: project, subscribed: true)
+ resource.subscriptions.create(user: create(:user), project: project, subscribed: false)
- expect(resource.subscribers).to eq [user]
+ expect(resource.subscribers(project)).to contain_exactly(user_1, user_2)
end
end
describe '#toggle_subscription' do
- it 'toggles the current subscription state for the given user' do
- expect(resource.subscribed?(user)).to be_falsey
+ context 'without project' do
+ it 'toggles the current subscription state for the given user' do
+ expect(resource.subscribed?(user_1)).to be_falsey
- resource.toggle_subscription(user)
+ resource.toggle_subscription(user_1)
- expect(resource.subscribed?(user)).to be_truthy
+ expect(resource.subscribed?(user_1)).to be_truthy
+ end
+ end
+
+ context 'with project' do
+ it 'toggles the current subscription state for the given user' do
+ expect(resource.subscribed?(user_1, project)).to be_falsey
+
+ resource.toggle_subscription(user_1, project)
+
+ expect(resource.subscribed?(user_1, project)).to be_truthy
+ end
end
end
describe '#subscribe' do
- it 'subscribes the given user' do
- expect(resource.subscribed?(user)).to be_falsey
+ context 'without project' do
+ it 'subscribes the given user' do
+ expect(resource.subscribed?(user_1)).to be_falsey
+
+ resource.subscribe(user_1)
+
+ expect(resource.subscribed?(user_1)).to be_truthy
+ end
+ end
+
+ context 'with project' do
+ it 'subscribes the given user' do
+ expect(resource.subscribed?(user_1, project)).to be_falsey
- resource.subscribe(user)
+ resource.subscribe(user_1, project)
- expect(resource.subscribed?(user)).to be_truthy
+ expect(resource.subscribed?(user_1, project)).to be_truthy
+ end
end
end
describe '#unsubscribe' do
- it 'unsubscribes the given current user' do
- resource.subscriptions.create(user: user, subscribed: true)
- expect(resource.subscribed?(user)).to be_truthy
+ context 'without project' do
+ it 'unsubscribes the given current user' do
+ resource.subscriptions.create(user: user_1, subscribed: true)
+ expect(resource.subscribed?(user_1)).to be_truthy
+
+ resource.unsubscribe(user_1)
+
+ expect(resource.subscribed?(user_1)).to be_falsey
+ end
+ end
+
+ context 'with project' do
+ it 'unsubscribes the given current user' do
+ resource.subscriptions.create(user: user_1, project: project, subscribed: true)
+ expect(resource.subscribed?(user_1, project)).to be_truthy
- resource.unsubscribe(user)
+ resource.unsubscribe(user_1, project)
- expect(resource.subscribed?(user)).to be_falsey
+ expect(resource.subscribed?(user_1, project)).to be_falsey
+ end
end
end
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index a94e6d0165f..60bbe3fcd72 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -166,4 +166,25 @@ describe Environment, models: true do
end
end
end
+
+ describe 'recently_updated_on_branch?' do
+ subject { environment.recently_updated_on_branch?('feature') }
+
+ context 'when last deployment to environment is the most recent one' do
+ before do
+ create(:deployment, environment: environment, ref: 'feature')
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when last deployment to environment is not the most recent' do
+ before do
+ create(:deployment, environment: environment, ref: 'feature')
+ create(:deployment, environment: environment, ref: 'master')
+ end
+
+ it { is_expected.to be false }
+ end
+ end
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 29a3af68a9b..b684053cd02 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -94,6 +94,7 @@ describe Event, models: true do
let(:admin) { create(:admin) }
let(:issue) { create(:issue, project: project, author: author, assignee: assignee) }
let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) }
+ let(:note_on_commit) { create(:note_on_commit, project: project) }
let(:note_on_issue) { create(:note_on_issue, noteable: issue, project: project) }
let(:note_on_confidential_issue) { create(:note_on_issue, noteable: confidential_issue, project: project) }
let(:event) { Event.new(project: project, target: target, author_id: author.id) }
@@ -103,6 +104,32 @@ describe Event, models: true do
project.team << [guest, :guest]
end
+ context 'commit note event' do
+ let(:target) { note_on_commit }
+
+ it do
+ aggregate_failures do
+ expect(event.visible_to_user?(non_member)).to eq true
+ expect(event.visible_to_user?(member)).to eq true
+ expect(event.visible_to_user?(guest)).to eq true
+ expect(event.visible_to_user?(admin)).to eq true
+ end
+ end
+
+ context 'private project' do
+ let(:project) { create(:empty_project, :private) }
+
+ it do
+ aggregate_failures do
+ expect(event.visible_to_user?(non_member)).to eq false
+ expect(event.visible_to_user?(member)).to eq true
+ expect(event.visible_to_user?(guest)).to eq false
+ expect(event.visible_to_user?(admin)).to eq true
+ end
+ end
+ end
+ end
+
context 'issue event' do
context 'for non confidential issues' do
let(:target) { issue }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 47f89f744cb..1613a586a2c 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Group, models: true do
- let!(:group) { create(:group) }
+ let!(:group) { create(:group, :access_requestable) }
describe 'associations' do
it { is_expected.to have_many :projects }
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 1a26cee9f3d..90731f55470 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -19,7 +19,7 @@ describe Key, models: true do
describe "#publishable_keys" do
it 'replaces SSH key comment with simple identifier of username + hostname' do
- expect(build(:key, user: user).publishable_key).to include("#{user.name} (localhost)")
+ expect(build(:key, user: user).publishable_key).to include("#{user.name} (#{Gitlab.config.gitlab.host})")
end
end
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 485121701af..4f7c8a36cb5 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -57,7 +57,7 @@ describe Member, models: true do
describe 'Scopes & finders' do
before do
- project = create(:empty_project, :public)
+ project = create(:empty_project, :public, :access_requestable)
group = create(:group)
@owner_user = create(:user).tap { |u| group.add_owner(u) }
@owner = group.members.find_by(user_id: @owner_user.id)
@@ -174,7 +174,7 @@ describe Member, models: true do
describe '.add_user' do
%w[project group].each do |source_type|
context "when source is a #{source_type}" do
- let!(:source) { create(source_type, :public) }
+ let!(:source) { create(source_type, :public, :access_requestable) }
let!(:user) { create(:user) }
let!(:admin) { create(:admin) }
@@ -443,6 +443,16 @@ describe Member, models: true do
member.accept_invite!(user)
end
+
+ it "refreshes user's authorized projects", truncate: true do
+ project = member.source
+
+ expect(user.authorized_projects).not_to include(project)
+
+ member.accept_invite!(user)
+
+ expect(user.authorized_projects.reload).to include(project)
+ end
end
describe "#decline_invite!" do
@@ -468,4 +478,16 @@ describe Member, models: true do
expect { member.generate_invite_token }.to change { member.invite_token}
end
end
+
+ describe "destroying a record", truncate: true do
+ it "refreshes user's authorized projects" do
+ project = create(:project, :private)
+ user = create(:user)
+ member = project.team << [user, :reporter]
+
+ member.destroy
+
+ expect(user.authorized_projects).not_to include(project)
+ end
+ end
end
diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb
index c5ff1941378..47397a822c1 100644
--- a/spec/models/project_group_link_spec.rb
+++ b/spec/models/project_group_link_spec.rb
@@ -14,4 +14,20 @@ describe ProjectGroupLink do
it { should validate_presence_of(:group) }
it { should validate_presence_of(:group_access) }
end
+
+ describe "destroying a record", truncate: true do
+ it "refreshes group users' authorized projects" do
+ project = create(:project, :private)
+ group = create(:group)
+ reporter = create(:user)
+ group_users = group.users
+
+ group.add_reporter(reporter)
+ project.project_group_links.create(group: group)
+ group_users.each { |user| expect(user.authorized_projects).to include(project) }
+
+ project.project_group_links.destroy_all
+ group_users.each { |user| expect(user.authorized_projects).not_to include(project) }
+ end
+ end
end
diff --git a/spec/models/project_services/chat_service_spec.rb b/spec/models/project_services/chat_service_spec.rb
new file mode 100644
index 00000000000..c6a45a3e1be
--- /dev/null
+++ b/spec/models/project_services/chat_service_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe ChatService, models: true do
+ describe "Associations" do
+ it { is_expected.to have_many :chat_names }
+ end
+
+ describe '#valid_token?' do
+ subject { described_class.new }
+
+ it 'is false as it has no token' do
+ expect(subject.valid_token?('wer')).to be_falsey
+ end
+ end
+end
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
index 652804fb444..9b80f0e7296 100644
--- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -35,9 +35,9 @@ describe GitlabIssueTrackerService, models: true do
end
it 'gives the correct path' do
- expect(@service.project_url).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues")
- expect(@service.new_issue_url).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues/new")
- expect(@service.issue_url(432)).to eq("http://localhost/gitlab/root/#{project.path_with_namespace}/issues/432")
+ expect(@service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues")
+ expect(@service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new")
+ expect(@service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432")
end
end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 05ee4a08391..d8c47322220 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -69,6 +69,7 @@ describe JiraService, models: true do
end
describe "Execute" do
+ let(:custom_base_url) { 'http://custom_url' }
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:merge_request) { create(:merge_request) }
@@ -85,17 +86,30 @@ describe JiraService, models: true do
project_key: 'GitLabProject'
)
+ # These stubs are needed to test JiraService#close_issue.
+ # We close the issue then do another request to API to check if it got closed.
+ # Here is stubbed the API return with a closed and an opened issues.
+ open_issue = JIRA::Resource::Issue.new(@jira_service.client, attrs: { "id" => "JIRA-123" })
+ closed_issue = open_issue.dup
+ allow(open_issue).to receive(:resolution).and_return(false)
+ allow(closed_issue).to receive(:resolution).and_return(true)
+ allow(JIRA::Resource::Issue).to receive(:find).and_return(open_issue, closed_issue)
+
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return("JIRA-123")
+
@jira_service.save
project_issues_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123'
@project_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/project/GitLabProject'
@transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions'
@comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment'
+ @remote_link_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/remotelink'
WebMock.stub_request(:get, @project_url)
WebMock.stub_request(:get, project_issues_url)
WebMock.stub_request(:post, @transitions_url)
WebMock.stub_request(:post, @comment_url)
+ WebMock.stub_request(:post, @remote_link_url)
end
it "calls JIRA API" do
@@ -106,11 +120,44 @@ describe JiraService, models: true do
).once
end
+ # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
+ # for more information
+ it "creates Remote Link reference in JIRA for comment" do
+ @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project))
+
+ # Creates comment
+ expect(WebMock).to have_requested(:post, @comment_url)
+
+ # Creates Remote Link in JIRA issue fields
+ expect(WebMock).to have_requested(:post, @remote_link_url).with(
+ body: hash_including(
+ GlobalID: "GitLab",
+ object: {
+ url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/#{merge_request.diff_head_sha}",
+ title: "GitLab: Solved by commit #{merge_request.diff_head_sha}.",
+ icon: { title: "GitLab", url16x16: "https://gitlab.com/favicon.ico" },
+ status: { resolved: true, icon: { url16x16: "http://www.openwebgraphics.com/resources/data/1768/16x16_apply.png", title: "Closed" } }
+ }
+ )
+ ).once
+ end
+
+ it "does not send comment or remote links to issues already closed" do
+ allow_any_instance_of(JIRA::Resource::Issue).to receive(:resolution).and_return(true)
+
+ @jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project))
+
+ expect(WebMock).not_to have_requested(:post, @comment_url)
+ expect(WebMock).not_to have_requested(:post, @remote_link_url)
+ end
+
it "references the GitLab commit/merge request" do
+ stub_config_setting(base_url: custom_base_url)
+
@jira_service.execute(merge_request, ExternalIssue.new("JIRA-123", project))
expect(WebMock).to have_requested(:post, @comment_url).with(
- body: /#{Gitlab.config.gitlab.url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/
+ body: /#{custom_base_url}\/#{project.path_with_namespace}\/commit\/#{merge_request.diff_head_sha}/
).once
end
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
new file mode 100644
index 00000000000..4a1037e950b
--- /dev/null
+++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
@@ -0,0 +1,99 @@
+require 'spec_helper'
+
+describe MattermostSlashCommandsService, models: true do
+ describe "Associations" do
+ it { is_expected.to respond_to :token }
+ end
+
+ describe '#valid_token?' do
+ subject { described_class.new }
+
+ context 'when the token is empty' do
+ it 'is false' do
+ expect(subject.valid_token?('wer')).to be_falsey
+ end
+ end
+
+ context 'when there is a token' do
+ before do
+ subject.token = '123'
+ end
+
+ it 'accepts equal tokens' do
+ expect(subject.valid_token?('123')).to be_truthy
+ end
+ end
+ end
+
+ describe '#trigger' do
+ subject { described_class.new }
+
+ context 'no token is passed' do
+ let(:params) { Hash.new }
+
+ it 'returns nil' do
+ expect(subject.trigger(params)).to be_nil
+ end
+ end
+
+ context 'with a token passed' do
+ let(:project) { create(:empty_project) }
+ let(:params) { { token: 'token' } }
+
+ before do
+ allow(subject).to receive(:token).and_return('token')
+ end
+
+ context 'no user can be found' do
+ context 'when no url can be generated' do
+ it 'responds with the authorize url' do
+ response = subject.trigger(params)
+
+ expect(response[:response_type]).to eq :ephemeral
+ expect(response[:text]).to start_with ":sweat_smile: Couldn't identify you"
+ end
+ end
+
+ context 'when an auth url can be generated' do
+ let(:params) do
+ {
+ team_domain: 'http://domain.tld',
+ team_id: 'T3423423',
+ user_id: 'U234234',
+ user_name: 'mepmep',
+ token: 'token'
+ }
+ end
+
+ let(:service) do
+ project.create_mattermost_slash_commands_service(
+ properties: { token: 'token' }
+ )
+ end
+
+ it 'generates the url' do
+ response = service.trigger(params)
+
+ expect(response[:text]).to start_with(':wave: Hi there!')
+ end
+ end
+ end
+
+ context 'when the user is authenticated' do
+ let!(:chat_name) { create(:chat_name, service: service) }
+ let(:service) do
+ project.create_mattermost_slash_commands_service(
+ properties: { token: 'token' }
+ )
+ end
+ let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } }
+
+ it 'triggers the command' do
+ expect_any_instance_of(Gitlab::ChatCommands::Command).to receive(:execute)
+
+ service.trigger(params)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb
index 38cfe4ad3e3..97f818125d3 100644
--- a/spec/models/project_services/slack_service/note_message_spec.rb
+++ b/spec/models/project_services/slack_service/note_message_spec.rb
@@ -37,8 +37,8 @@ describe SlackService::NoteMessage, models: true do
it 'returns a message regarding notes on commits' do
message = SlackService::NoteMessage.new(@args)
- expect(message.pretext).to eq("test.user commented on " \
- "<url|commit 5f163b2b> in <somewhere.com|project_name>: " \
+ expect(message.pretext).to eq("test.user <url|commented on " \
+ "commit 5f163b2b> in <somewhere.com|project_name>: " \
"*Added a commit message*")
expected_attachments = [
{
@@ -63,8 +63,8 @@ describe SlackService::NoteMessage, models: true do
it 'returns a message regarding notes on a merge request' do
message = SlackService::NoteMessage.new(@args)
- expect(message.pretext).to eq("test.user commented on " \
- "<url|merge request !30> in <somewhere.com|project_name>: " \
+ expect(message.pretext).to eq("test.user <url|commented on " \
+ "merge request !30> in <somewhere.com|project_name>: " \
"*merge request title*")
expected_attachments = [
{
@@ -90,8 +90,8 @@ describe SlackService::NoteMessage, models: true do
it 'returns a message regarding notes on an issue' do
message = SlackService::NoteMessage.new(@args)
expect(message.pretext).to eq(
- "test.user commented on " \
- "<url|issue #20> in <somewhere.com|project_name>: " \
+ "test.user <url|commented on " \
+ "issue #20> in <somewhere.com|project_name>: " \
"*issue title*")
expected_attachments = [
{
@@ -115,8 +115,8 @@ describe SlackService::NoteMessage, models: true do
it 'returns a message regarding notes on a project snippet' do
message = SlackService::NoteMessage.new(@args)
- expect(message.pretext).to eq("test.user commented on " \
- "<url|snippet #5> in <somewhere.com|project_name>: " \
+ expect(message.pretext).to eq("test.user <url|commented on " \
+ "snippet #5> in <somewhere.com|project_name>: " \
"*snippet title*")
expected_attachments = [
{
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 0810d06b50f..25458e20618 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -20,6 +20,7 @@ describe Project, models: true do
it { is_expected.to have_many(:deploy_keys) }
it { is_expected.to have_many(:hooks).dependent(:destroy) }
it { is_expected.to have_many(:protected_branches).dependent(:destroy) }
+ it { is_expected.to have_many(:chat_services) }
it { is_expected.to have_one(:forked_project_link).dependent(:destroy) }
it { is_expected.to have_one(:slack_service).dependent(:destroy) }
it { is_expected.to have_one(:pushover_service).dependent(:destroy) }
@@ -35,6 +36,7 @@ describe Project, models: true do
it { is_expected.to have_one(:hipchat_service).dependent(:destroy) }
it { is_expected.to have_one(:flowdock_service).dependent(:destroy) }
it { is_expected.to have_one(:assembla_service).dependent(:destroy) }
+ it { is_expected.to have_one(:mattermost_slash_commands_service).dependent(:destroy) }
it { is_expected.to have_one(:gemnasium_service).dependent(:destroy) }
it { is_expected.to have_one(:buildkite_service).dependent(:destroy) }
it { is_expected.to have_one(:bamboo_service).dependent(:destroy) }
@@ -76,7 +78,7 @@ describe Project, models: true do
end
describe '#members & #requesters' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public, :access_requestable) }
let(:requester) { create(:user) }
let(:developer) { create(:user) }
before do
@@ -496,9 +498,6 @@ describe Project, models: true do
end
it 'returns nil and does not query services when there is no external issue tracker' do
- project.build_missing_services
- project.reload
-
expect(project).not_to receive(:services)
expect(project.external_issue_tracker).to eq(nil)
@@ -506,9 +505,6 @@ describe Project, models: true do
it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
ext_project.reload # Factory returns a project with changed attributes
- ext_project.build_missing_services
- ext_project.reload
-
expect(ext_project).to receive(:services).once.and_call_original
2.times { expect(ext_project.external_issue_tracker).to be_a_kind_of(RedmineService) }
@@ -706,7 +702,7 @@ describe Project, models: true do
"/uploads/project/avatar/#{project.id}/uploads/avatar.png"
end
- it { should eq "http://localhost#{avatar_path}" }
+ it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" }
end
context 'When avatar file in git' do
@@ -718,7 +714,7 @@ describe Project, models: true do
"/#{project.namespace.name}/#{project.path}/avatar"
end
- it { should eq "http://localhost#{avatar_path}" }
+ it { should eq "http://#{Gitlab.config.gitlab.host}#{avatar_path}" }
end
context 'when git repo is empty' do
@@ -1520,7 +1516,7 @@ describe Project, models: true do
members_project.team << [developer, :developer]
members_project.team << [master, :master]
- create(:project_group_link, project: shared_project, group: group)
+ create(:project_group_link, project: shared_project, group: group, group_access: Gitlab::Access::DEVELOPER)
end
it 'returns false for no user' do
@@ -1549,7 +1545,9 @@ describe Project, models: true do
expect(members_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false)
expect(members_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true)
expect(shared_project.authorized_for_user?(developer, Gitlab::Access::MASTER)).to be(false)
- expect(shared_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(true)
+ expect(shared_project.authorized_for_user?(master, Gitlab::Access::MASTER)).to be(false)
+ expect(shared_project.authorized_for_user?(developer, Gitlab::Access::DEVELOPER)).to be(true)
+ expect(shared_project.authorized_for_user?(master, Gitlab::Access::DEVELOPER)).to be(true)
end
end
@@ -1646,15 +1644,18 @@ describe Project, models: true do
end
it 'returns environment when with_tags is set' do
- expect(project.environments_for('master', project.commit, with_tags: true)).to contain_exactly(environment)
+ expect(project.environments_for('master', commit: project.commit, with_tags: true))
+ .to contain_exactly(environment)
end
it 'does not return environment when no with_tags is set' do
- expect(project.environments_for('master', project.commit)).to be_empty
+ expect(project.environments_for('master', commit: project.commit))
+ .to be_empty
end
it 'does not return environment when commit is not part of deployment' do
- expect(project.environments_for('master', project.commit('feature'))).to be_empty
+ expect(project.environments_for('master', commit: project.commit('feature')))
+ .to be_empty
end
end
@@ -1664,15 +1665,65 @@ describe Project, models: true do
end
it 'returns environment when ref is set' do
- expect(project.environments_for('master', project.commit)).to contain_exactly(environment)
+ expect(project.environments_for('master', commit: project.commit))
+ .to contain_exactly(environment)
end
it 'does not environment when ref is different' do
- expect(project.environments_for('feature', project.commit)).to be_empty
+ expect(project.environments_for('feature', commit: project.commit))
+ .to be_empty
end
it 'does not return environment when commit is not part of deployment' do
- expect(project.environments_for('master', project.commit('feature'))).to be_empty
+ expect(project.environments_for('master', commit: project.commit('feature')))
+ .to be_empty
+ end
+
+ it 'returns environment when commit constraint is not set' do
+ expect(project.environments_for('master'))
+ .to contain_exactly(environment)
+ end
+ end
+ end
+
+ describe '#environments_recently_updated_on_branch' do
+ let(:project) { create(:project) }
+ let(:environment) { create(:environment, project: project) }
+
+ context 'when last deployment to environment is the most recent one' do
+ before do
+ create(:deployment, environment: environment, ref: 'feature')
+ end
+
+ it 'finds recently updated environment' do
+ expect(project.environments_recently_updated_on_branch('feature'))
+ .to contain_exactly(environment)
+ end
+ end
+
+ context 'when last deployment to environment is not the most recent' do
+ before do
+ create(:deployment, environment: environment, ref: 'feature')
+ create(:deployment, environment: environment, ref: 'master')
+ end
+
+ it 'does not find environment' do
+ expect(project.environments_recently_updated_on_branch('feature'))
+ .to be_empty
+ end
+ end
+
+ context 'when there are two environments that deploy to the same branch' do
+ let(:second_environment) { create(:environment, project: project) }
+
+ before do
+ create(:deployment, environment: environment, ref: 'feature')
+ create(:deployment, environment: second_environment, ref: 'feature')
+ end
+
+ it 'finds both environments' do
+ expect(project.environments_recently_updated_on_branch('feature'))
+ .to contain_exactly(environment, second_environment)
end
end
end
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index e0f2dadf189..12228425579 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -137,7 +137,7 @@ describe ProjectTeam, models: true do
describe '#find_member' do
context 'personal project' do
- let(:project) { create(:empty_project, :public) }
+ let(:project) { create(:empty_project, :public, :access_requestable) }
let(:requester) { create(:user) }
before do
@@ -155,7 +155,7 @@ describe ProjectTeam, models: true do
end
context 'group project' do
- let(:group) { create(:group) }
+ let(:group) { create(:group, :access_requestable) }
let(:project) { create(:empty_project, group: group) }
let(:requester) { create(:user) }
@@ -200,7 +200,7 @@ describe ProjectTeam, models: true do
let(:requester) { create(:user) }
context 'personal project' do
- let(:project) { create(:empty_project, :public) }
+ let(:project) { create(:empty_project, :public, :access_requestable) }
context 'when project is not shared with group' do
before do
@@ -243,7 +243,7 @@ describe ProjectTeam, models: true do
end
context 'group project' do
- let(:group) { create(:group) }
+ let(:group) { create(:group, :access_requestable) }
let(:project) { create(:empty_project, group: group) }
before do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index fe26b4ac18c..72ac41f3472 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -393,33 +393,33 @@ describe Repository, models: true do
end
end
- describe "search_files" do
- let(:results) { repository.search_files('feature', 'master') }
+ describe "search_files_by_content" do
+ let(:results) { repository.search_files_by_content('feature', 'master') }
subject { results }
it { is_expected.to be_an Array }
it 'regex-escapes the query string' do
- results = repository.search_files("test\\", 'master')
+ results = repository.search_files_by_content("test\\", 'master')
expect(results.first).not_to start_with('fatal:')
end
it 'properly handles an unmatched parenthesis' do
- results = repository.search_files("test(", 'master')
+ results = repository.search_files_by_content("test(", 'master')
expect(results.first).not_to start_with('fatal:')
end
it 'properly handles when query is not present' do
- results = repository.search_files('', 'master')
+ results = repository.search_files_by_content('', 'master')
expect(results).to match_array([])
end
it 'properly handles query when repo is empty' do
repository = create(:empty_project).repository
- results = repository.search_files('test', 'master')
+ results = repository.search_files_by_content('test', 'master')
expect(results).to match_array([])
end
@@ -432,6 +432,28 @@ describe Repository, models: true do
end
end
+ describe "search_files_by_name" do
+ let(:results) { repository.search_files_by_name('files', 'master') }
+
+ it 'returns result' do
+ expect(results.first).to eq('files/html/500.html')
+ end
+
+ it 'properly handles when query is not present' do
+ results = repository.search_files_by_name('', 'master')
+
+ expect(results).to match_array([])
+ end
+
+ it 'properly handles query when repo is empty' do
+ repository = create(:empty_project).repository
+
+ results = repository.search_files_by_name('test', 'master')
+
+ expect(results).to match_array([])
+ end
+ end
+
describe '#create_ref' do
it 'redirects the call to fetch_ref' do
ref, ref_path = '1', '2'
@@ -1332,6 +1354,28 @@ describe Repository, models: true do
repository.add_tag(user, '8.5', 'master', 'foo')
end
+ it 'does not create a tag when a pre-hook fails' do
+ allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, ''])
+
+ expect do
+ repository.add_tag(user, '8.5', 'master', 'foo')
+ end.to raise_error(GitHooksService::PreReceiveError)
+
+ repository.expire_tags_cache
+ expect(repository.find_tag('8.5')).to be_nil
+ end
+
+ it 'passes tag SHA to hooks' do
+ spy = GitHooksService.new
+ allow(GitHooksService).to receive(:new).and_return(spy)
+ allow(spy).to receive(:execute).and_call_original
+
+ tag = repository.add_tag(user, '8.5', 'master', 'foo')
+
+ expect(spy).to have_received(:execute).
+ with(anything, anything, anything, tag.target, anything)
+ end
+
it 'returns a Gitlab::Git::Tag object' do
tag = repository.add_tag(user, '8.5', 'master', 'foo')
@@ -1534,14 +1578,4 @@ describe Repository, models: true do
end.to raise_error(Repository::CommitError)
end
end
-
- describe '#remove_storage_from_path' do
- let(:storage_path) { project.repository_storage_path }
- let(:project_path) { project.path_with_namespace }
- let(:full_path) { File.join(storage_path, project_path) }
-
- it { expect(Repository.remove_storage_from_path(full_path)).to eq(project_path) }
- it { expect(Repository.remove_storage_from_path(project_path)).to eq(project_path) }
- it { expect(Repository.remove_storage_from_path(storage_path)).to eq('') }
- end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 43937a54b2c..b1615a95004 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -53,7 +53,7 @@ describe Service, models: true do
describe "Template" do
describe "for pushover service" do
- let(:service_template) do
+ let!(:service_template) do
PushoverService.create(
template: true,
properties: {
@@ -66,13 +66,9 @@ describe Service, models: true do
let(:project) { create(:project) }
describe 'is prefilled for projects pushover service' do
- before do
- service_template
- project.build_missing_services
- end
-
it "has all fields prefilled" do
- service = project.pushover_service
+ service = project.find_or_initialize_service('pushover')
+
expect(service.template).to eq(false)
expect(service.device).to eq('MyDevice')
expect(service.sound).to eq('mic')
diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb
new file mode 100644
index 00000000000..9ab112bb2ee
--- /dev/null
+++ b/spec/models/subscription_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Subscription, models: true do
+ describe 'relationships' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:subscribable) }
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:subscribable) }
+ it { is_expected.to validate_presence_of(:user) }
+
+ it 'validates uniqueness of project_id scoped to subscribable_id, subscribable_type, and user_id' do
+ create(:subscription)
+
+ expect(subject).to validate_uniqueness_of(:project_id).scoped_to([:subscribable_id, :subscribable_type, :user_id])
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3b152e15b61..e84042f8063 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -33,11 +33,12 @@ describe User, models: true do
it { is_expected.to have_many(:award_emoji).dependent(:destroy) }
it { is_expected.to have_many(:builds).dependent(:nullify) }
it { is_expected.to have_many(:pipelines).dependent(:nullify) }
+ it { is_expected.to have_many(:chat_names).dependent(:destroy) }
describe '#group_members' do
it 'does not include group memberships for which user is a requester' do
user = create(:user)
- group = create(:group, :public)
+ group = create(:group, :public, :access_requestable)
group.request_access(user)
expect(user.group_members).to be_empty
@@ -47,7 +48,7 @@ describe User, models: true do
describe '#project_members' do
it 'does not include project memberships for which user is a requester' do
user = create(:user)
- project = create(:project, :public)
+ project = create(:project, :public, :access_requestable)
project.request_access(user)
expect(user.project_members).to be_empty
@@ -490,6 +491,28 @@ describe User, models: true do
end
end
+ describe '.without_projects' do
+ let!(:project) { create(:empty_project, :public, :access_requestable) }
+ let!(:user) { create(:user) }
+ let!(:user_without_project) { create(:user) }
+ let!(:user_without_project2) { create(:user) }
+
+ before do
+ # add user to project
+ project.team << [user, :master]
+
+ # create invite to projet
+ create(:project_member, :developer, project: project, invite_token: '1234', invite_email: 'inviteduser1@example.com')
+
+ # create request to join project
+ project.request_access(user_without_project2)
+ end
+
+ it { expect(User.without_projects).not_to include user }
+ it { expect(User.without_projects).to include user_without_project }
+ it { expect(User.without_projects).to include user_without_project2 }
+ end
+
describe '.not_in_project' do
before do
User.delete_all
@@ -1050,7 +1073,7 @@ describe User, models: true do
it { is_expected.to eq([private_group]) }
end
- describe '#authorized_projects' do
+ describe '#authorized_projects', truncate: true do
context 'with a minimum access level' do
it 'includes projects for which the user is an owner' do
user = create(:user)
@@ -1070,6 +1093,80 @@ describe User, models: true do
.to contain_exactly(project)
end
end
+
+ it "includes user's personal projects" do
+ user = create(:user)
+ project = create(:project, :private, namespace: user.namespace)
+
+ expect(user.authorized_projects).to include(project)
+ end
+
+ it "includes personal projects user has been given access to" do
+ user1 = create(:user)
+ user2 = create(:user)
+ project = create(:project, :private, namespace: user1.namespace)
+
+ project.team << [user2, Gitlab::Access::DEVELOPER]
+
+ expect(user2.authorized_projects).to include(project)
+ end
+
+ it "includes projects of groups user has been added to" do
+ group = create(:group)
+ project = create(:project, group: group)
+ user = create(:user)
+
+ group.add_developer(user)
+
+ expect(user.authorized_projects).to include(project)
+ end
+
+ it "does not include projects of groups user has been removed from" do
+ group = create(:group)
+ project = create(:project, group: group)
+ user = create(:user)
+
+ member = group.add_developer(user)
+ expect(user.authorized_projects).to include(project)
+
+ member.destroy
+ expect(user.authorized_projects).not_to include(project)
+ end
+
+ it "includes projects shared with user's group" do
+ user = create(:user)
+ project = create(:project, :private)
+ group = create(:group)
+
+ group.add_reporter(user)
+ project.project_group_links.create(group: group)
+
+ expect(user.authorized_projects).to include(project)
+ end
+
+ it "does not include destroyed projects user had access to" do
+ user1 = create(:user)
+ user2 = create(:user)
+ project = create(:project, :private, namespace: user1.namespace)
+
+ project.team << [user2, Gitlab::Access::DEVELOPER]
+ expect(user2.authorized_projects).to include(project)
+
+ project.destroy
+ expect(user2.authorized_projects).not_to include(project)
+ end
+
+ it "does not include projects of destroyed groups user had access to" do
+ group = create(:group)
+ project = create(:project, namespace: group)
+ user = create(:user)
+
+ group.add_developer(user)
+ expect(user.authorized_projects).to include(project)
+
+ group.destroy
+ expect(user.authorized_projects).not_to include(project)
+ end
end
describe '#projects_where_can_admin_issues' do