Skip to content
Snippets Groups Projects
Commit 8f9beefa authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent e4bf776a
No related branches found
No related tags found
No related merge requests found
Showing
with 329 additions and 29 deletions
Loading
Loading
@@ -100,6 +100,8 @@ describe 'Group issues page' do
find('.empty-state .js-lazy-loaded')
find('.new-project-item-link').click
 
find('.select2-input').set(group.name)
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
expect(page).not_to have_content(project_with_issues_disabled.full_name)
Loading
Loading
Loading
Loading
@@ -3,8 +3,8 @@
require 'spec_helper'
 
describe Autocomplete::MoveToProjectFinder do
let(:user) { create(:user) }
let(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
 
let(:no_access_project) { create(:project) }
let(:guest_project) { create(:project) }
Loading
Loading
@@ -92,6 +92,15 @@ describe Autocomplete::MoveToProjectFinder do
expect(described_class.new(user, project_id: project.id, search: 'wadus').execute.to_a)
.to eq([wadus_project])
end
it 'allows searching by parent namespace' do
group = create(:group)
other_project = create(:project, group: group)
other_project.add_maintainer(user)
expect(described_class.new(user, project_id: project.id, search: group.name).execute.to_a)
.to contain_exactly(other_project)
end
end
end
end
Loading
Loading
@@ -123,7 +123,7 @@ describe GroupDescendantsFinder do
project = create(:project, namespace: group)
other_project = create(:project)
other_project.project_group_links.create(group: group,
group_access: ProjectGroupLink::MASTER)
group_access: ProjectGroupLink::MAINTAINER)
 
expect(finder.execute).to contain_exactly(project)
end
Loading
Loading
Loading
Loading
@@ -6,22 +6,22 @@ describe ProjectsFinder, :do_not_mock_admin_mode do
include AdminModeHelper
 
describe '#execute' do
let(:user) { create(:user) }
let(:group) { create(:group, :public) }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) }
 
let!(:private_project) do
let_it_be(:private_project) do
create(:project, :private, name: 'A', path: 'A')
end
 
let!(:internal_project) do
let_it_be(:internal_project) do
create(:project, :internal, group: group, name: 'B', path: 'B')
end
 
let!(:public_project) do
let_it_be(:public_project) do
create(:project, :public, group: group, name: 'C', path: 'C')
end
 
let!(:shared_project) do
let_it_be(:shared_project) do
create(:project, :private, name: 'D', path: 'D')
end
 
Loading
Loading
@@ -139,6 +139,12 @@ describe ProjectsFinder, :do_not_mock_admin_mode do
it { is_expected.to eq([public_project]) }
end
 
describe 'filter by group name' do
let(:params) { { name: group.name, search_namespaces: true } }
it { is_expected.to eq([public_project, internal_project]) }
end
describe 'filter by archived' do
let!(:archived_project) { create(:project, :public, :archived, name: 'E', path: 'E') }
 
Loading
Loading
Loading
Loading
@@ -54,7 +54,8 @@
"cached_markdown_version": { "type": "integer" },
"human_access": { "type": ["string", "null"] },
"toggle_award_path": { "type": "string" },
"path": { "type": "string" }
"path": { "type": "string" },
"commands_changes": { "type": "object", "additionalProperties": true }
},
"required": [
"id", "attachment", "author", "created_at", "updated_at",
Loading
Loading
Loading
Loading
@@ -19,6 +19,7 @@
},
"additionalProperties": false
},
"commands_changes": { "type": "object", "additionalProperties": true },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"system": { "type": "boolean" },
Loading
Loading
Loading
Loading
@@ -31,10 +31,11 @@ describe('Repository parent row component', () => {
});
 
it.each`
path | to
${'app'} | ${'/-/tree/master/'}
${'app/assets'} | ${'/-/tree/master/app'}
${'app/assets#/test'} | ${'/-/tree/master/app/assets%23'}
path | to
${'app'} | ${'/-/tree/master/'}
${'app/assets'} | ${'/-/tree/master/app'}
${'app/assets#/test'} | ${'/-/tree/master/app/assets%23'}
${'app/assets#/test/world'} | ${'/-/tree/master/app/assets%23/test'}
`('renders link in $path to $to', ({ path, to }) => {
factory(path);
 
Loading
Loading
Loading
Loading
@@ -22,12 +22,22 @@ describe OptionallySearch do
it 'delegates to the search method' do
expect(model)
.to receive(:search)
.with('foo')
.with('foo', {})
 
model.optionally_search('foo')
end
end
 
context 'when an option is provided' do
it 'delegates to the search method' do
expect(model)
.to receive(:search)
.with('foo', some_option: true)
model.optionally_search('foo', some_option: true)
end
end
context 'when no query is given' do
it 'returns the current relation' do
expect(model.optionally_search).to be_a_kind_of(ActiveRecord::Relation)
Loading
Loading
Loading
Loading
@@ -108,6 +108,8 @@ describe Project do
it { is_expected.to have_many(:external_pull_requests) }
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:source_pipelines) }
it { is_expected.to have_many(:prometheus_alert_events) }
it { is_expected.to have_many(:self_managed_prometheus_alert_events) }
 
it_behaves_like 'model with repository' do
let_it_be(:container) { create(:project, :repository, path: 'somewhere') }
Loading
Loading
@@ -1757,7 +1759,7 @@ describe Project do
expect(described_class.search(project.path.upcase)).to eq([project])
end
 
context 'by full path' do
context 'when include_namespace is true' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
 
Loading
Loading
@@ -1767,11 +1769,11 @@ describe Project do
end
 
it 'returns projects that match the group path' do
expect(described_class.search(group.path)).to eq([project])
expect(described_class.search(group.path, include_namespace: true)).to eq([project])
end
 
it 'returns projects that match the full path' do
expect(described_class.search(project.full_path)).to eq([project])
expect(described_class.search(project.full_path, include_namespace: true)).to eq([project])
end
end
 
Loading
Loading
@@ -1781,11 +1783,11 @@ describe Project do
end
 
it 'returns no results when searching by group path' do
expect(described_class.search(group.path)).to be_empty
expect(described_class.search(group.path, include_namespace: true)).to be_empty
end
 
it 'returns no results when searching by full path' do
expect(described_class.search(project.full_path)).to be_empty
expect(described_class.search(project.full_path, include_namespace: true)).to be_empty
end
end
end
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe PrometheusAlertEvent do
subject { build(:prometheus_alert_event) }
let(:alert) { subject.prometheus_alert }
describe 'associations' do
it { is_expected.to belong_to(:prometheus_alert).required }
end
describe 'validations' do
it { is_expected.to be_valid }
it { is_expected.to validate_presence_of(:prometheus_alert).with_message(:required) }
it { is_expected.to validate_uniqueness_of(:payload_key).scoped_to(:prometheus_alert_id) }
it { is_expected.to validate_presence_of(:started_at) }
describe 'payload_key & ended_at' do
context 'absent if firing?' do
subject { build(:prometheus_alert_event) }
it { is_expected.to validate_presence_of(:payload_key) }
it { is_expected.not_to validate_presence_of(:ended_at) }
end
context 'present if resolved?' do
subject { build(:prometheus_alert_event, :resolved) }
it { is_expected.not_to validate_presence_of(:payload_key) }
it { is_expected.to validate_presence_of(:ended_at) }
end
end
end
describe '#title' do
it 'delegates to alert' do
expect(subject.title).to eq(alert.title)
end
end
describe 'prometheus_metric_id' do
it 'delegates to alert' do
expect(subject.prometheus_metric_id).to eq(alert.prometheus_metric_id)
end
end
describe 'transaction' do
describe 'fire' do
let(:started_at) { Time.now }
context 'when status is none' do
subject { build(:prometheus_alert_event, :none) }
it 'fires an event' do
result = subject.fire(started_at)
expect(result).to eq(true)
expect(subject).to be_firing
expect(subject.started_at).to be_like_time(started_at)
end
end
context 'when firing' do
subject { build(:prometheus_alert_event) }
it 'cannot fire again' do
result = subject.fire(started_at)
expect(result).to eq(false)
end
end
end
describe 'resolve' do
let(:ended_at) { Time.now }
context 'when firing' do
subject { build(:prometheus_alert_event) }
it 'resolves an event' do
result = subject.resolve!(ended_at)
expect(result).to eq(true)
expect(subject).to be_resolved
expect(subject.ended_at).to be_like_time(ended_at)
end
end
context 'when resolved' do
subject { build(:prometheus_alert_event, :resolved) }
it 'cannot resolve again' do
result = subject.resolve(ended_at)
expect(result).to eq(false)
end
end
end
end
end
Loading
Loading
@@ -140,6 +140,41 @@ describe SnippetRepository do
let_it_be(:named_snippet) { { file_path: 'fee.txt', content: 'bar', action: :create } }
let_it_be(:unnamed_snippet) { { file_path: '', content: 'dummy', action: :create } }
 
context 'when existing file has a default name' do
let(:default_name) { 'snippetfile1.txt' }
let(:new_file) { { file_path: '', content: 'bar' } }
let(:existing_file) { { previous_path: default_name, file_path: '', content: 'new_content' } }
before do
expect(blob_at(snippet, default_name)).to be_nil
snippet_repository.multi_files_action(user, [new_file], commit_opts)
expect(blob_at(snippet, default_name)).to be
end
it 'reuses the existing file name' do
snippet_repository.multi_files_action(user, [existing_file], commit_opts)
blob = blob_at(snippet, default_name)
expect(blob.data).to eq existing_file[:content]
end
end
context 'when file name consists of one or several whitespaces' do
let(:default_name) { 'snippetfile1.txt' }
let(:new_file) { { file_path: ' ', content: 'bar' } }
it 'assigns a new name to the file' do
expect(blob_at(snippet, default_name)).to be_nil
snippet_repository.multi_files_action(user, [new_file], commit_opts)
blob = blob_at(snippet, default_name)
expect(blob.data).to eq new_file[:content]
end
end
context 'when some files are not named' do
let(:data) { [named_snippet] + Array.new(2) { unnamed_snippet.clone } }
 
Loading
Loading
Loading
Loading
@@ -302,7 +302,7 @@ describe API::Groups do
 
before do
group1.add_developer(user2)
group3.add_master(user2)
group3.add_maintainer(user2)
end
 
it 'returns an array of groups the user has at least master access' do
Loading
Loading
Loading
Loading
@@ -3,8 +3,8 @@
require 'spec_helper'
 
describe API::Notes do
let(:user) { create(:user) }
let!(:project) { create(:project, :public, namespace: user.namespace) }
let!(:user) { create(:user) }
let!(:project) { create(:project, :public) }
let(:private_user) { create(:user) }
 
before do
Loading
Loading
@@ -226,14 +226,56 @@ describe API::Notes do
let(:note) { merge_request_note }
end
 
let(:request_body) { 'Hi!' }
let(:request_path) { "/projects/#{project.id}/merge_requests/#{merge_request.iid}/notes" }
subject { post api(request_path, user), params: { body: request_body } }
context 'a command only note' do
let(:assignee) { create(:user) }
let(:request_body) { "/assign #{assignee.to_reference}" }
before do
project.add_developer(assignee)
project.add_developer(user)
end
it 'returns 202 Accepted status' do
subject
expect(response).to have_gitlab_http_status(:accepted)
end
it 'does not actually create a new note' do
expect { subject }.not_to change { Note.where(system: false).count }
end
it 'does however create a system note about the change' do
expect { subject }.to change { Note.system.count }.by(1)
end
it 'applies the commands' do
expect { subject }.to change { merge_request.reset.assignees }
end
it 'reports the changes' do
subject
expect(json_response).to include(
'commands_changes' => include(
'assignee_ids' => [Integer]
),
'summary' => include("Assigned #{assignee.to_reference}.")
)
end
end
context 'when the merge request discussion is locked' do
before do
merge_request.update_attribute(:discussion_locked, true)
end
 
context 'when a user is a team member' do
subject { post api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/notes", user), params: { body: 'Hi!' } }
it 'returns 200 status' do
subject
 
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@ describe "Internal Project Pages Access" do
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
group.add_owner(owner)
project.add_master(master)
project.add_maintainer(master)
project.add_developer(developer)
project.add_reporter(reporter)
project.add_guest(guest)
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@ describe "Private Project Pages Access" do
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
group.add_owner(owner)
project.add_master(master)
project.add_maintainer(master)
project.add_developer(developer)
project.add_reporter(reporter)
project.add_guest(guest)
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@ describe "Public Project Pages Access" do
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
group.add_owner(owner)
project.add_master(master)
project.add_maintainer(master)
project.add_developer(developer)
project.add_reporter(reporter)
project.add_guest(guest)
Loading
Loading
Loading
Loading
@@ -362,6 +362,21 @@ describe API::Projects do
end
end
 
context 'and using search and search_namespaces is true' do
let(:group) { create(:group) }
let!(:project_in_group) { create(:project, group: group) }
before do
group.add_guest(user)
end
it_behaves_like 'projects response' do
let(:filter) { { search: group.name, search_namespaces: true } }
let(:current_user) { user }
let(:projects) { [project_in_group] }
end
end
context 'and using id_after' do
it_behaves_like 'projects response' do
let(:filter) { { id_after: project2.id } }
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe PrometheusAlertEntity do
let(:user) { create(:user) }
let(:prometheus_alert) { create(:prometheus_alert) }
let(:request) { double('prometheus_alert', current_user: user) }
let(:entity) { described_class.new(prometheus_alert, request: request) }
subject { entity.as_json }
context 'when user can read prometheus alerts' do
before do
prometheus_alert.project.add_maintainer(user)
stub_licensed_features(prometheus_alerts: true)
end
it 'exposes prometheus_alert attributes' do
expect(subject).to include(:id, :title, :query, :operator, :threshold)
end
it 'exposes alert_path' do
expect(subject).to include(:alert_path)
end
end
end
Loading
Loading
@@ -92,6 +92,8 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
end
 
context 'Files::UpdateService success' do
let(:merge_request) { project.merge_requests.last }
before do
allow(::Files::UpdateService).to receive(:new).and_return(double(execute: { status: :success }))
end
Loading
Loading
@@ -107,6 +109,31 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
expect(service_call[:status]).to be :success
expect(service_call[:http_status]).to be :created
expect(service_call[:dashboard]).to match dashboard_details
expect(service_call[:merge_request]).to eq(Gitlab::UrlBuilder.build(merge_request))
end
context 'when the merge request does not succeed' do
let(:error_message) { 'There was an error' }
let(:merge_request) do
build(:merge_request, target_project: project, source_project: project, author: user)
end
before do
merge_request.errors.add(:base, error_message)
allow_next_instance_of(::MergeRequests::CreateService) do |mr|
allow(mr).to receive(:execute).and_return(merge_request)
end
end
it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(:bad_request)
expect(result[:message]).to eq(error_message)
end
end
 
context 'with escaped characters in file name' do
Loading
Loading
@@ -125,6 +152,25 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
expect(service_call[:dashboard]).to match dashboard_details
end
end
context 'when pushing to the default branch' do
let(:branch) { 'master' }
it 'does not create a merge request', :aggregate_failures do
dashboard_details = {
path: '.gitlab/dashboards/custom_dashboard.yml',
display_name: 'custom_dashboard.yml',
default: false,
system_dashboard: false
}
expect(::MergeRequests::CreateService).not_to receive(:new)
expect(service_call.keys).to contain_exactly(:dashboard, :http_status, :status)
expect(service_call[:status]).to be :success
expect(service_call[:http_status]).to be :created
expect(service_call[:dashboard]).to match dashboard_details
end
end
end
 
context 'Files::UpdateService fails' do
Loading
Loading
Loading
Loading
@@ -2790,7 +2790,7 @@ describe NotificationService, :mailer do
let!(:developer) { create(:user) }
 
before do
project.add_master(master)
project.add_maintainer(master)
end
 
it 'sends the email to owners and masters' do
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment